def test_DiffOperations(reset_NodeDict): x = Var('x') y = Var('y') fx = VSF('f', x) fy = VSF('f', y) gx = VSF('g', x) gy = VSF('g', y) gfx = VSF('g', fx) zero = Val(0) one = Val(1) assert (zero == Val(0)) assert (zero != one) assert (fx != gx) assert (unicode(Var('x')) == 'x') assert (unicode(fx) == 'f(x)') assert (unicode(gfx) == 'g(f(x))') assert (unicode(Mul(fx, gx)) == 'f(x)*g(x)') assert (unicode(Mul(fx, gy)) == 'f(x)*g(y)') assert (unicode(Mul(gfx, gy)) == 'g(f(x))*g(y)') z = '0.0' i = '1.0' assert (unicode(Mul( fx, gx).diff_no_simplify(x)) == u"f`(x)⨯%s⨯g(x)+f(x)⨯g`(x)⨯%s" % (i, i)) assert (unicode(Mul( fx, gy).diff_no_simplify(x)) == u"f`(x)⨯%s⨯g(y)+f(x)⨯g`(y)⨯%s" % (i, z)) assert (unicode(fx.diff_no_simplify(x)) == u"f`(x)⨯%s" % i) assert (unicode(gfx.diff_no_simplify(x)) == u"g`(f(x))⨯f`(x)⨯%s" % i) assert (unicode(gfx.diff_no_simplify(y)) == u"g`(f(x))⨯f`(x)⨯%s" % z) assert(unicode(Mul(gfx,gy).diff_no_simplify(x)) ==\ u'g`(f(x))⨯f`(x)⨯%s⨯g(y)+g(f(x))⨯g`(y)⨯%s'%(i,z)) assert(unicode(Mul(gfx,gy).diff_no_simplify(y)) ==\ u'g`(f(x))⨯f`(x)⨯%s⨯g(y)+g(f(x))⨯g`(y)⨯%s'%(z,i))
def test_ConvertToArray(): a = Val(1) assert a.val.shape == () b = Val([[2]]) assert b.val.shape == (1, 1) c = Val([1, 2, 1]) assert c.val.shape == (3, )
def test_ElementaryTypes(reset_NodeDict): val0 = Val(0) val2 = Val(2) val10 = Val(10) val = Mul(Val(2), Val(10)) assert (unicode(val) == '2*10') assert (unicode(val0) == '0') assert (unicode(val10) == '10')
def test_IdentifyZeroOrIdentityMatrix(reset_NodeDict): assert (np.all( np.identity(3, dtype=np.float32) == np.identity(3, dtype=np.float64))) zero = Val(np.zeros((3, 5))) assert (IsZero(zero)) zero = Val(np.zeros((3, 3))) i = Val(np.identity(3)) assert (IsZero(zero)) assert (not IsZero(i)) assert (IsIdentity(i)) assert (not IsIdentity(zero)) assert (not IsIdentity(Val(np.array([[1, 0, 0], [0, 1, 0]]))))
def test_DiffKnownFunctions(reset_NodeDict): x = Var('x') fx = VSF('sin', x) dfx = fx.diff(x) dfx.cache() #dfx is used in dgfx again. Forgetting to cache fx may casue subtle errors. assert (dfx.expression() == 'cos(x)') gfx = VSF('exp', Mul(Val(3), fx)) dgfx = gfx.diff(x) assert (dgfx.expression() == u'exp(3*sin(x))⨯3⨯cos(x)') #Caching top expressions only is enough gfx.cache() dgfx.cache() for v in [1.0, 2.0, 14.2, 5.1, 5.72341]: x.val = v assert (dfx.val == np.cos(v)) assert (gfx.val == np.exp(3 * np.sin(v))) #Allow slight difference for complex numpy expressions. np.testing.assert_allclose(dgfx.val, np.exp(3 * np.sin(v)) * 3 * np.cos(v), rtol=1e-10, atol=0) hfx = VSF('log', fx) dhfx = hfx.diff(x) assert (dhfx.expression() == u'1/(sin(x))⨯cos(x)') hx = VSF('log', Add(fx, VSF('exp', x))) dhx = hx.diff(x) assert (dhx.expression() == u'1/(sin(x)+exp(x))⨯{cos(x)+exp(x)}')
def test_concatenation(reset_NodeDict): vx = np.array([5, 1, 2]) vy = np.array([1, 3, 2]) x = Var('x', vx) y = Var('y', vy) xpy = Concat(x, y) dfdx = xpy.diff(x) ones = Val(np.ones(3)) zero = Val(np.zeros(3)) oz = Concat(ones, zero) assert_all(dfdx.val == oz.val) #It is a bit tricky; it is limitation of current implementation. assert oz is not dfdx dfdx.cache() ones = Val(np.ones(3)) zero = Val(np.zeros(3)) oz = Concat(ones, zero) assert oz is dfdx
def test_ParentsSettingOfCache(): x = Var('x') fx = VSF('sin', x) dfx = fx.diff(x) gfx = VSF('exp', Mul(Val(3), fx)) dgfx = gfx.diff(x) dgfx.cache() assert fx in x.parents and dfx in x.parents for expr in dgfx.children: assert dgfx in expr.parents
def test_Equality(reset_NodeDict): x = Var('x') y = Var('y') fx = VSF('f', x) #Each expressions are reused if cached. assert (x is not Var('x')) x.cache() assert (x is Var('x')) fx.cache() assert (fx is VSF('f', x)) assert (Var('x') == x) assert (Val(1) == Val(1)) #Values are simplified to scalar when possible: assert (Val(1) == Val(np.array([1]))) assert (Val(1) == Val(np.array([[1]])))
def _SimplePhrase(reset_NodeDict): W_left_init = Var('W_left', [0, 0, 0, 0]) W_right_init = Var('W_right', [0, 0, 0, 0]) bias_init = Var('bias', [1, 1]) rnn = RecursiveNN(W_left_init, W_right_init, bias_init) merge = rnn.combineTwoNodes the = Word('The') cat = Word('cat') assert (not hasattr(Val(11), 'expression')) assert (hasattr(the, 'expression')) assert (the.expression() == 'w2v(The)') assert (unicode(the) == 'The') the_cat = merge(the, cat) assert (unicode(the_cat) == '(The,cat)') assert ( the_cat.expression() == 'tanh(W_left*w2v(The)+W_right*w2v(cat)+bias)') assert (unicode(the_cat.diff_no_simplify(Var('W_left'))) == '') assert (the_cat.diff(Var('W_left')).expression() == 'tanh`(W_left*w2v(The)+W_right*w2v(cat)+bias)*w2v(The)') the_cat_is = merge(the_cat, Word('is')) assert (unicode(the_cat_is) == '((The,cat),is)') assert ( the_cat_is.expression() == 'tanh(W_left*tanh(W_left*w2v(The)+W_right*w2v(cat)+bias)+W_right*w2v(is)+bias)' ) expected='tanh`(W_left*tanh(W_left*w2v(The)+W_right*w2v(cat)+bias)+W_right*w2v(is)+bias)*'+ \ '(tanh(W_left*w2v(The)+W_right*w2v(cat)+bias)+W_left*tanh`(W_left*w2v(The)+W_right*w2v(cat)+bias)*w2v(The))' assert (the_cat_is.diff(Var('W_left')).expression() == expected) assert (unicode(merge(the_cat, merge(Word('is'), Word('cute')))) == '((The,cat),(is,cute))') the_cat_is_cute = merge(the_cat_is, Word('cute')) assert (unicode(the_cat_is_cute) == '(((The,cat),is),cute)') expected = 'tanh(W_left*tanh(W_left*tanh(W_left*w2v(The)+W_right*w2v(cat)+bias)+W_right*w2v(is)+bias)+W_right*w2v(cute)+bias)' assert (the_cat_is_cute.expression() == expected)
def Differentiation(expr, var): if not IsScalar(expr): raise ValueError( 'Differentiation on non-scalar value is not yet supported') return _Diff(Val(1), expr, Val(1), var)
def _Diff(expr_left, expr, expr_right, var): if not (IsScalar(expr_left) or IsVector(expr_left)): print expr_left.val, expr.val, expr_right.val, var raise ValueError( 'Left-side expression should be a scalar or a vector since we do not process tesnsor.' ) elif not (IsScalar(expr_left) or IsVector(expr_left)): print expr_left.val, expr.val, expr_right.val, var raise ValueError( 'Right-side expression should be a scalar or a vector since we do not process tesnsor.' ) if isinstance(expr, Val): v = np.zeros(expr.val.shape) zero = Val(v) return zero elif isinstance(expr, Var): v = np.ones(expr.val.shape) if (var.name != expr.name): v = np.zeros(expr.val.shape) val = Val(v) return CTimes(CTimes(Transpose(expr_left), val), Transpose(expr_right)).simplify() elif isinstance(expr, Dot): if not expr.x.isContain(var): return _Diff(_AccumulateSideExpression(expr_left, expr.x), expr.y, expr_right, var) elif not expr.y.isContain(var): return _Diff(expr_left, expr.x, _AccumulateSideExpression(expr.y, expr_right), var) else: #print 'x: ', expr.x,expr.x.isContain(var), 'y: ', expr.y,expr.y.isContain(var), 'var: ',var x_dy = _Diff(_AccumulateSideExpression(expr_left, expr.x), expr.y, expr_right, var) dx_y = _Diff(expr_left, expr.x, _AccumulateSideExpression(expr.y, expr_right), var) return Add(x_dy, dx_y).simplify() assert 0 elif isinstance(expr, Add): if not expr.x.isContain(var): return _Diff(expr_left, expr.y, expr_right, var) elif not expr.y.isContain(var): return _Diff(expr_left, expr.x, expr_right, var) else: #print 'x: ', expr.x,expr.x.isContain(var), 'y: ', expr.y,expr.y.isContain(var), 'var: ',var dx = _Diff(expr_left, expr.x, expr_right, var) dy = _Diff(expr_left, expr.y, expr_right, var) return Add(dx, dy).simplify() assert 0 elif isinstance(expr, Concat): if not expr.x.isContain(var): return _Diff(expr_left, expr.y, expr_right, var) elif not expr.y.isContain(var): return _Diff(expr_left, expr.x, expr_right, var) else: #print 'x: ', expr.x,expr.x.isContain(var), 'y: ', expr.y,expr.y.isContain(var), 'var: ',var dx = _Diff(expr_left, expr.x, expr_right, var) dy = _Diff(expr_left, expr.y, expr_right, var) return Concat(dx, dy).simplify() assert 0 elif isinstance(expr, Transpose): return Transpose(_Diff(expr_left, expr.var, expr_right, var)) elif isinstance(expr, VSF): df = VSF(expr.op_name + "`", expr.var) return _Diff(_AccumulateSideExpression(expr_left, Transpose(df)), expr.var, expr_right, var) elif isinstance(expr, Word) or isinstance(expr, Phrase): _Diff(expr_left, expr.vec, expr_right, var) raise ValueError('Differentiation of unknown expression')
def test_SimplifyZeroAndOne(reset_NodeDict): assert (IsIdentity(Val(1))) assert (Mul(Val(1), Val(1)).simplify() == Val(1)) assert (Mul(Mul(Val(1), Val(1)), Mul(Val(1), Mul(Val(1), Mul(Val(1), Val(1))))).simplify() == Val(1)) assert (Mul(Mul(Val(1), Val(1)), Mul(Val(1), Mul(Val(1), Mul(Val(1), Val(0))))).simplify() == Val(0)) x = Var('x') y = Var('y') fx = VSF('f', x) fy = VSF('f', y) gx = VSF('g', x) gy = VSF('g', y) hx = VSF('h', x) gfx = VSF('g', fx) zero = Val(0) one = Val(1) assert (unicode(Mul(one, Add(x, y))) == '1*{x+y}') assert (Mul(one, Add(x, y)).expression() == '1*{x+y}') assert (unicode(Mul(one, Add(x, y)).simplify()) == 'x+y') assert (Add(fx, zero).simplify() == fx) assert (Mul(fx, zero).simplify() == zero) assert (Mul(fx, one).simplify() == fx) assert (Mul(zero, gy).simplify() == zero) assert (Mul(gx, Mul(fx, zero)).simplify() == zero) assert (Mul(gy, Mul(gx, Mul(fx, zero))).simplify() == zero) assert (unicode(fx.diff(x)) == 'f`(x)') assert (unicode(Mul(gfx, gy).diff(x)) == u'g`(f(x))⨯f`(x)⨯g(y)') assert (unicode(Mul(gfx, gy).diff(y)) == u'g(f(x))⨯g`(y)') assert (unicode(Mul(hx, Mul(gx, fx))) == u'h(x)*g(x)*f(x)') assert (unicode(Mul(hx, Mul( gx, fx)).diff(x)) == u'h`(x)⨯g(x)*f(x)+h(x)⨯{g`(x)⨯f(x)+g(x)⨯f`(x)}') assert (unicode(Mul(hx, Mul(gx, fx)).diff(y)) == '0.0')
def test_SimplifyZeroAndIdentityMatrix(reset_NodeDict): i = np.identity(5) z = np.zeros((5, 5)) assert (IsIdentity(Val(i))) assert (Mul(Val(i), Val(i)).simplify() == Val(i)) assert (Mul(Mul(Val(i), Val(i)), Mul(Val(i), Mul(Val(i), Mul(Val(i), Val(i))))).simplify() == Val(i)) assert (Mul(Mul(Val(i), Add(Add(Val(z), Val(z)), Val(i))), Mul(Val(i), Mul(Val(i), Mul(Val(i), Val(i))))).simplify() == Val(i)) assert (Mul(Mul(Val(i), Val(i)), Mul(Val(i), Mul(Val(i), Mul(Val(i), Val(z))))).simplify() == Val(z))
def test_ValImmunity(): v1 = Val(1) with pytest.raises(TypeError): v1.val = 2 assert v1.val == 1