This is a request is for a subclass of Function that can be
given a callable and a set of symbols such that whenever
it is finally to be evaluated via sympy.lambdify you get the
callable function of its 'symbols'. It may already be possible, but I can't find out how to do it. Of course, derivatives
and integrals of such functions will not be very well-defined, but for my purposes, just being able to use "lambdify" to evaluate them is enough.
Let me call the class "NonParametric" because there are many different callables that could be used, but they are all functions of the given Symbols at initiation...
To illustrate the request: suppose I want a Symbol for
B_t, standard Brownian motion at time t. I could approximate B_t numerically via linear interpolation of a random walk up to time t. So, I would like (something like this) to work:
-------------------------------------------------------------------
B_t = NonParametric(interpolator_of_random_walk, t)
b = sympy.lambdify(B_t^2-1)
pylab.plot(t, b(t))
---------------------------------------------------------------------
The example below achieves this in some sense, but it uses lambdify with a dictionary. I guess being able to have
NonParametric insert its dictionary automatically in the call to lambdify might work....
----------------------------------------------------------------------
import numpy as np
import sympy
from scipy.interpolate import interp1d
r = np.random.standard_normal
n = 50000
tt = np.linspace(0,1,n)
# Two independent (almost) Brownian motions on [0,1]
i1 = interp1d(tt, np.array(np.cumsum(r(n)))/np.sqrt(n), bounds_error=False, fill_value=0.)
i2 = interp1d(tt, np.array(np.cumsum(r(n))/np.sqrt(n)), bounds_error=False, fill_value=0.)
# Symbols for the Brownian motion
f1 = sympy.Function('f1')
f2 = sympy.Function('f2')
t = sympy.Symbol('t')
s = sympy.Symbol('s')
p1 = sympy.lambdify(t, f1(t), {'f1':i1})
# an Ornstein-Uhlenbeck process
OU2 = sympy.lambdify(t, f2(sympy.exp(-t))/sympy.exp(-t/2.), [{'f2':i2}, 'numpy'])
p3 = lambda _t: np.array(sympy.lambdify(t, [f1(t), f2(t)], {'f1':i1, 'f2':i2})(_t))
p4 = sympy.lambdify((s, t), f1(s)-f2(t), {'f1':i1, 'f2':i2})
import pylab
pylab.figure(num=1)
pylab.clf()
pylab.plot(tt, p1(tt))
pylab.figure(num=2)
pylab.clf()
pylab.plot(tt,p2(tt))
pylab.figure(num=3)
pylab.clf()
pylab.plot(p3(tt)[0],p3(tt)[1])
pylab.figure(num=4)
pylab.clf()
v = np.mgrid[0:1:200j,0:1:200j].T.reshape(200**2,2)
pylab.imshow(np.array([p4(s,t) for s, t in v]).reshape((200,200)))
pylab.show()
"""
What I would like to have work:
class NonParametric(object):
???
B1 = NonParametric(i1, t)
B2 = NonParametric(lambda _t: i2(-np.exp(_t))/np.exp(-_t/2.), t)
B3 = NonParametric(lambda s : np.array([i1(s), i2(s)]), t)
B4 = NonParametric(lambda s,t : i1(s)-i2(t), s, t)
b1 = sympy.lambdify(t, B1)
b2 = sympy.lambdify(t, B2)
b3 = sympy.lambdify(t, B3)
b4 = sympy.lambdify((s,t), B4)
pylab.plot(tt, b1(tt))
pylab.plot(tt, b2(tt))
pylab.plot(tt, b3(tt))
pylab.imshow(np.array([b4(s,t) for s, t in v]))
"""
--
Jonathan Taylor
Dept. of Statistics
Sequoia Hall, 137
390 Serra Mall
Stanford, CA 94305
Tel:
650.723.9230
Fax:
650.725.8977Web:
http://www-stat.stanford.edu/~jtaylo