Skip to content

Python and C++ code refactoring - #9

Open
carloslihu wants to merge 108 commits into
davenza:masterfrom
carloslihu:master
Open

Python and C++ code refactoring#9
carloslihu wants to merge 108 commits into
davenza:masterfrom
carloslihu:master

Conversation

@carloslihu

Copy link
Copy Markdown
  • Python code is now formatted with black and isort, and has been refactored according to PEP 8 style guides.
  • Python code partially commented with google docstring format.
  • C++ code partially commented with doxygen docstring format.
  • Scott's and Normal Reference Rule's bandwidth calculation have been reordered and commented.
  • ArcOperatorSet::update_incoming_arcs_scores formulas have been reordered and commented.

@carloslihu

carloslihu commented Aug 11, 2025

Copy link
Copy Markdown
Author

Hello David, thank you for reviewing my changes, they are a lot:

  • The bug I'm talking about is about performing HC with cross-validation when you have a variable with low variability (but not 0 variance). For instance, a variable A with training values [0, 0, ..., 0, 1].
    When performing the validated k-fold cross-validation, it finds problems fitting the distribution when the "1" value is not found in the training fold.
    It is not a bug, more like a problem I found with some datasets. I do not have a clear solution for the algorithm. You may ignore the comment; I will remove it.

  • I still have pending to review that the python tests are still working and cleaning comments.
    It's a minor change, but I have planned to finish this month.
    Please wait for them, thanks

@carloslihu

Copy link
Copy Markdown
Author

Another issue is that I have retrocompatibility with the tests until the tag v0.5.2
However, afterwards I started using for KDE by default the diagonal covariance as the bandwidth matrix, instead of the full covariance (as suggested here)

This KDE learning faster and removes the Singular Covariance Matrix error.
Although it may return less accurate Bandwidth Matrices, in my experience, the differences are minimal.

If you like this change, I could adapt the tests so that they pass the results given this new method.

@davenza

davenza commented Aug 11, 2025

Copy link
Copy Markdown
Owner

Thank you @carloslihu. I will try to create a test with a case of almost 0 variance to try to control it. First, I wanna know where it is raising the error.

About the diagonal matrices: yes, many authors recommend using diagonal matrices. Less parameters to estimate and usually small degradation of performance. That is why I defined ProductKDE (https://pybnesian.readthedocs.io/en/latest/api/factors.html#pybnesian.ProductKDE).

I know that ProductKDE is not exactly the same as KDE with diagonal bandwidth matrix, but:

  • Do you remember if the methods to estimate the bandwidth are equal (in ProductKDE and diagonal KDE)?
  • If previous question is no. Do you think we need an specific implementation for the estimation of bandwidth in diagonal KDEs?

@carloslihu

carloslihu commented Aug 12, 2025

Copy link
Copy Markdown
Author

Hello David,
After analyzing the definition of PyBNesian ProductKDE and the definition of diagonal bandwidth matrix KDE found in the literature.
I think they represent the same concept with different notation.

For my implementation I wanted to use ProductKDE for Hill Climbing, but by lack of skill and time, I wasn't able to do so.
Therefore, my Hack Fix was to manually remove the non-diagonal elements from the covariance matrix in
NormalReferenceRule.hpp and ScottsBandwidth.hpp

This is just a temporary fix, I think that the best solution would be to allow the option of allowing the selection of your ProductKDE implementation for the Hill Climbing algorithm, but my lack of knowledge wouldn't let me.

@carloslihu

Copy link
Copy Markdown
Author

Hello David,
For the moment I have rebased my master branch to tag v0.5.2 (before adapting my diagonal bandwidth fix)
This way you may merge my latest changes without altering your functionality.

I will continue using the diagonal bandwidth in another personal branch (feature/diagonal-bandwidth) for the moment

carloslihu and others added 21 commits September 22, 2025 06:39
- Updated all instances of uppercase variable names (A, B, C, D) to lowercase (a, b, c, d) in the serialization tests for various Bayesian network models.
- Ensured consistency across fixtures and assertions to reflect the new naming convention.
Copilot AI lite review requested due to automatic review settings August 31, 2026 13:17

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

There are several correctness/build issues in the current diff (test import path, missing C++ includes, an integer-division bug in smoothing, and build configuration pitfalls) that should be addressed before merging.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

This PR modernizes PyBNesian’s Python/C++ codebase via formatting and documentation improvements, while also introducing new learning/independence-test functionality and build/dependency tweaks (including a version bump).

Changes:

  • Reformats and refactors many Python tests and updates documentation/changelogs for the 0.6.0 release.
  • Updates C++ internals around scoring/operators, KDE bandwidth handling, mutual information behavior, and introduces VP-tree–backed mixed-data mutual information tooling/bindings.
  • Adjusts build/packaging configuration (vcpkg, CMake, requirements/pyproject metadata, CI workflows).
File summaries
File Description
vcpkg.json Disables Arrow default features in vcpkg manifest.
vcpkg-configuration.json Reformatting only.
tests/serialization/serialize_models_type_test.py Import/order formatting and fixture/test formatting cleanup.
tests/serialization/serialize_factor_type_test.py Refactors tests to use pbn.* types consistently; formatting.
tests/serialization/serialize_factor_test.py Refactors to pbn.* usage and reformats; minor assertion adjustments.
tests/models/HeterogeneousBN_test.py Formatting and minor comment cleanup.
tests/models/DynamicBayesianNetwork_test.py Refactors to shared helpers, reformats, and adjusts regex handling.
tests/models/BayesianNetwork_type_test.py Refactors to shared helpers and pbn.* usage.
tests/learning/scores/bic_test.py Uses shared data helpers/constants; formatting.
tests/learning/parameters/mle_test.py Uses shared data helpers/constants; small assertion additions.
tests/learning/operators/operatorstabuset_test.py Formatting/whitespace cleanup.
tests/learning/operators/operatorset_test.py Uses shared data helpers/constants; formatting; variable-name updates.
tests/learning/operators/operators_test.py Formatting and consistent quoting.
tests/learning/operators/operatorpool_test.py Uses shared data helpers/constants; adds simple pool creation check.
tests/learning/independence_tests/independence_test.py New test suite for multiple independence tests.
tests/learning/algorithms/hillclimbing_test.py Refactors to shared helpers; adds custom BN type/classes in-test; formatting.
tests/learning/algorithms/constraint_test.py Refactors to pbn.* usage; formatting; adjusts node labels.
tests/helpers/util_test.py Removes legacy helper module (replaced by tests/helpers/data.py).
tests/helpers/kde.py Adds helper KDE routines for diagonal bandwidth / logpdf checks.
tests/factors/factor_type_test.py Refactors to pbn.* base classes and formatting.
tests/factors/discrete/DiscreteFactor_test.py Uses shared discrete data helper and refactors variable/category conventions.
tests/dataset/holdout_test.py Uses shared data helpers/constants; formatting.
tests/conftest.py Alters sys.path handling for test helper imports.
requirements.txt Removes version specifiers for dependencies.
README.md Updates badges/headers, repo clone URL, and formatting; links INSTALLATION.md.
pytest.ini Expands norecursedirs and adds -s default addopts.
pyproject.toml Version bump to 0.6.0; authors expanded; dependency metadata consolidated.
pybnesian/vptree/vptree.hpp New VP-tree interface/types for kNN-based algorithms.
pybnesian/util/validate_whitelists.hpp Adds Doxygen-style documentation blocks.
pybnesian/util/validate_options.hpp Changes score-validation seed type to unsigned int.
pybnesian/util/validate_options.cpp Adds documentation/comments; default score selection commentary; minor message text.
pybnesian/util/progress.hpp Adds formatted_log_t and spinner documentation.
pybnesian/util/basic_eigen_ops.hpp Refactors PSD check implementation and signature.
pybnesian/pybindings/pybindings_learning/pybindings_independences.cpp Adds Python bindings for MixedKMutualInformation.
pybnesian/pybindings/pybindings_learning/pybindings_algorithms.cpp Fixes docstring typo for validated-lik.
pybnesian/opencl/opencl_config.hpp Adds comments clarifying logsumexp steps.
pybnesian/models/BayesianNetwork.hpp Adds documentation and comments around blacklist/whitelist handling.
pybnesian/learning/scores/validated_likelihood.hpp Adds class/method documentation comments.
pybnesian/learning/scores/holdout_likelihood.hpp Adds class documentation comments.
pybnesian/learning/scores/cv_likelihood.hpp Adds class documentation comments.
pybnesian/learning/scores/cv_likelihood.cpp Adds documentation and clarifying comments.
pybnesian/learning/parameters/mle_DiscreteFactor.cpp Adds smoothing for discrete MLE probability estimation.
pybnesian/learning/operators/operators.hpp Adds deterministic comparator for delta sorting; adds documentation/comments.
pybnesian/learning/operators/operators.cpp Adds documentation/comments; refactors scoring update comments; minor logic commentary.
pybnesian/learning/independences/hybrid/mutual_information.cpp Ensures MI/CMI returns at least machine tolerance; guards pvalue against inf/nan.
pybnesian/learning/independences/hybrid/mixed_knncmi.hpp New mixed-data kNN-CMI interface declarations.
pybnesian/learning/algorithms/hillclimbing.cpp Adds extensive function documentation and commentary.
pybnesian/kde/ScottsBandwidth.hpp Improves messages/comments; enforces diagonal covariance handling and PSD checks.
pybnesian/kde/ProductKDE.hpp Include order tweak; adds bandwidth-related comments.
pybnesian/kde/opencl_kernels/KDE.cl.src Expands header comment.
pybnesian/kde/NormalReferenceRule.hpp Improves messages/comments; diagonal covariance handling adjustments.
pybnesian/kde/KDE.cpp Adds method documentation comments.
pybnesian/factors/discrete/DiscreteFactor.cpp Adds clarifying comment in ToString.
pybnesian/factors/continuous/LinearGaussianCPD.hpp Makes data_type() depend on training type.
pybnesian/factors/continuous/LinearGaussianCPD.cpp Tracks training type, improves sampling to support float/double, updates pickle state.
pybnesian/factors/continuous/CKDE.hpp Adds _fit documentation comment.
pybnesian/factors/continuous/CKDE.cpp Adds fit documentation comment.
pybnesian/dataset/holdout_adaptator.hpp Fixes formatting in thrown message.
pybnesian/dataset/dataset.hpp Fixes preprocessor conditional formatting.
pybnesian/dataset/dataset.cpp Fixes preprocessor conditional formatting; adds documentation comments.
lib/eigen-3.3.7/scripts/relicense.py Python 3 style/format fixes.
lib/eigen-3.3.7/debug/gdb/printers.py Python 3 style/format fixes and type-ignore.
INSTALLATION.md New detailed installation guide.
expand_sources.py Formatting and minor refactor for file operations.
docs/source/conf.py Updates version/authors and reformats Sphinx config.
docs/source/changelog.rst Adds v0.5.2 entry.
docs/source/api/learning/independences.rst Adds bibliography entries for new MI estimators.
conv_template.py Formatting, typing, and minor structure cleanup.
CMakeLists.txt Refactors conditionals; adds ccache; changes python invocation; adds vptree/mixed_knncmi sources.
CHANGELOG.md Adds entries for 0.6.0/0.5.3 and formatting improvements.
.readthedocs.yaml Minor formatting fix.
.gitignore Adds wheelhouse to ignored outputs.
.github/workflows/test_release.yml Captures/uploads vcpkg logs on failure.
.github/workflows/release.yml Captures/uploads vcpkg logs on failure.
Review details
  • Files reviewed: 86/89 changed files
  • Comments generated: 7
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread tests/conftest.py
import sys
sys.path.append(os.path.join(os.path.dirname(__file__), "helpers"))

sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "tests")))
Comment on lines 4 to +8
#include <indicators/indicators.hpp>
// #include <sstream>
// #include <boost/format.hpp> // sudo apt install libboost-all-dev
#include <iostream>
// enum class log_level_t { LOG_NOTHING, LOG_CRITICAL, LOG_ERROR, LOG_WARNING, LOG_INFO, LOG_DEBUG };
Comment on lines +4 to +8
#include <dataset/dataset.hpp>
#include <queue>
#include <random>
#include <algorithm>
#include <boost/functional/hash/hash.hpp>
Comment on lines +33 to +35
// Schurmann-Grassberger smoothing, lambda = 1 (uniform prior)
double lambda = 1 / cardinality(0);
double logsum_configuration = std::log(static_cast<double>(sum_configuration + lambda * cardinality(0)));
Comment thread CMakeLists.txt
Comment on lines +12 to +15
if(UNIX)
set(CMAKE_C_COMPILER "gcc")
set(CMAKE_CXX_COMPILER "g++")
endif()
Comment on lines 44 to 47
"\" specified. The possible alternatives are "
"\"bic\" (Bayesian Information Criterion), \"bge\" (Bayesian Gaussian equivalent), "
"\"cv-lik\" (Cross-Validated likelihood), \"holdout-l\" (Hold-out likelihood) "
" or \"validated-lik\" (Validated likelihood with cross-validation).");
Comment thread CHANGELOG.md
Comment on lines +2 to +7
## 0.6.0
- Fixed a bug with LinearGaussianCPD sampling
- Fixed pytests to work with diagonal bandwidth matrix.
- Added delta index comparator to fix seed in hc learning
- Refactor variable names in serialization tests to lowercase
- Updated installation guide with improved instructions and additional dependencies
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants