def test_patternsub_values_eq_approx(out_pattern, tracks): # PatternSub would fail when `values_eq_approx` and `get_nodes` were specified x = MyVariable("x") e = op1(x) fg = FunctionGraph([x], [e], clone=False) opt = EquilibriumOptimizer( [ PatternSub( (op1, "x"), out_pattern, tracks=[op1] if tracks else (), get_nodes=(lambda fgraph, node: [node]) if tracks else None, values_eq_approx=values_eq_approx_always_true, ) ], max_use_ratio=1, ) opt.optimize(fg) output = fg.outputs[0] if isinstance(out_pattern, tuple): assert output.owner.op == op2 assert output.tag.values_eq_approx is values_eq_approx_always_true elif out_pattern == "x": assert output is x assert output.tag.values_eq_approx is values_eq_approx_always_true else: # The replacement types do not match, so the substitution should've # failed assert output is e
def test_1(self): x, y, z = map(MyVariable, "xyz") e = op3(op4(x, y)) g = FunctionGraph([x, y, z], [e]) # print g opt = EquilibriumOptimizer( [ PatternSub((op1, "x", "y"), (op2, "x", "y")), PatternSub((op4, "x", "y"), (op1, "x", "y")), PatternSub((op3, (op2, "x", "y")), (op4, "x", "y")), ], max_use_ratio=10, ) opt.optimize(g) # print g assert str(g) == "FunctionGraph(Op2(x, y))"
def test_1(self): x, y, z = map(MyVariable, "xyz") # TODO FIXME: These `Op`s don't have matching/consistent `__prop__`s # and `__init__`s, so they can't be `etuplized` correctly e = op3(op4(x, y)) g = FunctionGraph([x, y, z], [e]) # print g opt = EquilibriumOptimizer( [ PatternSub((op1, "x", "y"), (op2, "x", "y")), PatternSub((op4, "x", "y"), (op1, "x", "y")), PatternSub((op3, (op2, "x", "y")), (op4, "x", "y")), ], max_use_ratio=10, ) opt.optimize(g) # print g assert str(g) == "FunctionGraph(Op2(x, y))"
def test_patternsub_invalid_dtype(out_pattern): # PatternSub would wrongly return output of different dtype as the original node x = MyVariable("x") e = op_cast_type2(x) fg = FunctionGraph([x], [e]) opt = EquilibriumOptimizer( [PatternSub( (op_cast_type2, "x"), out_pattern, )], max_use_ratio=1, ) opt.optimize(fg) assert fg.apply_nodes.pop().op == op_cast_type2
def test_low_use_ratio(self): x, y, z = map(MyVariable, "xyz") e = op3(op4(x, y)) g = FunctionGraph([x, y, z], [e]) # print 'before', g # display pesky warnings along with stdout # also silence logger for 'aesara.graph.opt' _logger = logging.getLogger("aesara.graph.opt") oldlevel = _logger.level _logger.setLevel(logging.CRITICAL) try: opt = EquilibriumOptimizer( [ PatternSub((op1, "x", "y"), (op2, "x", "y")), PatternSub((op4, "x", "y"), (op1, "x", "y")), PatternSub((op3, (op2, "x", "y")), (op4, "x", "y")), ], max_use_ratio=1.0 / len(g.apply_nodes), ) # each opt can only be applied once opt.optimize(g) finally: _logger.setLevel(oldlevel) # print 'after', g assert str(g) == "FunctionGraph(Op1(x, y))"
def test_patternsub_different_output_lengths(): # Test that PatternSub won't replace nodes with different numbers of outputs ps = PatternSub( (op1, "x"), ("x"), name="ps", ) opt = in2out(ps) x = MyVariable("x") e1, e2 = op_multiple_outputs(x) o = op1(e1) fgraph = FunctionGraph(inputs=[x], outputs=[o]) opt.optimize(fgraph) assert fgraph.outputs[0].owner.op == op1
def TopoPatternOptimizer(p1, p2, ign=True): return TopoOptimizer(PatternSub(p1, p2), ignore_newtrees=ign)
def PatternOptimizer(p1, p2, ign=False): return OpKeyOptimizer(PatternSub(p1, p2), ignore_newtrees=ign)
softplus = Elemwise(scalar_softplus, name="softplus") pprint.assign(softplus, printing.FunctionPrinter("softplus")) def _skip_mul_1(r): if r.owner and r.owner.op == mul: not_is_1 = [i for i in r.owner.inputs if not _is_1(i)] if len(not_is_1) == 1: return not_is_1[0] logsigm_to_softplus = PatternSub( (log, (sigmoid, "x")), (neg, (softplus, (neg, "x"))), allow_multiple_clients=True, values_eq_approx=values_eq_approx_remove_inf, skip_identities_fn=_skip_mul_1, ) def _is_1(expr): """ Returns ------- bool True iff expr is a constant close to 1. """ try: