def __new__(cls, name=None, longname=None): if name is None or name == "": name = "NoName_"+str(Quantity.dummy_count) Quantity.dummy_count += 1 self = Dummy.__new__(cls, name) else: self = Symbol.__new__(cls, name) self.count = Quantity.quantity_count Quantity.quantity_count += 1 self.abbrev = name self.name = name self.longname = longname self.value = None self.value_formula = None self.error = None self.error_formula = None self.prefer_unit = None self.dim = None return self
def __new__(cls, name=None, dummy_index=None, value=0, **assumptions): obj = Dummy.__new__(cls, name, dummy_index, **assumptions) obj.value = 0.0 return obj
def test_Dummy_assumption(): d = Dummy('d', nonzero=True) assert d == eval(srepr(d)) s1 = "Dummy('d', dummy_index=%s, nonzero=True)" % str(d.dummy_index) s2 = "Dummy('d', nonzero=True, dummy_index=%s)" % str(d.dummy_index) assert srepr(d) in (s1, s2)
def newtons_method(expr, wrt, atol=1e-12, delta=None, debug=False, itermax=None, counter=None): """ Generates an AST for Newton-Raphson method (a root-finding algorithm). Returns an abstract syntax tree (AST) based on ``sympy.codegen.ast`` for Netwon's method of root-finding. Parameters ========== expr : expression wrt : Symbol With respect to, i.e. what is the variable. atol : number or expr Absolute tolerance (stopping criterion) delta : Symbol Will be a ``Dummy`` if ``None``. debug : bool Whether to print convergence information during iterations itermax : number or expr Maximum number of iterations. counter : Symbol Will be a ``Dummy`` if ``None``. Examples ======== >>> from sympy import symbols, cos >>> from sympy.codegen.ast import Assignment >>> from sympy.codegen.algorithms import newtons_method >>> x, dx, atol = symbols('x dx atol') >>> expr = cos(x) - x**3 >>> algo = newtons_method(expr, x, atol, dx) >>> algo.has(Assignment(dx, -expr/expr.diff(x))) True References ========== .. [1] https://en.wikipedia.org/wiki/Newton%27s_method """ if delta is None: delta = Dummy() Wrapper = Scope name_d = 'delta' else: Wrapper = lambda x: x name_d = delta.name delta_expr = -expr / expr.diff(wrt) whl_bdy = [ Assignment(delta, delta_expr), AddAugmentedAssignment(wrt, delta) ] if debug: prnt = Print([wrt, delta], r"{0}=%12.5g {1}=%12.5g\n".format(wrt.name, name_d)) whl_bdy = [whl_bdy[0], prnt] + whl_bdy[1:] req = Gt(Abs(delta), atol) declars = [Declaration(Variable(delta, type=real, value=oo))] if itermax is not None: counter = counter or Dummy(integer=True) v_counter = Variable.deduced(counter, 0) declars.append(Declaration(v_counter)) whl_bdy.append(AddAugmentedAssignment(counter, 1)) req = And(req, Lt(counter, itermax)) whl = While(req, CodeBlock(*whl_bdy)) blck = declars + [whl] return Wrapper(CodeBlock(*blck))
def minimal_polynomial(ex, x=None, compose=True, polys=False, domain=None): """ Computes the minimal polynomial of an algebraic element. Parameters ========== ex : Expr Element or expression whose minimal polynomial is to be calculated. x : Symbol, optional Independent variable of the minimal polynomial compose : boolean, optional (default=True) Method to use for computing minimal polynomial. If ``compose=True`` (default) then ``_minpoly_compose`` is used, if ``compose=False`` then groebner bases are used. polys : boolean, optional (default=False) If ``True`` returns a ``Poly`` object else an ``Expr`` object. domain : Domain, optional Ground domain Notes ===== By default ``compose=True``, the minimal polynomial of the subexpressions of ``ex`` are computed, then the arithmetic operations on them are performed using the resultant and factorization. If ``compose=False``, a bottom-up algorithm is used with ``groebner``. The default algorithm stalls less frequently. If no ground domain is given, it will be generated automatically from the expression. Examples ======== >>> from sympy import minimal_polynomial, sqrt, solve, QQ >>> from sympy.abc import x, y >>> minimal_polynomial(sqrt(2), x) x**2 - 2 >>> minimal_polynomial(sqrt(2), x, domain=QQ.algebraic_field(sqrt(2))) x - sqrt(2) >>> minimal_polynomial(sqrt(2) + sqrt(3), x) x**4 - 10*x**2 + 1 >>> minimal_polynomial(solve(x**3 + x + 3)[0], x) x**3 + x + 3 >>> minimal_polynomial(sqrt(y), x) x**2 - y """ from sympy.polys.polytools import degree from sympy.polys.domains import FractionField from sympy.core.basic import preorder_traversal ex = sympify(ex) if ex.is_number: # not sure if it's always needed but try it for numbers (issue 8354) ex = _mexpand(ex, recursive=True) for expr in preorder_traversal(ex): if expr.is_AlgebraicNumber: compose = False break if x is not None: x, cls = sympify(x), Poly else: x, cls = Dummy('x'), PurePoly if not domain: if ex.free_symbols: domain = FractionField(QQ, list(ex.free_symbols)) else: domain = QQ if hasattr(domain, 'symbols') and x in domain.symbols: raise GeneratorsError("the variable %s is an element of the ground " "domain %s" % (x, domain)) if compose: result = _minpoly_compose(ex, x, domain) result = result.primitive()[1] c = result.coeff(x**degree(result, x)) if c.is_negative: result = expand_mul(-result) return cls(result, x, field=True) if polys else result.collect(x) if not domain.is_QQ: raise NotImplementedError("groebner method only works for QQ") result = _minpoly_groebner(ex, x, cls) return cls(result, x, field=True) if polys else result.collect(x)
def test_lambdify_mixed_symbol_dummy_args(): d = Dummy() # Contrived example of name clash dsym = symbols(str(d)) f = lambdify([d, dsym], d - dsym) assert f(4, 1) == 3
Xor, Complement, SymmetricDifference, AccumBounds, UnevaluatedExpr, Eq, Ne, Quaternion) from sympy.core import Expr, Mul from sympy.physics.units import second, joule from sympy.polys import Poly, rootof, RootSum, groebner, ring, field, ZZ, QQ, lex, grlex from sympy.geometry import Point, Circle from sympy.utilities.pytest import raises from sympy.core.compatibility import range from sympy.printing import sstr, sstrrepr, StrPrinter from sympy.core.trace import Tr from sympy import MatrixSymbol x, y, z, w, t = symbols('x,y,z,w,t') d = Dummy('d') def test_printmethod(): class R(Abs): def _sympystr(self, printer): return "foo(%s)" % printer._print(self.args[0]) assert sstr(R(x)) == "foo(x)" class R(Abs): def _sympystr(self, printer): return "foo" assert sstr(R(x)) == "foo"
def compute_characteristic_function(self, expr): d = self.compute_density(expr) t = Dummy('t', real=True) return Lambda(t, sum(exp(I * k * t) * v for k, v in d.items()))
def _eval_rewrite_as_Sum(self, expr, **kwargs): from sympy import Sum, Dummy i = Dummy('i') return Sum(self.arg[i, i], (i, 0, self.arg.rows - 1)).doit()
def lambdastr(args, expr, printer=None, dummify=False): """ Returns a string that can be evaluated to a lambda function. Examples ======== >>> from sympy.abc import x, y, z >>> from sympy.utilities.lambdify import lambdastr >>> lambdastr(x, x**2) 'lambda x: (x**2)' >>> lambdastr((x,y,z), [z,y,x]) 'lambda x,y,z: ([z, y, x])' Although tuples may not appear as arguments to lambda in Python 3, lambdastr will create a lambda function that will unpack the original arguments so that nested arguments can be handled: >>> lambdastr((x, (y, z)), x + y) 'lambda _0,_1: (lambda x,y,z: (x + y))(*list(__flatten_args__([_0,_1])))' """ # Transforming everything to strings. from sympy.matrices import DeferredVector from sympy import Dummy, sympify, Symbol, Function, flatten if printer is not None: if inspect.isfunction(printer): lambdarepr = printer else: if inspect.isclass(printer): lambdarepr = lambda expr: printer().doprint(expr) else: lambdarepr = lambda expr: printer.doprint(expr) else: #XXX: This has to be done here because of circular imports from sympy.printing.lambdarepr import lambdarepr def sub_args(args, dummies_dict): if isinstance(args, str): return args elif isinstance(args, DeferredVector): return str(args) elif iterable(args): dummies = flatten([sub_args(a, dummies_dict) for a in args]) return ",".join(str(a) for a in dummies) else: #Sub in dummy variables for functions or symbols if isinstance(args, (Function, Symbol)): dummies = Dummy() dummies_dict.update({args : dummies}) return str(dummies) else: return str(args) def sub_expr(expr, dummies_dict): try: expr = sympify(expr).xreplace(dummies_dict) except Exception: if isinstance(expr, DeferredVector): pass elif isinstance(expr, dict): k = [sub_expr(sympify(a), dummies_dict) for a in expr.keys()] v = [sub_expr(sympify(a), dummies_dict) for a in expr.values()] expr = dict(zip(k, v)) elif isinstance(expr, tuple): expr = tuple(sub_expr(sympify(a), dummies_dict) for a in expr) elif isinstance(expr, list): expr = [sub_expr(sympify(a), dummies_dict) for a in expr] return expr # Transform args def isiter(l): return iterable(l, exclude=(str, DeferredVector, NotIterable)) if isiter(args) and any(isiter(i) for i in args): from sympy.utilities.iterables import flatten import re dum_args = [str(Dummy(str(i))) for i in range(len(args))] iter_args = ','.join([i if isiter(a) else i for i, a in zip(dum_args, args)]) lstr = lambdastr(flatten(args), expr, printer=printer, dummify=dummify) flat = '__flatten_args__' rv = 'lambda %s: (%s)(*list(%s([%s])))' % ( ','.join(dum_args), lstr, flat, iter_args) if len(re.findall(r'\b%s\b' % flat, rv)) > 1: raise ValueError('the name %s is reserved by lambdastr' % flat) return rv dummies_dict = {} if dummify: args = sub_args(args, dummies_dict) else: if isinstance(args, str): pass elif iterable(args, exclude=DeferredVector): args = ",".join(str(a) for a in args) # Transform expr if dummify: if isinstance(expr, str): pass else: expr = sub_expr(expr, dummies_dict) expr = lambdarepr(expr) return "lambda %s: (%s)" % (args, expr)
def primitive_element(extension, x=None, **args): """Construct a common number field for all extensions. """ if not extension: raise ValueError("can't compute primitive element for empty extension") if x is not None: x, cls = sympify(x), Poly else: x, cls = Dummy('x'), PurePoly if not args.get('ex', False): gen, coeffs = extension[0], [1] # XXX when minimal_polynomial is extended to work # with AlgebraicNumbers this test can be removed if isinstance(gen, AlgebraicNumber): g = gen.minpoly.replace(x) else: g = minimal_polynomial(gen, x, polys=True) for ext in extension[1:]: _, factors = factor_list(g, extension=ext) g = _choose_factor(factors, x, gen) s, _, g = g.sqf_norm() gen += s * ext coeffs.append(s) if not args.get('polys', False): return g.as_expr(), coeffs else: return cls(g), coeffs generator = numbered_symbols('y', cls=Dummy) F, Y = [], [] for ext in extension: y = next(generator) if ext.is_Poly: if ext.is_univariate: f = ext.as_expr(y) else: raise ValueError("expected minimal polynomial, got %s" % ext) else: f = minpoly(ext, y) F.append(f) Y.append(y) coeffs_generator = args.get('coeffs', _coeffs_generator) for coeffs in coeffs_generator(len(Y)): f = x - sum([c * y for c, y in zip(coeffs, Y)]) G = groebner(F + [f], Y + [x], order='lex', field=True) H, g = G[:-1], cls(G[-1], x, domain='QQ') for i, (h, y) in enumerate(zip(H, Y)): try: H[i] = Poly(y - h, x, domain='QQ').all_coeffs() # XXX: composite=False except CoercionFailed: # pragma: no cover break # G is not a triangular set else: break else: # pragma: no cover raise RuntimeError("run out of coefficient configurations") _, g = g.clear_denoms() if not args.get('polys', False): return g.as_expr(), coeffs, H else: return g, coeffs, H
def compute_quantile(self, expr, **kwargs): if expr == self.value: p = Dummy("p", real=True) return Lambda(p, self.distribution.quantile(p, **kwargs)) else: raise NotImplementedError()
def compute_cdf(self, expr, **kwargs): if expr == self.value: x = Dummy("x", real=True) return Lambda(x, self.distribution.cdf(x, **kwargs)) else: raise NotImplementedError()
def compute_moment_generating_function(self, **kwargs): t = Dummy('t', real=True) x = Dummy('x', integer=True) pdf = self.pdf(x) mgf = summation(exp(t * x) * pdf, (x, self.set.inf, self.set.sup)) return Lambda(t, mgf)
def moment_generating_function(self): t = Dummy('t', real=True) return Lambda(t, sum(exp(k * t) * v for k, v in self.dict.items()))
from sympy.core.cache import clear_cache from sympy.core.expr import unchanged from sympy.core.function import (PoleError, _mexpand, arity, BadSignatureError, BadArgumentsError) from sympy.core.parameters import _exp_is_pow from sympy.core.sympify import sympify from sympy.matrices import MutableMatrix, ImmutableMatrix from sympy.sets.sets import FiniteSet from sympy.solvers.solveset import solveset from sympy.tensor.array import NDimArray from sympy.utilities.iterables import subsets, variations from sympy.testing.pytest import XFAIL, raises, warns_deprecated_sympy, _both_exp_pow from sympy.abc import t, w, x, y, z f, g, h = symbols('f g h', cls=Function) _xi_1, _xi_2, _xi_3 = [Dummy() for i in range(3)] def test_f_expand_complex(): x = Symbol('x', real=True) assert f(x).expand(complex=True) == I*im(f(x)) + re(f(x)) assert exp(x).expand(complex=True) == exp(x) assert exp(I*x).expand(complex=True) == cos(x) + I*sin(x) assert exp(z).expand(complex=True) == cos(im(z))*exp(re(z)) + \ I*sin(im(z))*exp(re(z)) def test_bug1(): e = sqrt(-log(w)) assert e.subs(log(w), -x) == sqrt(x)
def test_dice(): # TODO: Make iid method! X, Y, Z = Die('X', 6), Die('Y', 6), Die('Z', 6) a, b, t, p = symbols('a b t p') assert E(X) == 3 + S.Half assert variance(X) == Rational(35, 12) assert E(X + Y) == 7 assert E(X + X) == 7 assert E(a * X + b) == a * E(X) + b assert variance(X + Y) == variance(X) + variance(Y) == cmoment(X + Y, 2) assert variance(X + X) == 4 * variance(X) == cmoment(X + X, 2) assert cmoment(X, 0) == 1 assert cmoment(4 * X, 3) == 64 * cmoment(X, 3) assert covariance(X, Y) is S.Zero assert covariance(X, X + Y) == variance(X) assert density(Eq(cos(X * S.Pi), 1))[True] == S.Half assert correlation(X, Y) == 0 assert correlation(X, Y) == correlation(Y, X) assert smoment(X + Y, 3) == skewness(X + Y) assert smoment(X + Y, 4) == kurtosis(X + Y) assert smoment(X, 0) == 1 assert P(X > 3) == S.Half assert P(2 * X > 6) == S.Half assert P(X > Y) == Rational(5, 12) assert P(Eq(X, Y)) == P(Eq(X, 1)) assert E(X, X > 3) == 5 == moment(X, 1, 0, X > 3) assert E(X, Y > 3) == E(X) == moment(X, 1, 0, Y > 3) assert E(X + Y, Eq(X, Y)) == E(2 * X) assert moment(X, 0) == 1 assert moment(5 * X, 2) == 25 * moment(X, 2) assert quantile(X)(p) == Piecewise((nan, (p > 1) | (p < 0)),\ (S.One, p <= Rational(1, 6)), (S(2), p <= Rational(1, 3)), (S(3), p <= S.Half),\ (S(4), p <= Rational(2, 3)), (S(5), p <= Rational(5, 6)), (S(6), p <= 1)) assert P(X > 3, X > 3) is S.One assert P(X > Y, Eq(Y, 6)) is S.Zero assert P(Eq(X + Y, 12)) == Rational(1, 36) assert P(Eq(X + Y, 12), Eq(X, 6)) == Rational(1, 6) assert density(X + Y) == density(Y + Z) != density(X + X) d = density(2 * X + Y**Z) assert d[S(22)] == Rational(1, 108) and d[S(4100)] == Rational( 1, 216) and S(3130) not in d assert pspace(X).domain.as_boolean() == Or( *[Eq(X.symbol, i) for i in [1, 2, 3, 4, 5, 6]]) assert where(X > 3).set == FiniteSet(4, 5, 6) assert characteristic_function(X)(t) == exp(6 * I * t) / 6 + exp( 5 * I * t) / 6 + exp(4 * I * t) / 6 + exp(3 * I * t) / 6 + exp( 2 * I * t) / 6 + exp(I * t) / 6 assert moment_generating_function(X)( t) == exp(6 * t) / 6 + exp(5 * t) / 6 + exp(4 * t) / 6 + exp( 3 * t) / 6 + exp(2 * t) / 6 + exp(t) / 6 assert median(X) == FiniteSet(3, 4) D = Die('D', 7) assert median(D) == FiniteSet(4) # Bayes test for die BayesTest(X > 3, X + Y < 5) BayesTest(Eq(X - Y, Z), Z > Y) BayesTest(X > 3, X > 2) # arg test for die raises(ValueError, lambda: Die('X', -1)) # issue 8105: negative sides. raises(ValueError, lambda: Die('X', 0)) raises(ValueError, lambda: Die('X', 1.5)) # issue 8103: non integer sides. # symbolic test for die n, k = symbols('n, k', positive=True) D = Die('D', n) dens = density(D).dict assert dens == Density(DieDistribution(n)) assert set(dens.subs(n, 4).doit().keys()) == set([1, 2, 3, 4]) assert set(dens.subs(n, 4).doit().values()) == set([Rational(1, 4)]) k = Dummy('k', integer=True) assert E(D).dummy_eq(Sum(Piecewise((k / n, k <= n), (0, True)), (k, 1, n))) assert variance(D).subs(n, 6).doit() == Rational(35, 12) ki = Dummy('ki') cumuf = cdf(D)(k) assert cumuf.dummy_eq( Sum(Piecewise((1 / n, (ki >= 1) & (ki <= n)), (0, True)), (ki, 1, k))) assert cumuf.subs({n: 6, k: 2}).doit() == Rational(1, 3) t = Dummy('t') cf = characteristic_function(D)(t) assert cf.dummy_eq( Sum(Piecewise((exp(ki * I * t) / n, (ki >= 1) & (ki <= n)), (0, True)), (ki, 1, n))) assert cf.subs( n, 3).doit() == exp(3 * I * t) / 3 + exp(2 * I * t) / 3 + exp(I * t) / 3 mgf = moment_generating_function(D)(t) assert mgf.dummy_eq( Sum(Piecewise((exp(ki * t) / n, (ki >= 1) & (ki <= n)), (0, True)), (ki, 1, n))) assert mgf.subs(n, 3).doit() == exp(3 * t) / 3 + exp(2 * t) / 3 + exp(t) / 3
def compute_moment_generating_function(self, expr): d = self.compute_density(expr) t = Dummy('t', real=True) return Lambda(t, sum(exp(k * t) * v for k, v in d.items()))
def intersection_sets(a, b): # noqa:F811 from sympy.solvers.diophantine import diop_linear from sympy.core.numbers import ilcm from sympy import sign # non-overlap quick exits if not b: return S.EmptySet if not a: return S.EmptySet if b.sup < a.inf: return S.EmptySet if b.inf > a.sup: return S.EmptySet # work with finite end at the start r1 = a if r1.start.is_infinite: r1 = r1.reversed r2 = b if r2.start.is_infinite: r2 = r2.reversed # If both ends are infinite then it means that one Range is just the set # of all integers (the step must be 1). if r1.start.is_infinite: return b if r2.start.is_infinite: return a # this equation represents the values of the Range; # it's a linear equation eq = lambda r, i: r.start + i * r.step # we want to know when the two equations might # have integer solutions so we use the diophantine # solver va, vb = diop_linear(eq(r1, Dummy('a')) - eq(r2, Dummy('b'))) # check for no solution no_solution = va is None and vb is None if no_solution: return S.EmptySet # there is a solution # ------------------- # find the coincident point, c a0 = va.as_coeff_Add()[0] c = eq(r1, a0) # find the first point, if possible, in each range # since c may not be that point def _first_finite_point(r1, c): if c == r1.start: return c # st is the signed step we need to take to # get from c to r1.start st = sign(r1.start - c) * step # use Range to calculate the first point: # we want to get as close as possible to # r1.start; the Range will not be null since # it will at least contain c s1 = Range(c, r1.start + st, st)[-1] if s1 == r1.start: pass else: # if we didn't hit r1.start then, if the # sign of st didn't match the sign of r1.step # we are off by one and s1 is not in r1 if sign(r1.step) != sign(st): s1 -= st if s1 not in r1: return return s1 # calculate the step size of the new Range step = abs(ilcm(r1.step, r2.step)) s1 = _first_finite_point(r1, c) if s1 is None: return S.EmptySet s2 = _first_finite_point(r2, c) if s2 is None: return S.EmptySet # replace the corresponding start or stop in # the original Ranges with these points; the # result must have at least one point since # we know that s1 and s2 are in the Ranges def _updated_range(r, first): st = sign(r.step) * step if r.start.is_finite: rv = Range(first, r.stop, st) else: rv = Range(r.start, first + st, st) return rv r1 = _updated_range(a, s1) r2 = _updated_range(b, s2) # work with them both in the increasing direction if sign(r1.step) < 0: r1 = r1.reversed if sign(r2.step) < 0: r2 = r2.reversed # return clipped Range with positive step; it # can't be empty at this point start = max(r1.start, r2.start) stop = min(r1.stop, r2.stop) return Range(start, stop, step)
def integrate_pendulum_odes(self, adv_time_vector=None, pos_init=235): """ Method to integrate Nth-order pendulum ODEs. """ # Instantiates physics constants for position, velocity, mass, length, gravity, and time q, u = mechanics.dynamicsymbols("q:{0}".format(str( self.N))), mechanics.dynamicsymbols("u:{0}".format(str(self.N))) m, l = symbols("m:{0}".format(str(self.N))), symbols("l:{0}".format( str(self.N))) g, t = symbols("g t") # Creates intertial reference frame frame = mechanics.ReferenceFrame("frame") # Creates focus point in intertial reference frame point = mechanics.Point("point") point.set_vel(frame, 0) # Instantiates empty objects for pendulum segment points, reactionary forces, and resultant kinematic ODEs particles, forces, kin_odes = list(), list(), list() # Iteratively creates pendulum segment kinematics/dynamics objects for iterator in range(self.N): # Creates and sets angular velocity per reference frame for each pendulum segment frame_i = frame.orientnew("frame_{}".format(str(iterator)), "Axis", [q[iterator], frame.z]) frame_i.set_ang_vel(frame, u[iterator] * frame.z) # Creates and sets velocity of focus point for each pendulum segment point_i = point.locatenew("point_{}".format(str(iterator)), l[iterator] * frame_i.x) point_i.v2pt_theory(point, frame, frame_i) # Creates reference point for each pendulum segment ref_point_i = mechanics.Particle( "ref_point_{}".format(str(iterator)), point_i, m[iterator]) particles.append(ref_point_i) # Creates objects for reference frame dynamics forces.append((point_i, m[iterator] * g * frame.x)) kin_odes.append(q[iterator].diff(t) - u[iterator]) point = point_i # Generates position and velocity equation systems using Kane's Method kane = mechanics.KanesMethod(frame, q_ind=q, u_ind=u, kd_eqs=kin_odes) fr, frstar = kane.kanes_equations(particles, forces) # Creates vector for initial positions and velocities y0 = np.deg2rad( np.concatenate([ np.broadcast_to(pos_init, self.N), np.broadcast_to(self.vel_init, self.N) ])) # Creates vectors for pendulum segment lengths and masses length_vector = np.ones(self.N) / self.N length_vector = np.broadcast_to(length_vector, self.N) self.mass_vector = np.broadcast_to(self.mass_vector, self.N) # Instantiates and creates fixed constant vectors (gravity, lengths, masses) params = [g] + list(l) + list(m) param_vals = [9.81] + list(length_vector) + list(self.mass_vector) # Initializes objects to solve for unknown parameters dummy_params = [Dummy() for iterator in q + u] dummy_dict = dict(zip(q + u, dummy_params)) # Converts unknown parametric objects into Kane's Method objects for numerical substitution kin_diff_dict = kane.kindiffdict() mass_matrix = kane.mass_matrix_full.subs(kin_diff_dict).subs( dummy_dict) full_forcing_vector = kane.forcing_full.subs(kin_diff_dict).subs( dummy_dict) # Functionalizes Kane's Method unknown parametric objects using NumPy for numerical substitution mm_func = lambdify(dummy_params + params, mass_matrix) ff_func = lambdify(dummy_params + params, full_forcing_vector) # Defines helper method with gradient calculus to use with ODE integration def __parametric_gradient_function(y, t, args): """ Helper function to derive first-order equations of motion from parametric arguments. """ values = np.concatenate((y, args)) solutions = np.linalg.solve(mm_func(*values), ff_func(*values)) return np.array(solutions).T[0] if adv_time_vector is None: return odeint(__parametric_gradient_function, y0, self.time_vector, args=(param_vals, )) else: return odeint(__parametric_gradient_function, y0, adv_time_vector, args=(param_vals, ))
def intersection_sets(self, other): # noqa:F811 from sympy.solvers.diophantine import diophantine # Only handle the straight-forward univariate case if (len(self.lamda.variables) > 1 or self.lamda.signature != self.lamda.variables): return None base_set = self.base_sets[0] # Intersection between ImageSets with Integers as base set # For {f(n) : n in Integers} & {g(m) : m in Integers} we solve the # diophantine equations f(n)=g(m). # If the solutions for n are {h(t) : t in Integers} then we return # {f(h(t)) : t in integers}. if base_set is S.Integers: gm = None if isinstance(other, ImageSet) and other.base_sets == (S.Integers, ): gm = other.lamda.expr m = other.lamda.variables[0] elif other is S.Integers: m = gm = Dummy('x') if gm is not None: fn = self.lamda.expr n = self.lamda.variables[0] solns = list(diophantine(fn - gm, syms=(n, m))) if len(solns) == 0: return EmptySet elif len(solns) != 1: return else: soln, solm = solns[0] (t, ) = soln.free_symbols expr = fn.subs(n, soln.subs(t, n)) return imageset(Lambda(n, expr), S.Integers) if other == S.Reals: from sympy.solvers.solveset import solveset_real from sympy.core.function import expand_complex f = self.lamda.expr n = self.lamda.variables[0] n_ = Dummy(n.name, real=True) f_ = f.subs(n, n_) re, im = f_.as_real_imag() im = expand_complex(im) re = re.subs(n_, n) im = im.subs(n_, n) ifree = im.free_symbols lam = Lambda(n, re) if not im: # allow re-evaluation # of self in this case to make # the result canonical pass elif im.is_zero is False: return S.EmptySet elif ifree != {n}: return None else: # univarite imaginary part in same variable base_set = base_set.intersect(solveset_real(im, n)) return imageset(lam, base_set) elif isinstance(other, Interval): from sympy.solvers.solveset import (invert_real, invert_complex, solveset) f = self.lamda.expr n = self.lamda.variables[0] new_inf, new_sup = None, None new_lopen, new_ropen = other.left_open, other.right_open if f.is_real: inverter = invert_real else: inverter = invert_complex g1, h1 = inverter(f, other.inf, n) g2, h2 = inverter(f, other.sup, n) if all(isinstance(i, FiniteSet) for i in (h1, h2)): if g1 == n: if len(h1) == 1: new_inf = h1.args[0] if g2 == n: if len(h2) == 1: new_sup = h2.args[0] # TODO: Design a technique to handle multiple-inverse # functions # Any of the new boundary values cannot be determined if any(i is None for i in (new_sup, new_inf)): return range_set = S.EmptySet if all(i.is_real for i in (new_sup, new_inf)): # this assumes continuity of underlying function # however fixes the case when it is decreasing if new_inf > new_sup: new_inf, new_sup = new_sup, new_inf new_interval = Interval(new_inf, new_sup, new_lopen, new_ropen) range_set = base_set.intersect(new_interval) else: if other.is_subset(S.Reals): solutions = solveset(f, n, S.Reals) if not isinstance(range_set, (ImageSet, ConditionSet)): range_set = solutions.intersect(other) else: return if range_set is S.EmptySet: return S.EmptySet elif isinstance(range_set, Range) and range_set.size is not S.Infinity: range_set = FiniteSet(*list(range_set)) if range_set is not None: return imageset(Lambda(n, f), range_set) return else: return
def _minpoly_op_algebraic_element(op, ex1, ex2, x, dom, mp1=None, mp2=None): """ return the minimal polynomial for ``op(ex1, ex2)`` Parameters ========== op : operation ``Add`` or ``Mul`` ex1, ex2 : expressions for the algebraic elements x : indeterminate of the polynomials dom: ground domain mp1, mp2 : minimal polynomials for ``ex1`` and ``ex2`` or None Examples ======== >>> from sympy import sqrt, Add, Mul, QQ >>> from sympy.polys.numberfields import _minpoly_op_algebraic_element >>> from sympy.abc import x, y >>> p1 = sqrt(sqrt(2) + 1) >>> p2 = sqrt(sqrt(2) - 1) >>> _minpoly_op_algebraic_element(Mul, p1, p2, x, QQ) x - 1 >>> q1 = sqrt(y) >>> q2 = 1 / y >>> _minpoly_op_algebraic_element(Add, q1, q2, x, QQ.frac_field(y)) x**2*y**2 - 2*x*y - y**3 + 1 References ========== .. [1] https://en.wikipedia.org/wiki/Resultant .. [2] I.M. Isaacs, Proc. Amer. Math. Soc. 25 (1970), 638 "Degrees of sums in a separable field extension". """ y = Dummy(str(x)) if mp1 is None: mp1 = _minpoly_compose(ex1, x, dom) if mp2 is None: mp2 = _minpoly_compose(ex2, y, dom) else: mp2 = mp2.subs({x: y}) if op is Add: # mp1a = mp1.subs({x: x - y}) if dom == QQ: R, X = ring('X', QQ) p1 = R(dict_from_expr(mp1)[0]) p2 = R(dict_from_expr(mp2)[0]) else: (p1, p2), _ = parallel_poly_from_expr((mp1, x - y), x, y) r = p1.compose(p2) mp1a = r.as_expr() elif op is Mul: mp1a = _muly(mp1, x, y) else: raise NotImplementedError('option not available') if op is Mul or dom != QQ: r = resultant(mp1a, mp2, gens=[y, x]) else: r = rs_compose_add(p1, p2) r = expr_from_dict(r.as_expr_dict(), x) deg1 = degree(mp1, x) deg2 = degree(mp2, y) if op is Mul and deg1 == 1 or deg2 == 1: # if deg1 = 1, then mp1 = x - a; mp1a = x - y - a; # r = mp2(x - a), so that `r` is irreducible return r r = Poly(r, x, domain=dom) _, factors = r.factor_list() res = _choose_factor(factors, x, op(ex1, ex2), dom) return res.as_expr()
def ratint_logpart(f, g, x, t=None): r""" Lazard-Rioboo-Trager algorithm. Given a field K and polynomials f and g in K[x], such that f and g are coprime, deg(f) < deg(g) and g is square-free, returns a list of tuples (s_i, q_i) of polynomials, for i = 1..n, such that s_i in K[t, x] and q_i in K[t], and:: ___ ___ d f d \ ` \ ` -- - = -- ) ) a log(s_i(a, x)) dx g dx /__, /__, i=1..n a | q_i(a) = 0 Examples ======== >>> from sympy.integrals.rationaltools import ratint_logpart >>> from sympy.abc import x >>> from sympy import Poly >>> ratint_logpart(Poly(1, x, domain='ZZ'), ... Poly(x**2 + x + 1, x, domain='ZZ'), x) [(Poly(x + 3*_t/2 + 1/2, x, domain='QQ[_t]'), ...Poly(3*_t**2 + 1, _t, domain='ZZ'))] >>> ratint_logpart(Poly(12, x, domain='ZZ'), ... Poly(x**2 - x - 2, x, domain='ZZ'), x) [(Poly(x - 3*_t/8 - 1/2, x, domain='QQ[_t]'), ...Poly(-_t**2 + 16, _t, domain='ZZ'))] See Also ======== ratint, ratint_ratpart """ f, g = Poly(f, x), Poly(g, x) t = t or Dummy('t') a, b = g, f - g.diff() * Poly(t, x) res, R = resultant(a, b, includePRS=True) res = Poly(res, t, composite=False) assert res, "BUG: resultant(%s, %s) can't be zero" % (a, b) R_map, H = {}, [] for r in R: R_map[r.degree()] = r def _include_sign(c, sqf): if c.is_extended_real and (c < 0) == True: h, k = sqf[0] c_poly = c.as_poly(h.gens) sqf[0] = h * c_poly, k C, res_sqf = res.sqf_list() _include_sign(C, res_sqf) for q, i in res_sqf: _, q = q.primitive() if g.degree() == i: H.append((g, q)) else: h = R_map[i] h_lc = Poly(h.LC(), t, field=True) c, h_lc_sqf = h_lc.sqf_list(all=True) _include_sign(c, h_lc_sqf) for a, j in h_lc_sqf: h = h.quo(Poly(a.gcd(q)**j, x)) inv, coeffs = h_lc.invert(q), [S.One] for coeff in h.coeffs()[1:]: coeff = coeff.as_poly(inv.gens) T = (inv * coeff).rem(q) coeffs.append(T.as_expr()) h = Poly(dict(list(zip(h.monoms(), coeffs))), x) H.append((h, q)) return H
def f(): counter = 1 while True: yield Dummy("i_%i" % counter) counter += 1
def ratint(f, x, **flags): """ Performs indefinite integration of rational functions. Given a field :math:`K` and a rational function :math:`f = p/q`, where :math:`p` and :math:`q` are polynomials in :math:`K[x]`, returns a function :math:`g` such that :math:`f = g'`. >>> from sympy.integrals.rationaltools import ratint >>> from sympy.abc import x >>> ratint(36/(x**5 - 2*x**4 - 2*x**3 + 4*x**2 + x - 2), x) (12*x + 6)/(x**2 - 1) + 4*log(x - 2) - 4*log(x + 1) References ========== .. [Bro05] M. Bronstein, Symbolic Integration I: Transcendental Functions, Second Edition, Springer-Verlag, 2005, pp. 35-70 See Also ======== sympy.integrals.integrals.Integral.doit sympy.integrals.rationaltools.ratint_logpart sympy.integrals.rationaltools.ratint_ratpart """ if type(f) is not tuple: p, q = f.as_numer_denom() else: p, q = f p, q = Poly(p, x, composite=False, field=True), Poly(q, x, composite=False, field=True) coeff, p, q = p.cancel(q) poly, p = p.div(q) result = poly.integrate(x).as_expr() if p.is_zero: return coeff * result g, h = ratint_ratpart(p, q, x) P, Q = h.as_numer_denom() P = Poly(P, x) Q = Poly(Q, x) q, r = P.div(Q) result += g + q.integrate(x).as_expr() if not r.is_zero: symbol = flags.get('symbol', 't') if not isinstance(symbol, Symbol): t = Dummy(symbol) else: t = symbol.as_dummy() L = ratint_logpart(r, Q, x, t) real = flags.get('real') if real is None: if type(f) is not tuple: atoms = f.atoms() else: p, q = f atoms = p.atoms() | q.atoms() for elt in atoms - {x}: if not elt.is_extended_real: real = False break else: real = True eps = S.Zero if not real: for h, q in L: _, h = h.primitive() eps += RootSum(q, Lambda(t, t * log(h.as_expr())), quadratic=True) else: for h, q in L: _, h = h.primitive() R = log_to_real(h, q, x, t) if R is not None: eps += R else: eps += RootSum(q, Lambda(t, t * log(h.as_expr())), quadratic=True) result += eps return coeff * result
def test_Dummy(): d = Dummy('d') sT(d, "Dummy('d', dummy_index=%s)" % str(d.dummy_index))
def _try_expm1(expr): protected, old_new = expr.replace(exp, lambda arg: Dummy(), map=True) factored = protected.factor() new_old = {v: k for k, v in old_new.items()} return factored.replace( _d - 1, lambda d: expm1(new_old[d].args[0])).xreplace(new_old)
def test_other(self): from sympy.abc import x assert recognize(Lebesgue(0,1), x, density(Normal(Dummy(),0,1))(x)) == None assert recognize(Lebesgue(-oo,oo), x, exp(-x**4)) == None
def test_issue_9326(): from sympy import Dummy d1 = Dummy('d') d2 = Dummy('d') e = d1 + d2 assert e.evalf(subs={d1: 1, d2: 2}) == 3
def compute_cdf(self, expr, **kwargs): if expr == self.value: z = Dummy("z", real=True) return Lambda(z, self.distribution.cdf(z, **kwargs)) else: return ContinuousPSpace.compute_cdf(self, expr, **kwargs)
def _setup_design(self): """ Initialize design Create a callable object to evaluate the design matrix at a given set of parameter values to be specified by a recarray and observed Term values, also specified by a recarray. """ # the design expression is the differentiation of the expression # for the mean. It is a list d = self.design_expr # Before evaluating, we recreate the formula # with numbered terms, and numbered parameters. # This renaming has no impact on the # final design matrix as the # callable, self._f below, is a lambda # that does not care about the names of the terms. # First, find all terms in the mean expression, # and rename them in the form "__t%d__" with a # random offset. # This may cause a possible problem # when there are parameters named something like "__t%d__". # Using the random offset will minimize the possibility # of this happening. # This renaming is here principally because of the intercept. random_offset = np.random.random_integers(low=0, high=2**30) terms = getterms(self.mean) newterms = [] for i, t in enumerate(terms): newt = sympy.Symbol("__t%d__" % (i + random_offset)) for j, _ in enumerate(d): d[j] = d[j].subs(t, newt) newterms.append(newt) # Next, find all parameters that remain in the design expression. # In a standard regression model, there will be no parameters # because they will all be differentiated away in computing # self.design_expr. In nonlinear models, parameters will remain. params = getparams(self.design_expr) newparams = [] for i, p in enumerate(params): newp = Dummy("__p%d__" % (i + random_offset)) for j, _ in enumerate(d): d[j] = d[j].subs(p, newp) newparams.append(newp) # If there are any aliased functions, these need to be added # to the name space before sympy lambdifies the expression # These "aliased" functions are used for things like # the natural splines, etc. You can represent natural splines # with sympy but the expression is pretty awful. Note that # ``d`` here is list giving the differentiation of the # expression for the mean. self._f(...) therefore also returns # a list self._f = lambdify(newparams + newterms, d, ("numpy")) # The input to self.design will be a recarray of that must # have field names that the Formula will expect to see. # However, if any of self.terms are FactorTerms, then the field # in the recarray will not actually be in the Term. # # For example, if there is a Factor 'f' with levels ['a','b'], # there will be terms 'f_a' and 'f_b', though the input to # design will have a field named 'f'. In this sense, # the recarray used in the call to self.design # is not really made up of terms, but "preterms". # In this case, the callable preterm = [] for t in terms: if not is_factor_term(t): preterm.append(str(t)) else: preterm.append(t.factor_name) preterm = list(set(preterm)) # There is also an argument for parameters that are not # Terms. self._dtypes = { 'param': np.dtype([(str(p), np.float) for p in params]), 'term': np.dtype([(str(t), np.float) for t in terms]), 'preterm': np.dtype([(n, np.float) for n in preterm]) } self.__terms = terms