causing 2.4.3__tar.gz → 2.4.5__tar.gz

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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: causing
3
- Version: 2.4.3
3
+ Version: 2.4.5
4
4
  Summary: Causing: CAUSal INterpretation using Graphs
5
5
  Home-page: https://github.com/realrate/Causing
6
6
  Author: Dr. Holger Bartel
@@ -193,6 +193,10 @@ def create_graphs(graphs: Iterable[networkx.DiGraph], output_dir: Path, **kwargs
193
193
  print("Create", filename)
194
194
  dot_str = graph_to_dot(g, **kwargs)
195
195
  save_graph(output_dir / filename, dot_str)
196
+ # save the dot string
197
+ dot_path = output_dir / f"IME_{g.graph['id']}.dot"
198
+ with open(dot_path, "w") as f:
199
+ f.write(dot_str)
196
200
 
197
201
 
198
202
  def remove_node_keep_edges(graph, node):
@@ -51,65 +51,56 @@ class Model:
51
51
  def compute(
52
52
  self,
53
53
  xdat: np.array,
54
- # fix a yval
55
54
  fixed_yval: np.array = None,
56
55
  fixed_yind: int = None,
57
- # fix an arbitrary node going into a yval
58
56
  fixed_from_ind: int = None,
59
57
  fixed_to_yind: int = None,
60
58
  fixed_vals: list = None,
61
- # override default parameter values
62
59
  parameters: dict[str, float] = {},
63
60
  ) -> np.array:
64
- """Compute y values for given x values
65
-
61
+ """Compute y values for given x values (Optimized Version)
66
62
  xdat: m rows, tau columns
67
63
  returns: n rows, tau columns
68
64
  """
65
+
69
66
  assert xdat.ndim == 2, f"xdat must be m*tau (is {xdat.ndim}-dimensional)"
70
67
  assert xdat.shape[0] == self.mdim, f"xdat must be m*tau (is {xdat.shape})"
71
68
  tau = xdat.shape[1]
72
69
  parameters = self.parameters | parameters
73
70
 
74
- yhat = np.array([[float("nan")] * tau] * len(self.yvars))
71
+ # Use np.full for clarity and potential small performance gain
72
+ yhat = np.full((self.ndim, tau), np.nan)
73
+
75
74
  for i, eq in enumerate(self._model_lam):
75
+
76
76
  if fixed_yind == i:
77
77
  yhat[i, :] = fixed_yval
78
78
  else:
79
- eq_inputs = np.array(
80
- [[*xval, *yval] for xval, yval in zip(xdat.T, yhat.T)]
81
- )
79
+ # 1. Build inputs (Vectorized)
80
+ # Use np.vstack for efficient vertical stacking.
81
+ # `yhat` will have NaNs for unsolved variables, which is correct.
82
+ eq_inputs = np.vstack([xdat, yhat])
83
+
84
+ # 2. Apply fixed values if needed (Vectorized)
82
85
  if fixed_to_yind == i:
83
- eq_inputs[:, fixed_from_ind] = fixed_vals
86
+ # Directly modify the correct "row" in the input matrix.
87
+ # This is much cleaner and faster.
88
+ eq_inputs[fixed_from_ind, :] = fixed_vals
84
89
 
90
+ # 3. Evaluate equation (Vectorized)
85
91
  try:
86
- # print(f"Comuting variable: {self.yvars[i]}")
87
- # yhat[i] = np.array(
88
- # [eq(*eq_in, *parameters.values()) for eq_in in eq_inputs],
89
- # dtype=np.float64,
90
- # )
91
92
  np.seterr(under="ignore")
92
- computed_yvars = []
93
- for eq_in in eq_inputs:
94
- computed_yvars.append(eq(*eq_in, *parameters.values()))
95
-
96
- yhat[i] = np.array(
97
- computed_yvars,
98
- dtype=np.float64,
99
- )
93
+
94
+ # This is the core optimization. We unpack the rows of `eq_inputs`
95
+ # as separate arguments into the lambdified function. NumPy will
96
+ # then compute the results for all `tau` columns at once.
97
+ yhat[i, :] = eq(*eq_inputs, *parameters.values())
98
+
100
99
  except Exception as e:
101
- # for eq_in in eq_inputs:
102
- # print("--", self.yvars[i])
103
- # for var, val in zip(
104
- # self.vars + list(parameters.keys()),
105
- # list(eq_in) + list(parameters.values()),
106
- # ):
107
- # print(var, "=", val)
108
- # eq(*eq_in, *parameters.values())
109
100
  raise NumericModelError(
110
101
  f"Failed to compute model value for yvar {self.yvars[i]}: {e}"
111
102
  ) from e
112
- assert yhat.shape == (self.ndim, tau)
103
+
113
104
  return yhat
114
105
 
115
106
  def calc_effects(self, xdat: np.array, xdat_mean=None, yhat_mean=None):
@@ -198,10 +189,25 @@ class Model:
198
189
 
199
190
  @cached_property
200
191
  def _model_lam(self) -> Iterable[Callable]:
201
- return [
202
- sympy.lambdify(self.vars + list(self.parameters), eq)
203
- for eq in self.equations
204
- ]
192
+ """Create lambdified equations with NumPy-compatible functions."""
193
+ lambdas = []
194
+ ordered_vars = self.vars + list(self.parameters.keys())
195
+
196
+ # Define placeholder for vectorized max function
197
+ vectorized_max = sympy.Function("vectorized_max")
198
+
199
+ # Define custom translation mapping
200
+ custom_modules = [{"vectorized_max": np.maximum}, "numpy"]
201
+
202
+ for i, eq in enumerate(self.equations):
203
+ # Replace sympy.Max with our placeholder
204
+ fixed_eq = eq.subs(sympy.Max, vectorized_max)
205
+
206
+ # Lambdify with custom NumPy mapping
207
+ lam = sympy.lambdify(ordered_vars, fixed_eq, modules=custom_modules)
208
+ lambdas.append(lam)
209
+
210
+ return lambdas
205
211
 
206
212
  @cached_property
207
213
  def final_ind(self):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: causing
3
- Version: 2.4.3
3
+ Version: 2.4.5
4
4
  Summary: Causing: CAUSal INterpretation using Graphs
5
5
  Home-page: https://github.com/realrate/Causing
6
6
  Author: Dr. Holger Bartel
@@ -5,7 +5,7 @@ with open("README.md", "r", encoding="utf-8") as fh:
5
5
 
6
6
  setuptools.setup(
7
7
  name="causing",
8
- version="2.4.3",
8
+ version="2.4.5",
9
9
  author="Dr. Holger Bartel",
10
10
  author_email="holger.bartel@realrate.ai",
11
11
  description="Causing: CAUSal INterpretation using Graphs",
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes