Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 24 additions & 2 deletions python/sdist/amici/import_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -531,6 +531,11 @@
# y >= x => not(x < y) => not(x - y < 0) => not r < 0
return sp.Heaviside(root)

# rewrite n-ary XOR to OR to be handled below:
trigger = trigger.replace(sp.Xor, _xor_to_or)

# TODO: x == y

# or(x,y) = not(and(not(x),not(y))
if isinstance(trigger, sp.Or):
return sp.Integer(1) - sp.Mul(
Expand All @@ -540,8 +545,6 @@
]
)

# TODO: x XOR y = (A & ~B) | (~A & B)
# TODO: x == y
if isinstance(trigger, sp.And):
return sp.Mul(*[_parse_heaviside_trigger(arg) for arg in trigger.args])

Expand All @@ -551,6 +554,25 @@
)


def _xor_to_or(*args):
"""
Replace XOR by OR expression.

``xor(x, y, ...) = (x & ~y & ...) | (~x & y & ...) | ...``.

to be used in ``trigger = trigger.replace(sp.Xor, _xor_to_or)``.
"""
res = sp.false
for i in range(len(args)):
res = sp.Or(

Check warning on line 567 in python/sdist/amici/import_utils.py

View check run for this annotation

Codecov / codecov/patch

python/sdist/amici/import_utils.py#L565-L567

Added lines #L565 - L567 were not covered by tests
res,
sp.And(
*(arg if i == j else sp.Not(arg) for j, arg in enumerate(args))
),
)
return res.simplify()

Check warning on line 573 in python/sdist/amici/import_utils.py

View check run for this annotation

Codecov / codecov/patch

python/sdist/amici/import_utils.py#L573

Added line #L573 was not covered by tests


def grouper(
iterable: Iterable, n: int, fillvalue: Any = None
) -> Iterable[tuple[Any]]:
Expand Down
9 changes: 4 additions & 5 deletions python/sdist/amici/sbml_import.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
_default_simplify,
generate_flux_symbol,
_parse_piecewise_to_heaviside,
_xor_to_or,
)
from .logging import get_logger, log_execution_time, set_log_level
from .sbml_utils import SBMLException
Expand Down Expand Up @@ -2976,11 +2977,6 @@
f"Unsupported input: {var_or_math}, type: {type(var_or_math)}"
)

if expr.has(sp.Xor):
raise SBMLException(
"Xor is currently not supported as logical operation."
)

try:
_check_unsupported_functions_sbml(expr, expression_type=ele_name)
except SBMLException:
Expand Down Expand Up @@ -3218,6 +3214,9 @@
# y >= x or y > x
return root

# rewrite n-ary XOR to OR to be handled below:
trigger = trigger.replace(sp.Xor, _xor_to_or)

Check warning on line 3218 in python/sdist/amici/sbml_import.py

View check run for this annotation

Codecov / codecov/patch

python/sdist/amici/sbml_import.py#L3218

Added line #L3218 was not covered by tests

# or(x,y): any of {x,y} is > 0: sp.Max(x, y)
if isinstance(trigger, sp.Or):
return sp.Max(*[_parse_event_trigger(arg) for arg in trigger.args])
Expand Down
Loading