Exemple #1
0
def test_complex():
    t = Var('t')
    s = Var('s')

    assert str(Diff(Pow((t * 5), 2), t)) != '0'

    # XXX: doesn't work without global
    global p
    p = Par('3.', 'p')
    f = Fun(QuantSpec('f', str(2.0 + s - 10 * (t ** 2) + Exp(p))), ['s', 't'])
    assert str(2 * f.eval(s=3, t=t)) == '2*((2.0+3)-10*Pow(t,2)+Exp(p))'
    assert str(Diff('-10*Pow(t,2)', 't')) == '-20*t'
    assert str(Diff(2 * f.eval(s=3, t=t), t)) == '2*-20*t'
    assert str(Diff(3 + t * f.eval(s=3,
                                   t=t),
                    t)) == '((2.0+3)-10*Pow(t,2)+Exp(p))+t*(-10*2*t)'
    assert str(Diff(3 + t * f(s, t),
                    t).eval(s=3,
                            t=1,
                            p=p)) == '((2.0+3)-10*Pow(1,2)+Exp(p))+1*(-10*2*1)'
    # FIXME: segmentation fault!
    # assert_almost_equal(Diff(3 + t * f(s, t), t).eval(s=3,
    #                                                   t=1,
    #                                                   p=p()),
    #                     -4.914463076812332)
    assert Diff(str(f(s, t)), 't') == Diff(f(s, t), t)
    q1 = Diff(f(s, t), t)
    q2 = Diff(str(f(s, t)), t)
    assert q1 == q2

    assert str(Diff(f(t, s), t)) == '1'
    assert str(Diff(2 * f(3, t * 5), t)) == '2*-100*t*5'
    assert str(Diff(2 * f(3, t * 5), t)) != str(0)
    assert f(s, t) != f(t, s)

    assert str(f(s, t).eval()) == '(2.0+s)-10*Pow(t,2)+Exp(3.0)'
    q = f(s, t)
    assert str(q.eval()) == '(2.0+s)-10*Pow(t,2)+Exp(3.0)'

    assert str(Diff('g(s)', s)) == 'g_0(s)'
    assert str(Diff('g(s)', s).eval()) == 'g_0(s)'
    # XXX: doesn't work without global
    global dg_dt
    dg_dt = Fun(QuantSpec('g_0', '2-Sin(t/2)'), ['t'])
    assert str(Diff('g(t)', t).eval()) == '2-Sin(t/2)'
    assert str(Diff('g(s)', s)) == 'g_0(s)'
    assert str(Diff('g(s)', s).eval()) == '2-Sin(s/2)'

    g = Fun('', [t], 'g')  # declare empty function
    assert str(g(t)) == 'g(t)'
    assert str(Diff(g(s), s).eval()) == '2-Sin(s/2)'

    assert eval(str(Diff('pow(1,2)*t', 't'))) == 1
    assert eval(str(Diff(Pow(1, 2) * t, t))) == 1
    assert str(Diff(Sin(Pow(t, 1)), t)) == 'Cos(t)'

    q = QuantSpec('q', '-0+3+pow(g(x)*h(y,x),1)*1')
    assert str(Diff(q, 'x')) == '(g_0(x)*h(y,x)+g(x)*h_1(y,x))'
Exemple #2
0
def test_symbolic():
    assert doneg('-x-y') == 'x+y'
    assert doneg('(-x-y)') == '(x+y)'
    assert doneg('-(-x-y)') == '(-x-y)'
    assert dosub('1', '-x-y') == '(1+x+y)'

    g2 = expr2fun('1-max([0., -a+b*x])', **{'a': 3, 'b': 1.5})
    assert g2._args == ['x']
    assert g2(1) == 1.0
    assert g2(10) == -11.0

    ds = {'a': 3, 'bbb': 1}
    f = expr2fun('1+ds["a"]')
    assert f._args == ['ds']
    assert f(ds) == 4
    f2 = expr2fun('1+ds["a"]')
    assert f2(**{'ds': ds}) == 4
    assert f2._args == ['ds']
    g = expr2fun('1+ds["bbb"]', ds=ds)
    assert g() == 2
    # g must be dynamic and not based on static eval of ds on initialization
    ds['bbb'] = 2
    assert g._args == []
    assert g() == 3

    m = args(pars=copy(ds))
    h = expr2fun('m.pars["a"]+c', m=m, c=1)
    assert h() == 4
    assert h._args == []
    h2 = expr2fun('1 + m.pars["a"]/2.', m=m)
    assert h2() == 2.5
    assert h2._args == []

    def func(x, y):
        return x * (y + 1)

    m.func = func
    i = expr2fun('1+func(x,y)+b', func=m.func, b=0.5)
    assert 1 + func(2, 3) + 0.5 == i(2, 3)

    j = expr2fun('i(x,func(2,y))*2', i=i, func=m.func)
    assert j(1, 0) == 9

    fnspec = {'f': (['x', 'y'], 'x+1+2*y-a')}
    # a is expected to be in scope like a FuncSpec parameter
    # so can't use the above method of providing explicit functions
    k = expr2fun('-f(c,d)+b', f=fnspec['f'], b=0.5, a=1)
    assert k(1, 2) == -4.5

    s = '1+a/(f(x,y)-3)+h(2)'
    t = s.replace('y', 'g(x,z)')
    u = t.replace('z', 'f(z)')
    r1, d1 = replaceCallsWithDummies(s, ['f', 'g', 'h'])
    r2, d2 = replaceCallsWithDummies(t, ['f', 'g', 'h'])
    r3, d3 = replaceCallsWithDummies(u, ['f', 'g', 'h'])

    assert r1 == '1+a/(__dummy1__-3)+__dummy2__'
    assert len(d1) == 2
    assert r2 == '1+a/(__dummy2__-3)+__dummy3__'
    assert len(d2) == 3
    assert r2 == '1+a/(__dummy2__-3)+__dummy3__'
    assert len(d3) == 4

    ps = 'abs((HB9_fs_Vq-HB9_fs_V)*(-((HB9_fs_Lk_g*(HB9_fs_V-HB9_fs_Lk_vrev))+(-HB9_fs_Iapp_Ibias)+((HB9_fs_Na_g*(1.0/(1.0+exp((HB9_fs_V-HB9_fs_Na_theta_m)/HB9_fs_Na_k_m)))*(1.0/(1.0+exp((HB9_fs_V-HB9_fs_Na_theta_m)/HB9_fs_Na_k_m)))*(1.0/(1.0+exp((HB9_fs_V-HB9_fs_Na_theta_m)/HB9_fs_Na_k_m)))*(1-HB9_fs_K_n))*(HB9_fs_V-HB9_fs_Na_vrev))+(HB9_fs_K_g*HB9_fs_K_n*HB9_fs_K_n*HB9_fs_K_n*HB9_fs_K_n*(HB9_fs_V-HB9_fs_K_vrev))+(HB9_fs_isyn_g*(HB9_fs_V-HB9_fs_isyn_vrev))+(HB9_fs_esyn_g*(HB9_fs_V-HB9_fs_esyn_vrev)))/HB9_fs_C)+(HB9_fs_Knq-HB9_fs_K_n)*(((1.0/(1.0+exp((HB9_fs_V-HB9_fs_K_theta_n)/HB9_fs_K_k_n)))-HB9_fs_K_n)/(HB9_fs_K_taun_bar/cosh((HB9_fs_V-HB9_fs_K_theta_n)/(2*HB9_fs_K_k_n)))))/(sqrt(HB9_fs_Vq*HB9_fs_Vq+HB9_fs_Knq*HB9_fs_Knq)+sqrt(pow((-((HB9_fs_Lk_g*(HB9_fs_V-HB9_fs_Lk_vrev))+(-HB9_fs_Iapp_Ibias)+((HB9_fs_Na_g*(1.0/(1.0+exp((HB9_fs_V-HB9_fs_Na_theta_m)/HB9_fs_Na_k_m)))*(1.0/(1.0+exp((HB9_fs_V-HB9_fs_Na_theta_m)/HB9_fs_Na_k_m)))*(1.0/(1.0+exp((HB9_fs_V-HB9_fs_Na_theta_m)/HB9_fs_Na_k_m)))*(1-HB9_fs_K_n))*(HB9_fs_V-HB9_fs_Na_vrev))+(HB9_fs_K_g*HB9_fs_K_n*HB9_fs_K_n*HB9_fs_K_n*HB9_fs_K_n*(HB9_fs_V-HB9_fs_K_vrev))+(HB9_fs_isyn_g*(HB9_fs_V-HB9_fs_isyn_vrev))+(HB9_fs_esyn_g*(HB9_fs_V-HB9_fs_esyn_vrev)))/HB9_fs_C),2)+pow((((1.0/(1.0+exp((HB9_fs_V-HB9_fs_K_theta_n)/HB9_fs_K_k_n)))-HB9_fs_K_n)/(HB9_fs_K_taun_bar/cosh((HB9_fs_V-HB9_fs_K_theta_n)/(2*HB9_fs_K_k_n)))),2)))'
    parnames = [
        'HB9_fs_Vq', 'HB9_fs_Lk_g', 'HB9_fs_Lk_vrev', 'HB9_fs_Iapp_Ibias',
        'HB9_fs_Na_g', 'HB9_fs_Na_theta_m', 'HB9_fs_Na_k_m', 'HB9_fs_Na_vrev',
        'HB9_fs_K_g', 'HB9_fs_K_vrev', 'HB9_fs_isyn_g', 'HB9_fs_isyn_vrev',
        'HB9_fs_esyn_g', 'HB9_fs_esyn_vrev', 'HB9_fs_C', 'HB9_fs_Knq',
        'HB9_fs_K_theta_n', 'HB9_fs_K_k_n', 'HB9_fs_K_taun_bar'
    ]
    varnames = ['HB9_fs_V', 'HB9_fs_K_n']
    ps2 = convertPowers(ps, 'pow')
    for n in parnames + varnames:
        v = rand(1)[0] + 1e-5
        ps2 = ps2.replace(n, str(v))
        ps = ps.replace(n, str(v))
    eps = eval(ps)
    eps2 = eval(ps2)
    assert eps == eps2

    a = Par('3.5', 'a')
    qa = Var(['a*3', 'b'], 'array_test')
    assert str(qa.eval(a=1)) == '[3,b]'
    # explicit exporting 'a' to globals to make this work as expected
    globals()['a'] = a
    assert str(qa.eval()) == '[10.5,b]'

    testq = QuantSpec('d', 'a')
    testq.simplify()
    assert testq() == 'a'
    assert str(testq.eval(a=3)) == '3'
    q = QuantSpec('q', 'zeta(yrel(y,initcond(y)),z)-1')
    print(q.eval({}))
    assert 'initcond' in str(q.eval({}))
    q2 = QuantSpec('q', 'Exp(-spikeTable+b)/k')
    assert 'spikeTable' in q2.freeSymbols

    #    x = Var('x')
    #    print x.isDefined()
    #    xs = QuantSpec('x', '1-rel - 2*x + cos(z) + 2e10', 'RHSfuncSpec')
    #    x.bindSpec(xs)
    #    print x.isDefined(),"\n"

    x = Var(QuantSpec('x', '1-rel - 2*x + cos(z) + 2e10', 'RHSfuncSpec'))
    p = Par('p')
    az = Var(QuantSpec('z', 'myfunc(0,z)+abs(x+1)', 'RHSfuncSpec'))
    w = Var('x-1/w[i]', 'w[i,0,1]', specType='RHSfuncSpec')

    myLeaf1.compatibleContainers = (myNode, )
    myLeaf2.compatibleContainers = (myNode, )
    myNode.compatibleSubcomponents = (myLeaf1, myLeaf2)

    c = myLeaf1('leaf1')

    assert c.isDefined() == False
    c.add(x)
    print(c.freeSymbols, c.isDefined())
    c.add(az)
    print(c.freeSymbols, c.isDefined())
    c.add(w)
    print(c.freeSymbols, c.isDefined())

    c.compileFuncSpec()
    print(c.funcSpecDict)

    empty_fn = Fun('1+exp(1)', [], 'dumb_fn')
    print(empty_fn())

    q = Par('qpar')
    y = Var(QuantSpec('rel', 'v+p'), domain=[0, 1])
    g = Fun(QuantSpec('qfunc', '-1.e-05+sin(qpar)*(10.e-5-xtol)'), ['xtol'])
    d = myLeaf2('leaf2')
    ##    d.add(y)
    q_dummy = Var(QuantSpec('q_notpar', '-2+sin(30)'))
    g_dummy = Fun(QuantSpec('qfunc_dummy', 'sin(q_notpar)*(10.e-5-xtol)'),
                  ['xtol'])
    d.add([q_dummy, g_dummy])  # will delete these later
    d.add([q, g])

    d2 = myLeaf2('leaf3')
    d2.add([q, g])

    v = Var(QuantSpec('v', 'v * myfunc(rel,v) - sin(p)*t', 'RHSfuncSpec'))
    # p is a global parameter so this is ok in v
    f = Fun(QuantSpec('myfunc', '2.0+s-t+exp(p)'), ['s', 't'])
    # t is just a local argument here, so it won't clash with its
    # occurrence in v (which we'll see is declared as a global
    # when we call flattenSpec()).
    ipar = Par('ipar')
    z = Var('z[i]+v/(i*ipar)', 'z[i,0,5]', specType='RHSfuncSpec')
    a = myNode('sys1')

    a.add([f, p, y])
    print(a.isDefined(True))
    a.add(c)
    print(a.freeSymbols, a.isDefined(), a.isComplete())
    a.add(d)
    print(a.freeSymbols, a.isDefined(), a.isComplete())
    a.add(d2)
    print(a.freeSymbols, a.isDefined(), a.isComplete())
    a.add(v)
    print("Added v")
    print(a.freeSymbols, a.isDefined(), a.isComplete())
    print("Removed v")
    a.remove(v)
    print(a.freeSymbols, a.isDefined(), a.isComplete())
    a.add([z, ipar])
    print(a.freeSymbols, a.isDefined(), a.isComplete())
    print("\na._registry -->  ")
    print(a._registry)
    print("Re-added v")
    a.add(v)
    print(a.freeSymbols, a.isDefined(), a.isComplete())
    print("\nv in a -->", v in a)

    print("\n")
    with pytest.raises(TypeError):
        a.compileFuncSpec()
    a.remove(['leaf2.qfunc_dummy', 'leaf2.q_notpar'])

    print("---------  sys1: funcSpecDict ---------------------")
    a.compileFuncSpec()
    info(a.funcSpecDict)

    print("\n\n-------------  Flatten spec with unravelling\n")
    print("\n\ninfo(a.flattenSpec()) --> \n")
    info(a.flattenSpec(globalRefs=['t']), "Model specification")
    print("\n\n-------------  Flatten spec with no unravelling\n")
    print("\n\ninfo(a.flattenSpec(False, globalRefs=['t'])) --> \n")
    info(a.flattenSpec(False, globalRefs=['t']), "Model specification")

    print("\n\nDemos for functions (results are strings):\n")
    h = f(p, -x)
    z = QuantSpec('zero', '0')
    print("h = f(p, -x) --> ", h)
    print("z = QuantSpec('zero','0') --> ", z)
    print("f(g(3)*1,h) --> ", f(g(3) * 1, h))
    print("f(g(p),h) --> ", f(g(p), h))
    print("f(g(p),0*h) --> ", f(g(p), 0 * h))
    print("f(g(x),h+z) --> ", f(g(x), h + z))
    # e is the math constant, but it doesn't evaluate to a float!
    print("f(g(x()),(e+h)/2) --> ", f(g(x()), (e + h) / 2))
    print("f(g(x()),-h) --> ", f(g(x()), -h))
    print("f(g(x()),.5-h+0) --> ", f(g(x()), .5 - h + 0))
    print("Sin(pi+q) --> ", Sin(pi + q))
    qsin = QuantSpec('qsin', 'zv-sin(beta)')
    assert str(qsin.eval()) == 'zv-sin(beta)'

    print("\n\nDemos for local scope evaluation and **:\n")
    print("q=Var('xv+1','qv')")
    print("x=Var('3','xv')")
    q = Var('xv+1', 'qv')
    x = Var('3', 'xv')
    globals()['x'] = x
    globals()['q'] = q
    sc1 = str(q.eval()) == '4'
    print("q.eval() == 4? ", sc1)
    assert sc1
    print("a=x/q")
    a = x / q
    sc2 = str(a) == 'xv/qv'
    print("a == xv/qv? ", sc2)
    assert sc2
    sc3 = str(a.eval()) == '0.75'
    print("a.eval() == 0.75? ", sc3)
    assert sc3
    sc4 = str(a.eval(xv=5)) == '5/qv'
    print("a.eval(xv=5) == 5/q? ", sc4)
    assert sc4
    sc5 = (str(a.eval(xv=5, qv=q())), '0.83333333333333337')
    assert_approx_equal(*sc5)
    print("assert_approx_equal(%s,%s)" % sc5)
    sc6 = (str(a.eval({'xv': 10, 'qv': q()})), '0.90909090909090906')
    print("assert_approx_equal(%s,%s)" % sc6)
    assert_approx_equal(*sc6)

    print("qs=QuantSpec('qsv','xsv+1')")
    print("xs=QuantSpec('xsv','3')")
    qs = QuantSpec('qsv', 'xsv+1')
    xs = QuantSpec('xsv', '3')
    globals()['qs'] = qs
    globals()['xs'] = xs
    qse = qs.eval()
    qt1 = str(qse) == '4'
    print("qs.eval() == 4? ", qt1)
    assert qt1
    assert qse.tonumeric() == 4
    print("asq = xs/qs")
    asq = xs / qs
    qt2 = str(asq) == '3/(xsv+1)'
    print("asq == 3/(xsv+1)? ", qt2)
    assert qt2
    qt3 = str(asq.eval()) == '0.75'
    print("as.eval() == 0.75? ", qt3)
    assert qt3
    ps = asq**xs
    print("ps = as**xs")
    qt4 = str(ps) == 'Pow(3/(xsv+1),3)'
    print("ps == Pow(3/(xsv+1),3)? ", qt4)
    assert qt4
    qt5 = str(ps.eval()) == str(0.75**3)
    print("ps.eval() == 0.421875? ", qt5)
    assert qt5

    print("sq=QuantSpec('sv','sin(xsv)')")
    print("s2q=QuantSpec('s2v','Sin(xv)')")
    sq = QuantSpec('sv', 'sin(xsv)')
    s2q = QuantSpec('s2v', 'Sin(xv)')
    print("sq.eval() --> ", sq.eval())
    print("s2q.eval() --> ", s2q.eval())
    assert sq.eval().tonumeric() == s2q.eval().tonumeric()
    assert sq[:] == ['sin', '(', 'xsv', ')']

    print("\n\nDemos for multiple quantity definitions:\n")
    mp = QuantSpec('p', 'a + 3*z[4*i-2]')
    m = Var(mp, 'z[i,2,5]', specType='RHSfuncSpec')
    v = Var('3*z[i-1]+z4-i', 'z[i,1,5]', specType='RHSfuncSpec')
    print("mp=QuantSpec('p','a + 3*z[4*i-2]')")
    print("m=Var(mp, 'z[i,2,5]', specType='RHSfuncSpec')")
    print("v=Var('3*z[i-1]+z4-i', 'z[i,1,5]', specType='RHSfuncSpec')")
    print("v[3] -->", v[3])
    assert str(v[3]) == 'z3'
    print("v.freeSymbols -->", v.freeSymbols)
    assert v.freeSymbols == ['z0']
    print("\nModelSpec a already contains 'z0', which was defined as part of")
    print("a multiple quantity definition, so check that attempting to add")
    print("v to a results in an error ...")
    with pytest.raises(AttributeError):
        a.add(v)
    print("\nTest of eval method, e.g. on a function f(s,t)...")
    print("f.eval(s='1', t='t_val') -->", f.eval(s='1', t='t_val'))
    print("f.eval(s=1, t='t_val', p=0.5) -->", f.eval(s=1, t='t_val', p=0.5))
    print("\nTesting convertPowers():")
    cp_tests = [
        "phi1dot^m3", "1+phi1dot^m3*s", "phi1dot**m3", "1+phi1dot**m3*s",
        "sin(x^3)**4", "(2/3)^2.5", "3^cos(x)-pi", "3^(cos(x)-pi)",
        "2^(sin(y**p))"
    ]
    for spec in cp_tests:
        print(spec, " --> ", convertPowers(spec))

    globals().pop('a')
    qc = QuantSpec('t', "a+coot+b/'coot'")
    assert str(qc.eval()) == 'a+coot+b/"coot"'
    coot = QuantSpec('coot', "1.05")
    globals()['coot'] = coot
    assert str(qc.eval()) == 'a+1.05+b/"coot"'

    print("\nTest of function calling with argument names that clash with")
    print("bound names inside the function.")
    x0 = Var('x0')
    x1 = Var('x1')
    x2 = Var('x2')
    F = Fun([x0 * x2, x0 * 5, x2**0.5], [x0, x1, x2], 'F')
    print("F=Fun([x0*x2,x0*5,x2**0.5], [x0,x1,x2], 'F')")
    print("F(3,2,Sin(x0))) = [3*Sin(x0),15,Pow(Sin(x0),0.5)] ...")
    print("  ... even though x0 is a bound name inside definition of F")
    assert str(F(3, 2, Sin(x0))) == '[3*Sin(x0),15,Pow(Sin(x0),0.5)]'
Exemple #3
0
def test_symbolic_vector():
    # XXX: doesn't work without global
    global q0, q1
    p0 = Var('p0')
    q0 = Var(p0 + 3, 'q0')
    q1 = Var(Diff(1 + Sin(Pow(p0, 3) + q0), p0), 'q1')

    qv = Var([q0, q1], 'q')
    assert str(qv()) == '[q0,q1]'
    assert str(qv.eval()) == '[(p0+3),(3*Pow(p0,2)*Cos(Pow(p0,3)+(p0+3)))]'

    v = Var('v')
    w = Var('w')
    f = Var([-3 * Pow((2 * v + 1), 3) + 2 * (w + v), -w / 2], 'f')

    df = Diff(f, [v, w])
    assert str(df) == '[[-3*6*Pow((2*v+1),2)+2,2],[0,-0.5]]'
    dfe = df.eval(v=3, w=10).tonumeric()
    assert_allclose(dfe, [[-880.0, 2.0], [0.0, -0.5]])
    assert isinstance(dfe, ndarray)
    assert isinstance(df.fromvector(), list)

    y0 = Var('y0')
    y1 = Var('y1')
    y2 = Var('y2')
    t = Var('t')

    ydot0 = Fun(-0.04 * y0 + 1e4 * y1 * y2, [y0, y1, y2], 'ydot0')
    ydot2 = Fun(3e7 * y1 * y1, [y0, y1, y2], 'ydot2')
    ydot1 = Fun(-ydot0(y0, y1, y2) - ydot2(y0, y1, y2), [y0, y1, y2], 'ydot1')

    F = Fun([ydot0(y0, y1, y2),
             ydot1(y0, y1, y2),
             ydot2(y0, y1, y2)], [y0, y1, y2], 'F')
    assert F.dim == 3
    DF = Diff(F, [y0, y1, y2])
    DF0, DF1, DF2 = DF.fromvector()
    assert_approx_equal(DF0.fromvector()[0].tonumeric(), -0.04)
    # str(Diff(F,[y0,y1,y2])) should be (to within numerical rounding errors):
    # '[[-0.04,10000*y2,10000*y1],[0.040000000000000001,(-10000*y2)-30000000*2*y1,-10000*y1],[0,30000000*2*y1,0]]')

    jac = Fun(Diff(F, [y0, y1, y2]), [t, y0, y1, y2], 'Jacobian')
    assert jac(t, 0.1, y0 + 1, 0.5).eval(y0=0) == jac(t, 0.1, 1 + y0,
                                                      0.5).eval(y0=0)
    assert jac(t, 0.1, y0, 0.5) == jac(t, 0.1, 0 + y0, 0.5)

    x = Var('x')
    y = Var('y')

    f1 = Fun([-3 * x**3 + 2 * (x + y), -y / 2], [x, y], 'f1')
    f2 = ['-3*x**3+2*(x+y)', '-y/2']
    f3 = [-3 * x**3. + 2 * (x + y), -y / 2.]
    assert str(f1) == 'f1'
    assert str(f2) == '[\'-3*x**3+2*(x+y)\', \'-y/2\']'
    assert str(
        f3
    ) == '[QuantSpec __result__ (ExpFuncSpec), QuantSpec __result__ (ExpFuncSpec)]'

    f4 = [-3 * Pow((2 * x + 1), 3) + 2 * (x + y), -y / 2]
    xx = QuantSpec('dummy', 'x')
    f5 = Var([-3 * Pow((2 * x + 1), 3) + 2 * (x + y), -y / 2], 'f5')

    assert Diff(f1, x) == Diff(f1, 'x')
    assert str(Diff(f1, x)) == '[-3*3*Pow(x,2)+2,0]'
    assert str(Diff(f3, x)) == '[-3*3*Pow(x,2)+2,0]'
    assert str(Diff(f3, xx)) == '[-3*3*Pow(x,2)+2,0]'
    assert str(Diff(f4, x)) == '[-3*6*Pow((2*x+1),2)+2,0]'
    assert str(Diff(f4, xx)) == '[-3*6*Pow((2*x+1),2)+2,0]'

    # Examples of Jacobian Diff(f, [x,y])...
    assert Diff(f1, [x, y]) == Diff(f1, ['x', 'y']) == Diff(f1(x, y), [x, y])
    assert str(Diff(f2, ['x', 'y'])) == '[[-3*3*Pow(x,2)+2,2],[0,-0.5]]'
    assert str(Diff(f3, ['x', 'y'])) == '[[-3*3*Pow(x,2)+2,2],[0,-0.5]]'
    assert str(Diff(f1, [xx, y])) == '[[-3*3*Pow(x,2)+2,2],[0,-0.5]]'
    assert str(Diff(f1, [xx, 'y'])) == '[[-3*3*Pow(x,2)+2,2],[0,-0.5]]'
    assert str(Diff(f2, [x, y])) == '[[-3*3*Pow(x,2)+2,2],[0,-0.5]]'
    assert str(Diff(f3, [x, y])) == '[[-3*3*Pow(x,2)+2,2],[0,-0.5]]'
    assert str(Diff(f4, [x, y])) == '[[-3*6*Pow((2*x+1),2)+2,2],[0,-0.5]]'
    df5 = Diff(f5, [x, y])
    assert str(df5) == '[[-3*6*Pow((2*x+1),2)+2,2],[0,-0.5]]'
    assert_allclose(
        df5.eval(x=3, y=10).tonumeric(), [[-880.0, 2.0], [0.0, -0.5]])
    # FIXME: segmentation fault!
    # assert_allclose(df5.eval(x=3,y=10).fromvector(0), [-880.0,2.0])
    assert str(df5.eval(x=3, y=10).fromvector(0)) == '[-880.0,2]'
    assert str(df5.fromvector(0)) == '[-3*6*Pow((2*x+1),2)+2,2]'
    assert isinstance(df5.fromvector(), list)
    a = df5.fromvector(0).eval(x=3, y=10).tonumeric()
    b = df5.eval(x=3, y=10).tonumeric()[0]
    assert a[0] == b[0] and a[1] == b[1]