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_long_destroyers_loop(): x, y, z = inputs() e = dot(dot(add_in_place(x,y), add_in_place(y,z)), add(z,x)) g = Env([x,y,z], [e]) consistent(g) OpSubOptimizer(add, add_in_place).optimize(g) consistent(g) assert str(g) != "[Dot(Dot(AddInPlace(x, y), AddInPlace(y, z)), AddInPlace(z, x))]" # we don't want to see that! e2 = dot(dot(add_in_place(x,y), add_in_place(y,z)), add_in_place(z,x)) try: g2 = Env(*graph.clone([x,y,z], [e2])) raise Exception("Shouldn't have reached this point.") except InconsistencyError: pass
def test_expand(self): x, y, z = inputs() e = op1(op1(op1(x))) g = Env([x, y, z], [e]) PatternOptimizer((op1, '1'), (op2, (op1, '1')), ign=True).optimize(g) assert str(g) == "[Op2(Op1(Op2(Op1(Op2(Op1(x))))))]"
def test_multiple(self): # it should replace all occurrences of the pattern x, y, z = inputs() e = op1(op2(x, y), op2(x, y), op2(y, z)) g = Env([x, y, z], [e]) PatternOptimizer((op2, '1', '2'), (op4, '1')).optimize(g) assert str(g) == "[Op1(Op4(x), Op4(x), Op4(y))]"
def test_both_assert_merge_2_reverse(self): # Test case "test_both_assert_merge_2" but in reverse order x1 = T.matrix('x1') x2 = T.matrix('x2') x3 = T.matrix('x3') e = T.dot(x1, T.opt.assert_op(x2, (x2 > x3).all())) +\ T.dot(T.opt.assert_op(x1, (x1 > x3).all()), x2) g = Env([x1, x2, x3], [e]) MergeOptimizer().optimize(g) strg = theano.printing.debugprint(g, file='str') strref = '''Elemwise{add,no_inplace} [@A] '' 7 |dot [@B] '' 6 | |Assert{msg='Theano Assert failed!'} [@C] '' 5 | | |x1 [@D] | | |All [@E] '' 3 | | |Elemwise{gt,no_inplace} [@F] '' 1 | | |x1 [@D] | | |x3 [@G] | |Assert{msg='Theano Assert failed!'} [@H] '' 4 | |x2 [@I] | |All [@J] '' 2 | |Elemwise{gt,no_inplace} [@K] '' 0 | |x2 [@I] | |x3 [@G] |dot [@B] '' 6 ''' print(strg) assert strg == strref, (strg, strref)
def test_nested_odd(self): x, y, z = inputs() e = op1(op1(op1(op1(op1(x))))) g = Env([x, y, z], [e]) PatternOptimizer((op1, (op1, '1')), '1').optimize(g) assert str(g) == "[Op1(x)]"
def test_destroyers_loop(): # AddInPlace(x, y) and AddInPlace(y, x) should not coexist x, y, z = inputs() e1 = add(x, y) e2 = add(y, x) g = Env([x,y,z], [e1, e2]) chk = g.checkpoint() consistent(g) g.replace_validate(e1, add_in_place(x, y)) consistent(g) try: g.replace_validate(e2, add_in_place(y, x)) raise Exception("Shouldn't have reached this point.") except InconsistencyError: pass consistent(g) g.revert(chk) g.replace_validate(e2, add_in_place(y, x)) consistent(g) try: g.replace_validate(e1, add_in_place(x, y)) raise Exception("Shouldn't have reached this point.") except InconsistencyError: pass consistent(g)
def test_merge_outputs(self): x, y, z = inputs() e1 = op3(op2(x, y)) e2 = op3(op2(x, y)) g = Env([x, y, z], [e1, e2]) MergeOptimizer().optimize(g) assert str(g) == "[*1 -> Op3(Op2(x, y)), *1]"
def test_nested_out_pattern(self): x, y, z = inputs() e = op1(x, y) g = Env([x, y, z], [e]) PatternOptimizer((op1, '1', '2'), (op4, (op1, '1'), (op2, '2'), (op3, '1', '2'))).optimize(g) assert str(g) == "[Op4(Op1(x), Op2(y), Op3(x, y))]"
def test_multi(self): x, y, z = inputs() e0 = op1(x, y) e = op3(op4(e0), e0) g = Env([x, y, z], [e]) PatternOptimizer((op4, (op1, 'x', 'y')), (op3, 'x', 'y')).optimize(g) assert str(g) == "[Op3(Op4(*1 -> Op1(x, y)), *1)]"
def test_replace_subgraph(self): # replacing inside the graph x, y, z = inputs() e = op1(op2(x, y), z) g = Env([x, y, z], [e]) PatternOptimizer((op2, '1', '2'), (op1, '2', '1')).optimize(g) assert str(g) == "[Op1(Op1(y, x), z)]"
def test_match_same(self): x, y, z = inputs() e = op1(x, x) g = Env([x, y, z], [e]) PatternOptimizer((op1, 'x', 'y'), (op3, 'x', 'y')).optimize(g) assert str(g) == "[Op3(x, x)]"
def test_unification_2(self): x, y, z = inputs() e = op1(op2(x, y), z) # the arguments to op2 are different g = Env([x, y, z], [e]) PatternOptimizer((op1, (op2, '1', '1'), '2'), # they are the same in the pattern (op4, '2', '1')).optimize(g) # The replacement should NOT occur assert str(g) == "[Op1(Op2(x, y), z)]"
def test_unification_1(self): x, y, z = inputs() e = op1(op2(x, x), z) # the arguments to op2 are the same g = Env([x, y, z], [e]) PatternOptimizer((op1, (op2, '1', '1'), '2'), # they are the same in the pattern (op4, '2', '1')).optimize(g) # So the replacement should occur assert str(g) == "[Op4(z, x)]"
def test_value_repl_2(): x, y, z = inputs() sy = sigmoid(y) e = add_in_place(x, sy) g = Env([x,y], [e], False) consistent(g) g.replace(sy, transpose_view(MyConstant("abc"))) consistent(g)
def test_usage_loop_through_views(): x, y, z = inputs() aip = add_in_place(x, y) e = dot(aip, transpose_view(x)) g = Env([x,y,z], [e], False) inconsistent(g) g.replace_validate(aip, add(x, z)) consistent(g)
def test_multi_destroyers(): x, y, z = inputs() e = add(add_in_place(x, y), add_in_place(x, y)) try: g = Env([x,y,z], [e]) raise Exception("Shouldn't have reached this point.") except InconsistencyError, e: pass
def test_misc_2(): x, y, z = inputs() tv = transpose_view(x) e = add_in_place(x, tv) g = Env([x,y], [e], False) inconsistent(g) g.replace(tv, x) inconsistent(g)
def test_usage_loop_through_views_2(): x, y, z = inputs() e0 = transpose_view(transpose_view(sigmoid(x))) e = dot(add_in_place(x,y), transpose_view(e0)) g = Env([x,y,z], [e]) consistent(g) # because sigmoid can do the copy g.replace(e0, x) inconsistent(g) # we cut off the path to the sigmoid
def test_replace_output(self): # replacing the whole graph x, y, z = inputs() e = op1(op2(x, y), z) g = Env([x, y, z], [e]) PatternOptimizer((op1, (op2, '1', '2'), '3'), (op4, '3', '2')).optimize(g) assert str(g) == "[Op4(z, y)]"
def test_constant_unification(self): x = Constant(MyType(), 2, name='x') y = MyVariable('y') z = Constant(MyType(), 2, name='z') e = op1(op1(x, y), y) g = Env([y], [e]) PatternOptimizer((op1, z, '1'), (op2, '1', z)).optimize(g) assert str(g) == "[Op1(Op2(y, z), y)]"
def test_nested_even(self): # regardless of the order in which we optimize, this # should work x, y, z = inputs() e = op1(op1(op1(op1(x)))) g = Env([x, y, z], [e]) PatternOptimizer((op1, (op1, '1')), '1').optimize(g) assert str(g) == "[x]"
def test_indirect_2(): x, y, z = inputs() e0 = transpose_view(x) e = dot(sigmoid(add_in_place(x, y)), e0) g = Env([x,y,z], [e], False) inconsistent(g) new_e0 = add(e0, y) g.replace(e0, new_e0) consistent(g)
def test_multi_destroyers_through_views(): x, y, z = inputs() e = dot(add(transpose_view(z), y), add(z, x)) g = Env([x,y,z], [e]) consistent(g) fail = FailureWatch() OpSubOptimizer(add, add_in_place, fail).optimize(g) consistent(g) assert fail.failures == 1 # should have succeeded once and failed once
def test_eq(self): # replacing the whole graph x, y, z = inputs() e = op1(op_y(x, y), z) g = Env([x, y, z], [e]) PatternOptimizer((op1, (op_z, '1', '2'), '3'), (op4, '3', '2')).optimize(g) str_g = str(g) assert str_g == "[Op4(z, y)]"
def test_usage_loop_insert_views(): x, y, z = inputs() e = dot(add_in_place(x, add(y, z)), sigmoid(sigmoid(sigmoid(sigmoid(sigmoid(x)))))) g = Env([x,y,z], [e]) consistent(g) fail = FailureWatch() OpSubOptimizer(sigmoid, transpose_view, fail).optimize(g) consistent(g) assert fail.failures == 1 # it must keep one sigmoid in the long sigmoid chain
def test_indestructible_through_views(): x, y, z = inputs() x.tag.indestructible = True tv = transpose_view(x) e = add_in_place(tv, y) g = Env([x,y,z], [e], False) inconsistent(g) g.replace_validate(tv, sigmoid(x)) consistent(g)
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 = Env([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_ambiguous(self): # this test should always work with TopoOptimizer and the # ignore_newtrees flag set to False. Behavior with ignore_newtrees # = True or with other NavigatorOptimizers may differ. x, y, z = inputs() e = op1(op1(op1(op1(op1(x))))) g = Env([x, y, z], [e]) TopoPatternOptimizer((op1, (op1, '1')), (op1, '1'), ign=False).optimize(g) assert str(g) == "[Op1(x)]"
def test_no_recurse(self): # if the out pattern is an acceptable in pattern # and that the ignore_newtrees flag is True, # it should do the replacement and stop x, y, z = inputs() e = op1(op2(x, y), z) g = Env([x, y, z], [e]) PatternOptimizer((op2, '1', '2'), (op2, '2', '1'), ign=True).optimize(g) assert str(g) == "[Op1(Op2(y, x), z)]"