pyAgrum-nightly 2.3.1.9.dev202512261765915415__cp310-abi3-macosx_10_15_x86_64.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 +165 -0
- pyagrum/_pyagrum.so +0 -0
- pyagrum/bnmixture/BNMInference.py +268 -0
- pyagrum/bnmixture/BNMLearning.py +376 -0
- pyagrum/bnmixture/BNMixture.py +464 -0
- pyagrum/bnmixture/__init__.py +60 -0
- pyagrum/bnmixture/notebook.py +1058 -0
- pyagrum/causal/_CausalFormula.py +280 -0
- pyagrum/causal/_CausalModel.py +436 -0
- pyagrum/causal/__init__.py +81 -0
- pyagrum/causal/_causalImpact.py +356 -0
- pyagrum/causal/_dSeparation.py +598 -0
- pyagrum/causal/_doAST.py +761 -0
- pyagrum/causal/_doCalculus.py +361 -0
- pyagrum/causal/_doorCriteria.py +374 -0
- pyagrum/causal/_exceptions.py +95 -0
- pyagrum/causal/_types.py +61 -0
- pyagrum/causal/causalEffectEstimation/_CausalEffectEstimation.py +1175 -0
- pyagrum/causal/causalEffectEstimation/_IVEstimators.py +718 -0
- pyagrum/causal/causalEffectEstimation/_RCTEstimators.py +132 -0
- pyagrum/causal/causalEffectEstimation/__init__.py +46 -0
- pyagrum/causal/causalEffectEstimation/_backdoorEstimators.py +774 -0
- pyagrum/causal/causalEffectEstimation/_causalBNEstimator.py +324 -0
- pyagrum/causal/causalEffectEstimation/_frontdoorEstimators.py +396 -0
- pyagrum/causal/causalEffectEstimation/_learners.py +118 -0
- pyagrum/causal/causalEffectEstimation/_utils.py +466 -0
- pyagrum/causal/notebook.py +172 -0
- pyagrum/clg/CLG.py +658 -0
- pyagrum/clg/GaussianVariable.py +111 -0
- pyagrum/clg/SEM.py +312 -0
- pyagrum/clg/__init__.py +63 -0
- pyagrum/clg/canonicalForm.py +408 -0
- pyagrum/clg/constants.py +54 -0
- pyagrum/clg/forwardSampling.py +202 -0
- pyagrum/clg/learning.py +776 -0
- pyagrum/clg/notebook.py +480 -0
- pyagrum/clg/variableElimination.py +271 -0
- pyagrum/common.py +60 -0
- pyagrum/config.py +319 -0
- pyagrum/ctbn/CIM.py +513 -0
- pyagrum/ctbn/CTBN.py +573 -0
- pyagrum/ctbn/CTBNGenerator.py +216 -0
- pyagrum/ctbn/CTBNInference.py +459 -0
- pyagrum/ctbn/CTBNLearner.py +161 -0
- pyagrum/ctbn/SamplesStats.py +671 -0
- pyagrum/ctbn/StatsIndepTest.py +355 -0
- pyagrum/ctbn/__init__.py +79 -0
- pyagrum/ctbn/constants.py +54 -0
- pyagrum/ctbn/notebook.py +264 -0
- pyagrum/defaults.ini +199 -0
- pyagrum/deprecated.py +95 -0
- 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 +46 -0
- pyagrum/lib/_colors.py +390 -0
- pyagrum/lib/bn2graph.py +299 -0
- pyagrum/lib/bn2roc.py +1026 -0
- pyagrum/lib/bn2scores.py +217 -0
- pyagrum/lib/bn_vs_bn.py +605 -0
- pyagrum/lib/cn2graph.py +305 -0
- pyagrum/lib/discreteTypeProcessor.py +1102 -0
- pyagrum/lib/discretizer.py +58 -0
- pyagrum/lib/dynamicBN.py +390 -0
- pyagrum/lib/explain.py +57 -0
- pyagrum/lib/export.py +84 -0
- pyagrum/lib/id2graph.py +258 -0
- pyagrum/lib/image.py +387 -0
- pyagrum/lib/ipython.py +307 -0
- pyagrum/lib/mrf2graph.py +471 -0
- pyagrum/lib/notebook.py +1821 -0
- pyagrum/lib/proba_histogram.py +552 -0
- pyagrum/lib/utils.py +138 -0
- pyagrum/pyagrum.py +31495 -0
- pyagrum/skbn/_MBCalcul.py +242 -0
- pyagrum/skbn/__init__.py +49 -0
- pyagrum/skbn/_learningMethods.py +282 -0
- pyagrum/skbn/_utils.py +297 -0
- pyagrum/skbn/bnclassifier.py +1014 -0
- pyagrum_nightly-2.3.1.9.dev202512261765915415.dist-info/LICENSE.md +12 -0
- pyagrum_nightly-2.3.1.9.dev202512261765915415.dist-info/LICENSES/LGPL-3.0-or-later.txt +304 -0
- pyagrum_nightly-2.3.1.9.dev202512261765915415.dist-info/LICENSES/MIT.txt +18 -0
- pyagrum_nightly-2.3.1.9.dev202512261765915415.dist-info/METADATA +145 -0
- pyagrum_nightly-2.3.1.9.dev202512261765915415.dist-info/RECORD +107 -0
- pyagrum_nightly-2.3.1.9.dev202512261765915415.dist-info/WHEEL +4 -0
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
############################################################################
|
|
2
|
+
# This file is part of the aGrUM/pyAgrum library. #
|
|
3
|
+
# #
|
|
4
|
+
# Copyright (c) 2005-2025 by #
|
|
5
|
+
# - Pierre-Henri WUILLEMIN(_at_LIP6) #
|
|
6
|
+
# - Christophe GONZALES(_at_AMU) #
|
|
7
|
+
# #
|
|
8
|
+
# The aGrUM/pyAgrum library is free software; you can redistribute it #
|
|
9
|
+
# and/or modify it under the terms of either : #
|
|
10
|
+
# #
|
|
11
|
+
# - the GNU Lesser General Public License as published by #
|
|
12
|
+
# the Free Software Foundation, either version 3 of the License, #
|
|
13
|
+
# or (at your option) any later version, #
|
|
14
|
+
# - the MIT license (MIT), #
|
|
15
|
+
# - or both in dual license, as here. #
|
|
16
|
+
# #
|
|
17
|
+
# (see https://agrum.gitlab.io/articles/dual-licenses-lgplv3mit.html) #
|
|
18
|
+
# #
|
|
19
|
+
# This aGrUM/pyAgrum library is distributed in the hope that it will be #
|
|
20
|
+
# useful, but WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, #
|
|
21
|
+
# INCLUDING BUT NOT LIMITED TO THE WARRANTIES MERCHANTABILITY or FITNESS #
|
|
22
|
+
# FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE #
|
|
23
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER #
|
|
24
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, #
|
|
25
|
+
# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR #
|
|
26
|
+
# OTHER DEALINGS IN THE SOFTWARE. #
|
|
27
|
+
# #
|
|
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 #
|
|
34
|
+
# #
|
|
35
|
+
# Contact : info_at_agrum_dot_org #
|
|
36
|
+
# homepage : http://agrum.gitlab.io #
|
|
37
|
+
# gitlab : https://gitlab.com/agrumery/agrum #
|
|
38
|
+
# #
|
|
39
|
+
############################################################################
|
|
40
|
+
|
|
41
|
+
"""
|
|
42
|
+
class GaussianVariable: Continuous Gaussian Variable
|
|
43
|
+
"""
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class GaussianVariable:
|
|
47
|
+
def __init__(self, name: str, mu: float, sigma: float):
|
|
48
|
+
self._mu = mu
|
|
49
|
+
self._sigma = sigma
|
|
50
|
+
self._name = name
|
|
51
|
+
|
|
52
|
+
def __repr__(self):
|
|
53
|
+
return str(self)
|
|
54
|
+
|
|
55
|
+
def name(self) -> str:
|
|
56
|
+
"""
|
|
57
|
+
Returns the name of the variable.
|
|
58
|
+
|
|
59
|
+
Returns
|
|
60
|
+
-------
|
|
61
|
+
str
|
|
62
|
+
The name of the variable.
|
|
63
|
+
"""
|
|
64
|
+
return self._name
|
|
65
|
+
|
|
66
|
+
def mu(self) -> float:
|
|
67
|
+
"""
|
|
68
|
+
Returns the mean of the variable.
|
|
69
|
+
|
|
70
|
+
Returns
|
|
71
|
+
-------
|
|
72
|
+
float
|
|
73
|
+
The mean of the variable.
|
|
74
|
+
"""
|
|
75
|
+
return self._mu
|
|
76
|
+
|
|
77
|
+
def sigma(self) -> float:
|
|
78
|
+
"""
|
|
79
|
+
Returns the standard deviation of the variable.
|
|
80
|
+
|
|
81
|
+
Returns
|
|
82
|
+
-------
|
|
83
|
+
float
|
|
84
|
+
The standard deviation of the variable.
|
|
85
|
+
"""
|
|
86
|
+
return self._sigma
|
|
87
|
+
|
|
88
|
+
def setMu(self, mu: float):
|
|
89
|
+
"""
|
|
90
|
+
Set the mean of the variable.
|
|
91
|
+
|
|
92
|
+
Parameters
|
|
93
|
+
----------
|
|
94
|
+
mu : float
|
|
95
|
+
The new mean of the variable.
|
|
96
|
+
"""
|
|
97
|
+
self._mu = mu
|
|
98
|
+
|
|
99
|
+
def setSigma(self, sigma: float):
|
|
100
|
+
"""
|
|
101
|
+
Set the standard deviation of the variable.
|
|
102
|
+
|
|
103
|
+
Parameters
|
|
104
|
+
----------
|
|
105
|
+
sigma : float
|
|
106
|
+
The new standard deviation of the variable.
|
|
107
|
+
"""
|
|
108
|
+
self._sigma = sigma
|
|
109
|
+
|
|
110
|
+
def __str__(self) -> str:
|
|
111
|
+
return f"{self._name}:{self._mu}[{self._sigma}]"
|
pyagrum/clg/SEM.py
ADDED
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
############################################################################
|
|
2
|
+
# This file is part of the aGrUM/pyAgrum library. #
|
|
3
|
+
# #
|
|
4
|
+
# Copyright (c) 2005-2025 by #
|
|
5
|
+
# - Pierre-Henri WUILLEMIN(_at_LIP6) #
|
|
6
|
+
# - Christophe GONZALES(_at_AMU) #
|
|
7
|
+
# #
|
|
8
|
+
# The aGrUM/pyAgrum library is free software; you can redistribute it #
|
|
9
|
+
# and/or modify it under the terms of either : #
|
|
10
|
+
# #
|
|
11
|
+
# - the GNU Lesser General Public License as published by #
|
|
12
|
+
# the Free Software Foundation, either version 3 of the License, #
|
|
13
|
+
# or (at your option) any later version, #
|
|
14
|
+
# - the MIT license (MIT), #
|
|
15
|
+
# - or both in dual license, as here. #
|
|
16
|
+
# #
|
|
17
|
+
# (see https://agrum.gitlab.io/articles/dual-licenses-lgplv3mit.html) #
|
|
18
|
+
# #
|
|
19
|
+
# This aGrUM/pyAgrum library is distributed in the hope that it will be #
|
|
20
|
+
# useful, but WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, #
|
|
21
|
+
# INCLUDING BUT NOT LIMITED TO THE WARRANTIES MERCHANTABILITY or FITNESS #
|
|
22
|
+
# FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE #
|
|
23
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER #
|
|
24
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, #
|
|
25
|
+
# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR #
|
|
26
|
+
# OTHER DEALINGS IN THE SOFTWARE. #
|
|
27
|
+
# #
|
|
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 #
|
|
34
|
+
# #
|
|
35
|
+
# Contact : info_at_agrum_dot_org #
|
|
36
|
+
# homepage : http://agrum.gitlab.io #
|
|
37
|
+
# gitlab : https://gitlab.com/agrumery/agrum #
|
|
38
|
+
# #
|
|
39
|
+
############################################################################
|
|
40
|
+
|
|
41
|
+
"""
|
|
42
|
+
This module contains the SEM class, which is used to parse a SEM into a CLG model or convert a CLG model into a SEM.
|
|
43
|
+
"""
|
|
44
|
+
|
|
45
|
+
import re
|
|
46
|
+
import warnings
|
|
47
|
+
|
|
48
|
+
from .CLG import CLG
|
|
49
|
+
from .GaussianVariable import GaussianVariable
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
class SEM:
|
|
53
|
+
"""
|
|
54
|
+
This class is used to parse a SEM into a CLG model or convert a CLG model into a SEM.
|
|
55
|
+
|
|
56
|
+
code
|
|
57
|
+
----
|
|
58
|
+
|
|
59
|
+
sem = SEM('''
|
|
60
|
+
# hyper parameters
|
|
61
|
+
A = 4[5]
|
|
62
|
+
B = 3[5]
|
|
63
|
+
C = -2[5]
|
|
64
|
+
|
|
65
|
+
# equations
|
|
66
|
+
D = A[.2] # D is a noisy version of A
|
|
67
|
+
E = 1 + D + 2
|
|
68
|
+
B[2]
|
|
69
|
+
F = E + C + 3.5*B + E[0.001]
|
|
70
|
+
''')
|
|
71
|
+
"""
|
|
72
|
+
|
|
73
|
+
NUMBER = r"[0-9]*\.?[0-9]*"
|
|
74
|
+
ID = r"[a-zA-Z_]\w*"
|
|
75
|
+
FIND_VAR = rf"^({ID})$"
|
|
76
|
+
FIND_STDDEV = rf"^\[({NUMBER})\]$"
|
|
77
|
+
FIND_FLOAT = rf"^({NUMBER})$"
|
|
78
|
+
FIND_TERM = rf"^({NUMBER})\*?({ID})$"
|
|
79
|
+
|
|
80
|
+
_reg_variable = re.compile(FIND_VAR)
|
|
81
|
+
_reg_stddev = re.compile(FIND_STDDEV)
|
|
82
|
+
_reg_term = re.compile(FIND_TERM)
|
|
83
|
+
_reg_float = re.compile(FIND_FLOAT)
|
|
84
|
+
|
|
85
|
+
def __init__(self):
|
|
86
|
+
"""
|
|
87
|
+
Constructor
|
|
88
|
+
"""
|
|
89
|
+
warnings.warn("SEM has not to be instantiated.")
|
|
90
|
+
|
|
91
|
+
@staticmethod
|
|
92
|
+
def _check_token(s, pos, pattern):
|
|
93
|
+
"""
|
|
94
|
+
Check if the string s[pos:] matches the pattern.
|
|
95
|
+
If it does, return the match and the position of the next character.
|
|
96
|
+
If it does not, return None, None.
|
|
97
|
+
|
|
98
|
+
Parameters
|
|
99
|
+
----------
|
|
100
|
+
s : str
|
|
101
|
+
The string to be checked.
|
|
102
|
+
pos : int
|
|
103
|
+
The position in the string where to start the check.
|
|
104
|
+
pattern : re.Pattern
|
|
105
|
+
The pattern to be matched.
|
|
106
|
+
|
|
107
|
+
Returns
|
|
108
|
+
-------
|
|
109
|
+
Tuple[str, int] or Tuple[None, None]
|
|
110
|
+
The match and the position of the next character if the string matches the pattern.
|
|
111
|
+
"""
|
|
112
|
+
res = pattern.match(s[pos:])
|
|
113
|
+
if res is None:
|
|
114
|
+
return None, None
|
|
115
|
+
else:
|
|
116
|
+
return res.group(1), res.end()
|
|
117
|
+
|
|
118
|
+
@staticmethod
|
|
119
|
+
def _parse_line(s: str):
|
|
120
|
+
"""
|
|
121
|
+
This function parses a line of a SEM.
|
|
122
|
+
|
|
123
|
+
Parameters
|
|
124
|
+
----------
|
|
125
|
+
s : str
|
|
126
|
+
The line to be parsed.
|
|
127
|
+
|
|
128
|
+
Returns
|
|
129
|
+
-------
|
|
130
|
+
Tuple[str, Dict[str, str | float], float]
|
|
131
|
+
The name of the variable, the dictionary of the terms and the standard deviation.
|
|
132
|
+
"""
|
|
133
|
+
|
|
134
|
+
ss = s.split("#")[0]
|
|
135
|
+
ss = "".join(ss.split())
|
|
136
|
+
# allow every tokens to be separated with "+"
|
|
137
|
+
ss = ss.replace("-+", "-")
|
|
138
|
+
ss = ss.replace("-", "+-")
|
|
139
|
+
ss = ss.replace("=", "=+")
|
|
140
|
+
ss = ss.replace("[", "+[")
|
|
141
|
+
|
|
142
|
+
# to be sure there are now empty tokens
|
|
143
|
+
tokens = [s for s in ss.split("+") if s != ""]
|
|
144
|
+
|
|
145
|
+
token = tokens.pop()
|
|
146
|
+
if SEM._reg_stddev.match(token) is None:
|
|
147
|
+
raise SyntaxError(f"{token=} not recognized as a stdev")
|
|
148
|
+
stddev = token[1:-1]
|
|
149
|
+
|
|
150
|
+
tokens.reverse()
|
|
151
|
+
token = tokens.pop()
|
|
152
|
+
if token[-1] != "=":
|
|
153
|
+
raise SyntaxError("No affectation operator ('=')")
|
|
154
|
+
variable = token[:-1]
|
|
155
|
+
if SEM._reg_variable.match(variable) is None:
|
|
156
|
+
raise SyntaxError(f"{variable=} not a variable")
|
|
157
|
+
|
|
158
|
+
terms = {}
|
|
159
|
+
for token in tokens:
|
|
160
|
+
# get rid of "-" at the beginning of token
|
|
161
|
+
if token[0] == "-":
|
|
162
|
+
coef = -1
|
|
163
|
+
token = token[1:]
|
|
164
|
+
else:
|
|
165
|
+
coef = 1
|
|
166
|
+
|
|
167
|
+
if (m := SEM._reg_variable.match(token)) is not None:
|
|
168
|
+
var = m.group(0)
|
|
169
|
+
elif (m := SEM._reg_float.match(token)) is not None:
|
|
170
|
+
coef *= float(m.group(0))
|
|
171
|
+
var = ""
|
|
172
|
+
elif (m := SEM._reg_term.match(token)) is not None:
|
|
173
|
+
coef *= float(m.group(1))
|
|
174
|
+
var = m.group(2)
|
|
175
|
+
else:
|
|
176
|
+
break
|
|
177
|
+
|
|
178
|
+
# allow more than one term for the same variable (or more than one constant)
|
|
179
|
+
if var in terms:
|
|
180
|
+
terms[var] += coef
|
|
181
|
+
else:
|
|
182
|
+
terms[var] = coef
|
|
183
|
+
|
|
184
|
+
if len(terms) > len(tokens):
|
|
185
|
+
raise SyntaxError("Some tokens not recognized")
|
|
186
|
+
if len(terms) + 2 < len(tokens):
|
|
187
|
+
raise SyntaxError("Tokens after stddev")
|
|
188
|
+
|
|
189
|
+
return variable, terms, float(stddev)
|
|
190
|
+
|
|
191
|
+
@staticmethod
|
|
192
|
+
def toclg(sem: str) -> CLG:
|
|
193
|
+
"""
|
|
194
|
+
This function parses a SEM into a CLG model.
|
|
195
|
+
|
|
196
|
+
Parameters
|
|
197
|
+
----------
|
|
198
|
+
sem : str
|
|
199
|
+
The SEM to be parsed.
|
|
200
|
+
|
|
201
|
+
Returns
|
|
202
|
+
-------
|
|
203
|
+
CLG
|
|
204
|
+
The CLG model corresponding to the SEM.
|
|
205
|
+
"""
|
|
206
|
+
|
|
207
|
+
canonic_form = []
|
|
208
|
+
for line in re.split("\n+", sem):
|
|
209
|
+
line = line.strip()
|
|
210
|
+
if line == "":
|
|
211
|
+
continue
|
|
212
|
+
if line[0] == "#":
|
|
213
|
+
continue
|
|
214
|
+
if "=" in line: # new equation
|
|
215
|
+
canonic_form.append(line)
|
|
216
|
+
else:
|
|
217
|
+
if len(canonic_form) == 0:
|
|
218
|
+
raise SyntaxError(f"Line '{line}' is not an equation.")
|
|
219
|
+
canonic_form[-1] += line
|
|
220
|
+
|
|
221
|
+
# parsing the canonic_form
|
|
222
|
+
clg = CLG()
|
|
223
|
+
arcs = []
|
|
224
|
+
arcs = []
|
|
225
|
+
for line in canonic_form:
|
|
226
|
+
try:
|
|
227
|
+
var, terms, stddev = SEM._parse_line(line)
|
|
228
|
+
except SyntaxError as e:
|
|
229
|
+
raise SyntaxError(f"In line {line}, {e.msg()}.")
|
|
230
|
+
mu = 0
|
|
231
|
+
for parent in terms:
|
|
232
|
+
if parent == "":
|
|
233
|
+
mu = terms[""]
|
|
234
|
+
else:
|
|
235
|
+
arcs.append((parent, var, terms[parent]))
|
|
236
|
+
clg.add(GaussianVariable(var, mu, stddev))
|
|
237
|
+
for head, tail, coef in arcs:
|
|
238
|
+
clg.addArc(head, tail, coef)
|
|
239
|
+
|
|
240
|
+
return clg
|
|
241
|
+
|
|
242
|
+
@staticmethod
|
|
243
|
+
def tosem(clg: CLG) -> str:
|
|
244
|
+
"""
|
|
245
|
+
This function converts a CLG model into a SEM.
|
|
246
|
+
|
|
247
|
+
Parameters
|
|
248
|
+
----------
|
|
249
|
+
clg : CLG
|
|
250
|
+
The CLG model to be converted.
|
|
251
|
+
|
|
252
|
+
Returns
|
|
253
|
+
-------
|
|
254
|
+
lines : str
|
|
255
|
+
The SEM corresponding to the CLG model.
|
|
256
|
+
"""
|
|
257
|
+
|
|
258
|
+
lines = ""
|
|
259
|
+
for node in clg.topologicalOrder():
|
|
260
|
+
line = ""
|
|
261
|
+
|
|
262
|
+
# after the "="
|
|
263
|
+
for parent in clg.parents(node):
|
|
264
|
+
if clg._arc2coef[(parent, node)] == 1:
|
|
265
|
+
line += f"+{clg._id2var[parent].name()}"
|
|
266
|
+
elif clg._arc2coef[(parent, node)] < 0:
|
|
267
|
+
line += f"-{-clg._arc2coef[(parent, node)]}{clg._id2var[parent].name()}"
|
|
268
|
+
else:
|
|
269
|
+
line += f"+{clg._arc2coef[(parent, node)]}{clg._id2var[parent].name()}"
|
|
270
|
+
line += f"[{clg._id2var[node].sigma()}]"
|
|
271
|
+
|
|
272
|
+
# before the "="
|
|
273
|
+
line = clg._id2var[node].name() + "=" + str(clg._id2var[node].mu()) + line
|
|
274
|
+
line = line.replace("=0+", "=") # remove the 0
|
|
275
|
+
|
|
276
|
+
lines += line + "\n"
|
|
277
|
+
|
|
278
|
+
return lines
|
|
279
|
+
|
|
280
|
+
@staticmethod
|
|
281
|
+
def saveCLG(clg: CLG, filename: str):
|
|
282
|
+
"""
|
|
283
|
+
Save the CLG as a SEM to a file.
|
|
284
|
+
|
|
285
|
+
Parameters
|
|
286
|
+
----------
|
|
287
|
+
clg : CLG
|
|
288
|
+
The CLG model to be saved.
|
|
289
|
+
filename : str
|
|
290
|
+
The name of the file containing the SEM of CLG.
|
|
291
|
+
"""
|
|
292
|
+
with open(filename, "w") as file:
|
|
293
|
+
file.write(SEM.tosem(clg))
|
|
294
|
+
|
|
295
|
+
@staticmethod
|
|
296
|
+
def loadCLG(filename: str) -> CLG:
|
|
297
|
+
"""
|
|
298
|
+
Load the CLG from the file containing a SEM.
|
|
299
|
+
|
|
300
|
+
Parameters
|
|
301
|
+
----------
|
|
302
|
+
filename : str
|
|
303
|
+
The name of the file containing the SEM of CLG.
|
|
304
|
+
|
|
305
|
+
Returns
|
|
306
|
+
-------
|
|
307
|
+
the loaded CLG
|
|
308
|
+
"""
|
|
309
|
+
with open(filename, "r") as file:
|
|
310
|
+
sem = file.read()
|
|
311
|
+
|
|
312
|
+
return SEM.toclg(sem)
|
pyagrum/clg/__init__.py
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
############################################################################
|
|
2
|
+
# This file is part of the aGrUM/pyAgrum library. #
|
|
3
|
+
# #
|
|
4
|
+
# Copyright (c) 2005-2025 by #
|
|
5
|
+
# - Pierre-Henri WUILLEMIN(_at_LIP6) #
|
|
6
|
+
# - Christophe GONZALES(_at_AMU) #
|
|
7
|
+
# #
|
|
8
|
+
# The aGrUM/pyAgrum library is free software; you can redistribute it #
|
|
9
|
+
# and/or modify it under the terms of either : #
|
|
10
|
+
# #
|
|
11
|
+
# - the GNU Lesser General Public License as published by #
|
|
12
|
+
# the Free Software Foundation, either version 3 of the License, #
|
|
13
|
+
# or (at your option) any later version, #
|
|
14
|
+
# - the MIT license (MIT), #
|
|
15
|
+
# - or both in dual license, as here. #
|
|
16
|
+
# #
|
|
17
|
+
# (see https://agrum.gitlab.io/articles/dual-licenses-lgplv3mit.html) #
|
|
18
|
+
# #
|
|
19
|
+
# This aGrUM/pyAgrum library is distributed in the hope that it will be #
|
|
20
|
+
# useful, but WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, #
|
|
21
|
+
# INCLUDING BUT NOT LIMITED TO THE WARRANTIES MERCHANTABILITY or FITNESS #
|
|
22
|
+
# FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE #
|
|
23
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER #
|
|
24
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, #
|
|
25
|
+
# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR #
|
|
26
|
+
# OTHER DEALINGS IN THE SOFTWARE. #
|
|
27
|
+
# #
|
|
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 #
|
|
34
|
+
# #
|
|
35
|
+
# Contact : info_at_agrum_dot_org #
|
|
36
|
+
# homepage : http://agrum.gitlab.io #
|
|
37
|
+
# gitlab : https://gitlab.com/agrumery/agrum #
|
|
38
|
+
# #
|
|
39
|
+
############################################################################
|
|
40
|
+
|
|
41
|
+
""" """
|
|
42
|
+
|
|
43
|
+
__author__ = "Pierre-Henri Wuillemin, Zhe Huang"
|
|
44
|
+
__copyright__ = "(c) 2022-2023 PARIS"
|
|
45
|
+
|
|
46
|
+
from .canonicalForm import CanonicalForm
|
|
47
|
+
from .CLG import CLG, randomCLG
|
|
48
|
+
from .forwardSampling import ForwardSampling
|
|
49
|
+
from .GaussianVariable import GaussianVariable
|
|
50
|
+
from .variableElimination import CLGVariableElimination
|
|
51
|
+
from .learning import CLGLearner
|
|
52
|
+
from .SEM import SEM
|
|
53
|
+
|
|
54
|
+
__all__ = [
|
|
55
|
+
"CanonicalForm",
|
|
56
|
+
"CLG",
|
|
57
|
+
"randomCLG",
|
|
58
|
+
"ForwardSampling",
|
|
59
|
+
"GaussianVariable",
|
|
60
|
+
"CLGVariableElimination",
|
|
61
|
+
"CLGLearner",
|
|
62
|
+
"SEM",
|
|
63
|
+
]
|