Skip to content

Conversation

@mmohrhard
Copy link
Contributor

Previously the test would fail with:

    def test_piecewise():
        grid = Grid(shape=(11,))
        u = Function(name='u', grid=grid, space_order=2)
        v = Function(name='u', grid=grid, space_order=2)
        eq_u = Eq(u, Piecewise((1, v < 10), (2, True)))
>       op = Operator(eq_u)
             ^^^^^^^^^^^^^^

tests/test_symbolics.py:1112:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
devito/operator/operator.py:173: in __new__
    op = cls._build(expressions, **kwargs)
         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
devito/operator/operator.py:206: in _build
    irs, byproduct = cls._lower(expressions, profiler=profiler, **kwargs)
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
devito/operator/operator.py:288: in _lower
    clusters = cls._lower_clusters(expressions, **kwargs)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
devito/tools/timing.py:76: in __call__
    retval = self.func(*args, **kwargs)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^
devito/operator/operator.py:397: in _lower_clusters
    clusters = cls._specialize_clusters(clusters, **kwargs)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
devito/tools/timing.py:76: in __call__
    retval = self.func(*args, **kwargs)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^
devito/core/cpu.py:178: in _specialize_clusters
    clusters = optimize_pows(clusters)
               ^^^^^^^^^^^^^^^^^^^^^^^
devito/ir/clusters/visitors.py:174: in __call__
    processed = [maybe_timed(c, *args) if self.cond(c) else c
                 ^^^^^^^^^^^^^^^^^^^^^
devito/ir/clusters/visitors.py:167: in <lambda>
    timed_pass(self.func, self.func.__name__)(*_args, **kwargs)
devito/tools/timing.py:76: in __call__
    retval = self.func(*args, **kwargs)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^
devito/passes/clusters/misc.py:423: in optimize_pows
    return cluster.rebuild(exprs=[pow_to_mul(e) for e in cluster.exprs])
                                  ^^^^^^^^^^^^^
devito/symbolics/manipulation.py:360: in pow_to_mul
    args = [pow_to_mul(i) for i in expr.args]
            ^^^^^^^^^^^^^
devito/symbolics/manipulation.py:360: in pow_to_mul
    args = [pow_to_mul(i) for i in expr.args]
            ^^^^^^^^^^^^^
E           TypeError: ExprCondPair.__new__() got an unexpected keyword argument 'evaluate'

devito/symbolics/manipulation.py:373: TypeError

Previously the test would fail with:

```
    def test_piecewise():
        grid = Grid(shape=(11,))
        u = Function(name='u', grid=grid, space_order=2)
        v = Function(name='u', grid=grid, space_order=2)
        eq_u = Eq(u, Piecewise((1, v < 10), (2, True)))
>       op = Operator(eq_u)
             ^^^^^^^^^^^^^^

tests/test_symbolics.py:1112:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
devito/operator/operator.py:173: in __new__
    op = cls._build(expressions, **kwargs)
         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
devito/operator/operator.py:206: in _build
    irs, byproduct = cls._lower(expressions, profiler=profiler, **kwargs)
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
devito/operator/operator.py:288: in _lower
    clusters = cls._lower_clusters(expressions, **kwargs)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
devito/tools/timing.py:76: in __call__
    retval = self.func(*args, **kwargs)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^
devito/operator/operator.py:397: in _lower_clusters
    clusters = cls._specialize_clusters(clusters, **kwargs)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
devito/tools/timing.py:76: in __call__
    retval = self.func(*args, **kwargs)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^
devito/core/cpu.py:178: in _specialize_clusters
    clusters = optimize_pows(clusters)
               ^^^^^^^^^^^^^^^^^^^^^^^
devito/ir/clusters/visitors.py:174: in __call__
    processed = [maybe_timed(c, *args) if self.cond(c) else c
                 ^^^^^^^^^^^^^^^^^^^^^
devito/ir/clusters/visitors.py:167: in <lambda>
    timed_pass(self.func, self.func.__name__)(*_args, **kwargs)
devito/tools/timing.py:76: in __call__
    retval = self.func(*args, **kwargs)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^
devito/passes/clusters/misc.py:423: in optimize_pows
    return cluster.rebuild(exprs=[pow_to_mul(e) for e in cluster.exprs])
                                  ^^^^^^^^^^^^^
devito/symbolics/manipulation.py:360: in pow_to_mul
    args = [pow_to_mul(i) for i in expr.args]
            ^^^^^^^^^^^^^
devito/symbolics/manipulation.py:360: in pow_to_mul
    args = [pow_to_mul(i) for i in expr.args]
            ^^^^^^^^^^^^^
E           TypeError: ExprCondPair.__new__() got an unexpected keyword argument 'evaluate'

devito/symbolics/manipulation.py:373: TypeError

```
else:
# Default. We should not end up here as all cases are handled
return expr
elif expr.func is ExprCondPair:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Likely doesn't need special casing but rather only add TypeError to the except line 373 and gaurd the expr. func

        # Some SymPy versions will evaluate the two-args case
        # `(negative integer, mul)` despite the `evaluate=False`. For example,
        # `Mul(-2, 1/a*a, evaluate=False)` gets evaluated to `-2/a**2`. By swapping
        # the args, the issue disappears...
        try:
            a0, a1 = args
            if a0.is_Number and a0 < 0 and not q_leaf(a1):
                args = [a1, a0]
        except (ValueError, TypeError):
            pass

        try:
            return expr.func(*args, evaluate=False)
        except TypeError:
            return expr.func(*args)

Which would make it robust to most non-standard case rather than just the ExprCondPair one

@mloubout mloubout added the API api (symbolics, types, ...) label Oct 20, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

API api (symbolics, types, ...)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants