def test_merge_with_weird_eq(): # numpy arrays don't compare equal like other python objects # SCALAR CASE x = T.constant(np.asarray(1), name="x") y = T.constant(np.asarray(1), name="y") g = Env([x, y], [x + y]) MergeOptimizer().optimize(g) assert len(g.apply_nodes) == 1 node = list(g.apply_nodes)[0] assert len(node.inputs) == 2 assert node.inputs[0] is node.inputs[1] # NONSCALAR CASE # This was created to test TensorConstantSignature x = T.constant(np.ones(5), name="x") y = T.constant(np.ones(5), name="y") g = Env([x, y], [x + y]) MergeOptimizer().optimize(g) assert len(g.apply_nodes) == 1 node = list(g.apply_nodes)[0] assert len(node.inputs) == 2 assert node.inputs[0] is node.inputs[1]
def test_merge_outputs(self): x, y, z = inputs() e1 = op3(op2(x, y)) e2 = op3(op2(x, y)) g = FunctionGraph([x, y, z], [e1, e2]) MergeOptimizer().optimize(g) assert str(g) == "FunctionGraph(*1 -> Op3(Op2(x, y)), *1)"
def est_both_assert_merge_2_reverse(self): # Test case "test_both_assert_merge_2" but in reverse order x1 = tt.matrix("x1") x2 = tt.matrix("x2") x3 = tt.matrix("x3") e = tt.dot(x1, tt.opt.assert_op(x2, (x2 > x3).all())) + tt.dot( tt.opt.assert_op(x1, (x1 > x3).all()), x2) g = FunctionGraph([x1, x2, x3], [e]) MergeOptimizer().optimize(g) strg = theano.printing.debugprint(g, file="str") strref = """Elemwise{add,no_inplace} [id A] '' 7 |dot [id B] '' 6 | |Assert{msg='Theano Assert failed!'} [id C] '' 5 | | |x1 [id D] | | |All [id E] '' 3 | | |Elemwise{gt,no_inplace} [id F] '' 1 | | |x1 [id D] | | |x3 [id G] | |Assert{msg='Theano Assert failed!'} [id H] '' 4 | |x2 [id I] | |All [id J] '' 2 | |Elemwise{gt,no_inplace} [id K] '' 0 | |x2 [id I] | |x3 [id G] |dot [id B] '' 6 """ print(strg) assert strg == strref, (strg, strref)
def est_both_assert_merge_2(self): # Merge two nodes, both have assert on different node x1 = T.matrix('x1') x2 = T.matrix('x2') x3 = T.matrix('x3') e = T.dot(T.opt.assert_op(x1, (x1 > x3).all()), x2) +\ T.dot(x1, T.opt.assert_op(x2, (x2 > x3).all())) g = FunctionGraph([x1, x2, x3], [e]) MergeOptimizer().optimize(g) strg = theano.printing.debugprint(g, file='str') strref = '''Elemwise{add,no_inplace} [id A] '' 7 |dot [id B] '' 6 | |Assert{msg='Theano Assert failed!'} [id C] '' 5 | | |x1 [id D] | | |All [id E] '' 3 | | |Elemwise{gt,no_inplace} [id F] '' 1 | | |x1 [id D] | | |x3 [id G] | |Assert{msg='Theano Assert failed!'} [id H] '' 4 | |x2 [id I] | |All [id J] '' 2 | |Elemwise{gt,no_inplace} [id K] '' 0 | |x2 [id I] | |x3 [id G] |dot [id B] '' 6 ''' # print(strg) assert strg == strref, (strg, strref)
def test_constant_merging(self): x = MyVariable('x') y = Constant(MyType(), 2, name='y') z = Constant(MyType(), 2, name='z') e = op1(op2(x, y), op2(x, y), op2(x, z)) g = FunctionGraph([x, y, z], [e]) MergeOptimizer().optimize(g) strg = str(g) assert strg == "[Op1(*1 -> Op2(x, y), *1, *1)]" \ or strg == "[Op1(*1 -> Op2(x, z), *1, *1)]"
def test_merge_noinput(self): # Check that identical Apply nodes without inputs will be merged x = NoInputOp(param=0)() y = NoInputOp(param=0)() z = NoInputOp(param=1)() fg = FunctionGraph([], [x, y, z]) MergeOptimizer().optimize(fg) no_input_ops = [n for n in fg.apply_nodes if isinstance(n.op, NoInputOp)] assert len(no_input_ops) == 2, fg.apply_nodes
def test_constant_merging(self): x = MyVariable("x") y = Constant(MyType(), 2, name="y") z = Constant(MyType(), 2, name="z") e = op1(op2(x, y), op2(x, y), op2(x, z)) g = FunctionGraph([x, y, z], [e]) MergeOptimizer().optimize(g) strg = str(g) assert (strg == "FunctionGraph(Op1(*1 -> Op2(x, y), *1, *1))" or strg == "FunctionGraph(Op1(*1 -> Op2(x, z), *1, *1))")
def test_identical_constant_args(self): x = MyVariable("x") y = Constant(MyType(), 2, name="y") z = Constant(MyType(), 2, name="z") with config.change_flags(compute_test_value="off"): e1 = op1(y, z) g = FunctionGraph([x, y, z], [e1]) MergeOptimizer().optimize(g) strg = str(g) assert strg == "FunctionGraph(Op1(y, y))" or strg == "FunctionGraph(Op1(z, z))"
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 == "[Op1(*1 -> Op1(x, y), Op4(*2 -> Op2(Op3(x), y, z), *1), Op1(*2))]" \ or strg == "[Op1(*2 -> Op1(x, y), Op4(*1 -> Op2(Op3(x), y, z), *2), Op1(*1))]"
def test_identical_constant_args(self): x = MyVariable("x") y = Constant(MyType(), 2, name="y") z = Constant(MyType(), 2, name="z") ctv_backup = config.compute_test_value config.compute_test_value = "off" try: e1 = op1(y, z) finally: config.compute_test_value = ctv_backup g = FunctionGraph([x, y, z], [e1]) MergeOptimizer().optimize(g) strg = str(g) assert strg == "FunctionGraph(Op1(y, y))" or strg == "FunctionGraph(Op1(z, z))"
def test_identical_constant_args(self): x = MyVariable('x') y = Constant(MyType(), 2, name='y') z = Constant(MyType(), 2, name='z') ctv_backup = config.compute_test_value config.compute_test_value = 'off' try: e1 = op1(y, z) finally: config.compute_test_value = ctv_backup g = FunctionGraph([x, y, z], [e1]) MergeOptimizer().optimize(g) strg = str(g) assert strg == '[Op1(y, y)]' or strg == '[Op1(z, z)]'
def est_both_assert_merge_1(self): # Merge two nodes, both have assert on the same node # with different conditions. x1 = T.matrix("x1") x2 = T.matrix("x2") x3 = T.matrix("x3") e = T.dot(T.opt.assert_op(x1, (x1 > x3).all()), x2) + T.dot( T.opt.assert_op(x1, (x1 > x2).all()), x2 ) g = FunctionGraph([x1, x2, x3], [e]) MergeOptimizer().optimize(g) strg = theano.printing.debugprint(g, file="str") strref1 = """Elemwise{add,no_inplace} [id A] '' 6 |dot [id B] '' 5 | |Assert{msg='Theano Assert failed!'} [id C] '' 4 | | |x1 [id D] | | |All [id E] '' 3 | | | |Elemwise{gt,no_inplace} [id F] '' 1 | | | |x1 [id D] | | | |x3 [id G] | | |All [id H] '' 2 | | |Elemwise{gt,no_inplace} [id I] '' 0 | | |x1 [id D] | | |x2 [id J] | |x2 [id J] |dot [id B] '' 5 """ strref2 = """Elemwise{add,no_inplace} [id A] '' 6 |dot [id B] '' 5 | |Assert{msg='Theano Assert failed!'} [id C] '' 4 | | |x1 [id D] | | |All [id E] '' 3 | | | |Elemwise{gt,no_inplace} [id F] '' 1 | | | |x1 [id D] | | | |x2 [id G] | | |All [id H] '' 2 | | |Elemwise{gt,no_inplace} [id I] '' 0 | | |x1 [id D] | | |x3 [id J] | |x2 [id G] |dot [id B] '' 5 """ # print(strg) assert strg == strref1 or strg == strref2, (strg, strref1, strref2)
def est_one_assert_merge(self): # Merge two nodes, one has assert, the other not. x1 = tt.matrix("x1") x2 = tt.matrix("x2") e = tt.dot(x1, x2) + tt.dot(tt.opt.assert_op(x1, (x1 > x2).all()), x2) g = FunctionGraph([x1, x2], [e]) MergeOptimizer().optimize(g) strg = theano.printing.debugprint(g, file="str") strref = """Elemwise{add,no_inplace} [id A] '' 4 |dot [id B] '' 3 | |Assert{msg='Theano Assert failed!'} [id C] '' 2 | | |x1 [id D] | | |All [id E] '' 1 | | |Elemwise{gt,no_inplace} [id F] '' 0 | | |x1 [id D] | | |x2 [id G] | |x2 [id G] |dot [id B] '' 3 """ assert strg == strref, (strg, strref)
def is_same_graph_with_merge(var1, var2, givens=None): """ Merge-based implementation of `theano.gof.graph.is_same_graph`. See help on `theano.gof.graph.is_same_graph` for additional documentation. """ from theano.gof.opt import MergeOptimizer if givens is None: givens = {} # Copy variables since the MergeOptimizer will modify them. copied = copy.deepcopy([var1, var2, givens]) vars = copied[0:2] givens = copied[2] # Create FunctionGraph. graph_inputs = list(inputs(vars)) # The clone isn't needed as we did a deepcopy and we cloning will # break the mapping in givens. fgraph = theano.gof.fg.FunctionGraph(graph_inputs, vars, clone=False) # Perform Variable substitution. for to_replace, replace_by in givens.items(): fgraph.replace(to_replace, replace_by) # Perform merge optimization. MergeOptimizer().optimize(fgraph) # When two variables perform the same computations, they will have the same # owner in the optimized graph. # We need to be careful with the special case where the owner is None, # which happens when the graph is made of a single Variable. # We also need to make sure we replace a Variable if it is present in # `givens`. vars_replaced = [givens.get(v, v) for v in vars] o1, o2 = [v.owner for v in vars_replaced] if o1 is None and o2 is None: # Comparing two single-Variable graphs: they are equal if they are # the same Variable. return vars_replaced[0] == vars_replaced[1] else: return o1 is o2
def test_both_assert_merge_identical(self): # Merge two nodes, both have assert on the same node # with the same conditions. x1 = tt.matrix("x1") x2 = tt.matrix("x2") e = tt.dot(tt.opt.assert_op(x1, (x1 > x2).all()), x2) + tt.dot( tt.opt.assert_op(x1, (x1 > x2).all()), x2) g = FunctionGraph([x1, x2], [e]) MergeOptimizer().optimize(g) strg = theano.printing.debugprint(g, file="str") strref = """Elemwise{add,no_inplace} [id A] '' 4 |dot [id B] '' 3 | |Assert{msg='Theano Assert failed!'} [id C] '' 2 | | |x1 [id D] | | |All [id E] '' 1 | | |Elemwise{gt,no_inplace} [id F] '' 0 | | |x1 [id D] | | |x2 [id G] | |x2 [id G] |dot [id B] '' 3 """ # print(strg) assert strg == strref, (strg, strref)
def test_no_merge(self): x, y, z = inputs() e = op1(op3(op2(x, y)), op3(op2(y, x))) g = FunctionGraph([x, y, z], [e]) MergeOptimizer().optimize(g) assert str(g) == "FunctionGraph(Op1(Op3(Op2(x, y)), Op3(Op2(y, x))))"
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)))"
def test_straightforward(self): x, y, z = inputs() e = op1(op2(x, y), op2(x, y), op2(x, z)) g = FunctionGraph([x, y, z], [e]) MergeOptimizer().optimize(g) assert str(g) == "FunctionGraph(Op1(*1 -> Op2(x, y), *1, Op2(x, z)))"