mxlpy 0.16.0__py3-none-any.whl → 0.18.0__py3-none-any.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.
@@ -1,25 +1,43 @@
1
1
  from collections.abc import Callable
2
2
  from dataclasses import dataclass
3
+ from typing import Self
3
4
 
4
5
  import numpy as np
5
6
  import pandas as pd
6
7
  import torch
7
- import tqdm
8
8
  from torch import nn
9
9
  from torch.optim.adam import Adam
10
10
  from torch.optim.optimizer import ParamsT
11
11
 
12
- from mxlpy.nn._torch import MLP, DefaultDevice
12
+ from mxlpy.nn._torch import MLP, DefaultDevice, train
13
13
  from mxlpy.types import AbstractSurrogate
14
14
 
15
+ type LossFn = Callable[[torch.Tensor, torch.Tensor], torch.Tensor]
16
+
15
17
  __all__ = [
16
- "TorchSurrogate",
17
- "train_torch_surrogate",
18
+ "LossFn",
19
+ "Torch",
20
+ "TorchTrainer",
21
+ "train_torch",
18
22
  ]
19
23
 
20
24
 
25
+ def _mean_abs(x: torch.Tensor, y: torch.Tensor) -> torch.Tensor:
26
+ """Standard loss for surrogates.
27
+
28
+ Args:
29
+ x: Predictions of a model.
30
+ y: Targets.
31
+
32
+ Returns:
33
+ torch.Tensor: loss.
34
+
35
+ """
36
+ return torch.mean(torch.abs(x - y))
37
+
38
+
21
39
  @dataclass(kw_only=True)
22
- class TorchSurrogate(AbstractSurrogate):
40
+ class Torch(AbstractSurrogate):
23
41
  """Surrogate model using PyTorch.
24
42
 
25
43
  Attributes:
@@ -48,90 +66,92 @@ class TorchSurrogate(AbstractSurrogate):
48
66
  ).numpy()
49
67
 
50
68
 
51
- def _train_batched(
52
- aprox: nn.Module,
53
- features: pd.DataFrame,
54
- targets: pd.DataFrame,
55
- epochs: int,
56
- optimizer: Adam,
57
- device: torch.device,
58
- batch_size: int,
59
- ) -> pd.Series:
60
- """Train the neural network using mini-batch gradient descent.
61
-
62
- Args:
63
- aprox: Neural network model to train.
64
- features: Input features as a tensor.
65
- targets: Target values as a tensor.
66
- epochs: Number of training epochs.
67
- optimizer: Optimizer for training.
68
- device: torch device
69
- batch_size: Size of mini-batches for training.
70
-
71
- Returns:
72
- pd.Series: Series containing the training loss history.
73
-
74
- """
75
- rng = np.random.default_rng()
76
- losses = {}
77
- for i in tqdm.trange(epochs):
78
- idxs = rng.choice(features.index, size=batch_size)
79
- X = torch.Tensor(features.iloc[idxs].to_numpy(), device=device)
80
- Y = torch.Tensor(targets.iloc[idxs].to_numpy(), device=device)
81
- optimizer.zero_grad()
82
- loss = torch.mean(torch.abs(aprox(X) - Y))
83
- loss.backward()
84
- optimizer.step()
85
- losses[i] = loss.detach().numpy()
86
- return pd.Series(losses, dtype=float)
87
-
88
-
89
- def _train_full(
90
- aprox: nn.Module,
91
- features: pd.DataFrame,
92
- targets: pd.DataFrame,
93
- epochs: int,
94
- optimizer: Adam,
95
- device: torch.device,
96
- ) -> pd.Series:
97
- """Train the neural network using full-batch gradient descent.
98
-
99
- Args:
100
- aprox: Neural network model to train.
101
- features: Input features as a tensor.
102
- targets: Target values as a tensor.
103
- epochs: Number of training epochs.
104
- optimizer: Optimizer for training.
105
- device: Torch device
106
-
107
- Returns:
108
- pd.Series: Series containing the training loss history.
109
-
110
- """
111
- X = torch.Tensor(features.to_numpy(), device=device)
112
- Y = torch.Tensor(targets.to_numpy(), device=device)
113
-
114
- losses = {}
115
- for i in tqdm.trange(epochs):
116
- optimizer.zero_grad()
117
- loss = torch.mean(torch.abs(aprox(X) - Y))
118
- loss.backward()
119
- optimizer.step()
120
- losses[i] = loss.detach().numpy()
121
- return pd.Series(losses, dtype=float)
69
+ @dataclass(init=False)
70
+ class TorchTrainer:
71
+ features: pd.DataFrame
72
+ targets: pd.DataFrame
73
+ approximator: nn.Module
74
+ optimizer: Adam
75
+ device: torch.device
76
+ losses: list[pd.Series]
77
+ loss_fn: LossFn
78
+
79
+ def __init__(
80
+ self,
81
+ features: pd.DataFrame,
82
+ targets: pd.DataFrame,
83
+ approximator: nn.Module | None = None,
84
+ optimimzer_cls: Callable[[ParamsT], Adam] = Adam,
85
+ device: torch.device = DefaultDevice,
86
+ loss_fn: LossFn = _mean_abs,
87
+ ) -> None:
88
+ self.features = features
89
+ self.targets = targets
90
+
91
+ if approximator is None:
92
+ approximator = MLP(
93
+ n_inputs=len(features.columns),
94
+ neurons_per_layer=[50, 50, len(targets.columns)],
95
+ )
96
+ self.approximator = approximator.to(device)
97
+
98
+ self.optimizer = optimimzer_cls(approximator.parameters())
99
+ self.device = device
100
+ self.loss_fn = loss_fn
101
+ self.losses = []
102
+
103
+ def train(
104
+ self,
105
+ epochs: int,
106
+ batch_size: int | None = None,
107
+ ) -> Self:
108
+ losses = train(
109
+ aprox=self.approximator,
110
+ features=self.features.to_numpy(),
111
+ targets=self.targets.to_numpy(),
112
+ epochs=epochs,
113
+ optimizer=self.optimizer,
114
+ batch_size=batch_size,
115
+ device=self.device,
116
+ loss_fn=self.loss_fn,
117
+ )
118
+ if len(self.losses) > 0:
119
+ losses.index += self.losses[-1].index[-1]
120
+ self.losses.append(losses)
121
+ return self
122
+
123
+ def get_loss(self) -> pd.Series:
124
+ return pd.concat(self.losses)
125
+
126
+ def get_surrogate(
127
+ self,
128
+ surrogate_args: list[str] | None = None,
129
+ surrogate_outputs: list[str] | None = None,
130
+ surrogate_stoichiometries: dict[str, dict[str, float]] | None = None,
131
+ ) -> Torch:
132
+ return Torch(
133
+ model=self.approximator,
134
+ args=surrogate_args if surrogate_args is not None else [],
135
+ outputs=surrogate_outputs if surrogate_outputs is not None else [],
136
+ stoichiometries=surrogate_stoichiometries
137
+ if surrogate_stoichiometries is not None
138
+ else {},
139
+ )
122
140
 
123
141
 
124
- def train_torch_surrogate(
142
+ def train_torch(
125
143
  features: pd.DataFrame,
126
144
  targets: pd.DataFrame,
127
145
  epochs: int,
128
146
  surrogate_args: list[str] | None = None,
147
+ surrogate_outputs: list[str] | None = None,
129
148
  surrogate_stoichiometries: dict[str, dict[str, float]] | None = None,
130
149
  batch_size: int | None = None,
131
150
  approximator: nn.Module | None = None,
132
151
  optimimzer_cls: Callable[[ParamsT], Adam] = Adam,
133
152
  device: torch.device = DefaultDevice,
134
- ) -> tuple[TorchSurrogate, pd.Series]:
153
+ loss_fn: LossFn = _mean_abs,
154
+ ) -> tuple[Torch, pd.Series]:
135
155
  """Train a PyTorch surrogate model.
136
156
 
137
157
  Examples:
@@ -143,54 +163,38 @@ def train_torch_surrogate(
143
163
  ... surrogate_stoichiometries={
144
164
  ... "v1": {"x1": -1, "x2": 1, "ATP": -1},
145
165
  ... },
146
- ...)
166
+ ...)surrogate_stoichiometries
147
167
 
148
168
  Args:
149
169
  features: DataFrame containing the input features for training.
150
170
  targets: DataFrame containing the target values for training.
151
171
  epochs: Number of training epochs.
152
- surrogate_args: List of input variable names for the surrogate model.
153
- surrogate_stoichiometries: Dictionary mapping reaction names to stoichiometries.
172
+ surrogate_args: Names of inputs arguments for the surrogate model.
173
+ surrogate_outputs: Names of output arguments from the surrogate.
174
+ surrogate_stoichiometries: Mapping of variables to their stoichiometries
154
175
  batch_size: Size of mini-batches for training (None for full-batch).
155
176
  approximator: Predefined neural network model (None to use default MLP features-50-50-output).
156
177
  optimimzer_cls: Optimizer class to use for training (default: Adam).
157
178
  device: Device to run the training on (default: DefaultDevice).
179
+ loss_fn: Custom loss function or instance of torch loss object
158
180
 
159
181
  Returns:
160
182
  tuple[TorchSurrogate, pd.Series]: Trained surrogate model and loss history.
161
183
 
162
184
  """
163
- if approximator is None:
164
- approximator = MLP(
165
- n_inputs=len(features.columns),
166
- neurons_per_layer=[50, 50, len(targets.columns)],
167
- ).to(device)
168
-
169
- optimizer = optimimzer_cls(approximator.parameters())
170
- if batch_size is None:
171
- losses = _train_full(
172
- aprox=approximator,
173
- features=features,
174
- targets=targets,
175
- epochs=epochs,
176
- optimizer=optimizer,
177
- device=device,
178
- )
179
- else:
180
- losses = _train_batched(
181
- aprox=approximator,
182
- features=features,
183
- targets=targets,
184
- epochs=epochs,
185
- optimizer=optimizer,
186
- device=device,
187
- batch_size=batch_size,
188
- )
189
- surrogate = TorchSurrogate(
190
- model=approximator,
191
- args=surrogate_args if surrogate_args is not None else [],
192
- stoichiometries=surrogate_stoichiometries
193
- if surrogate_stoichiometries is not None
194
- else {},
185
+ trainer = TorchTrainer(
186
+ features=features,
187
+ targets=targets,
188
+ approximator=approximator,
189
+ optimimzer_cls=optimimzer_cls,
190
+ device=device,
191
+ loss_fn=loss_fn,
192
+ ).train(
193
+ epochs=epochs,
194
+ batch_size=batch_size,
195
195
  )
196
- return surrogate, losses
196
+ return trainer.get_surrogate(
197
+ surrogate_args=surrogate_args,
198
+ surrogate_outputs=surrogate_outputs,
199
+ surrogate_stoichiometries=surrogate_stoichiometries,
200
+ ), trainer.get_loss()
@@ -27,9 +27,7 @@ import tqdm
27
27
  from sympy import Matrix
28
28
  from sympy.matrices import zeros
29
29
 
30
- from mxlpy.model import Model
31
-
32
- from .symbolic_model import SymbolicModel, to_symbolic_model
30
+ from .symbolic_model import SymbolicModel
33
31
 
34
32
  __all__ = [
35
33
  "Options",
mxlpy/types.py CHANGED
@@ -22,6 +22,7 @@ from dataclasses import dataclass, field
22
22
  import pandas as pd
23
23
 
24
24
  __all__ = [
25
+ "AbstractEstimator",
25
26
  "AbstractSurrogate",
26
27
  "Array",
27
28
  "ArrayLike",
@@ -45,9 +46,6 @@ __all__ = [
45
46
  "unwrap2",
46
47
  ]
47
48
 
48
- # Re-exporting some types here, because their imports have
49
- # changed between Python versions and I have no interest in
50
- # fixing it in every file
51
49
  from collections.abc import Callable, Iterator, Mapping
52
50
  from typing import TYPE_CHECKING, Any, ParamSpec, Protocol, TypeVar, cast
53
51
 
@@ -444,7 +442,8 @@ class AbstractSurrogate:
444
442
 
445
443
  """
446
444
 
447
- args: list[str] = field(default_factory=list)
445
+ args: list[str]
446
+ outputs: list[str]
448
447
  stoichiometries: dict[str, dict[str, float]] = field(default_factory=dict)
449
448
 
450
449
  @abstractmethod
@@ -455,7 +454,7 @@ class AbstractSurrogate:
455
454
  """Predict outputs based on input data."""
456
455
  return dict(
457
456
  zip(
458
- self.stoichiometries,
457
+ self.outputs,
459
458
  self.predict_raw(y),
460
459
  strict=True,
461
460
  )
@@ -475,7 +474,7 @@ class AbstractSurrogate:
475
474
  args: pd.DataFrame,
476
475
  ) -> None:
477
476
  """Predict outputs based on input data."""
478
- args[list(self.stoichiometries)] = pd.DataFrame(
477
+ args[self.outputs] = pd.DataFrame(
479
478
  [self.predict(y) for y in args.loc[:, self.args].to_numpy()],
480
479
  index=args.index,
481
480
  dtype=float,
@@ -491,4 +490,15 @@ class MockSurrogate(AbstractSurrogate):
491
490
  y: np.ndarray,
492
491
  ) -> dict[str, float]:
493
492
  """Predict outputs based on input data."""
494
- return dict(zip(self.stoichiometries, y, strict=True))
493
+ return dict(zip(self.outputs, y, strict=True))
494
+
495
+
496
+ @dataclass(kw_only=True)
497
+ class AbstractEstimator:
498
+ """Abstract class for parameter estimation using neural networks."""
499
+
500
+ parameter_names: list[str]
501
+
502
+ @abstractmethod
503
+ def predict(self, features: pd.Series | pd.DataFrame) -> pd.DataFrame:
504
+ """Predict the target values for the given features."""
@@ -1,17 +1,17 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mxlpy
3
- Version: 0.16.0
3
+ Version: 0.18.0
4
4
  Summary: A package to build metabolic models
5
5
  Author-email: Marvin van Aalst <marvin.vanaalst@gmail.com>
6
6
  Maintainer-email: Marvin van Aalst <marvin.vanaalst@gmail.com>
7
- License-Expression: GPL-3.0-or-later
7
+ License-Expression: MIT
8
8
  License-File: LICENSE
9
9
  Keywords: metabolic,modelling,ode
10
10
  Classifier: Development Status :: 5 - Production/Stable
11
11
  Classifier: Environment :: Console
12
12
  Classifier: Intended Audience :: Developers
13
13
  Classifier: Intended Audience :: Science/Research
14
- Classifier: License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)
14
+ Classifier: License :: OSI Approved :: MIT License
15
15
  Classifier: Operating System :: MacOS
16
16
  Classifier: Operating System :: Microsoft :: Windows
17
17
  Classifier: Operating System :: OS Independent
@@ -47,7 +47,6 @@ Requires-Dist: jupyter>=1.1.1; extra == 'dev'
47
47
  Requires-Dist: mkdocs-jupyter>=0.25.1; extra == 'dev'
48
48
  Requires-Dist: mkdocs-material>=9.5.42; extra == 'dev'
49
49
  Requires-Dist: mkdocs>=1.6.1; extra == 'dev'
50
- Requires-Dist: mypy>=1.13.0; extra == 'dev'
51
50
  Requires-Dist: pre-commit>=4.0.1; extra == 'dev'
52
51
  Requires-Dist: pyright>=1.1.387; extra == 'dev'
53
52
  Requires-Dist: pytest-cov>=5.0.0; extra == 'dev'
@@ -68,7 +67,7 @@ Description-Content-Type: text/markdown
68
67
 
69
68
  [![pypi](https://img.shields.io/pypi/v/mxlpy.svg)](https://pypi.python.org/pypi/mxlpy)
70
69
  [![docs][docs-badge]][docs]
71
- ![License](https://img.shields.io/badge/license-GPL--3.0-blue?style=flat-square)
70
+ ![License](https://img.shields.io/badge/license-MIT-blue?style=flat-square)
72
71
  ![Coverage](https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fgist.github.com%2Fmarvinvanaalst%2F98ab3ce1db511de42f9871e91d85e4cd%2Fraw%2Fcoverage.json&query=%24.message&label=Coverage&color=%24.color&suffix=%20%25)
73
72
  [![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
74
73
  [![security: bandit](https://img.shields.io/badge/security-bandit-yellow.svg)](https://github.com/PyCQA/bandit)
@@ -91,10 +90,10 @@ pixi add --pypi mxlpy[torch]
91
90
 
92
91
  ## How to cite
93
92
 
94
- If you use this software in your scientific work, please cite [this article](...):
93
+ If you use this software in your scientific work, please cite [this article](https://doi.org/10.1101/2025.05.06.652335):
95
94
 
96
- - [doi](https://doi.org/)
97
- - [bibtex file](https://fillme.out)
95
+ - [doi](https://doi.org/10.1101/2025.05.06.652335)
96
+ - [bibtex file](https://github.com/Computational-Biology-Aachen/MxlPy/citation.bibtex)
98
97
 
99
98
 
100
99
  ## Development setup
@@ -1,50 +1,51 @@
1
- mxlpy/__init__.py,sha256=XZYNFyDC5rWcKi6139mq04cROI7LwJvxB2_3ApKwcvY,4194
1
+ mxlpy/__init__.py,sha256=lGo7XQTVuR1p8rW1J6gZsgdQWRqfYa9AWbvZQwT8oLQ,4236
2
2
  mxlpy/distributions.py,sha256=ce6RTqn19YzMMec-u09fSIUA8A92M6rehCuHuXWcX7A,8734
3
- mxlpy/fit.py,sha256=LwSoLfNVrqSlTtuUApwH36LjzGU0HLs4C_2qqTTjXFE,7859
4
- mxlpy/fns.py,sha256=ct_RFj9koW8vXHyr27GnbZUHUS_zfs4rDysybuFiOaU,4599
5
- mxlpy/identify.py,sha256=af52SCG4nlY9sSw22goaIheuvXR09QYK4ksCT24QHWI,1946
3
+ mxlpy/fit.py,sha256=WNg98wW47xkd4gNEgj3t8eNNTqfVpHEJTbXMRQBe22o,12457
4
+ mxlpy/fns.py,sha256=VxDDyEdtGD7fEoT5LiiEaRqFk-0fIunRXHr1dCMpCdE,14002
5
+ mxlpy/identify.py,sha256=veYYCjTDAlzibrWtciX2egfEWWgosOpqgLBgbfVj42g,2130
6
6
  mxlpy/label_map.py,sha256=urv-QTb0MUEKjwWvKtJSB8H2kvhLn1EKfRIH7awQQ8Y,17769
7
7
  mxlpy/linear_label_map.py,sha256=DqzN_akacPccZwzYAR3ANIdzAU_GU6Xe6gWV9DHAAWU,10282
8
8
  mxlpy/mc.py,sha256=oYd8a3ycyZLyh-ZxTYUjDRNfsCcwSQaLWssxv0yC5Cc,17399
9
9
  mxlpy/mca.py,sha256=1_qBX9lHI6svXSebtwvMldAMwPlLqMylAPmxMbMQdWw,9359
10
- mxlpy/model.py,sha256=qzol8nDSbM3HdESh50c4UFjn6Pw5JwcvhQ5AyKnbyvc,57576
11
- mxlpy/npe.py,sha256=oiRLA43-qf-AcS2KpQfJIOt7-Ev9Aj5sF6TMq9bJn84,8747
10
+ mxlpy/model.py,sha256=H1rAKaB5pAQcMuBh5GnXuBReADTx5IDa1x0CdUZ6VlI,58411
12
11
  mxlpy/parallel.py,sha256=kX4Td5YoovDwZp6kX_3cfO6QtHSS9ieJ0bMZiKs3Xv8,5002
13
12
  mxlpy/parameterise.py,sha256=2jMhhO-bHTFP_0kXercJekeATAZYBg5FrK1MQ_mWGpk,654
14
13
  mxlpy/paths.py,sha256=TK2wO4N9lG-UV1JGfeB64q48JVDbwqIUj63rl55MKuQ,1022
15
- mxlpy/plot.py,sha256=4uu-6d8LH-GWX-sG_TlSpkSsnikv1DLTtnjJzA7nuRA,24670
14
+ mxlpy/plot.py,sha256=Bu69ZSerqQlY_Hut-Wmn-KpqT1cwW96n8paa6dXOVrw,28853
16
15
  mxlpy/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
17
- mxlpy/report.py,sha256=h7dhcBzPFydLPxdsEXokzDf7Ce4PirXMsvLqlDZLSWM,7181
16
+ mxlpy/report.py,sha256=ZwnjquPAvo4A8UqK-BT19SZFSEUOy1FALqoh7uTmbAI,7793
18
17
  mxlpy/scan.py,sha256=FBPpjv66v4IWZ5OwG_EWUdrucLWR9gq_XEsLFC-otaw,18969
19
18
  mxlpy/simulator.py,sha256=9Ne4P5Jrwgx4oAlljPvCqSCCy98_5Lv1B87y1AkbI4c,21041
20
- mxlpy/types.py,sha256=GbdyzEDTN8QfUH6-XXdNgf_TzqIXaYvcZGxaXc5kVio,14509
19
+ mxlpy/types.py,sha256=EOIOPuxD2vqRjYgX4vYByclxmG7bCCR1WWXYE0Msz7A,14669
21
20
  mxlpy/experimental/__init__.py,sha256=kZTE-92OErpHzNRqmgSQYH4CGXrogGJ5EL35XGZQ81M,206
22
21
  mxlpy/experimental/diff.py,sha256=4bztagJzFMsQJM7dlun_kv-WrWssM8CIw7gcL63hFf8,8952
23
22
  mxlpy/integrators/__init__.py,sha256=kqmV6a0TRyLGR_XqbyAI652AfptYnXAUpqbSFg0CpP8,450
24
23
  mxlpy/integrators/int_assimulo.py,sha256=TCBWQd558ZeRdBba1jCNsFyLBOssKvm8dXK36Aqg4_k,4817
25
24
  mxlpy/integrators/int_scipy.py,sha256=dFHlYTeb2zX97f3VuNdMJdI7WEYshF4JAIgprKKk2z4,4581
26
25
  mxlpy/meta/__init__.py,sha256=Jyy4063fZy6iT4LSwjPyEAVr4N_3xxcLc8wDBoDPyKc,278
27
- mxlpy/meta/codegen_latex.py,sha256=R0OJqzE7PnOCWLk52C3XWuRb-zI2eYTvV2oJZJvPsOE,13414
26
+ mxlpy/meta/codegen_latex.py,sha256=vONj--_wmFM_FJpe15aAYyT06-kolqQwSe2NEbKrQWo,19934
28
27
  mxlpy/meta/codegen_modebase.py,sha256=_ZAW4NvXhKwJQLGz5hkwwZpL2JMAJlfG-GUWkYIiNvw,3124
29
28
  mxlpy/meta/codegen_py.py,sha256=xSdeuEGPGc-QKRMgJO4VSPGMlxCPEV5prkKjNQ2D2hg,3483
30
- mxlpy/meta/source_tools.py,sha256=EN3OoGQaXeIsDTJvA7S15-xDBra3DCIyFZEJ6h0Fy0k,11125
29
+ mxlpy/meta/source_tools.py,sha256=IyiCLZ1KScSqADC9p_QSRgedoHGibs9U1RGJuXm827U,13464
31
30
  mxlpy/nn/__init__.py,sha256=yUc4o-iqfVVzkq9tZCstWwizrCqNlMft0YUwWGFFO-E,219
32
31
  mxlpy/nn/_tensorflow.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
33
- mxlpy/nn/_torch.py,sha256=_4Rw87zpIlCnrOsXC7iFp1c64_FcpfVmgBXBU0p8mlg,4063
32
+ mxlpy/nn/_torch.py,sha256=DORLixCSteCUMb7PTrIwd5FrVZ4_k0GIaLc6PI3ViwE,5796
33
+ mxlpy/npe/__init__.py,sha256=IQmqUPJc5A8QXJLzp6Dq6Sjm8Hh2KAYZLrMxXQVeQP8,1181
34
+ mxlpy/npe/_torch.py,sha256=pynnkdspO7NwTT3Pb_BU21jgBjJEvuLBJwaw_A-jAFg,11681
34
35
  mxlpy/sbml/__init__.py,sha256=AS7IwrBzBgN8coUZkyBEtiYa9ICWyY1wzp1ujVm5ItA,226
35
36
  mxlpy/sbml/_data.py,sha256=XwT1sSxn6KLTXYMbk4ORbEAEgZhQDBfoyrjMBDAoY_s,1135
36
37
  mxlpy/sbml/_export.py,sha256=Q6B9rxy-yt73DORzAYu4BpfkZXxCS3MDSDUXwpoXV6Q,19970
37
- mxlpy/sbml/_import.py,sha256=5DJklsAe2sMV1CFxAbkSFRT3amPzOZmpo53y9NYv6TY,22015
38
+ mxlpy/sbml/_import.py,sha256=5odQBdpD93mQJp2bVIabmPo6NK60nxqrdSVB8fEsF_A,22099
38
39
  mxlpy/sbml/_mathml.py,sha256=bNk9RQ_NQFDhY1R354p-gwqqHaIiyAwZ1xLPHHhiguQ,24436
39
40
  mxlpy/sbml/_name_conversion.py,sha256=XK9DEyzhrD0GBBwwjK9RA0yORrDX5c-Uvx0VtKMR5rA,1325
40
41
  mxlpy/sbml/_unit_conversion.py,sha256=dW_I6_Ou09ccwnp6LIdrPriIQnQUK5lJcjzM2Fawm6U,1927
41
- mxlpy/surrogates/__init__.py,sha256=N_iXERECKvmrHiihwnyQEKOSBsmlGEuQhEotn-mWKdk,924
42
- mxlpy/surrogates/_poly.py,sha256=E54CFscQBCcYMrty1X2ynl9GlS9uoEeAUgBPnhm3iIA,3113
43
- mxlpy/surrogates/_torch.py,sha256=E_1eDUlPSVFwROkdMDCqYwwHE-61pjNMJWotnhjzge0,5891
42
+ mxlpy/surrogates/__init__.py,sha256=ofHPNwe0LAILP2ZUWivAQpOv9LyHHzLZc6iu1cV2LeQ,894
43
+ mxlpy/surrogates/_poly.py,sha256=n1pe4xuD2A4BK8jJagzZ-17WW3kqvFBO-ZYuznmfosw,3303
44
+ mxlpy/surrogates/_torch.py,sha256=dpRZL8qOD8toezniuVPJ7NFTMpA97dF9dyrXfBAcTro,5984
44
45
  mxlpy/symbolic/__init__.py,sha256=3hQjCMw8-6iOxeUdfnCg8449fF_BRF2u6lCM1GPpkRY,222
45
- mxlpy/symbolic/strikepy.py,sha256=r6nRtckV1nxKq3i1bYYWZOkzwZ5XeKQuZM5ck44vUo0,20010
46
+ mxlpy/symbolic/strikepy.py,sha256=UMx2LMRwCkASKjdCYEvh9tKlW9dk3nDoWM9NNJXWL_8,19960
46
47
  mxlpy/symbolic/symbolic_model.py,sha256=YL9noEeP3_0DoKXwMPELtfmPuP6mgNcLIJgDRCkyB7A,2434
47
- mxlpy-0.16.0.dist-info/METADATA,sha256=ySMK4udu6wgaUpG7Wn0sa-XYUkaVz4u19C5PjMEM5p0,4551
48
- mxlpy-0.16.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
49
- mxlpy-0.16.0.dist-info/licenses/LICENSE,sha256=bEzjyjy1stQhfRDVaVHa3xV1x-V8emwdlbMvYO8Zo84,35073
50
- mxlpy-0.16.0.dist-info/RECORD,,
48
+ mxlpy-0.18.0.dist-info/METADATA,sha256=LgAn8m3f6oRfZl03E3X8UHak-2pJmoUdhealdJXQsJA,4567
49
+ mxlpy-0.18.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
50
+ mxlpy-0.18.0.dist-info/licenses/LICENSE,sha256=lHX9Eu70g3Iv1aOxXTWNHa3vq9vaVYSPQx4jOLYmDpw,1096
51
+ mxlpy-0.18.0.dist-info/RECORD,,
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) [2025] [Marvin van Aalst, Anna Matuszyńska]
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.