def test_merge_with_weird_eq(): """numpy arrays don't compare equal like other python objects""" #SCALAR CASE x = T.constant(numpy.asarray(1), name='x') y = T.constant(numpy.asarray(1), name='y') g = Env([x, y], [x + y]) MergeOptimizer().optimize(g) assert len(g.nodes) == 1 node = list(g.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(numpy.ones(5), name='x') y = T.constant(numpy.ones(5), name='y') g = Env([x, y], [x + y]) MergeOptimizer().optimize(g) assert len(g.nodes) == 1 node = list(g.nodes)[0] assert len(node.inputs) == 2 assert node.inputs[0] is node.inputs[1]
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_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(): 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_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(MyValue("abc"))) consistent(g)
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_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_indestructible(): x, y, z = inputs() x.tag.indestructible = True x = copy(x) assert x.tag.indestructible # checking if indestructible survives the copy! e = add_in_place(x, y) g = Env([x,y,z], [e], False) inconsistent(g) g.replace_validate(e, add(x, y)) consistent(g)
def test_repair_destroy_path(): x, y, z = inputs() e1 = transpose_view(transpose_view(x)) e2 = transpose_view(transpose_view(e1)) e3 = add_in_place(e2, y) e4 = add_in_place(e1, z) g = Env([x,y,z], [e3, e4], False) inconsistent(g) g.replace(e2, transpose_view(x)) inconsistent(g)
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_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_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_aliased_inputs_replacement(): x, y, z = inputs() tv = transpose_view(x) tvv = transpose_view(tv) sx = sigmoid(x) e = add_in_place(x, tv) g = Env([x, y], [e], False) inconsistent(g) g.replace(tv, sx) consistent(g) g.replace(sx, tv) inconsistent(g) g.replace(tv, tvv) inconsistent(g) g.replace(tv, sx) 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_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_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_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_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_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_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_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_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_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_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_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_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_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_straightforward(self): x, y, z = inputs() e0 = dot(y, z) e = add(add(sigmoid(x), sigmoid(sigmoid(z))), dot(add(x, y), e0)) g = Env([x, y, z], [e]) g.extend(NodeFinder()) assert hasattr(g, 'get_nodes') for type, num in ((add, 3), (sigmoid, 3), (dot, 2)): if not len([x for x in g.get_nodes(type)]) == num: raise Exception("Expected: %i times %s" % (num, type)) new_e0 = add(y, z) assert e0.owner in g.get_nodes(dot) assert new_e0.owner not in g.get_nodes(add) g.replace(e0, new_e0) assert e0.owner not in g.get_nodes(dot) assert new_e0.owner in g.get_nodes(add) for type, num in ((add, 4), (sigmoid, 3), (dot, 1)): if not len([x for x in g.get_nodes(type)]) == num: raise Exception("Expected: %i times %s" % (num, type))
def test_misc(): x, y, z = inputs() e = transpose_view(transpose_view(transpose_view(transpose_view(x)))) g = Env([x,y,z], [e]) consistent(g) chk = g.checkpoint() PatternOptimizer((transpose_view, (transpose_view, 'x')), 'x').optimize(g) assert str(g) == "[x]" new_e = add(x,y) g.replace_validate(x, new_e) assert str(g) == "[Add(x, y)]" g.replace(new_e, dot(add_in_place(x,y), transpose_view(x))) assert str(g) == "[Dot(AddInPlace(x, y), TransposeView(x))]" inconsistent(g) g.revert(chk) consistent(g) assert str(g) == "[TransposeView(TransposeView(TransposeView(TransposeView(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)