def test_op_collector_order_determinism(): class TestOperator(sym.Operator): def __init__(self): sym.Operator.__init__(self, sym.DD_VOLUME, sym.DD_VOLUME) mapper_method = "map_test_operator" from grudge.symbolic.mappers import BoundOperatorCollector class TestBoundOperatorCollector(BoundOperatorCollector): def map_test_operator(self, expr): return self.map_operator(expr) v0 = sym.var("v0") ob0 = sym.OperatorBinding(TestOperator(), v0) v1 = sym.var("v1") ob1 = sym.OperatorBinding(TestOperator(), v1) # The output order isn't significant, but it should always be the same. assert list(TestBoundOperatorCollector(TestOperator)(ob0 + ob1)) == [ob0, ob1]
def map_product(self, expr): if len(expr.children) == 0: return expr from pymbolic.primitives import flattened_product, Product first = expr.children[0] if isinstance(first, op.Operator): prod = flattened_product(expr.children[1:]) if isinstance(prod, Product) and len(prod.children) > 1: from warnings import warn warn("Binding '%s' to more than one " "operand in a product is ambiguous - " "use the parenthesized form instead." % first) return sym.OperatorBinding(first, self.rec(prod)) else: return self.rec(first) * self.rec( flattened_product(expr.children[1:]))