lca-algebraic 1.4.1.dev3__tar.gz → 1.4.1.dev6__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.
- {lca_algebraic-1.4.1.dev3 → lca_algebraic-1.4.1.dev6}/PKG-INFO +2 -1
- {lca_algebraic-1.4.1.dev3 → lca_algebraic-1.4.1.dev6}/lca_algebraic/activity.py +49 -12
- {lca_algebraic-1.4.1.dev3 → lca_algebraic-1.4.1.dev6}/lca_algebraic/base_utils.py +18 -7
- {lca_algebraic-1.4.1.dev3 → lca_algebraic-1.4.1.dev6}/lca_algebraic/bw_wrapper/__init__.py +5 -0
- {lca_algebraic-1.4.1.dev3 → lca_algebraic-1.4.1.dev6}/lca_algebraic/bw_wrapper/bw2.py +10 -0
- {lca_algebraic-1.4.1.dev3 → lca_algebraic-1.4.1.dev6}/lca_algebraic/bw_wrapper/bw25.py +10 -0
- {lca_algebraic-1.4.1.dev3 → lca_algebraic-1.4.1.dev6}/lca_algebraic/bw_wrapper/protocol.py +3 -0
- {lca_algebraic-1.4.1.dev3 → lca_algebraic-1.4.1.dev6}/lca_algebraic/cache.py +18 -3
- {lca_algebraic-1.4.1.dev3 → lca_algebraic-1.4.1.dev6}/lca_algebraic/lambda_expression.py +28 -1
- {lca_algebraic-1.4.1.dev3 → lca_algebraic-1.4.1.dev6}/lca_algebraic/lca.py +175 -28
- {lca_algebraic-1.4.1.dev3 → lca_algebraic-1.4.1.dev6}/lca_algebraic/matrix.py +38 -13
- {lca_algebraic-1.4.1.dev3 → lca_algebraic-1.4.1.dev6}/lca_algebraic/methods.py +9 -7
- {lca_algebraic-1.4.1.dev3 → lca_algebraic-1.4.1.dev6}/lca_algebraic/params.py +83 -17
- {lca_algebraic-1.4.1.dev3 → lca_algebraic-1.4.1.dev6}/lca_algebraic/stats.py +123 -16
- {lca_algebraic-1.4.1.dev3 → lca_algebraic-1.4.1.dev6}/lca_algebraic/sympy_utils.py +1 -3
- {lca_algebraic-1.4.1.dev3 → lca_algebraic-1.4.1.dev6}/lca_algebraic.egg-info/PKG-INFO +2 -1
- {lca_algebraic-1.4.1.dev3 → lca_algebraic-1.4.1.dev6}/lca_algebraic.egg-info/SOURCES.txt +6 -0
- {lca_algebraic-1.4.1.dev3 → lca_algebraic-1.4.1.dev6}/lca_algebraic.egg-info/requires.txt +1 -0
- {lca_algebraic-1.4.1.dev3 → lca_algebraic-1.4.1.dev6}/pyproject.toml +3 -2
- lca_algebraic-1.4.1.dev6/test/test_expand_params.py +26 -0
- lca_algebraic-1.4.1.dev6/test/test_methods.py +35 -0
- lca_algebraic-1.4.1.dev6/test/test_overwrite.py +73 -0
- lca_algebraic-1.4.1.dev6/test/test_params.py +90 -0
- lca_algebraic-1.4.1.dev6/test/test_proxy_cache.py +47 -0
- lca_algebraic-1.4.1.dev6/test/test_stats.py +99 -0
- {lca_algebraic-1.4.1.dev3 → lca_algebraic-1.4.1.dev6}/test/test_units.py +71 -7
- {lca_algebraic-1.4.1.dev3 → lca_algebraic-1.4.1.dev6}/LICENSE +0 -0
- {lca_algebraic-1.4.1.dev3 → lca_algebraic-1.4.1.dev6}/README.md +0 -0
- {lca_algebraic-1.4.1.dev3 → lca_algebraic-1.4.1.dev6}/lca_algebraic/__init__.py +0 -0
- {lca_algebraic-1.4.1.dev3 → lca_algebraic-1.4.1.dev6}/lca_algebraic/axis_dict.py +0 -0
- {lca_algebraic-1.4.1.dev3 → lca_algebraic-1.4.1.dev6}/lca_algebraic/database.py +0 -0
- {lca_algebraic-1.4.1.dev3 → lca_algebraic-1.4.1.dev6}/lca_algebraic/interpolation.py +0 -0
- {lca_algebraic-1.4.1.dev3 → lca_algebraic-1.4.1.dev6}/lca_algebraic/io.py +0 -0
- {lca_algebraic-1.4.1.dev3 → lca_algebraic-1.4.1.dev6}/lca_algebraic/log.py +0 -0
- {lca_algebraic-1.4.1.dev3 → lca_algebraic-1.4.1.dev6}/lca_algebraic/settings.py +0 -0
- {lca_algebraic-1.4.1.dev3 → lca_algebraic-1.4.1.dev6}/lca_algebraic/units.py +0 -0
- {lca_algebraic-1.4.1.dev3 → lca_algebraic-1.4.1.dev6}/lca_algebraic.egg-info/dependency_links.txt +0 -0
- {lca_algebraic-1.4.1.dev3 → lca_algebraic-1.4.1.dev6}/lca_algebraic.egg-info/top_level.txt +0 -0
- {lca_algebraic-1.4.1.dev3 → lca_algebraic-1.4.1.dev6}/setup.cfg +0 -0
- {lca_algebraic-1.4.1.dev3 → lca_algebraic-1.4.1.dev6}/test/test_axis_dict.py +0 -0
- {lca_algebraic-1.4.1.dev3 → lca_algebraic-1.4.1.dev6}/test/test_axis_matrices_cache.py +0 -0
- {lca_algebraic-1.4.1.dev3 → lca_algebraic-1.4.1.dev6}/test/test_cache.py +0 -0
- {lca_algebraic-1.4.1.dev3 → lca_algebraic-1.4.1.dev6}/test/test_premise.py +0 -0
- {lca_algebraic-1.4.1.dev3 → lca_algebraic-1.4.1.dev6}/test/test_sympy.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: lca_algebraic
|
|
3
|
-
Version: 1.4.1.
|
|
3
|
+
Version: 1.4.1.dev6
|
|
4
4
|
Summary: This library provides a layer above Brightway for defining parametric models and running super fast LCA for monte carlo analysis.
|
|
5
5
|
Author-email: OIE - Mines ParisTech <raphael.jolivet@mines-paristech.fr>
|
|
6
6
|
License: BSD
|
|
@@ -41,6 +41,7 @@ Requires-Dist: pre-commit; extra == "dev"
|
|
|
41
41
|
Requires-Dist: pytest; extra == "dev"
|
|
42
42
|
Requires-Dist: nbmake; extra == "dev"
|
|
43
43
|
Requires-Dist: build; extra == "dev"
|
|
44
|
+
Requires-Dist: twine>=6.1; extra == "dev"
|
|
44
45
|
Dynamic: license-file
|
|
45
46
|
|
|
46
47
|
|
|
@@ -13,12 +13,14 @@ from lca_algebraic.bw_wrapper import (
|
|
|
13
13
|
Activity,
|
|
14
14
|
Exchange,
|
|
15
15
|
ExchangeDataset,
|
|
16
|
+
activity_not_found,
|
|
16
17
|
copy_activity_skip_keys,
|
|
17
18
|
dict_as_exchangedataset,
|
|
18
19
|
exchange_type_for_sub_act,
|
|
19
20
|
get_activity,
|
|
20
21
|
process_node_default,
|
|
21
22
|
production_edge_default,
|
|
23
|
+
purge_activity_content,
|
|
22
24
|
)
|
|
23
25
|
from lca_algebraic.database import (
|
|
24
26
|
_find_biosphere_db,
|
|
@@ -29,6 +31,7 @@ from lca_algebraic.database import (
|
|
|
29
31
|
)
|
|
30
32
|
from lca_algebraic.params import (
|
|
31
33
|
STORE_FORMULA_KEY,
|
|
34
|
+
STORE_FORMULA_TAG,
|
|
32
35
|
DbContext,
|
|
33
36
|
ParamDef,
|
|
34
37
|
_complete_and_expand_params,
|
|
@@ -167,6 +170,11 @@ class ActivityExtended(Activity):
|
|
|
167
170
|
or activity for updating only input,
|
|
168
171
|
or dict of attributes, for updating both at once, or any other attribute.
|
|
169
172
|
The amount can reference the symbol 'old_amount' that will be replaced with the current amount of the exchange.
|
|
173
|
+
|
|
174
|
+
Passing a dict of attributes is also the way to tag a single exchange with an axis \
|
|
175
|
+
(see ``compute_impacts``) : only that exchange will be ventilated under the category::
|
|
176
|
+
|
|
177
|
+
myActivity.updateExchanges({some_act: dict(amount=2, phase="transport")})
|
|
170
178
|
"""
|
|
171
179
|
if not _isForeground(self["database"]) and not Settings.internals:
|
|
172
180
|
msg = f"You are updating a background activity in {self['database']}. Use copyActivity() in a foreground db instead."
|
|
@@ -318,6 +326,9 @@ class ActivityExtended(Activity):
|
|
|
318
326
|
def _amount_to_formula(self, amount: ValueOrExpression, exchange: ExchangeDataset):
|
|
319
327
|
res = dict()
|
|
320
328
|
if isinstance(amount, Basic):
|
|
329
|
+
if amount.is_number:
|
|
330
|
+
return {"amount": float(amount.evalf())}
|
|
331
|
+
|
|
321
332
|
current_amount = exchange.get("amount", None)
|
|
322
333
|
if current_amount is not None:
|
|
323
334
|
amount = amount.subs(old_amount, current_amount)
|
|
@@ -329,8 +340,9 @@ class ActivityExtended(Activity):
|
|
|
329
340
|
raise Exception("Symbol '%s' not found in params : %s" % (symbol, all_symbols))
|
|
330
341
|
|
|
331
342
|
res[STORE_FORMULA_KEY] = str(amount)
|
|
343
|
+
res[STORE_FORMULA_TAG] = True
|
|
332
344
|
res["amount"] = 0
|
|
333
|
-
elif isinstance(amount, float
|
|
345
|
+
elif isinstance(amount, float | int):
|
|
334
346
|
res["amount"] = amount
|
|
335
347
|
else:
|
|
336
348
|
raise Exception(
|
|
@@ -349,6 +361,9 @@ class ActivityExtended(Activity):
|
|
|
349
361
|
# Update units
|
|
350
362
|
amount = self._transform_unit(amount, exchange["unit"])
|
|
351
363
|
|
|
364
|
+
updates.pop(STORE_FORMULA_TAG, None)
|
|
365
|
+
exchange.pop(STORE_FORMULA_TAG, None)
|
|
366
|
+
|
|
352
367
|
# Extract formula if two separate field "amount" and "formula"
|
|
353
368
|
# Update the list of updates
|
|
354
369
|
updates.update(self._amount_to_formula(amount, exchange))
|
|
@@ -392,7 +407,14 @@ class ActivityExtended(Activity):
|
|
|
392
407
|
yield exch
|
|
393
408
|
|
|
394
409
|
def updateMeta(self, **kwargs):
|
|
395
|
-
"""Update any property
|
|
410
|
+
"""Update any custom property of the activity.
|
|
411
|
+
|
|
412
|
+
This is typically used to tag an activity with an axis : all its outgoing
|
|
413
|
+
exchanges will then be ventilated under that category by ``compute_impacts``::
|
|
414
|
+
|
|
415
|
+
myActivity.updateMeta(phase="manufacturing")
|
|
416
|
+
compute_impacts(model, methods, axis="phase")
|
|
417
|
+
"""
|
|
396
418
|
for key, val in kwargs.items():
|
|
397
419
|
self._data[key] = val
|
|
398
420
|
self.save()
|
|
@@ -475,6 +497,11 @@ def findActivity(
|
|
|
475
497
|
search = search.lower()
|
|
476
498
|
search = search.replace(",", " ")
|
|
477
499
|
|
|
500
|
+
# bw2data >= 4 backs `search` with FTS5, which rejects blank queries
|
|
501
|
+
# while bw2data 3 silently returned nothing.
|
|
502
|
+
if not search.strip():
|
|
503
|
+
return []
|
|
504
|
+
|
|
478
505
|
# Find candidates via index
|
|
479
506
|
# candidates = _find_candidates(db_name, name_key)
|
|
480
507
|
candidates = _getDb(db_name).search(search, limit=limit)
|
|
@@ -482,7 +509,8 @@ def findActivity(
|
|
|
482
509
|
if len(candidates) == 0:
|
|
483
510
|
# Try again removing strange caracters
|
|
484
511
|
search = re.sub(r"\w*[^a-zA-Z ]+\w*", " ", search)
|
|
485
|
-
|
|
512
|
+
if search.strip():
|
|
513
|
+
candidates = _getDb(db_name).search(search, limit=limit)
|
|
486
514
|
|
|
487
515
|
# Exact match
|
|
488
516
|
return list(filter(act_filter, candidates))
|
|
@@ -546,13 +574,19 @@ def _newAct(db_name, code):
|
|
|
546
574
|
warn(msg)
|
|
547
575
|
|
|
548
576
|
db = _getDb(db_name)
|
|
549
|
-
# Already present : delete it ?
|
|
550
|
-
for act in db:
|
|
551
|
-
if act["code"] == code:
|
|
552
|
-
warn("Activity '%s' was already in '%s'. Overwriting it" % (code, db_name))
|
|
553
|
-
act.delete()
|
|
554
577
|
|
|
555
|
-
|
|
578
|
+
try:
|
|
579
|
+
act = getActByCode(db_name, code)
|
|
580
|
+
except activity_not_found():
|
|
581
|
+
return db.new_activity(code)
|
|
582
|
+
|
|
583
|
+
# Already present : overwrite it in place.
|
|
584
|
+
# We must not delete+recreate the activity : on brightway 2.5, deleting an
|
|
585
|
+
# activity also removes the incoming links (exchanges from other activities
|
|
586
|
+
# consuming it), which would silently break previously built models.
|
|
587
|
+
warn("Activity '%s' was already in '%s'. Overwriting it" % (code, db_name))
|
|
588
|
+
purge_activity_content(act)
|
|
589
|
+
return act
|
|
556
590
|
|
|
557
591
|
|
|
558
592
|
def newActivity(
|
|
@@ -630,7 +664,7 @@ def newActivity(
|
|
|
630
664
|
|
|
631
665
|
@atomic
|
|
632
666
|
def copyActivity(
|
|
633
|
-
db_name, activity: ActivityExtended, code=None, withExchanges=True, input_mapping=None, **kwargs
|
|
667
|
+
db_name, activity: ActivityExtended, code=None, withExchanges=True, stripFormula=True, input_mapping=None, **kwargs
|
|
634
668
|
) -> ActivityExtended:
|
|
635
669
|
"""Copy an activity and its exchanges into another database. You usually want to copy activities from your background to
|
|
636
670
|
your foreground DB to update them, keeping your background DB clean.
|
|
@@ -643,7 +677,10 @@ def copyActivity(
|
|
|
643
677
|
Source activity
|
|
644
678
|
code:
|
|
645
679
|
Code of the target activity. Also used as its name
|
|
646
|
-
|
|
680
|
+
withExchange:
|
|
681
|
+
Copy exchanges is True (default), otherwise do not copy them
|
|
682
|
+
stripFormula:
|
|
683
|
+
keep exchanges formula if True, default is False
|
|
647
684
|
|
|
648
685
|
Returns
|
|
649
686
|
-------
|
|
@@ -680,7 +717,7 @@ def copyActivity(
|
|
|
680
717
|
|
|
681
718
|
# Chemical formulas might be in ecoinvent technosphere
|
|
682
719
|
# We don't want them
|
|
683
|
-
if "formula" in data:
|
|
720
|
+
if stripFormula and ("formula" in data) and (STORE_FORMULA_TAG not in data):
|
|
684
721
|
del data["formula"]
|
|
685
722
|
ExchangeDataset.create(**dict_as_exchangedataset(data))
|
|
686
723
|
|
|
@@ -3,14 +3,16 @@ from functools import cache
|
|
|
3
3
|
from inspect import isfunction
|
|
4
4
|
from typing import Dict, Iterable, Tuple, Union
|
|
5
5
|
|
|
6
|
+
import sympy
|
|
6
7
|
import ipywidgets as widgets
|
|
7
8
|
import numpy as np
|
|
8
9
|
import pandas as pd
|
|
9
10
|
from IPython.display import display
|
|
10
11
|
from six import raise_from
|
|
11
12
|
from sympy import Basic
|
|
12
|
-
from
|
|
13
|
+
from pint import Quantity
|
|
13
14
|
|
|
15
|
+
from lca_algebraic.settings import Settings
|
|
14
16
|
from lca_algebraic.bw_wrapper import Activity, Database, is_output_exchange
|
|
15
17
|
|
|
16
18
|
_user_functions = dict()
|
|
@@ -48,14 +50,23 @@ def _getDb(dbname):
|
|
|
48
50
|
return dbs[dbname]
|
|
49
51
|
|
|
50
52
|
|
|
51
|
-
def
|
|
52
|
-
|
|
53
|
-
return (a + b + abs(a - b)) / 2
|
|
53
|
+
def _MinMax(op, arg0, *args):
|
|
54
|
+
from lca_algebraic.units import unit_registry as u
|
|
54
55
|
|
|
56
|
+
if not Settings.units_enabled:
|
|
57
|
+
return op(arg0, *args)
|
|
58
|
+
same_unit = all(x.units == arg0.units for x in args)
|
|
59
|
+
if not same_unit:
|
|
60
|
+
raise Exception("MinMax argments must have the same units")
|
|
61
|
+
return u.Quantity(op(arg0.magnitude, *[x.magnitude for x in args]), arg0.units)
|
|
55
62
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
return (
|
|
63
|
+
|
|
64
|
+
def Max(arg0, *args):
|
|
65
|
+
return _MinMax(sympy.Max, arg0, *args)
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def Min(arg0, *args):
|
|
69
|
+
return _MinMax(sympy.Min, arg0, *args)
|
|
59
70
|
|
|
60
71
|
|
|
61
72
|
def _actDesc(act: Activity):
|
|
@@ -111,6 +111,10 @@ def copy_activity_skip_keys() -> set:
|
|
|
111
111
|
return _backend.copy_activity_skip_keys()
|
|
112
112
|
|
|
113
113
|
|
|
114
|
+
def purge_activity_content(act) -> None:
|
|
115
|
+
_backend.purge_activity_content(act)
|
|
116
|
+
|
|
117
|
+
|
|
114
118
|
def bw2setup() -> None:
|
|
115
119
|
_backend.bw2setup()
|
|
116
120
|
|
|
@@ -146,5 +150,6 @@ __all__ = [
|
|
|
146
150
|
"process_node_default",
|
|
147
151
|
"production_edge_default",
|
|
148
152
|
"projects",
|
|
153
|
+
"purge_activity_content",
|
|
149
154
|
"sqlite3_lci_db",
|
|
150
155
|
]
|
|
@@ -91,6 +91,16 @@ class BW2Backend:
|
|
|
91
91
|
def copy_activity_skip_keys(self) -> set:
|
|
92
92
|
return {"database", "code"}
|
|
93
93
|
|
|
94
|
+
def purge_activity_content(self, act) -> None:
|
|
95
|
+
"""Remove an activity's outgoing exchanges and non-identity attributes.
|
|
96
|
+
|
|
97
|
+
The activity row, its code and the incoming links (exchanges of other
|
|
98
|
+
activities pointing to it) are preserved.
|
|
99
|
+
"""
|
|
100
|
+
act.exchanges().delete()
|
|
101
|
+
for key in [k for k in act._data if k not in {"database", "code"}]:
|
|
102
|
+
del act._data[key]
|
|
103
|
+
|
|
94
104
|
def bw2setup(self):
|
|
95
105
|
bw.bw2setup()
|
|
96
106
|
|
|
@@ -108,6 +108,16 @@ class BW25Backend:
|
|
|
108
108
|
def copy_activity_skip_keys(self) -> set:
|
|
109
109
|
return {"database", "code", "id"}
|
|
110
110
|
|
|
111
|
+
def purge_activity_content(self, act) -> None:
|
|
112
|
+
"""Remove an activity's outgoing exchanges and non-identity attributes.
|
|
113
|
+
|
|
114
|
+
The activity row, its code and the incoming links (exchanges of other
|
|
115
|
+
activities pointing to it) are preserved.
|
|
116
|
+
"""
|
|
117
|
+
act.exchanges().delete(allow_in_sourced_project=True)
|
|
118
|
+
for key in [k for k in act._data if k not in {"database", "code", "id"}]:
|
|
119
|
+
del act._data[key]
|
|
120
|
+
|
|
111
121
|
def bw2setup(self) -> None:
|
|
112
122
|
raise NotImplementedError("bw2setup is only supported with brightway2")
|
|
113
123
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import os
|
|
2
2
|
import time
|
|
3
|
+
from base64 import b32encode
|
|
3
4
|
from collections.abc import MutableMapping
|
|
4
5
|
from datetime import datetime
|
|
5
6
|
from os import path
|
|
@@ -19,6 +20,10 @@ EXPR_CACHE = "expr"
|
|
|
19
20
|
MAPPING_CACHE = "mapping"
|
|
20
21
|
|
|
21
22
|
|
|
23
|
+
def _filename_encode(s: str):
|
|
24
|
+
return b32encode(s.encode("utf-8")).decode("utf-8")
|
|
25
|
+
|
|
26
|
+
|
|
22
27
|
# Overide the behaviour for pickling sympy.UndefineFunction
|
|
23
28
|
class MyPickler(Pickler):
|
|
24
29
|
def reducer_override(self, obj):
|
|
@@ -44,8 +49,16 @@ def flush_caches():
|
|
|
44
49
|
cache.sync()
|
|
45
50
|
|
|
46
51
|
|
|
47
|
-
def get_dependant_dbs(db_name, skip_proxy=
|
|
48
|
-
"""Recursively get list of dependant db names, including the current one
|
|
52
|
+
def get_dependant_dbs(db_name, skip_proxy=None):
|
|
53
|
+
"""Recursively get list of dependant db names, including the current one
|
|
54
|
+
|
|
55
|
+
Proxy databases are skipped unless background factorization is enabled : with
|
|
56
|
+
``factorize_static_bg`` the developed expressions / LCIA of a database refer to
|
|
57
|
+
the acts of its ``<db>-proxy`` databases, so a change of those proxies must be
|
|
58
|
+
visible (see the staleness check in ``_CacheDict``).
|
|
59
|
+
"""
|
|
60
|
+
if skip_proxy is None:
|
|
61
|
+
skip_proxy = not Settings.factorize_static_bg
|
|
49
62
|
|
|
50
63
|
# Only work if database is up to date (processed)
|
|
51
64
|
if databases[db_name].get("dirty"):
|
|
@@ -89,7 +102,9 @@ class SyncDict(MutableMapping):
|
|
|
89
102
|
self.load()
|
|
90
103
|
|
|
91
104
|
def _filename(self):
|
|
92
|
-
return path.join(
|
|
105
|
+
return path.join(
|
|
106
|
+
projects.dir, f"lca_algebraic_cache-{_filename_encode(self.name)}-{_filename_encode(self.db_name)}.pickle"
|
|
107
|
+
)
|
|
93
108
|
|
|
94
109
|
# ---------- core MutableMapping ----------
|
|
95
110
|
def __getitem__(self, key):
|
|
@@ -3,6 +3,7 @@ from dataclasses import dataclass
|
|
|
3
3
|
from typing import Dict, List, Optional
|
|
4
4
|
|
|
5
5
|
from sympy import Basic, Expr, lambdify, parse_expr
|
|
6
|
+
from sympy.core import S
|
|
6
7
|
from sympy.printing.numpy import NumPyPrinter
|
|
7
8
|
|
|
8
9
|
from lca_algebraic.axis_dict import AxisDict
|
|
@@ -19,6 +20,32 @@ from lca_algebraic.settings import CSE, Settings
|
|
|
19
20
|
from lca_algebraic.sympy_utils import find_cses, find_symbols
|
|
20
21
|
|
|
21
22
|
|
|
23
|
+
class NumPyPrinterExt(NumPyPrinter):
|
|
24
|
+
def __init__(self, settings=None):
|
|
25
|
+
super().__init__(settings=settings)
|
|
26
|
+
|
|
27
|
+
def _helper_piecewise(self, *args):
|
|
28
|
+
from sympy.logic.boolalg import ITE, simplify_logic
|
|
29
|
+
|
|
30
|
+
def print_cond(cond):
|
|
31
|
+
"""Problem having an ITE in the cond."""
|
|
32
|
+
if cond.has(ITE):
|
|
33
|
+
return self._print(simplify_logic(cond))
|
|
34
|
+
else:
|
|
35
|
+
return self._print(cond)
|
|
36
|
+
|
|
37
|
+
return "{}({},{},{})".format(
|
|
38
|
+
self._module_format(self._module + ".where"),
|
|
39
|
+
print_cond(args[0].cond),
|
|
40
|
+
self._print(args[0].expr),
|
|
41
|
+
self._helper_piecewise(*args[1:]) if len(args) > 1 else self._print(S.NaN),
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
def _print_Piecewise(self, expr):
|
|
45
|
+
"Piecewise function printer"
|
|
46
|
+
return self._helper_piecewise(*expr.args)
|
|
47
|
+
|
|
48
|
+
|
|
22
49
|
@dataclass
|
|
23
50
|
class ValueContext:
|
|
24
51
|
"""Represents a result value, with all parameters values used in context"""
|
|
@@ -172,7 +199,7 @@ class LambdWrapper:
|
|
|
172
199
|
def _lambdify(expr: Basic, expanded_params):
|
|
173
200
|
"""Lambdify, handling manually the case of SymDict (for impacts by axis)"""
|
|
174
201
|
|
|
175
|
-
printer =
|
|
202
|
+
printer = NumPyPrinterExt(
|
|
176
203
|
{"fully_qualified_modules": False, "inline": True, "allow_unknown_functions": True, "user_functions": dict()}
|
|
177
204
|
)
|
|
178
205
|
|