def test_multi(self): x, y, z = inputs() e0 = op1(x, y) e = op3(op4(e0), e0) g = FunctionGraph([x, y, z], [e]) PatternOptimizer((op4, (op1, "x", "y")), (op3, "x", "y")).optimize(g) assert str(g) == "FunctionGraph(Op3(Op4(*1 -> Op1(x, y)), *1))"
def test_deep_merge(self): x, y, z = inputs() e = op1(op3(op2(x, y), z), op4(op3(op2(x, y), z))) g = FunctionGraph([x, y, z], [e], clone=False) MergeOptimizer().optimize(g) out_var = g.outputs[0] var_1, var_2 = out_var.owner.inputs assert var_2.owner.inputs[0] is var_1
def test_allow_multiple_clients(self): x, y, z = inputs() e0 = op1(x, y) # `e0` has multiple clients (i.e. the `op4` and `op3` nodes) e = op3(op4(e0), e0) g = FunctionGraph([x, y, z], [e]) PatternOptimizer((op4, (op1, "x", "y")), (op3, "x", "y")).optimize(g) assert str(g) == "FunctionGraph(Op3(Op4(*1 -> Op1(x, y)), *1))"
def test_constraints(self): x, y, z = inputs() e = op4(op1(op2(x, y)), op1(op1(x, y))) g = FunctionGraph([x, y, z], [e]) def constraint(r): # Only replacing if the input is an instance of Op2 return r.owner.op == op2 PatternOptimizer((op1, { "pattern": "1", "constraint": constraint }), (op3, "1")).optimize(g) assert str(g) == "FunctionGraph(Op4(Op3(Op2(x, y)), Op1(Op1(x, y))))"
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_multiple_merges(self): x, y, z = inputs() e1 = op1(x, y) e2 = op2(op3(x), y, z) e = op1(e1, op4(e2, e1), op1(e2)) g = FunctionGraph([x, y, z], [e]) MergeOptimizer().optimize(g) strg = str(g) # note: graph.as_string can only produce the following two possibilities, but if # the implementation was to change there are 6 other acceptable answers. assert ( strg == "FunctionGraph(Op1(*1 -> Op1(x, y), Op4(*2 -> Op2(Op3(x), y, z), *1), Op1(*2)))" or strg == "FunctionGraph(Op1(*2 -> Op1(x, y), Op4(*1 -> Op2(Op3(x), y, z), *2), Op1(*1)))" )
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_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_straightforward_2(self): x, y, z = inputs() e = op1(op2(x), op3(y), op4(z)) g = FunctionGraph([x, y, z], [e]) OpSubOptimizer(op3, op4).optimize(g) assert str(g) == "FunctionGraph(Op1(Op2(x), Op4(y), Op4(z)))"
def test_deep_merge(self): x, y, z = inputs() e = op1(op3(op2(x, y), z), op4(op3(op2(x, y), z))) g = FunctionGraph([x, y, z], [e]) MergeOptimizer().optimize(g) assert str(g) == "FunctionGraph(Op1(*1 -> Op3(Op2(x, y), z), Op4(*1)))"