def test_undefined_function(): from sage.symbolic.ring import SR from sage.calculus.var import function from sympy import Symbol, Function f = function('f') sf = Function('f') x,y = SR.var('x y') sx = Symbol('x') sy = Symbol('y') assert f(x)._sympy_() == sf(sx) assert f(x) == sf(sx)._sage_() assert f(x,y)._sympy_() == sf(sx, sy) assert f(x,y) == sf(sx, sy)._sage_() assert f._sympy_() == sf assert f == sf._sage_()
def _eval_subs(self, old, new): if self==old: return new arg = self.args[0] o = old if old.is_Pow: # handle (exp(3*log(x))).subs(x**2, z) -> z**(3/2) old = exp(old.exp * log(old.base)) if old.func is exp: # exp(a*expr) .subs( exp(b*expr), y ) -> y ** (a/b) a, expr_terms = self.args[0].as_coeff_terms() b, expr_terms_= old .args[0].as_coeff_terms() if expr_terms == expr_terms_: return new ** (a/b) if arg.is_Add: # exp(2*x+a).subs(exp(3*x),y) -> y**(2/3) * exp(a) # exp(exp(x) + exp(x**2)).subs(exp(exp(x)), w) -> w * exp(exp(x**2)) oarg = old.args[0] new_l = [] old_al = [] coeff2,terms2 = oarg.as_coeff_terms() for a in arg.args: a = a._eval_subs(old, new) coeff1,terms1 = a.as_coeff_terms() if terms1==terms2: new_l.append(new**(coeff1/coeff2)) else: old_al.append(a._eval_subs(old, new)) if new_l: new_l.append(self.func(C.Add(*old_al))) r = C.Mul(*new_l) return r old = o return Function._eval_subs(self, old, new)
def _eval_subs(self, old, new): if self==old: return new arg = self[0] o = old if isinstance(old, Basic.Pow): # handle (exp(3*log(x))).subs(x**2, z) -> z**(3/2) old = exp(old.exp * S.Log(old.base)) if isinstance(old, exp): b,e = self.as_base_exp() bo,eo = old.as_base_exp() if b==bo: return new ** (e/eo) # exp(2/3*x*3).subs(exp(3*x),y) -> y**(2/3) if isinstance(arg, Basic.Add): # exp(2*x+a).subs(exp(3*x),y) -> y**(2/3) * exp(a) # exp(exp(x) + exp(x**2)).subs(exp(exp(x)), w) -> w * exp(exp(x**2)) oarg = old[0] new_l = [] old_al = [] coeff2,terms2 = oarg.as_coeff_terms() for a in arg: a = a.subs(old, new) coeff1,terms1 = a.as_coeff_terms() if terms1==terms2: new_l.append(new**(coeff1/coeff2)) else: old_al.append(a.subs(old, new)) if new_l: new_l.append(self.func(Basic.Add(*old_al))) r = Basic.Mul(*new_l) return r old = o return Function._eval_subs(self, old, new)
def _eval_subs(self, old, new): # keep processing of power-like args centralized in Pow if old.is_Pow: # handle (exp(3*log(x))).subs(x**2, z) -> z**(3/2) old = exp(old.exp * log(old.base)) elif old is S.Exp1 and new.is_Function: old = exp if old.func is exp or old is S.Exp1: f = lambda a: Pow(*a.as_base_exp(), evaluate=False) if (a.is_Pow or a.func is exp) else a return Pow._eval_subs(f(self), f(old), new) if old is exp and not new.is_Function: return new ** self.exp._subs(old, new) return Function._eval_subs(self, old, new)
def __new__(cls, *args): if len(args) == 5: args = [(args[0], args[1]), (args[2], args[3]), args[4]] if len(args) != 3: raise TypeError("args must eiter be as, as', bs, bs', z or " "as, bs, z") def tr(p): if len(p) != 2: raise TypeError("wrong argument") return TupleArg(_prep_tuple(p[0]), _prep_tuple(p[1])) # TODO should we check convergence conditions? return Function.__new__(cls, tr(args[0]), tr(args[1]), args[2])
def __new__(cls, *args): if len(args) == 5: args = [(args[0], args[1]), (args[2], args[3]), args[4]] if len(args) != 3: raise TypeError("args must be either as, as', bs, bs', z or " "as, bs, z") def tr(p): if len(p) != 2: raise TypeError("wrong argument") return TupleArg(_prep_tuple(p[0]), _prep_tuple(p[1])) arg0, arg1 = tr(args[0]), tr(args[1]) if Tuple(arg0, arg1).has(oo, zoo, -oo): raise ValueError("G-function parameters must be finite") if any((a - b).is_Integer and a - b > 0 for a in arg0[0] for b in arg1[0]): raise ValueError("no parameter a1, ..., an may differ from " "any b1, ..., bm by a positive integer") # TODO should we check convergence conditions? return Function.__new__(cls, arg0, arg1, args[2])
def _eval_subs(self, old, new): arg = self.args[0] o = old if old.is_Pow: # handle (exp(3*log(x))).subs(x**2, z) -> z**(3/2) o = exp(o.exp*log(o.base)) if o.func is exp: # exp(a*expr) .subs( exp(b*expr), y ) -> y ** (a/b) a, expr_terms = self.args[0].as_independent( C.Symbol, as_Add=False) b, expr_terms_ = o.args[0].as_independent( C.Symbol, as_Add=False) if expr_terms == expr_terms_: return new**(a/b) if arg.is_Add: # exp(2*x+a).subs(exp(3*x),y) -> y**(2/3) * exp(a) # exp(exp(x) + exp(x**2)).subs(exp(exp(x)), w) -> w * exp(exp(x**2)) oarg = o.args[0] new_l = [] o_al = [] coeff2, terms2 = oarg.as_coeff_mul() for a in arg.args: a = a._subs(o, new) coeff1, terms1 = a.as_coeff_mul() if terms1 == terms2: new_l.append(new**(coeff1/coeff2)) else: o_al.append(a._subs(o, new)) if new_l: new_l.append(self.func(Add(*o_al))) r = Mul(*new_l) return r if o is S.Exp1: # treat this however Pow is being treated u = C.Dummy('u', positive=True) return (u**self.args[0]).xreplace({u: new}) return Function._eval_subs(self, o, new)
def __new__(cls, ap, bq, z): # TODO should we check convergence conditions? return Function.__new__(cls, _prep_tuple(ap), _prep_tuple(bq), z)
def _eval_evalf(self, prec): if (self.args[0]/polar_lift(-1)).is_positive: return Function._eval_evalf(self, prec) + (I*pi)._eval_evalf(prec) return Function._eval_evalf(self, prec)
def test_recurse_Application_args(): F = Lambda((x, y), exp(2 * x + 3 * y)) f = Function('f') A = f(x, f(x, x)) C = F(x, F(x, x)) assert A.subs(f, F) == A.replace(f, F) == C
def pdsolve(eq, func=None, hint='default', dict=False, solvefun=None, **kwargs): """ Solves any (supported) kind of partial differential equation. **Usage** pdsolve(eq, f(x,y), hint) -> Solve partial differential equation eq for function f(x,y), using method hint. **Details** ``eq`` can be any supported partial differential equation (see the pde docstring for supported methods). This can either be an Equality, or an expression, which is assumed to be equal to 0. ``f(x,y)`` is a function of two variables whose derivatives in that variable make up the partial differential equation. In many cases it is not necessary to provide this; it will be autodetected (and an error raised if it couldn't be detected). ``hint`` is the solving method that you want pdsolve to use. Use classify_pde(eq, f(x,y)) to get all of the possible hints for a PDE. The default hint, 'default', will use whatever hint is returned first by classify_pde(). See Hints below for more options that you can use for hint. ``solvefun`` is the convention used for arbitrary functions returned by the PDE solver. If not set by the user, it is set by default to be F. **Hints** Aside from the various solving methods, there are also some meta-hints that you can pass to pdsolve(): "default": This uses whatever hint is returned first by classify_pde(). This is the default argument to pdsolve(). "all": To make pdsolve apply all relevant classification hints, use pdsolve(PDE, func, hint="all"). This will return a dictionary of hint:solution terms. If a hint causes pdsolve to raise the NotImplementedError, value of that hint's key will be the exception object raised. The dictionary will also include some special keys: - order: The order of the PDE. See also ode_order() in deutils.py - default: The solution that would be returned by default. This is the one produced by the hint that appears first in the tuple returned by classify_pde(). "all_Integral": This is the same as "all", except if a hint also has a corresponding "_Integral" hint, it only returns the "_Integral" hint. This is useful if "all" causes pdsolve() to hang because of a difficult or impossible integral. This meta-hint will also be much faster than "all", because integrate() is an expensive routine. See also the classify_pde() docstring for more info on hints, and the pde docstring for a list of all supported hints. **Tips** - You can declare the derivative of an unknown function this way: >>> from sympy import Function, Derivative >>> from sympy.abc import x, y # x and y are the independent variables >>> f = Function("f")(x, y) # f is a function of x and y >>> # fx will be the partial derivative of f with respect to x >>> fx = Derivative(f, x) >>> # fy will be the partial derivative of f with respect to y >>> fy = Derivative(f, y) - See test_pde.py for many tests, which serves also as a set of examples for how to use pdsolve(). - pdsolve always returns an Equality class (except for the case when the hint is "all" or "all_Integral"). Note that it is not possible to get an explicit solution for f(x, y) as in the case of ODE's - Do help(pde.pde_hintname) to get help more information on a specific hint Examples ======== >>> from sympy.solvers.pde import pdsolve >>> from sympy import Function, diff, Eq >>> from sympy.abc import x, y >>> f = Function('f') >>> u = f(x, y) >>> ux = u.diff(x) >>> uy = u.diff(y) >>> eq = Eq(1 + (2*(ux/u)) + (3*(uy/u))) >>> pdsolve(eq) Eq(f(x, y), F(3*x - 2*y)*exp(-2*x/13 - 3*y/13)) """ given_hint = hint # hint given by the user. if not solvefun: solvefun = Function('F') # See the docstring of _desolve for more details. hints = _desolve(eq, func=func, hint=hint, simplify=True, type='pde', **kwargs) eq = hints.pop('eq', False) all_ = hints.pop('all', False) if all_: # TODO : 'best' hint should be implemented when adequate # number of hints are added. pdedict = {} failed_hints = {} gethints = classify_pde(eq, dict=True) pdedict.update({ 'order': gethints['order'], 'default': gethints['default'] }) for hint in hints: try: rv = _helper_simplify(eq, hint, hints[hint]['func'], hints[hint]['order'], hints[hint][hint], solvefun) except NotImplementedError as detail: failed_hints[hint] = detail else: pdedict[hint] = rv pdedict.update(failed_hints) return pdedict else: return _helper_simplify(eq, hints['hint'], hints['func'], hints['order'], hints[hints['hint']], solvefun)
def test_Min(): from sympy.abc import x, y, z n = Symbol('n', negative=True) n_ = Symbol('n_', negative=True) nn = Symbol('nn', nonnegative=True) nn_ = Symbol('nn_', nonnegative=True) p = Symbol('p', positive=True) p_ = Symbol('p_', positive=True) np = Symbol('np', nonpositive=True) np_ = Symbol('np_', nonpositive=True) r = Symbol('r', real=True) assert Min(5, 4) == 4 assert Min(-oo, -oo) == -oo assert Min(-oo, n) == -oo assert Min(n, -oo) == -oo assert Min(-oo, np) == -oo assert Min(np, -oo) == -oo assert Min(-oo, 0) == -oo assert Min(0, -oo) == -oo assert Min(-oo, nn) == -oo assert Min(nn, -oo) == -oo assert Min(-oo, p) == -oo assert Min(p, -oo) == -oo assert Min(-oo, oo) == -oo assert Min(oo, -oo) == -oo assert Min(n, n) == n assert unchanged(Min, n, np) assert Min(np, n) == Min(n, np) assert Min(n, 0) == n assert Min(0, n) == n assert Min(n, nn) == n assert Min(nn, n) == n assert Min(n, p) == n assert Min(p, n) == n assert Min(n, oo) == n assert Min(oo, n) == n assert Min(np, np) == np assert Min(np, 0) == np assert Min(0, np) == np assert Min(np, nn) == np assert Min(nn, np) == np assert Min(np, p) == np assert Min(p, np) == np assert Min(np, oo) == np assert Min(oo, np) == np assert Min(0, 0) == 0 assert Min(0, nn) == 0 assert Min(nn, 0) == 0 assert Min(0, p) == 0 assert Min(p, 0) == 0 assert Min(0, oo) == 0 assert Min(oo, 0) == 0 assert Min(nn, nn) == nn assert unchanged(Min, nn, p) assert Min(p, nn) == Min(nn, p) assert Min(nn, oo) == nn assert Min(oo, nn) == nn assert Min(p, p) == p assert Min(p, oo) == p assert Min(oo, p) == p assert Min(oo, oo) == oo assert Min(n, n_).func is Min assert Min(nn, nn_).func is Min assert Min(np, np_).func is Min assert Min(p, p_).func is Min # lists assert Min() == S.Infinity assert Min(x) == x assert Min(x, y) == Min(y, x) assert Min(x, y, z) == Min(z, y, x) assert Min(x, Min(y, z)) == Min(z, y, x) assert Min(x, Max(y, -oo)) == Min(x, y) assert Min(p, oo, n, p, p, p_) == n assert Min(p_, n_, p) == n_ assert Min(n, oo, -7, p, p, 2) == Min(n, -7) assert Min(2, x, p, n, oo, n_, p, 2, -2, -2) == Min(-2, x, n, n_) assert Min(0, x, 1, y) == Min(0, x, y) assert Min(1000, 100, -100, x, p, n) == Min(n, x, -100) assert unchanged(Min, sin(x), cos(x)) assert Min(sin(x), cos(x)) == Min(cos(x), sin(x)) assert Min(cos(x), sin(x)).subs(x, 1) == cos(1) assert Min(cos(x), sin(x)).subs(x, S(1) / 2) == sin(S(1) / 2) raises(ValueError, lambda: Min(cos(x), sin(x)).subs(x, I)) raises(ValueError, lambda: Min(I)) raises(ValueError, lambda: Min(I, x)) raises(ValueError, lambda: Min(S.ComplexInfinity, x)) assert Min(1, x).diff(x) == Heaviside(1 - x) assert Min(x, 1).diff(x) == Heaviside(1 - x) assert Min(0, -x, 1 - 2*x).diff(x) == -Heaviside(x + Min(0, -2*x + 1)) \ - 2*Heaviside(2*x + Min(0, -x) - 1) # issue 7619 f = Function('f') assert Min(1, 2 * Min(f(1), 2)) # doesn't fail # issue 7233 e = Min(0, x) assert e.evalf == e.n assert e.n().args == (0, x) # issue 8643 m = Min(n, p_, n_, r) assert m.is_positive is False assert m.is_nonnegative is False assert m.is_negative is True m = Min(p, p_) assert m.is_positive is True assert m.is_nonnegative is True assert m.is_negative is False m = Min(p, nn_, p_) assert m.is_positive is None assert m.is_nonnegative is True assert m.is_negative is False m = Min(nn, p, r) assert m.is_positive is None assert m.is_nonnegative is None assert m.is_negative is None
# needed for testing. # Some of the pretty forms shown denote how the expressions just # above them should look with pretty printing. N = CoordSys3D('N') C = N.orient_new_axis('C', a, N.k) # type: ignore v = [] d = [] v.append(Vector.zero) v.append(N.i) # type: ignore v.append(-N.i) # type: ignore v.append(N.i + N.j) # type: ignore v.append(a * N.i) # type: ignore v.append(a * N.i - b * N.j) # type: ignore v.append((a**2 + N.x) * N.i + N.k) # type: ignore v.append((a**2 + b) * N.i + 3 * (C.y - c) * N.k) # type: ignore f = Function('f') v.append(N.j - (Integral(f(b)) - C.x**2) * N.k) # type: ignore upretty_v_8 = """\ ⎛ 2 ⌠ ⎞ \n\ j_N + ⎜x_C - ⎮ f(b) db⎟ k_N\n\ ⎝ ⌡ ⎠ \ """ pretty_v_8 = """\ j_N + / / \\\n\ | 2 | |\n\ |x_C - | f(b) db|\n\ | | |\n\ \\ / / \ """ v.append(N.i + C.k) # type: ignore
def __new__(cls, *args): return Function.__new__(cls, *sorted(args, key=default_sort_key))
def pde_1st_linear_constant_coeff_homogeneous(eq, func, order, match, solvefun): r""" Solves a first order linear homogeneous partial differential equation with constant coefficients. The general form of this partial differential equation is a*f(x,y).diff(x) + b*f(x,y).diff(y) + f(x,y) = 0 where a, b and c are constants. The general solution of the differential equation, can be found by the method of characteristics. It is given by f(x,y) = F(b*x - a*y)*exp(-c/(a**2 + b**2)*(a*x + b*y)) >>> from sympy.solvers import pdsolve >>> from sympy.abc import x, y, a, b, c >>> from sympy import Function, pprint >>> f = Function('f') >>> u = f(x,y) >>> ux = u.diff(x) >>> uy = u.diff(y) >>> genform = a*u + b*ux + c*uy >>> pprint(genform) d d a*f(x, y) + b*--(f(x, y)) + c*--(f(x, y)) dx dy >>> pprint(pdsolve(genform)) -a*(b*x + c*y) -------------- 2 2 b + c f(x, y) = F(-b*y + c*x)*e Examples ======== >>> from sympy.solvers.pde import ( ... pde_1st_linear_constant_coeff_homogeneous) >>> from sympy import pdsolve >>> from sympy import Function, diff, pprint >>> from sympy.abc import x,y >>> f = Function('f') >>> pdsolve(f(x,y) + f(x,y).diff(x) + f(x,y).diff(y)) f(x, y) == F(x - y)*exp(-x/2 - y/2) >>> pprint(pdsolve(f(x,y) + f(x,y).diff(x) + f(x,y).diff(y))) x y - - - - 2 2 f(x, y) = F(x - y)*e References ========== - Viktor Grigoryan, "Partial Differential Equations" Math 124A - Fall 2010, pp.7 """ # TODO : For now homogeneous first order linear PDE's having # two variables are implemented. Once there is support for # solving systems of ODE's, this can be extended to n variables. f = func.func x = func.args[0] y = func.args[1] g = Function('g') b = match[match['b']] c = match[match['c']] d = match[match['d']] return Eq(f(x,y), exp(-S(d)/(b**2 + c**2)*(b*x + c*y))*solvefun(c*x - b*y))
def test_Min(): from sympy.abc import x, y, z n = Symbol('n', negative=True) n_ = Symbol('n_', negative=True) nn = Symbol('nn', nonnegative=True) nn_ = Symbol('nn_', nonnegative=True) p = Symbol('p', positive=True) p_ = Symbol('p_', positive=True) np = Symbol('np', nonpositive=True) np_ = Symbol('np_', nonpositive=True) assert Min(5, 4) == 4 assert Min(-oo, -oo) == -oo assert Min(-oo, n) == -oo assert Min(n, -oo) == -oo assert Min(-oo, np) == -oo assert Min(np, -oo) == -oo assert Min(-oo, 0) == -oo assert Min(0, -oo) == -oo assert Min(-oo, nn) == -oo assert Min(nn, -oo) == -oo assert Min(-oo, p) == -oo assert Min(p, -oo) == -oo assert Min(-oo, oo) == -oo assert Min(oo, -oo) == -oo assert Min(n, n) == n assert Min(n, np) == Min(n, np) assert Min(np, n) == Min(np, n) assert Min(n, 0) == n assert Min(0, n) == n assert Min(n, nn) == n assert Min(nn, n) == n assert Min(n, p) == n assert Min(p, n) == n assert Min(n, oo) == n assert Min(oo, n) == n assert Min(np, np) == np assert Min(np, 0) == np assert Min(0, np) == np assert Min(np, nn) == np assert Min(nn, np) == np assert Min(np, p) == np assert Min(p, np) == np assert Min(np, oo) == np assert Min(oo, np) == np assert Min(0, 0) == 0 assert Min(0, nn) == 0 assert Min(nn, 0) == 0 assert Min(0, p) == 0 assert Min(p, 0) == 0 assert Min(0, oo) == 0 assert Min(oo, 0) == 0 assert Min(nn, nn) == nn assert Min(nn, p) == Min(nn, p) assert Min(p, nn) == Min(p, nn) assert Min(nn, oo) == nn assert Min(oo, nn) == nn assert Min(p, p) == p assert Min(p, oo) == p assert Min(oo, p) == p assert Min(oo, oo) == oo assert Min(n, n_).func is Min assert Min(nn, nn_).func is Min assert Min(np, np_).func is Min assert Min(p, p_).func is Min # lists raises(ValueError, lambda: Min()) assert Min(x, y) == Min(y, x) assert Min(x, y, z) == Min(z, y, x) assert Min(x, Min(y, z)) == Min(z, y, x) assert Min(x, Max(y, -oo)) == Min(x, y) assert Min(p, oo, n, p, p, p_) == n assert Min(p_, n_, p) == n_ assert Min(n, oo, -7, p, p, 2) == Min(n, -7) assert Min(2, x, p, n, oo, n_, p, 2, -2, -2) == Min(-2, x, n, n_) assert Min(0, x, 1, y) == Min(0, x, y) assert Min(1000, 100, -100, x, p, n) == Min(n, x, -100) assert Min(cos(x), sin(x)) == Min(cos(x), sin(x)) assert Min(cos(x), sin(x)).subs(x, 1) == cos(1) assert Min(cos(x), sin(x)).subs(x, S(1)/2) == sin(S(1)/2) raises(ValueError, lambda: Min(cos(x), sin(x)).subs(x, I)) raises(ValueError, lambda: Min(I)) raises(ValueError, lambda: Min(I, x)) raises(ValueError, lambda: Min(S.ComplexInfinity, x)) assert Min(1, x).diff(x) == Heaviside(1 - x) assert Min(x, 1).diff(x) == Heaviside(1 - x) assert Min(0, -x, 1 - 2*x).diff(x) == -Heaviside(x + Min(0, -2*x + 1)) \ - 2*Heaviside(2*x + Min(0, -x) - 1) a, b = Symbol('a', real=True), Symbol('b', real=True) # a and b are both real, Min(a, b) should be real assert Min(a, b).is_real # issue 7619 f = Function('f') assert Min(1, 2*Min(f(1), 2)) # doesn't fail # issue 7233 e = Min(0, x) assert e.evalf == e.n assert e.n().args == (0, x)
def _eval_rewrite_as_pde(self, *args, **kwargs): mu, epsilon, x, t = symbols('mu, epsilon, x, t') E = Function('E') return Derivative(E(x, t), x, 2) + mu * epsilon * Derivative(E(x, t), t, 2)
def test_manualintegrate_trivial_substitution(): assert manualintegrate((exp(x) - exp(-x)) / x, x) == -Ei(-x) + Ei(x) f = Function('f') assert manualintegrate((f(x) - f(-x))/x, x) == \ -Integral(f(-x)/x, x) + Integral(f(x)/x, x)
else: pass return expr_.func(*compo), True else: return expr_, False else: return expr_, keep def replace_args_first(expr_, old, new): """a""" return _replace_args_first(expr_, old, new)[0] M3 = (Function("MAdd"), Function("MSub"), Function("Conv")) def _flatten_add_f(expr01, cof_list, cof_dict, vector_add): if len(expr01.args) > 0: if isinstance(expr01, sympy.Add): arg_list = [] for i, argi in enumerate(expr01.args): argi_new = _flatten_add_f(argi, cof_list, cof_dict, vector_add) if isinstance(argi_new, M3): if vector_add: arg_list.append(argi_new) # except with both W and V else: wi = sympy.Symbol("W%s" % len(cof_list))
def prove(Eq): p = Function('p') q = Function('q') Eq << apply(p, q)
homogeneous_order, dsolve) from sympy.solvers.ode.subscheck import checkodesol from sympy.solvers.ode.ode import (classify_sysode, constant_renumber, constantsimp, get_numbered_constants, solve_ics) from sympy.solvers.ode.nonhomogeneous import _undetermined_coefficients_match from sympy.solvers.ode.single import LinearCoefficients from sympy.solvers.deutils import ode_order from sympy.testing.pytest import XFAIL, raises, slow from sympy.utilities.misc import filldedent C0, C1, C2, C3, C4, C5, C6, C7, C8, C9, C10 = symbols('C0:11') u, x, y, z = symbols('u,x:z', real=True) f = Function('f') g = Function('g') h = Function('h') # Note: Examples which were specifically testing Single ODE solver are moved to test_single.py # and all the system of ode examples are moved to test_systems.py # Note: the tests below may fail (but still be correct) if ODE solver, # the integral engine, solve(), or even simplify() changes. Also, in # differently formatted solutions, the arbitrary constants might not be # equal. Using specific hints in tests can help to avoid this. # Tests of order higher than 1 should run the solutions through # constant_renumber because it will normalize it (constant_renumber causes # dsolve() to return different results on different machines)
def test_issue_15056(): t = Symbol('t') C3 = Symbol('C3') assert get_numbered_constants(Symbol('C1') * Function('C2')(t)) == C3
from mpmath import bernfrac, workprec from mpmath.libmp import ifib as _ifib def _product(a, b): p = 1 for k in xrange(a, b + 1): p *= k return p from sympy.utilities.memoization import recurrence_memo # Dummy symbol used for computing polynomial sequences _sym = Symbol('x') _symbols = Function('x') #----------------------------------------------------------------------------# # # # Fibonacci numbers # # # #----------------------------------------------------------------------------# class fibonacci(Function): r""" Fibonacci numbers / Fibonacci polynomials The Fibonacci numbers are the integer sequence defined by the initial terms F_0 = 0, F_1 = 1 and the two-term recurrence relation F_n = F_{n-1} + F_{n-2}. This definition
def pdsolve(eq, func=None, hint='default', dict=False, solvefun=None, **kwargs): """ Solves any (supported) kind of partial differential equation. **Usage** pdsolve(eq, f(x,y), hint) -> Solve partial differential equation eq for function f(x,y), using method hint. **Details** ``eq`` can be any supported partial differential equation (see the pde docstring for supported methods). This can either be an Equality, or an expression, which is assumed to be equal to 0. ``f(x,y)`` is a function of two variables whose derivatives in that variable make up the partial differential equation. In many cases it is not necessary to provide this; it will be autodetected (and an error raised if it couldn't be detected). ``hint`` is the solving method that you want pdsolve to use. Use classify_pde(eq, f(x,y)) to get all of the possible hints for a PDE. The default hint, 'default', will use whatever hint is returned first by classify_pde(). See Hints below for more options that you can use for hint. ``solvefun`` is the convention used for arbitrary functions returned by the PDE solver. If not set by the user, it is set by default to be F. **Hints** Aside from the various solving methods, there are also some meta-hints that you can pass to pdsolve(): "default": This uses whatever hint is returned first by classify_pde(). This is the default argument to pdsolve(). See also the classify_pde() docstring for more info on hints, and the pde docstring for a list of all supported hints. **Tips** - You can declare the derivative of an unknown function this way: >>> from sympy import Function, Derivative >>> from sympy.abc import x, y # x and y are the independent variables >>> f = Function("f")(x, y) # f is a function of x and y >>> # fx will be the partial derivative of f with respect to x >>> fx = Derivative(f, x) >>> # fy will be the partial derivative of f with respect to y >>> fy = Derivative(f, y) - See test_pde.py for many tests, which serves also as a set of examples for how to use pdsolve(). - pdsolve always returns an Equality class (except for the case when the hint is "all" or "all_Integral"). Note that it is not possible to get an explicit solution for f(x, y) as in the case of ODE's - Do help(pde.pde_hintname) to get help more information on a specific hint Examples ======== >>> from sympy.solvers.pde import pdsolve >>> from sympy import Function, diff, Eq >>> from sympy.abc import x, y >>> f = Function('f') >>> u = f(x, y) >>> ux = u.diff(x) >>> uy = u.diff(y) >>> eq = Eq(1 + (2*(ux/u)) + (3*(uy/u))) >>> pdsolve(eq) f(x, y) == F(3*x - 2*y)*exp(-2*x/13 - 3*y/13) """ given_hint = hint # hint given by the user. if not solvefun: solvefun = Function('F') # See the docstring of _desolve for more details. hints = _desolve(eq, func=func, hint=hint, simplify=True, type='pde', **kwargs) eq = hints['eq'] all_ = hints.pop('all', False) if all_: raise NotImplementedError("Only one hint has been added till now") else: solvefunc = globals()['pde_' + hints[hint]] return solvefunc(eq, hints['func'], hints['order'], hints[hints['hint']], solvefun)
def _eval_nseries(self, x, n): i = self.args[0].limit(x, 0) / S.Pi if i and i.is_Integer: return self.rewrite(cos)._eval_nseries(x, n=n) return Function._eval_nseries(self, x, n=n)
def shape(self): (Wh, ) = self.limits[1] d = Wh.shape[-1] / 3 if len(self.limits) > 3: return (d, ) x = self.arg x_shape = x.shape shape = (x_shape[-2], d) if len(x_shape) > 2: shape = (x[0], ) + shape return shape gru = Function.gru(real=True, eval=gru_recursive, shape=property(shape)) def GRU(x, *limits): (Wx, ), (Wh, ), (b, ) = limits n = x.shape[0] t = Symbol.t(integer=True) return Lamda[t:n](gru[Wx, Wh, b, t](x)) assert shape.__name__ == 'shape' GRU = Function.GRU(real=True, eval=GRU, shape=property(shape))
from sympy.functions.elementary.miscellaneous import (root, sqrt) from sympy.functions.elementary.trigonometric import (asin, cos, csc, sec, sin, tan) from sympy.integrals.integrals import Integral from sympy.series.limits import Limit from sympy.core.relational import Eq, Ne, Lt, Le, Gt, Ge from sympy.physics.quantum.state import Bra, Ket from sympy.abc import x, y, z, a, b, c, t, k, n antlr4 = import_module("antlr4") # disable tests if antlr4-python*-runtime is not present if not antlr4: disabled = True theta = Symbol('theta') f = Function('f') # shorthand definitions def _Add(a, b): return Add(a, b, evaluate=False) def _Mul(a, b): return Mul(a, b, evaluate=False) def _Pow(a, b): return Pow(a, b, evaluate=False)
def _eval_evalf(self, prec): if (self.args[0] / polar_lift(-1)).is_positive: return Function._eval_evalf(self, prec) + (I * pi)._eval_evalf(prec) return Function._eval_evalf(self, prec)
from axiom.utility import plausible from sympy.core.relational import Equality from sympy.functions.elementary.exponential import softmax from sympy import Symbol from sympy.functions.elementary.miscellaneous import sqrt, Min, Max from sympy.matrices.expressions.matmul import MatMul from sympy.concrete.summations import Sum from sympy.concrete.expr_with_limits import LAMBDA from sympy.core.function import Function from sympy.sets.contains import Contains from sympy.sets.sets import Interval clip = Function.clip(nargs=(3,), shape=(), eval=lambda a, a_min, a_max: Min(a_max, Max(a, a_min))) @plausible def apply(n, dx, dz): x = Symbol.x(shape=(n, dx), real=True) W_Q = Symbol("W^Q", shape=(dx, dz), real=True) W_K = Symbol("W^K", shape=(dx, dz), real=True) W_V = Symbol("W^V", shape=(dx, dz), real=True) Q = Symbol.Q(definition=x @ W_Q) K = Symbol.K(definition=x @ W_K) i = Symbol.i(integer=True) j = Symbol.j(integer=True) k = Symbol.k(integer=True, positive=True) w_K = Symbol("w^K", shape=(2 * k + 1, dz), real=True) w_V = Symbol("w^V", shape=(2 * k + 1, dz), real=True)
def pde_1st_linear_variable_coeff(eq, func, order, match, solvefun): r""" Solves a first order linear partial differential equation with variable coefficients. The general form of this partial differential equation is .. math:: a(x, y) \frac{df(x, y)}{dx} + a(x, y) \frac{df(x, y)}{dy} + c(x, y) f(x, y) - G(x, y) where `a(x, y)`, `b(x, y)`, `c(x, y)` and `G(x, y)` are arbitrary functions in `x` and `y`. This PDE is converted into an ODE by making the following transformation. 1] `\xi` as `x` 2] `\eta` as the constant in the solution to the differential equation `\frac{dy}{dx} = -\frac{b}{a}` Making the following substitutions reduces it to the linear ODE .. math:: a(\xi, \eta)\frac{du}{d\xi} + c(\xi, \eta)u - d(\xi, \eta) = 0 which can be solved using dsolve. The general form of this PDE is:: >>> from sympy.solvers.pde import pdsolve >>> from sympy.abc import x, y >>> from sympy import Function, pprint >>> a, b, c, G, f= [Function(i) for i in ['a', 'b', 'c', 'G', 'f']] >>> u = f(x,y) >>> ux = u.diff(x) >>> uy = u.diff(y) >>> genform = a(x, y)*u + b(x, y)*ux + c(x, y)*uy - G(x,y) >>> pprint(genform) d d -G(x, y) + a(x, y)*f(x, y) + b(x, y)*--(f(x, y)) + c(x, y)*--(f(x, y)) dx dy Examples ======== >>> from sympy.solvers.pde import pdsolve >>> from sympy import Function, diff, pprint, exp >>> from sympy.abc import x,y >>> f = Function('f') >>> eq = x*(u.diff(x)) - y*(u.diff(y)) + y**2*u - y**2 >>> pdsolve(eq) Eq(f(x, y), F(x*y)*exp(y**2/2) + 1) References ========== - Viktor Grigoryan, "Partial Differential Equations" Math 124A - Fall 2010, pp.7 """ from sympy.integrals.integrals import integrate from sympy.solvers.ode import dsolve xi, eta = symbols("xi eta") f = func.func x = func.args[0] y = func.args[1] b = match[match['b']] c = match[match['c']] d = match[match['d']] e = -match[match['e']] if not d: # To deal with cases like b*ux = e or c*uy = e if not (b and c): if c: try: tsol = integrate(e / c, y) except NotImplementedError: raise NotImplementedError("Unable to find a solution" " due to inability of integrate") else: return Eq(f(x, y), solvefun(x) + tsol) if b: try: tsol = integrate(e / b, x) except NotImplementedError: raise NotImplementedError("Unable to find a solution" " due to inability of integrate") else: return Eq(f(x, y), solvefun(y) + tsol) if not c: # To deal with cases when c is 0, a simpler method is used. # The PDE reduces to b*(u.diff(x)) + d*u = e, which is a linear ODE in x plode = f(x).diff(x) * b + d * f(x) - e sol = dsolve(plode, f(x)) syms = sol.free_symbols - plode.free_symbols - set([x, y]) rhs = _simplify_variable_coeff(sol.rhs, syms, solvefun, y) return Eq(f(x, y), rhs) if not b: # To deal with cases when b is 0, a simpler method is used. # The PDE reduces to c*(u.diff(y)) + d*u = e, which is a linear ODE in y plode = f(y).diff(y) * c + d * f(y) - e sol = dsolve(plode, f(y)) syms = sol.free_symbols - plode.free_symbols - set([x, y]) rhs = _simplify_variable_coeff(sol.rhs, syms, solvefun, x) return Eq(f(x, y), rhs) dummy = Function('d') h = (c / b).subs(y, dummy(x)) sol = dsolve(dummy(x).diff(x) - h, dummy(x)) if isinstance(sol, list): sol = sol[0] solsym = sol.free_symbols - h.free_symbols - set([x, y]) if len(solsym) == 1: solsym = solsym.pop() etat = (solve(sol, solsym)[0]).subs(dummy(x), y) ysub = solve(eta - etat, y)[0] deq = (b * (f(x).diff(x)) + d * f(x) - e).subs(y, ysub) final = (dsolve(deq, f(x), hint='1st_linear')).rhs if isinstance(final, list): final = final[0] finsyms = final.free_symbols - deq.free_symbols - set([x, y]) rhs = _simplify_variable_coeff(final, finsyms, solvefun, etat) return Eq(f(x, y), rhs) else: raise NotImplementedError( "Cannot solve the partial differential equation due" " to inability of constantsimp")
def test_deriv_sub_bug3(): f = Function('f') pat = Derivative(f(x), x, x) assert pat.subs(y, y**2) == Derivative(f(x), x, x) assert pat.subs(y, y**2) != Derivative(f(x), x)
def test_equality_subs2(): f = Function('f') eq = Eq(f(x)**2, 16) assert bool(eq.subs(f(x), 3)) is False assert bool(eq.subs(f(x), 4)) is True
def test_core_dynamicfunctions(): # This fails because f is assumed to be a class at sympy.basic.function.f f = Function("f") check(f)
def test_equality_subs1(): f = Function('f') eq = Eq(f(x)**2, x) res = Eq(Integer(16), x) assert eq.subs(f(x), 4) == res
def test_karr_convention(): # Test the Karr product convention that we want to hold. # See his paper "Summation in Finite Terms" for a detailed # reasoning why we really want exactly this definition. # The convention is described for sums on page 309 and # essentially in section 1.4, definition 3. For products # we can find in analogy: # # \prod_{m <= i < n} f(i) 'has the obvious meaning' for m < n # \prod_{m <= i < n} f(i) = 0 for m = n # \prod_{m <= i < n} f(i) = 1 / \prod_{n <= i < m} f(i) for m > n # # It is important to note that he defines all products with # the upper limit being *exclusive*. # In contrast, SymPy and the usual mathematical notation has: # # prod_{i = a}^b f(i) = f(a) * f(a+1) * ... * f(b-1) * f(b) # # with the upper limit *inclusive*. So translating between # the two we find that: # # \prod_{m <= i < n} f(i) = \prod_{i = m}^{n-1} f(i) # # where we intentionally used two different ways to typeset the # products and its limits. i = Symbol("i", integer=True) k = Symbol("k", integer=True) j = Symbol("j", integer=True, positive=True) # A simple example with a concrete factors and symbolic limits. # The normal product: m = k and n = k + j and therefore m < n: m = k n = k + j a = m b = n - 1 S1 = Product(i**2, (i, a, b)).doit() # The reversed product: m = k + j and n = k and therefore m > n: m = k + j n = k a = m b = n - 1 S2 = Product(i**2, (i, a, b)).doit() assert S1 * S2 == 1 # Test the empty product: m = k and n = k and therefore m = n: m = k n = k a = m b = n - 1 Sz = Product(i**2, (i, a, b)).doit() assert Sz == 1 # Another example this time with an unspecified factor and # numeric limits. (We can not do both tests in the same example.) f = Function("f") # The normal product with m < n: m = 2 n = 11 a = m b = n - 1 S1 = Product(f(i), (i, a, b)).doit() # The reversed product with m > n: m = 11 n = 2 a = m b = n - 1 S2 = Product(f(i), (i, a, b)).doit() assert simplify(S1 * S2) == 1 # Test the empty product with m = n: m = 5 n = 5 a = m b = n - 1 Sz = Product(f(i), (i, a, b)).doit() assert Sz == 1
def test_core_undefinedfunctions_fail(): # This fails because f is assumed to be a class at sympy.basic.function.f f = Function("f") check(f)
def test_issue_5095(): f = Function('f') raises(ValueError, lambda: dsolve(f(x).diff(x)**2, f(x), 'fdsjf'))
def _eval_nseries(self, x, n, logx): i = self.args[0].limit(x, 0)/S.Pi if i and i.is_Integer: return self.rewrite(cos)._eval_nseries(x, n=n, logx=logx) return Function._eval_nseries(self, x, n=n, logx=logx)
def apart(f, z, **flags): """Compute partial fraction decomposition of a rational function. Given a rational function 'f', performing only gcd operations over the algebraic closue of the initial field of definition, compute full partial fraction decomposition with fractions having linear denominators. For all other kinds of expressions the input is returned in an unchanged form. Note however, that 'apart' function can thread over sums and relational operators. Note that no factorization of the initial denominator of 'f' is needed. The final decomposition is formed in terms of a sum of RootSum instances. By default RootSum tries to compute all its roots to simplify itself. This behaviour can be however avoided by seting the keyword flag evaluate=False, which will make this function return a formal decomposition. >>> from sympy import * >>> x,y = symbols('xy') >>> apart(y/(x+2)/(x+1), x) y/(1 + x) - y/(2 + x) >>> apart(1/(1+x**5), x, evaluate=False) RootSum(Lambda(_a, -1/5/(x - _a)*_a), x**5 + 1, x) For more information on the implemented algorithm refer to: [1] M. Bronstein, B. Salvy, Full partial fraction decomposition of rational functions, in: M. Bronstein, ed., Proceedings ISSAC '93, ACM Press, Kiev, Ukraine, 1993, pp. 157-160. """ if not f.has(z): return f f = Poly.cancel(f, z) P, Q = f.as_numer_denom() if not Q.has(z): return f partial, r = div(P, Q, z) f, q, U = r / Q, Q, [] u = Function('u')(z) a = Symbol('a', dummy=True) for k, d in enumerate(poly_sqf(q, z)): n, b = k + 1, d.as_basic() U += [ u.diff(z, k) ] h = together(Poly.cancel(f*b**n, z) / u**n) H, subs = [h], [] for j in range(1, n): H += [ H[-1].diff(z) / j ] for j in range(1, n+1): subs += [ (U[j-1], b.diff(z, j) / j) ] for j in range(0, n): P, Q = together(H[j]).as_numer_denom() for i in range(0, j+1): P = P.subs(*subs[j-i]) Q = Q.subs(*subs[0]) P, Q = Poly(P, z), Poly(Q, z) G = poly_gcd(P, d) D = poly_quo(d, G) B, g = poly_half_gcdex(Q, D) b = poly_rem(P * poly_quo(B, g), D) numer = b.as_basic() denom = (z-a)**(n-j) expr = numer.subs(z, a) / denom partial += RootSum(Lambda(a, expr), D, **flags) return partial