Changelog for aGrUM/pyAgrum 3.0.0
Changelog for 3.0.0
This major release brings three headline changes:
- Causal module promoted to C++: the causal inference layer moves from a pure-Python package to a
first-class C++ module (
CM), with SWIG bindings, an AST for do-calculus, and a complete Python API. - Extended structure learning: PC, FCI (with PAG output), GreedyThickThinning, and triangle deletions
in GreedyHillClimbing are all integrated into
BNLearner. - New GUM serialization format (
jgum/bgum): a first-class JSON and binary format for all graphical models (BN, ID, MRF), with round-trip string API (proceedFromString) and full Python bindings (saveGUM/loadGUM/saveGUMstring/loadGUMstring).
This major release brings more than 410 commits since 2.3.2.
This release also reflects a sustained optimization effort. On the C++ side, the test suite expanded from 1 487 to 1 890 tests — all previous ones included — while execution time dropped from 150 s to 130 s (measured on a Mac Studio, Apple M2 Ultra, 24 cores, 128 GB RAM). The pyAgrum library (_pyagrum.so) shrank from 13 MB down to 7.8 MB despite the addition of new structure-learning algorithms, the full causal module, and more.
Additionally, this release consolidates widespread API modernisation (C++20 std::format, string_view,
optional_ref, std::optional, concepts) and several breaking renames detailed below.
1. pyAgrum
1.1 Breaking API
-
Causal module — renames and signature changes:
CausalModel.observedBN()renamed →observationalBN()CausalModel.addLatentVariable(..., keepArcs=...)— parameterkeepArcsrenamed →assumeNonSpuriousCausalModel.backDoor(),frontDoor()— returnNoneinstead of raising when no valid set exists;set()when the empty set is valid.DoorCriteria:EnumerationOptionsremoved; options (excluded_nodes,max_cardinality,only_minimal,stopAtFirst) are now direct keyword parameters; all methods are now static.CausalImpact: direct access toresultfield removed — useimpact().Counterfactual:getResult()→impact().DSeparationrenamed →Separation.
-
BNClassifier — API change:
BNClassifiernow requires aDiscreteTypeProcessoras a constructor parameter.- Factory function
createBNClassifiersignature changed accordingly. - Binary prediction dispatch and
predict_probaupdated;model()method added (returns a copy of the underlying BN). - Notebooks and tests updated to the new API.
-
Graph — path-finding functions return
Nonewhen no path exists:undirectedPath,directedPath,directedUnorientedPath,mixedOrientedPath,mixedUnorientedPathnow returnNoneinstead of raisingNotFound(or returning[]) when no path exists.
-
Type aliases removed (
ctbn,clg):NodeIdandNameOrIdtype aliases inpyagrum.ctbnandpyagrum.clghave been removed. UseintforNodeIdandint | strforNameOrId.
-
Pickle metadata:
_gum_add_properties_while_getstate_removed; pickle metadata now handled byupdateMetaData(). Pickled objects from earlier versions may not unpickle correctly.
1.2 New Functionalities
-
100% docstring coverage:
- Added
%feature(docstring)entries for all 2174 methods; docstrings follow NumPy format.
- Added
-
Native GUM format (jgum / bgum):
- Added
saveGUM(),loadGUM(),saveGUMstring(),loadGUMstring()toBayesNet,InfluenceDiagram, andMarkovRandomField. - Added SWIG type mapping for
optional<vector<NodeId>>. - Added
GumFormatTestSuitecovering jgum/bgum round-trips and string serialization. - Added Sphinx page
jgum-bgum-format.rstwith format reference and usage examples. - Added notebook 91-Tools-LoadAndSaveGraphicalModels illustrating all I/O formats.
- Added
-
Causal Integration:
- Added SWIG Python bindings for the C++ causal module (
CausalModel,CausalFormula,DoorCriteria,Counterfactual, …). - Refactored
causalEffectEstimationas a top-level subpackage. - Fixed type references in docstrings (
pyagrum.causal.CausalModel→pyagrum.CausalModel). - Restructured causality section in Sphinx documentation.
- Updated causality notebooks.
- Added
causal2graphutility for causal graph visualization. - Added AST printing for
CausalImpactresults.
- Added SWIG Python bindings for the C++ causal module (
-
New learning algorithms:
- FCI and PAG: added SWIG bindings for
PAG(Partial Ancestral Graph) and the FCI (Fast Causal Inference) algorithm; exposedBNLearner.useFCI(),fciExhaustiveSepSet()/setFCIExhaustiveSepSet(); added documentation and test suite for PAG/FCI. - PC algorithm: exposed
BNLearner.usePC(), integrating constraint-based structure learning alongside Miic and FCI, withsetPCAlpha(),setPCStable(),setPCMaxCondSetSize(),setPCUnshieldedColliderSorted(). - GreedyThickThinning: exposed
BNLearner.useGreedyThickThinning()for score-based structure learning, withsetGreedyThickThinningReversals(). - GreedyHillClimbing — triangle deletions: exposed
BNLearner.useExtendedGreedyHillClimbing()andallowArcTriangleDeletions(), adding arc-triangle deletion moves to the existing add/reverse/delete arc operators.
- FCI and PAG: added SWIG bindings for
-
qBNSampling (experimental, thanks to Tibor Dubois, Thierry Rioual, Mehmet Gunes):
- New
pyagrum.qBNSamplingmodule: quantum circuit encoding of Bayesian Networks and rejection-sampling inference.
- New
-
CLG (Conditional Linear Gaussian):
- Added
CLG.asDiscreteBN()method to convert a CLG model to a discretized BN. - Added
CLG.__eq__,__getstate__,__setstate__(pickle support). - New
CLGModelTestSuiteand extendedCLGInference/SEM/Sampling/Randomtest suites. randomCLGgainsmax_parentsandratio_arcparameters;GaussianVariablesigma guard added (thanks to Ima Bernada).
- Added
-
BNClassifier:
- Added
model()method returning a copy of the underlying BN. - Full coverage
BNClassifierTestSuite.
- Added
-
StructuralMetrics:
- Exposed
StructuralMetrics(formerlyStructuralComparator) with SHD, tp/fp/fn/tn accessors and SID (Structural Intervention Distance) for BN comparison. - Updated
GraphicalBNComparatorto delegate toStructuralMetrics;structuralFScoreadded.
- Exposed
-
Tensor:
Tensormethodsrandom(),randomDistribution(),randomCPT(),noising()now returnselffor chaining (viaCHANGE_THEN_RETURN_SELF).- Python bindings for
mean(),variance(),stdDev(),isNumerical(). - Numpy interop: new
as_nparray(),toarray(), andfillWith(ndarray)methods.
-
Graph API extensions:
- Exposed
nameFromId(),idFromName(),setName(),hasName()on all graph types (DiGraph,DAG,MixedGraph, …). - Added
connectedComponents()(returnsdict[int, int]),connectedComponentsList(), andconnectedComponentsCount(). - Fixed missing
descendants()/ancestors()onDiGraph;NodeSet,ArcSet,EdgeSetreturns now use dedicated typemaps.
- Exposed
-
SWIG sentinel typedefs:
- Added sentinel typedefs to replace
-> objectwith precise Python return type annotations in generated bindings.
- Added sentinel typedefs to replace
1.3 Improvements
-
Performance & Data Handling:
- Optimized
Tensornumpy access: zero-copy__getitem__,memcpy-based__setitem__(numpy >= 1.7required). - Introduced
PYTHONIZED_MARGINALSmacro and global numpy import for generated inference code. - Lazy-import of
pandasviaTYPE_CHECKING(~240 ms saved on import time).
- Optimized
-
Type annotations & static analysis:
- Added full type annotations to all pyLibs (
lib/,clg/,skbn/,bnmixture/,ctbn/,causalEffectEstimation/). - Added inference type aliases:
BNInference,MRFInference,CNInference. - Replaced
mypywith pyrefly inact guideline; fixed all type errors across pyLibs. MatrixLike/ArrayLiketype aliases added to__init__.in.py.
- Added full type annotations to all pyLibs (
-
skbn / BNClassifier (thanks to Lou Toubiana):
- Refactored for full sklearn API compliance:
ClassifierMixinplaced beforeBaseEstimatorin MRO, fitted attributes renamed to trailing-underscore convention (bn_,threshold_,target_, …),validate_data()used for input validation infit,predict, andpredict_proba. fit(X, y)signature is now positional and strictly sklearn-compliant; the oldfit(X=None, y=None, data=None, targetName=None)form is removed.- Fixed pandas 2.x compatibility:
Xis cast toobjectdtype before processing infit. - Suppressed spurious sklearn
'X does not have valid feature names'warning inpredict/predict_proba.
- Refactored for full sklearn API compliance:
-
BNMixture:
- Manifest-based
saveBNM/loadBNM;loadRetroCompatibleBNMfor backward compatibility. - Fixed
saveBNM/loadBNMon Windows (colons in BN names).
- Manifest-based
-
explain (ShAP / SHALL):
- API improvements, causal SHAP fix, binary BN test resources added.
- Fixed uninitialized array in
_labelToPos(np.empty→np.zeros).
-
ipython / notebook utilities:
- Rewritten
ipython.py, newjt2graph.py, fixedprepareDotfontcolor. - Fixed
html2imageissues in notebook contexts; improved export cropping.
- Rewritten
-
Infrastructure:
act install: support no-make mode viacmake --install;--onlyflag (alias for--build no-make).act test pyAgrum: persistent--test_build_pathoption.- Fixed
fastPrototypedocstring separator. - Removed useless
newFactorymethods.
2. aGrUM
2.1 Breaking API
-
Causal module — renames and signature changes:
CausalModel::observedBN()renamed →observationalBN()CausalModel::addLatentVariable(..., keepArcs=...)— parameterkeepArcsrenamed →assumeNonSpuriousCausalModel::backDoor(),frontDoor()— return typeNodeSet→std::optional<NodeSet>(nullopt = no valid set;{}= empty set is valid).DoorCriteria:EnumerationOptionsstruct removed; options are now direct parameters; all methods are nowstatic.DoorCriteria::nodesOnDirectedPaths(dag, X, Y)— return typeNodeSet→std::optional<NodeSet>.CausalImpact: direct access toresultfield removed — useimpact().Counterfactual<GUM_ELEMENT>: template parameter renamed fromGUM_SCALAR;getResult()→impact().DSeparation(inCM/tools/) renamed →Separation.
-
Core containers —
tryGet/tryFirst/trySecond/tryPos:-
HashTable<Key,Val>::tryGet(key)and related methods:Old return type New return type Val*(nullptr if absent)optional_ref<Val>const Val*(nullptr if absent)optional_ref<const Val> -
gum::optional_ref<T>behaves likestd::optionalfor references (C++26 feature backported). Update callers:// beforeif (auto* p = table.tryGet(key)) { use(*p); }// afterif (auto ref = table.tryGet(key)) { use(*ref); } -
Same applies to
tryFirst,trySecond,tryPos.
-
-
Graph — path-finding functions return
std::optional:directedPath,directedUnorientedPath,undirectedPath,mixedOrientedPath,mixedUnorientedPathnow returnstd::optional<std::vector<NodeId>>—nulloptwhen no path exists. Applies toDiGraph,UndiGraph,MixedGraph,PDAG,CliqueGraph, and allGUM_DiGraphable/GUM_UndiGraphable/GUM_MixedGraphablegraphs.
-
Signaler— variadic template:Signaler1<A>,Signaler2<A,B>,Signaler3<A,B,C>, … removed. Use variadicSignaler<A>,Signaler<A,B>,Signaler<A,B,C>, … instead.
-
string_viewmigration (widespread):const std::string¶meters replaced bystd::string_viewacross the public API (BayesNet, variables, I/O readers, learning, …). Passingstd::stringor string literals remains compatible. Code that stored or comparedconst std::string&bindings directly may need adjustment.
-
I/O writers —
write()no longerconst:-
BNWriter<GUM_SCALAR>::write()(and all subclass writers includingGumBNWriter) no longer takes the BN byconstreference:// beforevoid write(std::ostream& output, const IBayesNet<GUM_SCALAR>& bn);// aftervoid write(std::ostream& output, IBayesNet<GUM_SCALAR>& bn); -
Required to allow writers to call
bn.updateMetaData()before serialization.CredalNet::saveBNsMinMax()is similarly affected.
-
-
DiscreteGraphicalModel— new base class:IBayesNetandIMarkovRandomFieldnow inherit fromDiscreteGraphicalModel, which factors five variable-map accessors (variable,variableNodeMap,nodeId,idFromName,existsInModel) previously duplicated in each interface. Direct subclasses must no longer define those accessors themselves.
-
DiscreteVariable::closestLabel— now virtual:- ABI change: recompilation required for any code linking against aGrUM as a shared library.
-
DAGmodel::dag()andUGmodel::graph()— return named copies:dag()andgraph()now return value copies (with node names propagated), notconstreferences. UseinternalDag()/internalGraph()for the O(1) stableconstreference when graph mutation through the model API is not needed. Code that heldconst auto&bindings to the old return values must switch tointernalDag()/internalGraph().
-
StructuralComparatorrenamed toStructuralMetrics:- The class
StructuralComparatorhas been renamedStructuralMetrics. Update all include paths and type names accordingly.
- The class
2.2 New Functionalities
-
FCI algorithm and PAG:
- Added
PAG(Partial Ancestral Graph) type for FCI output. - Implemented
FCI(Fast Causal Inference) algorithm producing a PAG from data. - Integrated FCI into
IBNLearner/BNLearnerAPI (setAlgorithmFCI). - Fixed
possibleDSepcriterion (Zhang 2008); added exhaustive sepset mode (setFCIExhaustiveSepSet); enforced background knowledge in orientation rules (R1/R2/R9/R10).
- Added
-
PC algorithm:
- Added
PCconstraint-based structure learning algorithm. - Integrated into
IBNLearner/BNLearneralongside Miic.
- Added
-
GreedyThickThinning algorithm:
- Added
GreedyThickThinningscore-based structure learning algorithm. - Integrated into
IBNLearner/BNLearner.
- Added
-
GreedyHillClimbing — triangle deletions:
- Extended structural constraints with arc-triangle deletion operations.
GraphChangesSelector4DiGraphnow supportsapplyArcDeletion,applyArcReversal,applyTriangleDeletion.LocalSearchWithTabuListupdated;totalOrderconstraint added.
-
Independence tests refactoring:
- Extracted
CachedContingencyCounterbase class from Chi2 and G2 implementations. IndependenceTest::statistics()made pure virtual; overridden inIndepTestChi2andIndepTestG2.- Added silent-cell df correction in Chi2/G2 tests; fixed G2 df for sampling zeros.
- New
Chi2TestSuite.
- Extracted
-
ConstraintBasedLearning refactoring:
- Extracted
ConstraintBasedLearningbase class from Miic. - Extracted
CIBasedLearningbase class adding scorer-agnostic API (learnPDAG/learnDAG/learnBN). - CMI types and comparators moved to Miic;
setMutualInformation()injector added. applyStructuralConstraints_factored intoConstraintBasedLearning.- Renamed
scores_and_tests/directory toscores/; updated all includes.
- Extracted
-
Causal Module (CM) (thanks to SCALNYX):
- Promoted the causal module from pure Python to a first-class C++ module.
- Introduced
CausalModelandCausalFormula. - Developed an AST for do-calculus with LaTeX export and evaluation.
- Added
DoorCriteriaclass for backdoor and frontdoor set enumeration. - Implemented ID/IDC algorithms and formula introspection.
- Added
counterfactualandcounterfactualModelfunctions with tests.
-
Native GUM format (jgum / bgum):
- Added
GumBNReader/GumBNWriter,GumIDReader/GumIDWriter,GumMRFReader/GumMRFWritersupporting both JSON (.jgum) and binary (.bgum) serialization. - All GUM readers support
proceedFromString()and a no-filename constructor for in-memory round-trips. - Extracted
_readVector_/_writeVector_helpers toGumBinaryIO.h. - Fixed empty-BN jgum serialization; fixed binary writers to open files with
ios::binary. - Fixed
IDReader::proceed()return type (void→Size).
- Added
-
Node names in
NodeGraphPart:- Added optional node name support:
nameFromId(),idFromName(),setName(),hasName(). - Names propagated to
toDot()output (format:id:name). checkConsistency()made public;frienddeclarations for test suites removed.GraphicalModel::_nameNodes_()propagates node names to returned graphs:moralGraph(),moralizedAncestralGraph(),EssentialGraph::pdag()/skeleton(),MarkovBlanket::dag().
- Added optional node name support:
-
C++20 graph concepts and generic algorithms:
- Added C++20 concepts
GUM_DiGraphable,GUM_UndiGraphable,GUM_MixedGraphablefor graph-agnostic programming. - Added generic path/reachability/cycle algorithms operating on any concept-satisfying graph type.
- Added generic moralization and separation algorithms;
DAG/PDAGmethods now delegate. - Added generic
BayesBallalgorithm;dSeparatedandBayesBall::requisiteNodesdelegate. - Promoted
minimalCondSet,markovBlanket,areConnectedto the generic graph layer.
- Added C++20 concepts
-
StructuralMetrics (formerly StructuralComparator):
- Renamed
StructuralComparator→StructuralMetrics. - Added SHD metrics with tp/fp/fn/tn accessors.
- Added SID (Structural Intervention Distance) for DAG-vs-DAG and
BayesNetoverload. - Name-based alignment for BN compare/SID.
- Renamed
-
BIFXMLBNReaderimprovements (thanks to Omi Johnson):- Added
std::istreamconstructor for in-memory parsing. - Now reads the network
NAMEproperty from BIF/XML files.
- Added
-
Modeling & Core API:
- Added
connectedComponents()toDAGmodelandUGmodel; C++ and Python tests for BN, ID, MRF. - Added
descendants()andancestors()toMarkovBlanketandEssentialGraph. - Introduced
DiscreteGraphicalModelto factor variable management acrossIBayesNetandIMarkovRandomField. - Replaced nullable pointers with
optional_ref<T>andstd::optionalin various interfaces. - Added
data()method toMultiDimArrayfor contiguous buffer access. - Made
DiscreteVariable::closestLabel(double)virtual. - Added
DiscreteVariable::isNumerical()— returnstrueiffvarType != LABELIZED. - Added
Tensor::mean(),variance(),stdDev()(fixes variance computation: was E[X²], now E[(X−μ)²]). - Added
isCloseToZero()/isCloseToOne()helpers; used inTensor::mean()/variance(). Tensor::toStringnow uses Unicode box-drawing characters (│ ║ ─) for table borders.
- Added
-
CN module:
- Fixed critical bugs: removed invalid
delete[]onstrtokpointer, fixedsetCPTconst-ref signature, correctedinsertEvidenceFileoverride placement, fixed operator precedence inLrsWrapperguards. - Fixed
CNLoopyPropagation: arcs were rebuilt on every access instead of reused, riskingArcsL_min_/ArcsL_max_desynchronization. - Fixed naming convention violations: protected attributes renamed to trailing-underscore convention.
- Fixed critical bugs: removed invalid
2.3 Improvements
-
Performance:
- Removed exception-based control flow (
try/catch(NotFound)) from hot paths inBayesNetFactory,IBayesNet,ShaferShenoy,LazyPropagation,BNLearner,SimpleMiic, andCN, contributing to the overall execution-time reduction.
- Removed exception-based control flow (
-
Code quality & C++20:
- Replaced
std::stringstreamwithstd::formatacross all modules. - Added
overridespecifier to all virtual method overrides across the codebase. - Added
[[nodiscard]]toclone()and factory methods across all modules. - Normalized include guards to the
GUM_SOMETHING_Hconvention across the codebase. - Added parent
#includein_inl.h/_tpl.hfiles for IDE LSP support.
- Replaced
-
Portability & warnings:
- Fixed
int2Pow: useuint64_tfor portable 64-bit shift on Windows. - Fixed GCC 16 warnings:
-Warray-boundspragmas,gum::Sizecasts for signed/unsigned comparisons. - Fixed GCC
optimizepragma guard against Clang inBNLearner. - Fixed
-Wextra-semiandextern templateSWIG warnings. - Fixed Windows compilation issues (binary writers, CI uninstall).
- Fixed
-
Static analysis:
- Integrated
clang-tidyintoact guideline(check tidy /--correctionapplies fixes). - DeepSeek static-analysis audit: fixed all CRIT/HIGH/MED/LOW issues across the codebase.
clang-formatapplied to C++ test suites and BN learning sources.- Fixed
noexceptonIndepTestChi2/G2moves, braced-init returns.
- Integrated
-
Learning:
MeekRulesimprovements.- Fixed
propagateToCPDAG: restored edges-before-arcs insertion order in PDAG. - Fixed
ArcDeletionbug inGraphChangesSelector4DiGraph. BayesBall(_bayesBall_): replacedexists+insert+[]pattern withgetWithDefault; added 9 deterministic tests.
-
Tests:
- Replaced deprecated
tmpnamwithgetTempFilePathhelper across all test suites. - Added
LpInterface/LrsWrappertests and marginal sanity checks. - Updated
doctestfrom 2.4.12 to 2.5.2; suppressed-Wc2y-extensions.
- Replaced deprecated
-
Move semantics:
- Added move constructors and move assignment operators across the class hierarchy; fixed GUM debug macros and atexit table.
-
CMake:
- Removed uninstall target and obsolete policies.
AVLTree: removednoexceptfrom moveoperator=(containsGUM_ERROR).
-
act:
--statsflag for project stats;--consolidatesplit;cm.handbase/ioadded to dep map.act guideline:--dry-run,--checkwith+/-syntax,--verbosenon-persistent.