pyAgrum-nightly 2.1.1.9.dev202506061747485979__cp310-abi3-manylinux2014_aarch64.whl → 2.3.1.9.dev202601031765915415__cp310-abi3-manylinux2014_aarch64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pyagrum/__init__.py +6 -2
- pyagrum/_pyagrum.so +0 -0
- pyagrum/bnmixture/BNMInference.py +6 -2
- pyagrum/bnmixture/BNMLearning.py +12 -2
- pyagrum/bnmixture/BNMixture.py +6 -2
- pyagrum/bnmixture/__init__.py +6 -2
- pyagrum/bnmixture/notebook.py +6 -2
- pyagrum/causal/_CausalFormula.py +6 -2
- pyagrum/causal/_CausalModel.py +6 -2
- pyagrum/causal/__init__.py +6 -2
- pyagrum/causal/_causalImpact.py +6 -2
- pyagrum/causal/_dSeparation.py +6 -2
- pyagrum/causal/_doAST.py +6 -2
- pyagrum/causal/_doCalculus.py +6 -2
- pyagrum/causal/_doorCriteria.py +6 -2
- pyagrum/causal/_exceptions.py +6 -2
- pyagrum/causal/_types.py +6 -2
- pyagrum/causal/causalEffectEstimation/_CausalEffectEstimation.py +6 -2
- pyagrum/causal/causalEffectEstimation/_IVEstimators.py +6 -2
- pyagrum/causal/causalEffectEstimation/_RCTEstimators.py +6 -2
- pyagrum/causal/causalEffectEstimation/__init__.py +6 -2
- pyagrum/causal/causalEffectEstimation/_backdoorEstimators.py +6 -2
- pyagrum/causal/causalEffectEstimation/_causalBNEstimator.py +6 -2
- pyagrum/causal/causalEffectEstimation/_frontdoorEstimators.py +6 -2
- pyagrum/causal/causalEffectEstimation/_learners.py +6 -2
- pyagrum/causal/causalEffectEstimation/_utils.py +6 -2
- pyagrum/causal/notebook.py +8 -3
- pyagrum/clg/CLG.py +6 -2
- pyagrum/clg/GaussianVariable.py +6 -2
- pyagrum/clg/SEM.py +6 -2
- pyagrum/clg/__init__.py +6 -2
- pyagrum/clg/canonicalForm.py +6 -2
- pyagrum/clg/constants.py +6 -2
- pyagrum/clg/forwardSampling.py +6 -2
- pyagrum/clg/learning.py +6 -2
- pyagrum/clg/notebook.py +6 -2
- pyagrum/clg/variableElimination.py +6 -2
- pyagrum/common.py +7 -3
- pyagrum/config.py +7 -2
- pyagrum/ctbn/CIM.py +6 -2
- pyagrum/ctbn/CTBN.py +6 -2
- pyagrum/ctbn/CTBNGenerator.py +6 -2
- pyagrum/ctbn/CTBNInference.py +6 -2
- pyagrum/ctbn/CTBNLearner.py +6 -2
- pyagrum/ctbn/SamplesStats.py +6 -2
- pyagrum/ctbn/StatsIndepTest.py +6 -2
- pyagrum/ctbn/__init__.py +6 -2
- pyagrum/ctbn/constants.py +6 -2
- pyagrum/ctbn/notebook.py +6 -2
- pyagrum/deprecated.py +6 -2
- pyagrum/explain/_ComputationCausal.py +75 -0
- pyagrum/explain/_ComputationConditional.py +48 -0
- pyagrum/explain/_ComputationMarginal.py +48 -0
- pyagrum/explain/_CustomShapleyCache.py +110 -0
- pyagrum/explain/_Explainer.py +176 -0
- pyagrum/explain/_Explanation.py +70 -0
- pyagrum/explain/_FIFOCache.py +54 -0
- pyagrum/explain/_ShallCausalValues.py +204 -0
- pyagrum/explain/_ShallConditionalValues.py +155 -0
- pyagrum/explain/_ShallMarginalValues.py +155 -0
- pyagrum/explain/_ShallValues.py +296 -0
- pyagrum/explain/_ShapCausalValues.py +208 -0
- pyagrum/explain/_ShapConditionalValues.py +126 -0
- pyagrum/explain/_ShapMarginalValues.py +191 -0
- pyagrum/explain/_ShapleyValues.py +298 -0
- pyagrum/explain/__init__.py +81 -0
- pyagrum/explain/_explGeneralizedMarkovBlanket.py +152 -0
- pyagrum/explain/_explIndependenceListForPairs.py +146 -0
- pyagrum/explain/_explInformationGraph.py +264 -0
- pyagrum/explain/notebook/__init__.py +54 -0
- pyagrum/explain/notebook/_bar.py +142 -0
- pyagrum/explain/notebook/_beeswarm.py +174 -0
- pyagrum/explain/notebook/_showShapValues.py +97 -0
- pyagrum/explain/notebook/_waterfall.py +220 -0
- pyagrum/explain/shapley.py +225 -0
- pyagrum/lib/__init__.py +6 -2
- pyagrum/lib/_colors.py +6 -2
- pyagrum/lib/bn2graph.py +6 -2
- pyagrum/lib/bn2roc.py +6 -2
- pyagrum/lib/bn2scores.py +6 -2
- pyagrum/lib/bn_vs_bn.py +6 -2
- pyagrum/lib/cn2graph.py +6 -2
- pyagrum/lib/discreteTypeProcessor.py +99 -81
- pyagrum/lib/discretizer.py +6 -2
- pyagrum/lib/dynamicBN.py +6 -2
- pyagrum/lib/explain.py +17 -492
- pyagrum/lib/export.py +6 -2
- pyagrum/lib/id2graph.py +6 -2
- pyagrum/lib/image.py +6 -2
- pyagrum/lib/ipython.py +6 -2
- pyagrum/lib/mrf2graph.py +6 -2
- pyagrum/lib/notebook.py +6 -2
- pyagrum/lib/proba_histogram.py +6 -2
- pyagrum/lib/utils.py +6 -2
- pyagrum/pyagrum.py +976 -126
- pyagrum/skbn/_MBCalcul.py +6 -2
- pyagrum/skbn/__init__.py +6 -2
- pyagrum/skbn/_learningMethods.py +6 -2
- pyagrum/skbn/_utils.py +6 -2
- pyagrum/skbn/bnclassifier.py +6 -2
- pyagrum_nightly-2.1.1.9.dev202506061747485979.dist-info/LICENSE → pyagrum_nightly-2.3.1.9.dev202601031765915415.dist-info/LICENSE.md +3 -1
- pyagrum_nightly-2.3.1.9.dev202601031765915415.dist-info/LICENSES/LGPL-3.0-or-later.txt +304 -0
- pyagrum_nightly-2.3.1.9.dev202601031765915415.dist-info/LICENSES/MIT.txt +18 -0
- {pyagrum_nightly-2.1.1.9.dev202506061747485979.dist-info → pyagrum_nightly-2.3.1.9.dev202601031765915415.dist-info}/METADATA +3 -1
- pyagrum_nightly-2.3.1.9.dev202601031765915415.dist-info/RECORD +107 -0
- {pyagrum_nightly-2.1.1.9.dev202506061747485979.dist-info → pyagrum_nightly-2.3.1.9.dev202601031765915415.dist-info}/WHEEL +1 -1
- pyagrum/lib/shapley.py +0 -657
- pyagrum_nightly-2.1.1.9.dev202506061747485979.dist-info/LICENSE.LGPL +0 -165
- pyagrum_nightly-2.1.1.9.dev202506061747485979.dist-info/LICENSE.MIT +0 -17
- pyagrum_nightly-2.1.1.9.dev202506061747485979.dist-info/RECORD +0 -83
|
@@ -25,8 +25,12 @@
|
|
|
25
25
|
# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR #
|
|
26
26
|
# OTHER DEALINGS IN THE SOFTWARE. #
|
|
27
27
|
# #
|
|
28
|
-
# See
|
|
29
|
-
#
|
|
28
|
+
# See LICENCES for more details. #
|
|
29
|
+
# #
|
|
30
|
+
# SPDX-FileCopyrightText: Copyright 2005-2025 #
|
|
31
|
+
# - Pierre-Henri WUILLEMIN(_at_LIP6) #
|
|
32
|
+
# - Christophe GONZALES(_at_AMU) #
|
|
33
|
+
# SPDX-License-Identifier: LGPL-3.0-or-later OR MIT #
|
|
30
34
|
# #
|
|
31
35
|
# Contact : info_at_agrum_dot_org #
|
|
32
36
|
# homepage : http://agrum.gitlab.io #
|
|
@@ -125,7 +129,12 @@ class DiscreteTypeProcessor:
|
|
|
125
129
|
|
|
126
130
|
"""
|
|
127
131
|
|
|
128
|
-
def __init__(
|
|
132
|
+
def __init__(
|
|
133
|
+
self,
|
|
134
|
+
defaultDiscretizationMethod="quantile",
|
|
135
|
+
defaultNumberOfBins=10,
|
|
136
|
+
discretizationThreshold=25,
|
|
137
|
+
):
|
|
129
138
|
"""
|
|
130
139
|
Initializes the DiscreteTypeProcessor object.
|
|
131
140
|
|
|
@@ -174,7 +183,7 @@ class DiscreteTypeProcessor:
|
|
|
174
183
|
self.discretizationParametersDictionary = {}
|
|
175
184
|
|
|
176
185
|
@gum.deprecated_arg(newA="parameters", oldA="paramDiscretizationMethod", version="2.0.0")
|
|
177
|
-
def setDiscretizationParameters(self, variableName
|
|
186
|
+
def setDiscretizationParameters(self, variableName: str, method: str, parameters: Any = None):
|
|
178
187
|
"""
|
|
179
188
|
Sets the discretization parameters for a variable. If variableName is None, sets the default parameters.
|
|
180
189
|
|
|
@@ -197,44 +206,40 @@ class DiscreteTypeProcessor:
|
|
|
197
206
|
- 'expert': this parameter is the set of ticks proposed by the expert. The discretized variable will set the flag
|
|
198
207
|
'empirical' which means that if the values found in the data are not in the proposed intervals, they did not raise
|
|
199
208
|
any exception but are nevertheless accepted (as belonging to the smallest or biggest interval).
|
|
200
|
-
- 'NoDiscretization': this parameter is a superset of the values for the variable found in the database.
|
|
209
|
+
- 'NoDiscretization': this parameter is a superset of the values for the variable found in the database (or None).
|
|
201
210
|
"""
|
|
202
|
-
if
|
|
203
|
-
|
|
204
|
-
oldMethod = self.discretizationParametersDictionary[variableName]["method"]
|
|
205
|
-
else:
|
|
206
|
-
oldParamDiscretizationMethod = self.defaultParamDiscretizationMethod
|
|
207
|
-
oldMethod = self.defaultMethod
|
|
208
|
-
|
|
209
|
-
if method is None:
|
|
210
|
-
method = oldMethod
|
|
211
|
-
|
|
212
|
-
if parameters is None and method not in {"NoDiscretization", "expert"}:
|
|
213
|
-
parameters = oldParamDiscretizationMethod
|
|
214
|
-
|
|
215
|
-
if method not in {"kmeans", "uniform", "quantile", "NML", "MDLP", "CAIM", "NoDiscretization", "expert"}:
|
|
216
|
-
raise ValueError(
|
|
217
|
-
"This discretization method is not recognized! Possible values are kmeans, uniform, quantile, NML, "
|
|
218
|
-
"CAIM, MDLP, NoDiscretization or expert. You have entered " + str(method)
|
|
219
|
-
)
|
|
211
|
+
if parameters is None:
|
|
212
|
+
parameters = self.defaultParamDiscretizationMethod
|
|
220
213
|
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
214
|
+
match method:
|
|
215
|
+
case "quantile" | "NML":
|
|
216
|
+
if type(parameters) is not int:
|
|
217
|
+
raise ValueError(
|
|
218
|
+
"The parameter for the quantile/NML method must be an integer. You have entered: " + str(parameters)
|
|
219
|
+
)
|
|
220
|
+
case "kmeans" | "uniform":
|
|
221
|
+
if type(parameters) is not int and str(parameters) != "elbowMethod":
|
|
222
|
+
raise ValueError(
|
|
223
|
+
"The parameter for the kmeans/uniform method must be an integer or the string 'elbowMethod'. You have entered: "
|
|
224
|
+
+ str(parameters)
|
|
225
|
+
)
|
|
226
|
+
case "expert":
|
|
227
|
+
if not (isinstance(parameters, list) and all(map(check_float, parameters))):
|
|
228
|
+
raise ValueError(
|
|
229
|
+
"The parameter for the expert method must be a list of float. You have entered: " + str(parameters)
|
|
230
|
+
)
|
|
231
|
+
case "NoDiscretization":
|
|
232
|
+
if parameters is not None and not (isinstance(parameters, str)):
|
|
233
|
+
raise ValueError(
|
|
234
|
+
"The parameter for the NoDiscretization method must be a string (fastVar syntax) or None. You have "
|
|
235
|
+
"entered: " + str(parameters)
|
|
236
|
+
)
|
|
237
|
+
case "CAIM" | "MDLP":
|
|
238
|
+
pass
|
|
239
|
+
case _:
|
|
236
240
|
raise ValueError(
|
|
237
|
-
|
|
241
|
+
"This discretization method is not recognized! Possible values are kmeans, uniform, quantile, NML, "
|
|
242
|
+
"CAIM, MDLP, NoDiscretization or expert. You have entered " + str(method)
|
|
238
243
|
)
|
|
239
244
|
|
|
240
245
|
if variableName is None:
|
|
@@ -378,7 +383,12 @@ class DiscreteTypeProcessor:
|
|
|
378
383
|
Xsorted = X[X.argsort(axis=None)]
|
|
379
384
|
binEdgeMatrix = [[]] * 14
|
|
380
385
|
for k in range(2, 16):
|
|
381
|
-
discretizer = skp.KBinsDiscretizer(
|
|
386
|
+
discretizer = skp.KBinsDiscretizer(
|
|
387
|
+
k,
|
|
388
|
+
strategy=discretizationStrategy,
|
|
389
|
+
quantile_method="averaged_inverted_cdf",
|
|
390
|
+
subsample=None,
|
|
391
|
+
)
|
|
382
392
|
discretizer.fit(Xsorted)
|
|
383
393
|
binEdges = discretizer.bin_edges_[0]
|
|
384
394
|
centresArray = (binEdges[1:] + binEdges[:-1]) / 2
|
|
@@ -404,7 +414,8 @@ class DiscreteTypeProcessor:
|
|
|
404
414
|
transformedCoordinates = numpy.zeros((2, 14))
|
|
405
415
|
for i in range(14):
|
|
406
416
|
transformedCoordinates[:, i] = numpy.matmul(
|
|
407
|
-
coordinateChangeMatrix,
|
|
417
|
+
coordinateChangeMatrix,
|
|
418
|
+
numpy.array([[i], [variationArray[i] - variationArray[0]]]),
|
|
408
419
|
).reshape(2)
|
|
409
420
|
|
|
410
421
|
# we search for the minimum in our newly obtained curve
|
|
@@ -414,7 +425,8 @@ class DiscreteTypeProcessor:
|
|
|
414
425
|
minkIndex = k
|
|
415
426
|
# when we have found the minimum, we apply the inverse linear transformation to recover the optimal value of k
|
|
416
427
|
minimumVector = numpy.matmul(
|
|
417
|
-
numpy.linalg.inv(coordinateChangeMatrix),
|
|
428
|
+
numpy.linalg.inv(coordinateChangeMatrix),
|
|
429
|
+
transformedCoordinates[:, minkIndex].reshape(2, 1),
|
|
418
430
|
)
|
|
419
431
|
|
|
420
432
|
# we return the list of bin edges found using said optimal number of k
|
|
@@ -511,7 +523,10 @@ class DiscreteTypeProcessor:
|
|
|
511
523
|
break
|
|
512
524
|
else:
|
|
513
525
|
currentValues["boundaryIndex"] = binEdgesIndex[position - 1] + 1
|
|
514
|
-
(
|
|
526
|
+
(
|
|
527
|
+
currentValues["leftSubintervalClass0"],
|
|
528
|
+
currentValues["leftSubintervalClass1"],
|
|
529
|
+
) = (0, 0)
|
|
515
530
|
minimalValues["classInformationEntropy"] = math.inf
|
|
516
531
|
continue
|
|
517
532
|
|
|
@@ -854,52 +869,46 @@ class DiscreteTypeProcessor:
|
|
|
854
869
|
else: # The user has manually set the discretization parameters for this variable
|
|
855
870
|
usingDefaultParameters = False
|
|
856
871
|
if self.discretizationParametersDictionary[variableName]["method"] != "NoDiscretization" and not isNumeric:
|
|
857
|
-
raise ValueError("The variable
|
|
872
|
+
raise ValueError(f"The variable {variableName} is not numeric and cannot be discretized!")
|
|
858
873
|
|
|
859
874
|
if self.discretizationParametersDictionary[variableName]["method"] == "NoDiscretization":
|
|
860
875
|
is_int_var = True
|
|
861
|
-
min_v = max_v = None
|
|
862
876
|
|
|
863
|
-
|
|
877
|
+
varSyntax = ""
|
|
864
878
|
if "param" in self.discretizationParametersDictionary[variableName]:
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
879
|
+
varSyntax = self.discretizationParametersDictionary[variableName]["param"]
|
|
880
|
+
if varSyntax is None:
|
|
881
|
+
varSyntax = ""
|
|
882
|
+
|
|
883
|
+
if varSyntax != "":
|
|
884
|
+
var = gum.fastVariable(variableName + varSyntax)
|
|
885
|
+
possibleValuesX = set(var.labels())
|
|
886
|
+
f = {str(x) for x in foundValuesX}
|
|
887
|
+
if not f.issubset(possibleValuesX):
|
|
872
888
|
raise ValueError(
|
|
873
|
-
f"The values passed in possibleValues ({possibleValuesX}) do not match database values (
|
|
889
|
+
f"The values passed in possibleValues ({sorted(possibleValuesX)}) do not match database values ("
|
|
890
|
+
f"{sorted(f)})"
|
|
874
891
|
)
|
|
892
|
+
return var
|
|
875
893
|
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
v = int(value)
|
|
879
|
-
if min_v is None or min_v > v:
|
|
880
|
-
min_v = v
|
|
881
|
-
if max_v is None or max_v < v:
|
|
882
|
-
max_v = v
|
|
883
|
-
else:
|
|
884
|
-
is_int_var = False
|
|
885
|
-
break
|
|
886
|
-
|
|
894
|
+
possibleValuesX = sorted(foundValuesX)
|
|
895
|
+
is_int_var = all(map(check_int, possibleValuesX))
|
|
887
896
|
if is_int_var:
|
|
897
|
+
possibleValuesX = [int(x) for x in possibleValuesX]
|
|
898
|
+
max_v = int(possibleValuesX[-1]) # sorted
|
|
899
|
+
min_v = int(possibleValuesX[0])
|
|
900
|
+
|
|
888
901
|
if len(possibleValuesX) == max_v - min_v + 1: # no hole in the list of int
|
|
889
|
-
|
|
902
|
+
return gum.RangeVariable(variableName, variableName, min_v, max_v)
|
|
890
903
|
else:
|
|
891
|
-
|
|
892
|
-
else:
|
|
893
|
-
is_float_var = True
|
|
894
|
-
for value in possibleValuesX:
|
|
895
|
-
if not check_float(value):
|
|
896
|
-
is_float_var = False
|
|
897
|
-
break
|
|
904
|
+
return gum.IntegerVariable(variableName, variableName, possibleValuesX)
|
|
898
905
|
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
906
|
+
is_float_var = all(map(check_float, possibleValuesX))
|
|
907
|
+
if is_float_var:
|
|
908
|
+
possibleValuesX = [float(x) for x in possibleValuesX]
|
|
909
|
+
return gum.NumericalDiscreteVariable(variableName, variableName, possibleValuesX)
|
|
910
|
+
else:
|
|
911
|
+
return gum.LabelizedVariable(variableName, variableName, [str(v) for v in possibleValuesX])
|
|
903
912
|
else:
|
|
904
913
|
self.numberOfContinuous += 1
|
|
905
914
|
if self.discretizationParametersDictionary[variableName]["method"] == "expert":
|
|
@@ -913,7 +922,10 @@ class DiscreteTypeProcessor:
|
|
|
913
922
|
if possibleValuesY is None:
|
|
914
923
|
possibleValuesY = numpy.unique(y)
|
|
915
924
|
binEdges = self._discretizationCAIM(
|
|
916
|
-
Xtransformed.reshape(n, 1),
|
|
925
|
+
Xtransformed.reshape(n, 1),
|
|
926
|
+
y.reshape(n, 1),
|
|
927
|
+
numpy.unique(Xtransformed),
|
|
928
|
+
possibleValuesY,
|
|
917
929
|
)
|
|
918
930
|
elif self.discretizationParametersDictionary[variableName]["method"] == "MDLP":
|
|
919
931
|
if y is None:
|
|
@@ -924,7 +936,10 @@ class DiscreteTypeProcessor:
|
|
|
924
936
|
if possibleValuesY is None:
|
|
925
937
|
possibleValuesY = numpy.unique(y)
|
|
926
938
|
binEdges = self._discretizationMDLP(
|
|
927
|
-
Xtransformed.reshape(n, 1),
|
|
939
|
+
Xtransformed.reshape(n, 1),
|
|
940
|
+
y.reshape(n, 1),
|
|
941
|
+
numpy.unique(Xtransformed),
|
|
942
|
+
possibleValuesY,
|
|
928
943
|
)
|
|
929
944
|
elif self.discretizationParametersDictionary[variableName]["method"] == "NML":
|
|
930
945
|
binEdges = self._discretizationNML(
|
|
@@ -935,12 +950,14 @@ class DiscreteTypeProcessor:
|
|
|
935
950
|
else:
|
|
936
951
|
if self.discretizationParametersDictionary[variableName]["param"] == "elbowMethod":
|
|
937
952
|
binEdges = self._discretizationElbowMethodRotation(
|
|
938
|
-
self.discretizationParametersDictionary[variableName]["method"],
|
|
953
|
+
self.discretizationParametersDictionary[variableName]["method"],
|
|
954
|
+
Xtransformed.flatten(),
|
|
939
955
|
)
|
|
940
956
|
else:
|
|
941
957
|
discre = skp.KBinsDiscretizer(
|
|
942
958
|
self.discretizationParametersDictionary[variableName]["param"],
|
|
943
959
|
strategy=self.discretizationParametersDictionary[variableName]["method"],
|
|
960
|
+
quantile_method="averaged_inverted_cdf",
|
|
944
961
|
subsample=None,
|
|
945
962
|
)
|
|
946
963
|
discre.fit(X.reshape(-1, 1))
|
|
@@ -1001,7 +1018,8 @@ class DiscreteTypeProcessor:
|
|
|
1001
1018
|
Class1ByLargeInterval.insert(position + 1, minimalValues["rightSubintervalClass1"])
|
|
1002
1019
|
continueDividingInterval.insert(position + 1, True)
|
|
1003
1020
|
totalCountByLargeInterval.insert(
|
|
1004
|
-
position + 1,
|
|
1021
|
+
position + 1,
|
|
1022
|
+
minimalValues["rightSubintervalClass0"] + minimalValues["rightSubintervalClass1"],
|
|
1005
1023
|
)
|
|
1006
1024
|
shannonEntropyByLargeInterval.insert(position + 1, minimalValues["rightSubintervalShannonEntropy"])
|
|
1007
1025
|
|
pyagrum/lib/discretizer.py
CHANGED
|
@@ -25,8 +25,12 @@
|
|
|
25
25
|
# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR #
|
|
26
26
|
# OTHER DEALINGS IN THE SOFTWARE. #
|
|
27
27
|
# #
|
|
28
|
-
# See
|
|
29
|
-
#
|
|
28
|
+
# See LICENCES for more details. #
|
|
29
|
+
# #
|
|
30
|
+
# SPDX-FileCopyrightText: Copyright 2005-2025 #
|
|
31
|
+
# - Pierre-Henri WUILLEMIN(_at_LIP6) #
|
|
32
|
+
# - Christophe GONZALES(_at_AMU) #
|
|
33
|
+
# SPDX-License-Identifier: LGPL-3.0-or-later OR MIT #
|
|
30
34
|
# #
|
|
31
35
|
# Contact : info_at_agrum_dot_org #
|
|
32
36
|
# homepage : http://agrum.gitlab.io #
|
pyagrum/lib/dynamicBN.py
CHANGED
|
@@ -25,8 +25,12 @@
|
|
|
25
25
|
# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR #
|
|
26
26
|
# OTHER DEALINGS IN THE SOFTWARE. #
|
|
27
27
|
# #
|
|
28
|
-
# See
|
|
29
|
-
#
|
|
28
|
+
# See LICENCES for more details. #
|
|
29
|
+
# #
|
|
30
|
+
# SPDX-FileCopyrightText: Copyright 2005-2025 #
|
|
31
|
+
# - Pierre-Henri WUILLEMIN(_at_LIP6) #
|
|
32
|
+
# - Christophe GONZALES(_at_AMU) #
|
|
33
|
+
# SPDX-License-Identifier: LGPL-3.0-or-later OR MIT #
|
|
30
34
|
# #
|
|
31
35
|
# Contact : info_at_agrum_dot_org #
|
|
32
36
|
# homepage : http://agrum.gitlab.io #
|