def test_lambdify(): # Test lambdify with implemented functions # first test basic (sympy) lambdify f = sympy.cos assert_equal(lambdify(x, f(x))(0), 1) assert_equal(lambdify(x, 1 + f(x))(0), 2) assert_equal(lambdify((x, y), y + f(x))(0, 1), 2) # make an implemented function and test f = implemented_function("f", lambda x : x+100) assert_equal(lambdify(x, f(x))(0), 100) assert_equal(lambdify(x, 1 + f(x))(0), 101) assert_equal(lambdify((x, y), y + f(x))(0, 1), 101) # Error for functions with same name and different implementation f2 = implemented_function("f", lambda x : x+101) assert_raises(ValueError, lambdify, x, f(f2(x))) # our lambdify, like sympy's lambdify, can also handle tuples, # lists, dicts as expressions lam = lambdify(x, (f(x), x)) assert_equal(lam(3), (103, 3)) lam = lambdify(x, [f(x), x]) assert_equal(lam(3), [103, 3]) lam = lambdify(x, [f(x), (f(x), x)]) assert_equal(lam(3), [103, (103, 3)]) lam = lambdify(x, {f(x): x}) assert_equal(lam(3), {103: 3}) lam = lambdify(x, {f(x): x}) assert_equal(lam(3), {103: 3}) lam = lambdify(x, {x: f(x)}) assert_equal(lam(3), {3: 103})
def test_2d(): B1, B2 = [gen_BrownianMotion() for _ in range(2)] B1s = implemented_function("B1", B1) B2s = implemented_function("B2", B2) s, t = sympy.symbols(('s', 't')) e = B1s(s)+B2s(t) ee = lambdify((s,t), e) assert_almost_equal(ee(B1.x, B2.x), B1.y + B2.y)
def test_alias(): x = F.Term('x') f = implemented_function('f', lambda x: 2*x) g = implemented_function('g', lambda x: np.sqrt(x)) ff = F.Formula([f(x), g(x)**2]) n = F.make_recarray([2,4,5], 'x') assert_almost_equal(ff.design(n)['f(x)'], n['x']*2) assert_almost_equal(ff.design(n)['g(x)**2'], n['x'])
def natural_spline(t, knots=None, order=3, intercept=False): """ Return a Formula containing a natural spline Spline for a Term with specified `knots` and `order`. Parameters ---------- t : ``Term`` knots : None or sequence, optional Sequence of float. Default None (same as empty list) order : int, optional Order of the spline. Defaults to a cubic (==3) intercept : bool, optional If True, include a constant function in the natural spline. Default is False Returns ------- formula : Formula A Formula with (len(knots) + order) Terms (if intercept=False, otherwise includes one more Term), made up of the natural spline functions. Examples -------- >>> x = Term('x') >>> n = natural_spline(x, knots=[1,3,4], order=3) >>> xval = np.array([3,5,7.]).view(np.dtype([('x', np.float)])) >>> n.design(xval, return_float=True) array([[ 3., 9., 27., 8., 0., -0.], [ 5., 25., 125., 64., 8., 1.], [ 7., 49., 343., 216., 64., 27.]]) >>> d = n.design(xval) >>> print(d.dtype.descr) [('ns_1(x)', '<f8'), ('ns_2(x)', '<f8'), ('ns_3(x)', '<f8'), ('ns_4(x)', '<f8'), ('ns_5(x)', '<f8'), ('ns_6(x)', '<f8')] """ if knots is None: knots = {} fns = [] for i in range(order+1): n = 'ns_%d' % i def f(x, i=i): return x**i s = implemented_function(n, f) fns.append(s(t)) for j, k in enumerate(knots): n = 'ns_%d' % (j+i+1,) def f(x, k=k, order=order): return (x-k)**order * np.greater(x, k) s = implemented_function(n, f) fns.append(s(t)) if not intercept: fns.pop(0) ff = Formula(fns) return ff
def test_implemented_function_evalf(): from sympy.utilities.lambdify import implemented_function f = Function('f') f = implemented_function(f, lambda x: x + 1) assert str(f(x)) == "f(x)" assert str(f(2)) == "f(2)" assert f(2).evalf() == 3 assert f(x).evalf() == f(x) f = implemented_function(Function('sin'), lambda x: x + 1) assert f(2).evalf() != sin(2) del f._imp_ # XXX: due to caching _imp_ would influence all other tests
def test_jscode_inline_function(): x = symbols("x") g = implemented_function("g", Lambda(x, 2 * x)) assert jscode(g(x)) == "2*x" g = implemented_function("g", Lambda(x, 2 * x / Catalan)) assert jscode(g(x)) == "var Catalan = %s;\n2*x/Catalan" % Catalan.n() A = IndexedBase("A") i = Idx("i", symbols("n", integer=True)) g = implemented_function("g", Lambda(x, x * (1 + x) * (2 + x))) assert jscode(g(A[i]), assign_to=A[i]) == ( "for (var i=0; i<n; i++){\n" " A[i] = A[i]*(1 + A[i])*(2 + A[i]);\n" "}" )
def test_jscode_inline_function(): x = symbols('x') g = implemented_function('g', Lambda(x, 2*x)) assert jscode(g(x)) == "2*x" g = implemented_function('g', Lambda(x, 2*x/Catalan)) assert jscode(g(x)) == "var Catalan = %s;\n2*x/Catalan" % Catalan.n() A = IndexedBase('A') i = Idx('i', symbols('n', integer=True)) g = implemented_function('g', Lambda(x, x*(1 + x)*(2 + x))) assert jscode(g(A[i]), assign_to=A[i]) == ( "for (var i=0; i<n; i++){\n" " A[i] = (A[i] + 1)*(A[i] + 2)*A[i];\n" "}" )
def test_ccode_inline_function(): x = symbols('x') g = implemented_function('g', Lambda(x, 2*x)) assert ccode(g(x)) == "2*x" g = implemented_function('g', Lambda(x, 2*x/Catalan)) assert ccode(g(x)) == "double const Catalan = %s;\n2*x/Catalan" %Catalan.n() A = IndexedBase('A') i = Idx('i', symbols('n', integer=True)) g = implemented_function('g', Lambda(x, x*(1 + x)*(2 + x))) assert ccode(g(A[i]), assign_to=A[i]) == ( "for (int i=0; i<n; i++){\n" " A[i] = A[i]*(1 + A[i])*(2 + A[i]);\n" "}" )
def test_glsl_code_inline_function(): x = symbols('x') g = implemented_function('g', Lambda(x, 2*x)) assert glsl_code(g(x)) == "2*x" g = implemented_function('g', Lambda(x, 2*x/Catalan)) assert glsl_code(g(x)) == "float Catalan = 0.915965594;\n2*x/Catalan" A = IndexedBase('A') i = Idx('i', symbols('n', integer=True)) g = implemented_function('g', Lambda(x, x*(1 + x)*(2 + x))) assert glsl_code(g(A[i]), assign_to=A[i]) == ( "for (int i=0; i<n; i++){\n" " A[i] = (A[i] + 1)*(A[i] + 2)*A[i];\n" "}" )
def test_implemented_function(): # Here we check if the default returned functions are anonymous - in # the sense that we can have more than one function with the same name f = implemented_function('f', lambda x: 2*x) g = implemented_function('f', lambda x: np.sqrt(x)) l1 = lambdify(x, f(x)) l2 = lambdify(x, g(x)) assert_equal(str(f(x)), str(g(x))) assert_equal(l1(3), 6) assert_equal(l2(3), np.sqrt(3)) # check that we can pass in a sympy function as input func = sympy.Function('myfunc') assert_false(hasattr(func, '_imp_')) f = implemented_function(func, lambda x: 2*x) assert_true(hasattr(func, '_imp_'))
def binary_function(symfunc, expr, **kwargs): """Returns a sympy function with expr as binary implementation This is a convenience function that automates the steps needed to autowrap the SymPy expression and attaching it to a Function object with implemented_function(). Parameters ========== symfunc : sympy Function The function to bind the callable to. expr : sympy Expression The expression used to generate the function. kwargs : dict Any kwargs accepted by autowrap. Examples ======== >>> from sympy.abc import x, y >>> from sympy.utilities.autowrap import binary_function >>> expr = ((x - y)**(25)).expand() >>> f = binary_function('f', expr) >>> type(f) <class 'sympy.core.function.UndefinedFunction'> >>> 2*f(x, y) 2*f(x, y) >>> f(x, y).evalf(2, subs={x: 1, y: 2}) -1.0 """ binary = autowrap(expr, **kwargs) return implemented_function(symfunc, binary)
def test_jscode_Pow(): g = implemented_function('g', Lambda(x, 2*x)) assert jscode(x**3) == "Math.pow(x, 3)" assert jscode(x**(y**3)) == "Math.pow(x, Math.pow(y, 3))" assert jscode(1/(g(x)*3.5)**(x - y**x)/(x**2 + y)) == \ "Math.pow(3.5*2*x, -x + Math.pow(y, x))/(Math.pow(x, 2) + y)" assert jscode(x**-1.0) == '1/x'
def test_inline_function(): from sympy.tensor import IndexedBase, Idx from sympy import symbols n, m = symbols("n m", integer=True) A, x, y = map(IndexedBase, "Axy") i = Idx("i", m) j = Idx("j", n) p = FCodeGen() func = implemented_function("func", Lambda(n, n * (n + 1))) routine = Routine("test_inline", Eq(y[i], func(x[i]))) code = get_string(p.dump_f95, [routine]) expected = ( "subroutine test_inline(m, x, y)\n" "implicit none\n" "INTEGER*4, intent(in) :: m\n" "REAL*8, intent(in), dimension(1:m) :: x\n" "REAL*8, intent(out), dimension(1:m) :: y\n" "INTEGER*4 :: i\n" "do i = 1, m\n" " y(i) = (1 + x(i))*x(i)\n" "end do\n" "end subroutine\n" ) assert code == expected
def test_inline_function(): from sympy.tensor import IndexedBase, Idx from sympy import symbols n, m = symbols('n m', integer=True) A, x, y = map(IndexedBase, 'Axy') i = Idx('i', m) p = FCodeGen() func = implemented_function('func', Lambda(n, n*(n + 1))) routine = make_routine('test_inline', Eq(y[i], func(x[i]))) code = get_string(p.dump_f95, [routine]) expected = ( 'subroutine test_inline(m, x, y)\n' 'implicit none\n' 'INTEGER*4, intent(in) :: m\n' 'REAL*8, intent(in), dimension(1:m) :: x\n' 'REAL*8, intent(out), dimension(1:m) :: y\n' 'INTEGER*4 :: i\n' 'do i = 1, m\n' ' y(i) = %s*%s\n' 'end do\n' 'end subroutine\n' ) args = ('x(i)', '(x(i) + 1)') assert code == expected % args or\ code == expected % args[::-1]
def test_Pow(): assert mcode(x**3) == "x.^3" assert mcode(x**(y**3)) == "x.^(y.^3)" assert mcode(x**Rational(2, 3)) == 'x.^(2/3)' g = implemented_function('g', Lambda(x, 2*x)) assert mcode(1/(g(x)*3.5)**(x - y**x)/(x**2 + y)) == \ "(3.5*2*x).^(-x + y.^x)./(x.^2 + y)"
def test_lambdify_imps(): # Test lambdify with implemented functions # first test basic (sympy) lambdify f = sympy.cos assert lambdify(x, f(x))(0) == 1 assert lambdify(x, 1 + f(x))(0) == 2 assert lambdify((x, y), y + f(x))(0, 1) == 2 # make an implemented function and test f = implemented_function("f", lambda x: x + 100) assert lambdify(x, f(x))(0) == 100 assert lambdify(x, 1 + f(x))(0) == 101 assert lambdify((x, y), y + f(x))(0, 1) == 101 # Can also handle tuples, lists, dicts as expressions lam = lambdify(x, (f(x), x)) assert lam(3) == (103, 3) lam = lambdify(x, [f(x), x]) assert lam(3) == [103, 3] lam = lambdify(x, [f(x), (f(x), x)]) assert lam(3) == [103, (103, 3)] lam = lambdify(x, {f(x): x}) assert lam(3) == {103: 3} lam = lambdify(x, {f(x): x}) assert lam(3) == {103: 3} lam = lambdify(x, {x: f(x)}) assert lam(3) == {3: 103} # Check that imp preferred to other namespaces by default d = {'f': lambda x: x + 99} lam = lambdify(x, f(x), d) assert lam(3) == 103 # Unless flag passed lam = lambdify(x, f(x), d, use_imps=False) assert lam(3) == 102
def test_Pow(): assert rust_code(1/x) == "x.recip()" assert rust_code(x**-1) == rust_code(x**-1.0) == "x.recip()" assert rust_code(sqrt(x)) == "x.sqrt()" assert rust_code(x**S.Half) == rust_code(x**0.5) == "x.sqrt()" assert rust_code(1/sqrt(x)) == "x.sqrt().recip()" assert rust_code(x**-S.Half) == rust_code(x**-0.5) == "x.sqrt().recip()" assert rust_code(1/pi) == "PI.recip()" assert rust_code(pi**-1) == rust_code(pi**-1.0) == "PI.recip()" assert rust_code(pi**-0.5) == "PI.sqrt().recip()" assert rust_code(x**Rational(1, 3)) == "x.cbrt()" assert rust_code(2**x) == "x.exp2()" assert rust_code(exp(x)) == "x.exp()" assert rust_code(x**3) == "x.powi(3)" assert rust_code(x**(y**3)) == "x.powf(y.powi(3))" assert rust_code(x**Rational(2, 3)) == "x.powf(2_f64/3.0)" g = implemented_function('g', Lambda(x, 2*x)) assert rust_code(1/(g(x)*3.5)**(x - y**x)/(x**2 + y)) == \ "(3.5*2*x).powf(-x + y.powf(x))/(x.powi(2) + y)" _cond_cfunc = [(lambda base, exp: exp.is_integer, "dpowi", 1), (lambda base, exp: not exp.is_integer, "pow", 1)] assert rust_code(x**3, user_functions={'Pow': _cond_cfunc}) == 'x.dpowi(3)' assert rust_code(x**3.2, user_functions={'Pow': _cond_cfunc}) == 'x.pow(3.2)'
def interp(times, values, fill=0, name=None, **kw): """ Generic interpolation function of t given `times` and `values` Imterpolator such that: f(times[i]) = values[i] if t < times[0] or t > times[-1]: f(t) = fill See ``scipy.interpolate.interp1d`` for details of interpolation types and other keyword arguments. Default is 'kind' is linear, making this function, by default, have the same behavior as ``linear_interp``. Parameters ---------- times : array-like Increasing sequence of times values : array-like Values at the specified times fill : None or float, optional Value on the interval (-np.inf, times[0]). Default 0. If None, raises error outside bounds name : None or str, optional Name of symbolic expression to use. If None, a default is used. \*\*kw : keyword args, optional passed to ``interp1d`` Returns ------- f : sympy expression A Function of t. Examples -------- >>> s = interp([0,4,5.],[2.,4,6]) >>> tval = np.array([-0.1,0.1,3.9,4.1,5.1]) >>> res = lambdify_t(s)(tval) 0 outside bounds by default >>> np.allclose(res, [0, 2.05, 3.95, 4.2, 0]) True """ if fill is not None: if kw.get('bounds_error') is True: raise ValueError('fill conflicts with bounds error') fv = kw.get('fill_value') if not (fv is None or fv is fill or fv == fill): # allow for fill=np.nan raise ValueError('fill conflicts with fill_value') kw['bounds_error'] = False kw['fill_value'] = fill interpolator = interp1d(times, values, **kw) # make a new name if none provided if name is None: name = 'interp%d' % interp.counter interp.counter += 1 s = implemented_function(name, interpolator) return s(T)
def ufuncify(args, expr, **kwargs): """ Generates a binary ufunc-like lambda function for numpy arrays ``args`` Either a Symbol or a tuple of symbols. Specifies the argument sequence for the ufunc-like function. ``expr`` A SymPy expression that defines the element wise operation ``kwargs`` Optional keyword arguments are forwarded to autowrap(). The returned function can only act on one array at a time, as only the first argument accept arrays as input. .. Note:: a *proper* numpy ufunc is required to support broadcasting, type casting and more. The function returned here, may not qualify for numpy's definition of a ufunc. That why we use the term ufunc-like. References ========== [1] http://docs.scipy.org/doc/numpy/reference/ufuncs.html Examples ======== >>> from sympy.utilities.autowrap import ufuncify >>> from sympy.abc import x, y >>> import numpy as np >>> f = ufuncify([x, y], y + x**2) >>> f([1, 2, 3], 2) [ 3. 6. 11.] >>> a = f(np.arange(5), 3) >>> isinstance(a, np.ndarray) True >>> print a [ 3. 4. 7. 12. 19.] """ y = C.IndexedBase(C.Dummy('y')) x = C.IndexedBase(C.Dummy('x')) m = C.Dummy('m', integer=True) i = C.Dummy('i', integer=True) i = C.Idx(i, m) l = C.Lambda(args, expr) f = implemented_function('f', l) if isinstance(args, C.Symbol): args = [args] else: args = list(args) # ensure correct order of arguments kwargs['args'] = [y, x] + args[1:] + [m] # first argument accepts an array args[0] = x[i] return autowrap(C.Equality(y[i], f(*args)), **kwargs)
def test_inline_function(): x = symbols('x') g = implemented_function('g', Lambda(x, 2*x)) assert rust_code(g(x)) == "2*x" g = implemented_function('g', Lambda(x, 2*x/Catalan)) assert rust_code(g(x)) == ( "const Catalan: f64 = %s;\n2*x/Catalan" % Catalan.n()) A = IndexedBase('A') i = Idx('i', symbols('n', integer=True)) g = implemented_function('g', Lambda(x, x*(1 + x)*(2 + x))) assert rust_code(g(A[i]), assign_to=A[i]) == ( "for i in 0..n {\n" " A[i] = (A[i] + 1)*(A[i] + 2)*A[i];\n" "}")
def test_glsl_code_Pow(): g = implemented_function('g', Lambda(x, 2*x)) assert glsl_code(x**3) == "pow(x, 3.0)" assert glsl_code(x**(y**3)) == "pow(x, pow(y, 3.0))" assert glsl_code(1/(g(x)*3.5)**(x - y**x)/(x**2 + y)) == \ "pow(3.5*2*x, -x + pow(y, x))/(pow(x, 2.0) + y)" assert glsl_code(x**-1.0) == '1.0/x'
def test_inline_function(): x = symbols('x') g = implemented_function('g', Lambda(x, 2*x)) assert fcode(g(x)) == " 2*x" g = implemented_function('g', Lambda(x, 2*pi/x)) assert fcode(g(x)) == ( " parameter (pi = %sd0)\n" " 2*pi/x" ) % pi.evalf(17) A = IndexedBase('A') i = Idx('i', symbols('n', integer=True)) g = implemented_function('g', Lambda(x, x*(1 + x)*(2 + x))) assert fcode(g(A[i]), assign_to=A[i]) == ( " do i = 1, n\n" " A(i) = (A(i) + 1)*(A(i) + 2)*A(i)\n" " end do" )
def test_fcode_Pow(): assert fcode(x**3) == "x**3" assert fcode(x**(y**3)) == "x**(y**3)" g = implemented_function('g2', Lambda(x, sin(x))) assert fcode((g(x)*3.5)**(x - y**x)/(x**2 + y)) == "(3.5d0*sin(x))**(x - y**x)/(x**2 + y)" assert fcode(x**-1.0) == '1.0/x' assert fcode(x**Rational(2, 3)) == 'x**(2.0d0/3.0d0)' assert fcode(x**-2.0, 'y') == 'y = x**(-2.0d0)'
def test_inline_function(): x = symbols('x') g = implemented_function('g', Lambda(x, 2*x)) assert fcode(g(x)) == " 2*x" g = implemented_function('g', Lambda(x, 2*pi/x)) assert fcode(g(x)) == ( " parameter (pi = 3.14159265358979d0)\n" " 2*pi/x" ) A = IndexedBase('A') i = Idx('i', symbols('n', integer=True)) g = implemented_function('g', Lambda(x, x*(1 + x)*(2 + x))) assert fcode(g(A[i]), assign_to=A[i]) == ( " do i = 1, n\n" " A(i) = A(i)*(1 + A(i))*(2 + A(i))\n" " end do" )
def test_rcode_inline_function(): x = symbols('x') g = implemented_function('g', Lambda(x, 2*x)) assert rcode(g(x)) == "2*x" g = implemented_function('g', Lambda(x, 2*x/Catalan)) assert rcode( g(x)) == "Catalan = %s;\n2*x/Catalan" % Catalan.n() A = IndexedBase('A') i = Idx('i', symbols('n', integer=True)) g = implemented_function('g', Lambda(x, x*(1 + x)*(2 + x))) res=rcode(g(A[i]), assign_to=A[i]) ref=( "for (i in 1:n){\n" " A[i] = (A[i] + 1)*(A[i] + 2)*A[i];\n" "}" ) assert res == ref
def test_implemented_function_evalf(): from sympy.utilities.lambdify import implemented_function f = Function('f') x = Symbol('x') f = implemented_function(f, lambda x: x + 1) assert str(f(x)) == "f(x)" assert str(f(2)) == "f(2)" assert f(2).evalf() == 3 assert f(x).evalf() == f(x)
def test_imps(): # Here we check if the default returned functions are anonymous - in # the sense that we can have more than one function with the same name f = implemented_function('f', lambda x: 2*x) g = implemented_function('f', lambda x: math.sqrt(x)) l1 = lambdify(x, f(x)) l2 = lambdify(x, g(x)) assert str(f(x)) == str(g(x)) assert l1(3) == 6 assert l2(3) == math.sqrt(3) # check that we can pass in a Function as input func = sympy.Function('myfunc') assert not hasattr(func, '_imp_') my_f = implemented_function(func, lambda x: 2*x) assert hasattr(my_f, '_imp_') # Error for functions with same name and different implementation f2 = implemented_function("f", lambda x: x + 101) raises(ValueError, lambda: lambdify(x, f(f2(x))))
def test_Pow(): assert julia_code(x**3) == "x.^3" assert julia_code(x**(y**3)) == "x.^(y.^3)" assert julia_code(x**Rational(2, 3)) == 'x.^(2/3)' g = implemented_function('g', Lambda(x, 2*x)) assert julia_code(1/(g(x)*3.5)**(x - y**x)/(x**2 + y)) == \ "(3.5*2*x).^(-x + y.^x)./(x.^2 + y)" # For issue 14160 assert julia_code(Mul(-2, x, Pow(Mul(y,y,evaluate=False), -1, evaluate=False), evaluate=False)) == '-2*x./(y.*y)'
def __init__(self, ells, comm): import sympy as sp from sympy.utilities.lambdify import implemented_function from sympy.parsing.sympy_parser import parse_expr from sympy.core import sympify self.ells = numpy.asarray(ells).astype(int) self.max_ell = max(self.ells) # look up table from ell to iell, index for cummulating results. self.ell_to_iell = numpy.empty(self.max_ell + 1, dtype=int) for iell, ell in enumerate(self.ells): self.ell_to_iell[ell] = iell lms = [(l,m) for l in ells for m in range(0, l+1)] # compute the Ylm string expressions in parallel exprs = [] for i in range(comm.rank, len(lms), comm.size): lm = lms[i] exprs.append((lm, str(self._get_Ylm(*lm)))) exprs = [x for sublist in comm.allgather(exprs) for x in sublist] # determine the powers entering into each expression args = {} for lm, expr in exprs: matches = [] for var in ['xpyhat', 'zhat']: for e in range(2, max(ells)+1): name = var + '**' + str(e) if name in expr: matches.append((sympify(name), 'cached_'+var, str(e))) args[lm] = matches # define a function to return cached power def from_cache(name, pow): return self._cache[str(name)+str(pow)] f = implemented_function(sp.Function('from_cache'), from_cache) # arguments to the sympy functions zhat = sp.Symbol('zhat', real=True, positive=True) xpyhat = sp.Symbol('xpyhat', complex=True) self._cache = {} # make the Ylm functions self._Ylms = OrderedDict() for lm, expr in exprs: expr = parse_expr(expr, local_dict={'zhat':zhat, 'xpyhat':xpyhat}) for var in args[lm]: expr = expr.replace(var[0], sympify('from_cache(%s, %s)' %var[1:])) self._Ylms[lm] = sp.lambdify((xpyhat, zhat), expr)
def test_rcode_Pow(): assert rcode(x**3) == "x^3" assert rcode(x**(y**3)) == "x^(y^3)" g = implemented_function('g', Lambda(x, 2*x)) assert rcode(1/(g(x)*3.5)**(x - y**x)/(x**2 + y)) == \ "(3.5*2*x)^(-x + y^x)/(x^2 + y)" assert rcode(x**-1.0) == '1.0/x' assert rcode(x**Rational(2, 3)) == 'x^(2.0/3.0)' _cond_cfunc = [(lambda base, exp: exp.is_integer, "dpowi"), (lambda base, exp: not exp.is_integer, "pow")] assert rcode(x**3, user_functions={'Pow': _cond_cfunc}) == 'dpowi(x, 3)' assert rcode(x**3.2, user_functions={'Pow': _cond_cfunc}) == 'pow(x, 3.2)'
def test_numexpr_userfunctions(): if not numpy: skip("numpy not installed.") if not numexpr: skip("numexpr not installed.") a, b = numpy.random.randn(2, 10) uf = type('uf', (Function, ), {'eval' : classmethod(lambda x, y : y**2+1)}) func = lambdify(x, 1-uf(x), modules='numexpr') assert numpy.allclose(func(a), -(a**2)) uf = implemented_function(Function('uf'), lambda x, y : 2*x*y+1) func = lambdify((x, y), uf(x, y), modules='numexpr') assert numpy.allclose(func(a, b), 2*a*b+1)
def step_function(times, values, name=None, fill=0): """ Right-continuous step function of time t Function of t such that f(times[i]) = values[i] if t < times[0]: f(t) = fill Parameters ---------- times : (N,) sequence Increasing sequence of times values : (N,) sequence Values at the specified times fill : float Value on the interval (-np.inf, times[0]) name : str Name of symbolic expression to use. If None, a default is used. Returns ------- f_t : sympy expr Sympy expression f(t) where f is a sympy implemented anonymous function of time that implements the step function. To get the numerical version of the function, use ``lambdify_t(f_t)`` Examples -------- >>> s = step_function([0,4,5],[2,4,6]) >>> tval = np.array([-0.1,3.9,4.1,5.1]) >>> lam = lambdify_t(s) >>> lam(tval) array([ 0., 2., 4., 6.]) """ if name is None: name = 'step%d' % step_function.counter step_function.counter += 1 def _imp(x): x = np.asarray(x) f = np.zeros(x.shape) + fill for time, val in zip(times, values): f[x >= time] = val return f s = implemented_function(name, _imp) return s(T)
def creation_funtion(): fonction = str(input("Enter the function you want = ")) f = implemented_function('f', lambda x: eval(fonction)) lam_f = lambdify(x, f(x)) min_value = input("Debut de l'interval = ") max_value = input("Fin de l'interval = ") #dans la partie qui va suivre, nous allons faire les calculs de la trajectoire with open('points_passage.csv', mode='w') as passage_file: passage_writer = csv.writer(passage_file, delimiter=',', quoting=csv.QUOTE_MINIMAL) for X in range(min_value,max_value+1): passage_writer.writerow([X,lam_f(X)])
def test_Pow(): assert julia_code(x**3) == "x.^3" assert julia_code(x**(y**3)) == "x.^(y.^3)" assert julia_code(x**Rational(2, 3)) == "x.^(2/3)" g = implemented_function("g", Lambda(x, 2 * x)) assert (julia_code(1 / (g(x) * 3.5)**(x - y**x) / (x**2 + y)) == "(3.5*2*x).^(-x + y.^x)./(x.^2 + y)") # For issue 14160 assert (julia_code( Mul( -2, x, Pow(Mul(y, y, evaluate=False), -1, evaluate=False), evaluate=False, )) == "-2*x./(y.*y)")
def test_imps_errors(): # Test errors that implemented functions can return, and still be able to # form expressions. # See: https://github.com/sympy/sympy/issues/10810 for val, error_class in product((0, 0., 2, 2.0), (AttributeError, TypeError, ValueError)): def myfunc(a): if a == 0: raise error_class return 1 f = implemented_function('f', myfunc) expr = f(val) assert expr == f(val)
def ufuncify(args, expr, **kwargs): """Generates a binary ufunc-like lambda function for numpy arrays ``args`` Either a Symbol or a tuple of symbols. Specifies the argument sequence for the ufunc-like function. ``expr`` A Sympy expression that defines the element wise operation ``kwargs`` Optional keyword arguments are forwarded to autowrap(). The returned function can only act on one array at a time, as only the first argument accept arrays as input. .. Note:: a *proper* numpy ufunc is required to support broadcasting, type casting and more. The function returned here, may not qualify for numpy's definition of a ufunc. That why we use the term ufunc-like. See http://docs.scipy.org/doc/numpy/reference/ufuncs.html :Examples ======== >>> from sympy.utilities.autowrap import ufuncify >>> from sympy.abc import x, y, z >>> f = ufuncify([x, y], y + x**2) # doctest: +SKIP >>> f([1, 2, 3], 2) # doctest: +SKIP [2. 5. 10.] """ y = C.IndexedBase(C.Dummy('y')) x = C.IndexedBase(C.Dummy('x')) m = C.Dummy('m', integer=True) i = C.Dummy('i', integer=True) i = C.Idx(i, m) l = C.Lambda(args, expr) f = implemented_function('f', l) if isinstance(args, C.Symbol): args = [args] else: args = list(args) # first argument accepts an array args[0] = x[i] return autowrap(C.Equality(y[i], f(*args)), **kwargs)
def test_Pow(): assert maple_code(x**3) == "x^3" assert maple_code(x**(y**3)) == "x^(y^3)" assert maple_code((x**3)**y) == "(x^3)^y" assert maple_code(x**Rational(2, 3)) == 'x^(2/3)' g = implemented_function('g', Lambda(x, 2 * x)) assert maple_code(1 / (g(x) * 3.5) ** (x - y ** x) / (x ** 2 + y)) == \ "(3.5*2*x)^(-x + y^x)/(x^2 + y)" # For issue 14160 assert maple_code( Mul(-2, x, Pow(Mul(y, y, evaluate=False), -1, evaluate=False), evaluate=False)) == '-2*x/(y*y)'
def linBspline(knots): """ Create linear B spline that is zero outside [knots[0], knots[-1]] (knots is assumed to be sorted). """ fns = [] knots = np.array(knots) for i in range(knots.shape[0]-2): name = 'bs_%s' % i k1, k2, k3 = knots[i:i+3] d1 = k2-k1 def anon(x,k1=k1,k2=k2,k3=k3): return ((x-k1) / d1 * np.greater(x, k1) * np.less_equal(x, k2) + (k3-x) / d1 * np.greater(x, k2) * np.less(x, k3)) fns.append(implemented_function(name, anon)) return fns
def main(): print(__doc__) x = symbols('x') # a numpy array we can apply the ufuncs to grid = np.linspace(-1, 1, 1000) # set mpmath precision to 20 significant numbers for verification mpmath.mp.dps = 20 print("Compiling legendre ufuncs and checking results:") # Let's also plot the ufunc's we generate plot1 = Plot(visible=False) for n in range(6): # Setup the SymPy expression to ufuncify expr = legendre(n, x) print("The polynomial of degree %i is" % n) pprint(expr) # This is where the magic happens: binary_poly = ufuncify(x, expr) # It's now ready for use with numpy arrays polyvector = binary_poly(grid) # let's check the values against mpmath's legendre function maxdiff = 0 for j in range(len(grid)): precise_val = mpmath.legendre(n, grid[j]) diff = abs(polyvector[j] - precise_val) if diff > maxdiff: maxdiff = diff print("The largest error in applied ufunc was %e" % maxdiff) assert maxdiff < 1e-14 # We can also attach the autowrapped legendre polynomial to a sympy # function and plot values as they are calculated by the binary function g = implemented_function('g', binary_poly) plot1[n] = g(x), [200] print( "Here's a plot with values calculated by the wrapped binary functions") plot1.show()
def test_imps_errors(): # Test errors that implemented functions can return, and still be able to # form expressions. # See: https://github.com/sympy/sympy/issues/10810 # # XXX: Removed AttributeError here. This test was added due to issue 10810 # but that issue was about ValueError. It doesn't seem reasonable to # "support" catching AttributeError in the same context... for val, error_class in product((0, 0., 2, 2.0), (TypeError, ValueError)): def myfunc(a): if a == 0: raise error_class return 1 f = implemented_function('f', myfunc) expr = f(val) assert expr == f(val)
def test_ccode_Pow(): assert ccode(x**3) == "pow(x, 3)" assert ccode(x**(y**3)) == "pow(x, pow(y, 3))" g = implemented_function('g', Lambda(x, 2 * x)) assert ccode(1/(g(x)*3.5)**(x - y**x)/(x**2 + y)) == \ "pow(3.5*2*x, -x + pow(y, x))/(pow(x, 2) + y)" assert ccode(x**-1.0) == '1.0/x' assert ccode(x**Rational(2, 3)) == 'pow(x, 2.0L/3.0L)' _cond_cfunc = [(lambda base, exp: exp.is_integer, "dpowi"), (lambda base, exp: not exp.is_integer, "pow")] assert ccode(x**3, user_functions={'Pow': _cond_cfunc}) == 'dpowi(x, 3)' assert ccode(x**3.2, user_functions={'Pow': _cond_cfunc}) == 'pow(x, 3.2)' _cond_cfunc2 = [(lambda base, exp: base == 2, lambda base, exp: 'exp2(%s)' % exp), (lambda base, exp: base != 2, 'pow')] # Related to gh-11353 assert ccode(2**x, user_functions={'Pow': _cond_cfunc2}) == 'exp2(x)' assert ccode(x**2, user_functions={'Pow': _cond_cfunc2}) == 'pow(x, 2)'
def test_ccode_Pow(): assert ccode(x ** 3) == "pow(x, 3)" assert ccode(x ** (y ** 3)) == "pow(x, pow(y, 3))" g = implemented_function("g", Lambda(x, 2 * x)) assert ( ccode(1 / (g(x) * 3.5) ** (x - y ** x) / (x ** 2 + y)) == "pow(3.5*2*x, -x + pow(y, x))/(pow(x, 2) + y)" ) assert ccode(x ** -1.0) == "1.0/x" assert ccode(x ** Rational(2, 3)) == "pow(x, 2.0/3.0)" assert ( ccode(x ** Rational(2, 3), type_aliases={real: float80}) == "powl(x, 2.0L/3.0L)" ) _cond_cfunc = [ (lambda base, exp: exp.is_integer, "dpowi"), (lambda base, exp: not exp.is_integer, "pow"), ] assert ccode(x ** 3, user_functions={"Pow": _cond_cfunc}) == "dpowi(x, 3)" assert ccode(x ** 0.5, user_functions={"Pow": _cond_cfunc}) == "pow(x, 0.5)" assert ( ccode(x ** Rational(16, 5), user_functions={"Pow": _cond_cfunc}) == "pow(x, 16.0/5.0)" ) _cond_cfunc2 = [ (lambda base, exp: base == 2, lambda base, exp: "exp2(%s)" % exp), (lambda base, exp: base != 2, "pow"), ] # Related to gh-11353 assert ccode(2 ** x, user_functions={"Pow": _cond_cfunc2}) == "exp2(x)" assert ccode(x ** 2, user_functions={"Pow": _cond_cfunc2}) == "pow(x, 2)" # For issue 14160 assert ( ccode( Mul( -2, x, Pow(Mul(y, y, evaluate=False), -1, evaluate=False), evaluate=False, ) ) == "-2*x/(y*y)" )
def binary_function(symfunc, expr, **kwargs): """Returns a sympy function with expr as binary implementation This is a convenience function that automates the steps needed to autowrap the SymPy expression and attaching it to a Function object with implemented_function(). >>> from sympy.abc import x, y >>> from sympy.utilities.autowrap import binary_function >>> expr = ((x - y)**(25)).expand() >>> f = binary_function('f', expr) >>> type(f) <class 'sympy.core.function.UndefinedFunction'> >>> 2*f(x, y) 2*f(x, y) >>> f(x, y).evalf(2, subs={x: 1, y: 2}) -1.0 """ binary = autowrap(expr, **kwargs) return implemented_function(symfunc, binary)
def test_inline_function(): from sympy.tensor import IndexedBase, Idx from sympy import symbols n, m = symbols('n m', integer=True) A, x, y = map(IndexedBase, 'Axy') i = Idx('i', m) p = FCodeGen() func = implemented_function('func', Lambda(n, n * (n + 1))) routine = Routine('test_inline', Eq(y[i], func(x[i]))) code = get_string(p.dump_f95, [routine]) expected = ('subroutine test_inline(m, x, y)\n' 'implicit none\n' 'INTEGER*4, intent(in) :: m\n' 'REAL*8, intent(in), dimension(1:m) :: x\n' 'REAL*8, intent(out), dimension(1:m) :: y\n' 'INTEGER*4 :: i\n' 'do i = 1, m\n' ' y(i) = x(i)*(1 + x(i))\n' 'end do\n' 'end subroutine\n') assert code == expected
def define(name, expr): """ Create function of t expression from arbitrary expression `expr` Take an arbitrarily complicated expression `expr` of 't' and make it an expression that is a simple function of t, of form ``'%s(t)' % name`` such that when it evaluates (via ``lambdify``) it has the right values. Parameters ---------- expr : sympy expression with only 't' as a Symbol name : str Returns ------- nexpr: sympy expression Examples -------- >>> t = Term('t') >>> expr = t**2 + 3*t >>> print(expr) #doctest: +SYMPY_EQUAL 3*t + t**2 >>> newexpr = define('f', expr) >>> print(newexpr) f(t) >>> f = lambdify_t(newexpr) >>> f(4) 28 >>> 3*4+4**2 28 """ # make numerical implementation of expression v = lambdify(T, expr, "numpy") # convert numerical implementation to sympy function f = implemented_function(name, v) # Return expression that is function of time return f(T)
def test_interp1d_numeric(): # Test wrapper for interp1d # See: https://github.com/sympy/sympy/issues/10810 # # Test TypeError raised for object func = Interp1dNumeric(range(10), range(10)) # Numeric values OK assert_almost_equal(func([1, 2, 3]), [1, 2, 3]) assert_almost_equal(func([1.5, 2.5, 3.5]), [1.5, 2.5, 3.5]) # Object values raise TypeError assert_raises(TypeError, func, t) # Check it works as expected via sympy sym_func = implemented_function('func', func) f = sym_func(t - 2) assert_almost_equal(lambdify_t(f)(4.5), 2.5) for val in (2, 2.): f = sym_func(val) # Input has no effect assert_almost_equal(lambdify_t(f)(-100), 2) assert_almost_equal(lambdify_t(f)(-1000), 2) # Float expression f = sym_func(t - 2.) assert_almost_equal(lambdify_t(f)(4.5), 2.5)
def ufuncify(args, expr, language=None, backend='numpy', tempdir=None, flags=None, verbose=False, helpers=None): """Generates a binary function that supports broadcasting on numpy arrays. Parameters ---------- args : iterable Either a Symbol or an iterable of symbols. Specifies the argument sequence for the function. expr A SymPy expression that defines the element wise operation. language : string, optional If supplied, (options: 'C' or 'F95'), specifies the language of the generated code. If ``None`` [default], the language is inferred based upon the specified backend. backend : string, optional Backend used to wrap the generated code. Either 'numpy' [default], 'cython', or 'f2py'. tempdir : string, optional Path to directory for temporary files. If this argument is supplied, the generated code and the wrapper input files are left intact in the specified path. flags : iterable, optional Additional option flags that will be passed to the backend verbose : bool, optional If True, autowrap will not mute the command line backends. This can be helpful for debugging. helpers : iterable, optional Used to define auxillary expressions needed for the main expr. If the main expression needs to call a specialized function it should be put in the ``helpers`` iterable. Autowrap will then make sure that the compiled main expression can link to the helper routine. Items should be tuples with (<funtion_name>, <sympy_expression>, <arguments>). It is mandatory to supply an argument sequence to helper routines. Note ---- The default backend ('numpy') will create actual instances of ``numpy.ufunc``. These support ndimensional broadcasting, and implicit type conversion. Use of the other backends will result in a "ufunc-like" function, which requires equal length 1-dimensional arrays for all arguments, and will not perform any type conversions. References ---------- [1] http://docs.scipy.org/doc/numpy/reference/ufuncs.html Examples ======== >>> from sympy.utilities.autowrap import ufuncify >>> from sympy.abc import x, y >>> import numpy as np >>> f = ufuncify((x, y), y + x**2) >>> type(f) <class 'numpy.ufunc'> >>> f([1, 2, 3], 2) array([ 3., 6., 11.]) >>> f(np.arange(5), 3) array([ 3., 4., 7., 12., 19.]) For the F2Py and Cython backends, inputs are required to be equal length 1-dimensional arrays. The F2Py backend will perform type conversion, but the Cython backend will error if the inputs are not of the expected type. >>> f_fortran = ufuncify((x, y), y + x**2, backend='F2Py') >>> f_fortran(1, 2) array([ 3.]) >>> f_fortran(np.array([1, 2, 3]), np.array([1.0, 2.0, 3.0])) array([ 2., 6., 12.]) >>> f_cython = ufuncify((x, y), y + x**2, backend='Cython') >>> f_cython(1, 2) # doctest: +ELLIPSIS Traceback (most recent call last): ... TypeError: Argument '_x' has incorrect type (expected numpy.ndarray, got int) >>> f_cython(np.array([1.0]), np.array([2.0])) array([ 3.]) """ if isinstance(args, Symbol): args = (args, ) else: args = tuple(args) if language: _validate_backend_language(backend, language) else: language = _infer_language(backend) helpers = helpers if helpers else () flags = flags if flags else () if backend.upper() == 'NUMPY': # maxargs is set by numpy compile-time constant NPY_MAXARGS # If a future version of numpy modifies or removes this restriction # this variable should be changed or removed maxargs = 32 helps = [] for name, expr, args in helpers: helps.append(make_routine(name, expr, args)) code_wrapper = UfuncifyCodeWrapper(C99CodeGen("ufuncify"), tempdir, flags, verbose) if not isinstance(expr, (list, tuple)): expr = [expr] if len(expr) == 0: raise ValueError('Expression iterable has zero length') if (len(expr) + len(args)) > maxargs: raise ValueError( 'Cannot create ufunc with more than {0} total arguments: got {1} in, {2} out' .format(maxargs, len(args), len(expr))) routines = [ make_routine('autofunc{}'.format(idx), exprx, args) for idx, exprx in enumerate(expr) ] return code_wrapper.wrap_code(routines, helpers=helps) else: # Dummies are used for all added expressions to prevent name clashes # within the original expression. y = IndexedBase(Dummy()) m = Dummy(integer=True) i = Idx(Dummy(integer=True), m) f = implemented_function(Dummy().name, Lambda(args, expr)) # For each of the args create an indexed version. indexed_args = [IndexedBase(Dummy(str(a))) for a in args] # Order the arguments (out, args, dim) args = [y] + indexed_args + [m] args_with_indices = [a[i] for a in indexed_args] return autowrap(Eq(y[i], f(*args_with_indices)), language, backend, tempdir, args, flags, verbose, helpers)
def generate_i(self, k, total_iter=5): # load kth expansion of g for k >= 1 rulex = { sym.Indexed('zx', i): self.ix_list[i](self.t) for i in range(k) } ruley = { sym.Indexed('zy', i): self.iy_list[i](self.t) for i in range(k) } rule = {**rulex, **ruley, **self.rule_g} ihx = self.hetx_list[k].subs(rule) ihy = self.hety_list[k].subs(rule) hetx_lam = lambdify(self.t, ihx) hety_lam = lambdify(self.t, ihy) if k == 0: init = copy.deepcopy(self.i0_init) total_iter = 0 else: init = [0, 0] # Newton for mm in range(total_iter): if False and k == 1: fig = plt.figure() ax = fig.add_subplot(111) iu = odeint(self.di, init, self.tLC, args=(hetx_lam, hety_lam, k), tfirst=True) ax.plot(iu[:, 0]) ax.plot(iu[:, 1]) ax.set_title('mm=' + str(mm) + ', k=' + str(k)) plt.show(block=True) init += lib.get_newton_jac(self.di, self.tLC, init, hetx_lam, hety_lam, k) iu = odeint(self.di, init, self.tLC, args=(hetx_lam, hety_lam, k), tfirst=True) if k == 1: # normalize gx = lambdify(self.t, self.gx_list[1](self.t)) gy = lambdify(self.t, self.gy_list[1](self.t)) zx = lambdify(self.t, self.zx_list[0](self.t)) zy = lambdify(self.t, self.zy_list[0](self.t)) ix = lambdify(self.t, self.ix_list[0](self.t)) iy = lambdify(self.t, self.iy_list[0](self.t)) F = lib.rhs([np.cos(0), np.sin(0)], 0, self.f) g1 = np.array([gx(0), gy(0)]) z0 = np.array([zx(0), zy(0)]) i0 = np.array([ix(0), iy(0)]) J = self.jacLC(0) i1 = iu[0, :] ijg = np.dot(i0, np.dot(J, g1)) be = (self.kappa - ijg - np.dot(i1, F)) / (np.dot(z0, F)) init = iu[0, :] + be * z0 iu = odeint(self.di, init, self.tLC, args=(hetx_lam, hety_lam, k), tfirst=True) fnx = interp1d(self.tLC, iu[:, 0]) fny = interp1d(self.tLC, iu[:, 1]) self.ix_list.append( implemented_function('ix_' + str(k), self.myFun(fnx))) self.iy_list.append( implemented_function('iy_' + str(k), self.myFun(fny))) self.ix_callable.append(lambdify(self.t, self.ix_list[k](self.t))) self.iy_callable.append(lambdify(self.t, self.iy_list[k](self.t))) return iu
def test_inline_function(): g = implemented_function('g', Lambda(x, 2 * x)) assert fcode(g(x)) == "2*x"
def interp(times, values, fill=0, name=None, **kw): """ Generic interpolation function of t given `times` and `values` Imterpolator such that: f(times[i]) = values[i] if t < times[0] or t > times[-1]: f(t) = fill See ``scipy.interpolate.interp1d`` for details of interpolation types and other keyword arguments. Default is 'kind' is linear, making this function, by default, have the same behavior as ``linear_interp``. Parameters ---------- times : array-like Increasing sequence of times values : array-like Values at the specified times fill : None or float, optional Value on the interval (-np.inf, times[0]). Default 0. If None, raises error outside bounds name : None or str, optional Name of symbolic expression to use. If None, a default is used. \*\*kw : keyword args, optional passed to ``interp1d`` Returns ------- f : sympy expression A Function of t. Examples -------- >>> s = interp([0,4,5.],[2.,4,6]) >>> tval = np.array([-0.1,0.1,3.9,4.1,5.1]) >>> res = lambdify_t(s)(tval) 0 outside bounds by default >>> np.allclose(res, [0, 2.05, 3.95, 4.2, 0]) True """ if fill is not None: if kw.get('bounds_error') is True: raise ValueError('fill conflicts with bounds error') fv = kw.get('fill_value') if not (fv is None or fv is fill or fv == fill): # allow for fill=np.nan raise ValueError('fill conflicts with fill_value') kw['bounds_error'] = False kw['fill_value'] = fill interpolator = Interp1dNumeric(times, values, **kw) # make a new name if none provided if name is None: name = 'interp%d' % interp.counter interp.counter += 1 s = implemented_function(name, interpolator) return s(T)
#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ Created on Fri Oct 19 13:35:48 2018 @author: gustavo """ from sympy.utilities.lambdify import implemented_function from sympy.physics.hydrogen import R_nl a, r = symbols('a r') psi_nl = implemented_function('psi_nl', Lambda([a, r], R_nl(1, 0, a, r))) psi_nl(a, r)
def main(): print(__doc__) # arrays are represented with IndexedBase, indices with Idx m = Symbol("m", integer=True) i = Idx("i", m) A = IndexedBase("A") B = IndexedBase("B") x = Symbol("x") print("Compiling ufuncs for radial harmonic oscillator solutions") # setup a basis of ho-solutions (for l=0) basis_ho = {} for n in range(basis_dimension): # Setup the radial ho solution for this n expr = R_nl(n, orbital_momentum_l, omega2, x) # Reduce the number of operations in the expression by eval to float expr = expr.evalf(15) print("The h.o. wave function with l = %i and n = %i is" % (orbital_momentum_l, n)) pprint(expr) # implement, compile and wrap it as a ufunc basis_ho[n] = ufuncify(x, expr) # now let's see if we can express a hydrogen radial wave in terms of # the ho basis. Here's the solution we will approximate: H_ufunc = ufuncify(x, hydro_nl(hydrogen_n, orbital_momentum_l, 1, x)) # The transformation to a different basis can be written like this, # # psi(r) = sum_i c(i) phi_i(r) # # where psi(r) is the hydrogen solution, phi_i(r) are the H.O. solutions # and c(i) are scalar coefficients. # # So in order to express a hydrogen solution in terms of the H.O. basis, we # need to determine the coefficients c(i). In position space, it means # that we need to evaluate an integral: # # psi(r) = sum_i Integral(R**2*conj(phi(R))*psi(R), (R, 0, oo)) phi_i(r) # # To calculate the integral with autowrap, we notice that it contains an # element-wise sum over all vectors. Using the Indexed class, it is # possible to generate autowrapped functions that perform summations in # the low-level code. (In fact, summations are very easy to create, and as # we will see it is often necessary to take extra steps in order to avoid # them.) # we need one integration ufunc for each wave function in the h.o. basis binary_integrator = {} for n in range(basis_dimension): # # setup basis wave functions # # To get inline expressions in the low level code, we attach the # wave function expressions to a regular SymPy function using the # implemented_function utility. This is an extra step needed to avoid # erroneous summations in the wave function expressions. # # Such function objects carry around the expression they represent, # but the expression is not exposed unless explicit measures are taken. # The benefit is that the routines that searches for repeated indices # in order to make contractions will not search through the wave # function expression. psi_ho = implemented_function( "psi_ho", Lambda(x, R_nl(n, orbital_momentum_l, omega2, x))) # We represent the hydrogen function by an array which will be an input # argument to the binary routine. This will let the integrators find # h.o. basis coefficients for any wave function we throw at them. psi = IndexedBase("psi") # # setup expression for the integration # step = Symbol("step") # use symbolic stepsize for flexibility # let i represent an index of the grid array, and let A represent the # grid array. Then we can approximate the integral by a sum over the # following expression (simplified rectangular rule, ignoring end point # corrections): expr = A[i]**2 * psi_ho(A[i]) * psi[i] * step if n == 0: print("Setting up binary integrators for the integral:") pprint(Integral(x**2 * psi_ho(x) * Function("psi")(x), (x, 0, oo))) # Autowrap it. For functions that take more than one argument, it is # a good idea to use the 'args' keyword so that you know the signature # of the wrapped function. (The dimension m will be an optional # argument, but it must be present in the args list.) binary_integrator[n] = autowrap(expr, args=[A.label, psi.label, step, m]) # Lets see how it converges with the grid dimension print("Checking convergence of integrator for n = %i" % n) for g in range(3, 8): grid, step = np.linspace(0, rmax, 2**g, retstep=True) print("grid dimension %5i, integral = %e" % (2**g, binary_integrator[n](grid, H_ufunc(grid), step))) print("A binary integrator has been set up for each basis state") print("We will now use them to reconstruct a hydrogen solution.") # Note: We didn't need to specify grid or use gridsize before now grid, stepsize = np.linspace(0, rmax, gridsize, retstep=True) print("Calculating coefficients with gridsize = %i and stepsize %f" % (len(grid), stepsize)) coeffs = {} for n in range(basis_dimension): coeffs[n] = binary_integrator[n](grid, H_ufunc(grid), stepsize) print("c(%i) = %e" % (n, coeffs[n])) print("Constructing the approximate hydrogen wave") hydro_approx = 0 all_steps = {} for n in range(basis_dimension): hydro_approx += basis_ho[n](grid) * coeffs[n] all_steps[n] = hydro_approx.copy() if pylab: line = pylab.plot(grid, all_steps[n], ":", label="max n = %i" % n) # check error numerically diff = np.max(np.abs(hydro_approx - H_ufunc(grid))) print("Error estimate: the element with largest deviation misses by %f" % diff) if diff > 0.01: print("This is much, try to increase the basis size or adjust omega") else: print("Ah, that's a pretty good approximation!") # Check visually if pylab: print("Here's a plot showing the contribution for each n") line[0].set_linestyle("-") pylab.plot(grid, H_ufunc(grid), "r-", label="exact") pylab.legend() pylab.show() print("""Note: These binary integrators were specialized to find coefficients for a harmonic oscillator basis, but they can process any wave function as long as it is available as a vector and defined on a grid with equidistant points. That is, on any grid you get from numpy.linspace. To make the integrators even more flexible, you can setup the harmonic oscillator solutions with symbolic parameters omega and l. Then the autowrapped binary routine will take these scalar variables as arguments, so that the integrators can find coefficients for *any* isotropic harmonic oscillator basis. """)
from sympy.utilities.lambdify import lambdify, implemented_function # Importaciones para: funcion = lambdify(variable, expresion) # Crear función definida def funcion(variable): # Crear función definida return expresion funcion_simbolica = sp.Function( 'nombre_función' ) # Crear función simbólica indefinida sin variable (se llama como "funcion_simbolica(variable)") funcion_simbolica = sp.Function('nombre_función')( variable ) # Crear función simbólica indefinida con variable (se llama como "funcion_simbolica") funcion_simbolica = implemented_function( 'nombre_funcion', lambda variable: expresión) # Crear función simbólica definida funcion_simbolica = implemented_function( 'nombre_funcion', funcion) # Covertir función definida a función simbólica definida funcion = lambdify(variable, funcion_simbolica ) # Covertir función simbólica definida a función definida # Ecuaciones sp.Eq(expresión_izquierda, expresión_derecha) # Crear ecuación expresión.lhs # Obtener expresión izquierda de la ecuación expresión.rhs # Obtener expresión derecha de la ecuación # Constrantes integradas sp.pi # Pi sp.E # euler
def generate_g(self, k, total_iter=4): # load kth expansion of g for k >= 0 if k == 0: # g0 is 0 self.g_list.append(np.zeros((self.TN, 2))) self.gx_list.append(implemented_function('gx_0', lambda t: 0)) self.gy_list.append(implemented_function('gy_0', lambda t: 0)) return rulex = { sym.Indexed('gx', i): self.gx_list[i](self.t) for i in range(k) } ruley = { sym.Indexed('gy', i): self.gy_list[i](self.t) for i in range(k) } rule = {**rulex, **ruley} # apply replacement self.ghx_list[k] = self.ghx_list[k].subs(rule) self.ghy_list[k] = self.ghy_list[k].subs(rule) # lambdify heterogeneous terms for use in integration hetx_lam = lambdify(self.t, self.ghx_list[k]) hety_lam = lambdify(self.t, self.ghy_list[k]) self.method = 'RK45' self.rtol = 1e-4 self.atol = 1e-8 # find intial condtion if k == 1: #init = [0,0] init = copy.deepcopy(self.g1_init) total_iter = 1 else: init = [0, 0] # Newton for mm in range(total_iter): out = lib.get_newton_jac(self, self.dg, -self.tLC, init, hetx_lam, hety_lam, k) print(out) init += out # get full solution gu = odeint(self.dg, init, -self.tLC, args=(hetx_lam, hety_lam, k), tfirst=True) gu = gu[::-1, :] # save soluton as lambda functions self.g_list.append(gu) fnx = interp1d(self.tLC, gu[:, 0], fill_value='extrapolate') fny = interp1d(self.tLC, gu[:, 1], fill_value='extrapolate') self.gx_list.append( implemented_function('gx_' + str(k), self.myFun(fnx))) self.gy_list.append( implemented_function('gy_' + str(k), self.myFun(fny))) if True and k == 1: fig = plt.figure() ax = fig.add_subplot(111) ax.plot(self.tLC, gu) ax.set_title('g1') plt.show(block=True) if True and k == 2: t = np.linspace(0, 1, 100) #fig = plt.figure() #ax = fig.add_subplot(111) #ax.plot(t,hetx_lam(t)) #ax.set_title('hetx_lam') #plt.show(block=True) fn = lambdify(self.t, self.gx_list[1](self.t)) fig = plt.figure() ax = fig.add_subplot(111) ax.plot(t, fn(t)) y = self.g_list[1][:, 0] ax.plot(np.linspace(0, 1, len(y)), y) ax.set_title('gx_list[1]') plt.show(block=True)
def construct(self): self.setup_axes(animate=True) semi_sin = self.get_graph(lambda x: np.cos(x) * (np.cos(x) > 0)) semi_sin.set_color(BLUE) self.play(ShowCreation(semi_sin)) # Set camera self.setup() zoomed_camera = self.zoomed_camera zoomed_display = self.zoomed_display frame = zoomed_camera.frame zoomed_display_frame = zoomed_display.display_frame zoomed_display_frame.set_color(RED) self.activate_zooming() # self.play( # # You have to add this line # self.get_zoomed_display_pop_out_animation(), # unfold_camera # ) an_graph = [] f0 = lambdify(x, 1 / PI) a0_graph = self.get_graph( lambda x: f0(x), # x_min=-4*PI, # x_max=4*PI, color=RED) func = implemented_function('func', lambda x: (1 / 2) * np.cos(x)) f = lambdify(x, func(x)) a1_graph = self.get_graph( lambda x: f(x), # x_min=-4*PI, # x_max=4*PI, color=RED) an_graph.append(a1_graph) for i in range(2, 8): a_graph = self.get_graph( lambda x: (2 / PI) * (1 / (1 - i ^ 2)) * np.cos(i * PI / 2) * np.cos(i * x), # x_min=-4*PI, # x_max=4*PI, color=RED) an_graph.append(a_graph) fourier_graph = [ self.get_graph( f, # x_min=-4*PI, # x_max=4*PI, color=RED) for f in self.fourier ] combine = [] self.play(ShowCreation(a0_graph)) for i in range(0, 7): self.wait(0.3) self.play(ShowCreation(an_graph[i])) self.wait(0.3) if i == 0: combine.append( VGroup(a0_graph.deepcopy(), an_graph[i].deepcopy())) self.play(Transform(combine[-1], fourier_graph[i]), ApplyMethod(a0_graph.fade, 0.9), ApplyMethod(an_graph[i].fade, 0.9)) else: combine.append( VGroup(fourier_graph[i - 1], an_graph[i].deepcopy())) self.play(Transform(combine[-1], fourier_graph[i]), ApplyMethod(an_graph[i].fade, 0.9), ApplyMethod(combine[i - 1].fade, 1)) self.wait(2)
def test_imps_wrong_args(): raises(ValueError, lambda: implemented_function(sin, lambda x: x))
def taylor_approx(hrf2decompose, time=None, delta=None): """ A Taylor series approximation of an HRF shifted by times `delta` Returns original HRF and gradient of HRF Parameters ---------- hrf2decompose : sympy expression An expression that can be lambdified as a function of 't'. This is the HRF to be expanded in PCA time : None or np.ndarray, optional None gives default value of np.linspace(-15,50,3251) chosen to match fMRIstat implementation. This corresponds to a time interval of 0.02. Presumed to be equally spaced. delta : None or np.ndarray, optional None results in default value of np.arange(-4.5, 4.6, 0.1) chosen to match fMRIstat implementation. Returns ------- hrf : [sympy expressions] Sequence length 2 comprising (`hrf2decompose`, ``dhrf``) where ``dhrf`` is the first derivative of `hrf2decompose`. approx : TODO References ---------- Liao, C.H., Worsley, K.J., Poline, J-B., Aston, J.A.D., Duncan, G.H., Evans, A.C. (2002). \'Estimating the delay of the response in fMRI data.\' NeuroImage, 16:593-606. """ if time is None: time = np.linspace(-15, 50, 3251) dt = time[1] - time[0] if delta is None: delta = np.arange(-4.5, 4.6, 0.1) # make numerical implementation from hrf function and symbol t. # hrft returns function values when called with values for time as # input. hrft = lambdify_t(hrf2decompose(T)) # interpolator for negative gradient of hrf dhrft = interp1d(time, -np.gradient(hrft(time), dt), bounds_error=False, fill_value=0.) dhrft.y *= 2 # Create stack of time-shifted HRFs. Time varies over row, delta # over column. ts_hrf_vals = np.array([hrft(time - d) for d in delta]).T # hrf, dhrf W = np.array([hrft(time), dhrft(time)]).T # regress hrf, dhrf at times against stack of time-shifted hrfs WH = np.dot(npl.pinv(W), ts_hrf_vals) # put these into interpolators to get estimated coefficients for any # value of delta coef = [interp1d(delta, w, bounds_error=False, fill_value=0.) for w in WH] def approx(time, delta): value = (coef[0](delta) * hrft(time) + coef[1](delta) * dhrft(time)) return value approx.coef = coef approx.components = [hrft, dhrft] (approx.theta, approx.inverse, approx.dinverse, approx.forward, approx.dforward) = invertR(delta, approx.coef) dhrf = implemented_function('d%s' % str(hrf2decompose), dhrft) return [hrf2decompose, dhrf], approx
def get_matrices(self, matrix_format="numeric"): from sympy.utilities.lambdify import lambdify, implemented_function # check for uniqueness nvars = [] for v in self["var_ordering"]: if v in nvars: print("[DSGE.read:]".ljust(15, " ") + " variable `%s` is defined twice..." % v) else: nvars.append(v) self["var_ordering"] = nvars vlist = self["var_ordering"] + self["fvars"] llist = [l(-1) for l in self["var_ordering"]] + self["fvars_lagged"] slist = self["shk_ordering"] subs_dict = {} eq_cond = self["perturb_eq"] + self["re_errors_eq"] sub_var = self["var_ordering"] subs_dict.update({v: 0 for v in sub_var}) subs_dict.update({v(1): 0 for v in sub_var}) subs_dict.update({v(-1): 0 for v in sub_var}) svar = len(vlist) evar = len(slist) rvar = len(self["re_errors"]) ovar = len(self["observables"]) sub_var = self["var_ordering"] fvarl = [l(+1) for l in sub_var] lvarl = [l(-1) for l in sub_var] no_var = len(sub_var) no_lvar = len(lvarl) bb = zeros(1, no_var + no_lvar) bb_PSI = zeros(1, evar) if self["const_var"]: AA = zeros(no_var - 1, no_var) BB = zeros(no_var - 1, no_var) CC = zeros(no_var - 1, no_var) PSI = zeros(no_var - 1, evar) bb_var = filter(lambda x: x.date <= 0, self["const_eq"].atoms(Variable)) bb_fwd = [ x for x in self["const_eq"].atoms(Variable) if x.date > 0 ] if bb_fwd: raise NotImplementedError( "Forward looking variables in the constraint equation are not (yet) implemented: ", *bb_fwd) full_var = sub_var + lvarl for v in bb_var: v_j = full_var.index(v) bb[v_j] = -( self["const_eq"]).set_eq_zero.diff(v).subs(subs_dict) shocks = filter(lambda x: x, self["const_eq"].atoms(Shock)) for s in shocks: s_j = slist.index(s) bb_PSI[s_j] = -( self["const_eq"]).set_eq_zero.diff(s).subs(subs_dict) else: AA = zeros(no_var, no_var) BB = zeros(no_var, no_var) CC = zeros(no_var, no_var) PSI = zeros(no_var, evar) eq_i = 0 for eq in self["perturb_eq"]: A_var = filter(lambda x: x.date > 0, eq.atoms(Variable)) for v in A_var: v_j = fvarl.index(v) AA[eq_i, v_j] = (eq).set_eq_zero.diff(v).subs(subs_dict) B_var = filter(lambda x: x.date == 0, eq.atoms(Variable)) for v in B_var: v_j = sub_var.index(v) BB[eq_i, v_j] = (eq).set_eq_zero.diff(v).subs(subs_dict) C_var = filter(lambda x: x.date < 0, eq.atoms(Variable)) for v in C_var: v_j = lvarl.index(v) CC[eq_i, v_j] = eq.set_eq_zero.diff(v).subs(subs_dict) shocks = filter(lambda x: x, eq.atoms(Shock)) for s in shocks: s_j = slist.index(s) PSI[eq_i, s_j] = -eq.set_eq_zero.diff(s).subs(subs_dict) eq_i += 1 ZZ0 = zeros(ovar, no_var) ZZ1 = zeros(ovar, 1) eq_i = 0 for obs in self["observables"]: eq = self["obs_equations"][str(obs)] ZZ1[eq_i, 0] = eq.subs(subs_dict) curr_var = filter(lambda x: x.date >= 0, eq.atoms(Variable)) for v in curr_var: v_j = vlist.index(v) ZZ0[eq_i, v_j] = eq.diff(v).subs(subs_dict) if self.const_var is v: self.const_obs = obs eq_i += 1 from collections import OrderedDict context = dict([(p.name, p) for p in self.parameters]) sol_dict = {} def ctf_reducer(f): """hack to reduce the calls-to-function""" def reducer(*x): try: return sol_dict[f, x] except KeyError: res = f(*x) sol_dict[f, x] = res return res return reducer # standard functions context["exp"] = implemented_function("exp", np.exp) context["log"] = implemented_function("log", np.log) context["sqrt"] = implemented_function("sqrt", np.sqrt) # distributions context["normpdf"] = implemented_function("normpdf", ctf_reducer(sst.norm.pdf)) context["normcdf"] = implemented_function("normcdf", ctf_reducer(sst.norm.cdf)) context["normppf"] = implemented_function("normppf", ctf_reducer(sst.norm.ppf)) context["norminv"] = implemented_function("norminv", ctf_reducer(sst.norm.ppf)) # things defined in *_funcs.py if self.func_file and os.path.exists(self.func_file): import importlib.util as iu import inspect spec = iu.spec_from_file_location("module", self.func_file) module = iu.module_from_spec(spec) spec.loader.exec_module(module) funcs_list = [ o for o in inspect.getmembers(module) if inspect.isroutine(o[1]) ] for func in funcs_list: context[func[0]] = implemented_function( func[0], ctf_reducer(func[1])) ss = {} checker = np.zeros_like(self["other_para"], dtype=bool) suc_loop = True while ~checker.all(): # print(checker) # raise if loop was unsuccessful raise_error = not suc_loop suc_loop = False # set to check if any progress in loop for i, p in enumerate(self["other_para"]): if not checker[i]: try: ss[str(p)] = eval(str(self["para_func"][p.name]), context) context[str(p)] = ss[str(p)] checker[i] = True suc_loop = True # loop was successful except NameError as error: if raise_error: error_msg = str(error) if not os.path.exists(self.func_file): fname = os.path.basename(self.func_file) error_msg += ( " (info: a file named `%s` was not found)" % fname) raise type(error)( str(error) + " (are definitions in `para_func` circular?)" ).with_traceback(sys.exc_info()[2]) ZZ0 = lambdify([self.parameters + self["other_para"]], ZZ0) ZZ1 = lambdify([self.parameters + self["other_para"]], ZZ1) PSI = lambdify([self.parameters + self["other_para"]], PSI) AA = lambdify([self.parameters + self["other_para"]], AA) BB = lambdify([self.parameters + self["other_para"]], BB) CC = lambdify([self.parameters + self["other_para"]], CC) bb = lambdify([self.parameters + self["other_para"]], bb) bb_PSI = lambdify([self.parameters + self["other_para"]], bb_PSI) psi = lambdify([self.parameters], [ss[str(px)] for px in self["other_para"]]) # , modules=context_f) def pcompile(px): return list(px) + psi(list(px)) self.pcompile = pcompile self.parafunc = [p.name for p in self["other_para"]], psi self.psi = psi self.PSI = PSI self.ZZ0 = ZZ0 self.ZZ1 = ZZ1 self.AA = AA self.BB = BB self.CC = CC self.bb = bb self.bb_PSI = bb_PSI QQ = lambdify([self.parameters + self["other_para"]], self["covariance"]) HH = lambdify([self.parameters + self["other_para"]], self["measurement_errors"]) self.QQ = QQ self.HH = HH
def test_issue_12092(): f = implemented_function('f', lambda x: x**2) assert f(f(2)).evalf() == Float(16)
def spectral_decomposition(hrf2decompose, time=None, delta=None, ncomp=2): """ PCA decomposition of symbolic HRF shifted over time Perform a PCA expansion of a symbolic HRF, time shifted over the values in delta, returning the first ncomp components. This smooths out the HRF as compared to using a Taylor series approximation. Parameters ---------- hrf2decompose : sympy expression An expression that can be lambdified as a function of 't'. This is the HRF to be expanded in PCA time : None or np.ndarray, optional None gives default value of np.linspace(-15,50,3251) chosen to match fMRIstat implementation. This corresponds to a time interval of 0.02. Presumed to be equally spaced. delta : None or np.ndarray, optional None results in default value of np.arange(-4.5, 4.6, 0.1) chosen to match fMRIstat implementation. ncomp : int, optional Number of principal components to retain. Returns ------- hrf : [sympy expressions] A sequence length `ncomp` of symbolic HRFs that are the principal components. approx : TODO """ if time is None: time = np.linspace(-15, 50, 3251) dt = time[1] - time[0] if delta is None: delta = np.arange(-4.5, 4.6, 0.1) # make numerical implementation from hrf function and symbol t. # hrft returns function values when called with values for time as # input. hrft = lambdify_t(hrf2decompose(T)) # Create stack of time-shifted HRFs. Time varies over row, delta # over column. ts_hrf_vals = np.array([hrft(time - d) for d in delta]).T ts_hrf_vals = np.nan_to_num(ts_hrf_vals) # PCA U, S, V = npl.svd(ts_hrf_vals, full_matrices=0) # make interpolators from the generated bases basis = [] for i in range(ncomp): b = interp1d(time, U[:, i], bounds_error=False, fill_value=0.) # normalize components witn integral of abs of first component if i == 0: d = np.fabs((b(time) * dt).sum()) b.y /= d basis.append(b) # reconstruct time courses for all bases W = np.array([b(time) for b in basis]).T # regress basis time courses against original time shifted time # courses, ncomps by len(delta) parameter matrix WH = np.dot(npl.pinv(W), ts_hrf_vals) # put these into interpolators to get estimated coefficients for any # value of delta coef = [interp1d(delta, w, bounds_error=False, fill_value=0.) for w in WH] # swap sign of first component to match that of input HRF. Swap # other components if we swap the first, to standardize signs of # components across SVD implementations. if coef[0](0) < 0: # coefficient at time shift of 0 for i in range(ncomp): coef[i].y *= -1. basis[i].y *= -1. def approx(time, delta): value = 0 for i in range(ncomp): value += coef[i](delta) * basis[i](time) return value approx.coef = coef approx.components = basis (approx.theta, approx.inverse, approx.dinverse, approx.forward, approx.dforward) = invertR(delta, approx.coef) # construct aliased functions from bases symbasis = [] for i, b in enumerate(basis): symbasis.append( implemented_function('%s%d' % (str(hrf2decompose), i), b)) return symbasis, approx