def test_Transform(): add1 = Transform(lambda x: x+1, lambda x: x % 2 == 1) assert add1[1] == 2 assert (1 in add1) is True assert add1.get(1) == 2 raises(KeyError, lambda: add1[2]) assert (2 in add1) is False assert add1.get(2) is None
def test_Transform(): add1 = Transform(lambda x: x + 1, lambda x: x % 2 == 1) assert add1[1] == 2 assert (1 in add1) is True assert add1.get(1) == 2 raises(KeyError, lambda: add1[2]) assert (2 in add1) is False assert add1.get(2) is None
def real_root(arg, n=None): """Return the real nth-root of arg if possible. If n is omitted then all instances of -1**(1/odd) will be changed to -1. Examples ======== >>> from sympy import root, real_root, Rational >>> from sympy.abc import x, n >>> real_root(-8, 3) -2 >>> root(-8, 3) 2*(-1)**(1/3) >>> real_root(_) -2 See Also ======== sympy.polys.rootoftools.RootOf sympy.core.power.integer_nthroot root, sqrt """ if n is not None: n = as_int(n) rv = C.Pow(arg, Rational(1, n)) if n % 2 == 0: return rv else: rv = sympify(arg) n1pow = Transform( lambda x: S.NegativeOne, lambda x: x.is_Pow and x.base is S.NegativeOne and x.exp.is_Rational and x.exp.p == 1 and x.exp.q % 2) return rv.xreplace(n1pow)
def real_root(arg, n=None, evaluate=None): """Return the real *n*'th-root of *arg* if possible. Parameters ========== n : int or None, optional If *n* is ``None``, then all instances of ``(-n)**(1/odd)`` will be changed to ``-n**(1/odd)``. This will only create a real root of a principal root. The presence of other factors may cause the result to not be real. evaluate : bool, optional The parameter determines if the expression should be evaluated. If ``None``, its value is taken from ``global_parameters.evaluate``. Examples ======== >>> from sympy import root, real_root >>> real_root(-8, 3) -2 >>> root(-8, 3) 2*(-1)**(1/3) >>> real_root(_) -2 If one creates a non-principal root and applies real_root, the result will not be real (so use with caution): >>> root(-8, 3, 2) -2*(-1)**(2/3) >>> real_root(_) -2*(-1)**(2/3) See Also ======== sympy.polys.rootoftools.rootof sympy.core.power.integer_nthroot root, sqrt """ from sympy.functions.elementary.complexes import Abs, im, sign from sympy.functions.elementary.piecewise import Piecewise if n is not None: return Piecewise((root(arg, n, evaluate=evaluate), Or(Eq(n, S.One), Eq(n, S.NegativeOne))), (Mul(sign(arg), root(Abs(arg), n, evaluate=evaluate), evaluate=evaluate), And(Eq(im(arg), S.Zero), Eq(Mod(n, 2), S.One))), (root(arg, n, evaluate=evaluate), True)) rv = sympify(arg) n1pow = Transform( lambda x: -(-x.base)**x.exp, lambda x: x.is_Pow and x.base.is_negative and x.exp.is_Rational and x.exp.p == 1 and x.exp.q % 2) return rv.xreplace(n1pow)
def __new__(cls, arg): # Mostly type checking here arg = _sympify(arg) predicates = arg.atoms(Predicate) applied_predicates = arg.atoms(AppliedPredicate) if predicates and applied_predicates: raise ValueError( "arg must be either completely free or singly applied") if not applied_predicates: obj = BooleanFunction.__new__(cls, arg) obj.pred = arg obj.expr = None return obj predicate_args = {pred.args[0] for pred in applied_predicates} if len(predicate_args) > 1: raise ValueError( "The AppliedPredicates in arg must be applied to a single expression." ) obj = BooleanFunction.__new__(cls, arg) obj.expr = predicate_args.pop() obj.pred = arg.xreplace( Transform(lambda e: e.func, lambda e: isinstance(e, AppliedPredicate))) applied = obj.apply() if applied is None: return obj return applied
def real_root(arg, n=None): """Return the real nth-root of arg if possible. If n is omitted then all instances of (-n)**(1/odd) will be changed to -n**(1/odd); this will only create a real root of a principle root -- the presence of other factors may cause the result to not be real. Examples ======== >>> from sympy import root, real_root, Rational >>> from sympy.abc import x, n >>> real_root(-8, 3) -2 >>> root(-8, 3) 2*(-1)**(1/3) >>> real_root(_) -2 If one creates a non-principle root and applies real_root, the result will not be real (so use with caution): >>> root(-8, 3, 2) -2*(-1)**(2/3) >>> real_root(_) -2*(-1)**(2/3) See Also ======== sympy.polys.rootoftools.RootOf sympy.core.power.integer_nthroot root, sqrt """ from sympy import im, Piecewise if n is not None: try: n = as_int(n) arg = sympify(arg) if arg.is_positive or arg.is_negative: rv = root(arg, n) else: raise ValueError except ValueError: return root(arg, n)*Piecewise( (S.One, ~Equality(im(arg), 0)), (Pow(S.NegativeOne, S.One/n)**(2*floor(n/2)), And( Equality(n % 2, 1), arg < 0)), (S.One, True)) else: rv = sympify(arg) n1pow = Transform(lambda x: -(-x.base)**x.exp, lambda x: x.is_Pow and x.base.is_negative and x.exp.is_Rational and x.exp.p == 1 and x.exp.q % 2) return rv.xreplace(n1pow)
def __call__(self, _q): cth = cos(self.theta_ + _q) sth = sin(self.theta_ + _q) res = sp.zeros(4, 4) res[0, 0] = cth res[0, 1] = -sth * self.cosal_ res[0, 2] = sth * self.sinal_ res[0, 3] = self.a_ * cth res[1, 0] = sth res[1, 1] = cth * self.cosal_ res[1, 2] = -cth * self.sinal_ res[1, 3] = self.a_ * sth res[2, 1] = self.sinal_ res[2, 2] = self.cosal_ res[2, 3] = self.d_ res[3, 3] = 1 for i in range(3): for j in range(4): res[i, j] = res[i, j].xreplace( Transform(lambda x: x.round(8), lambda x: isinstance(x, Float))) return res
def evaluate_old_assump(pred): """ Replace assumptions of expressions replaced with their values in the old assumptions (like Q.negative(-1) => True). Useful because some direct computations for numeric objects is defined most conveniently in the old assumptions. """ return pred.xreplace(Transform(_old_assump_replacer))
def real_root(arg, n=None): """Return the real nth-root of arg if possible. If n is omitted then all instances of (-n)**(1/odd) will be changed to -n**(1/odd); this will only create a real root of a principal root -- the presence of other factors may cause the result to not be real. Examples ======== >>> from sympy import root, real_root, Rational >>> from sympy.abc import x, n >>> real_root(-8, 3) -2 >>> root(-8, 3) 2*(-1)**(1/3) >>> real_root(_) -2 If one creates a non-principal root and applies real_root, the result will not be real (so use with caution): >>> root(-8, 3, 2) -2*(-1)**(2/3) >>> real_root(_) -2*(-1)**(2/3) See Also ======== sympy.polys.rootoftools.rootof sympy.core.power.integer_nthroot root, sqrt """ from sympy.functions.elementary.complexes import Abs, im, sign from sympy.functions.elementary.piecewise import Piecewise if n is not None: return Piecewise( (root(arg, n), Or(Eq(n, S.One), Eq(n, S.NegativeOne))), (sign(arg)*root(Abs(arg), n), And(Eq(im(arg), S.Zero), Eq(Mod(n, 2), S.One))), (root(arg, n), True)) rv = sympify(arg) n1pow = Transform(lambda x: -(-x.base)**x.exp, lambda x: x.is_Pow and x.base.is_negative and x.exp.is_Rational and x.exp.p == 1 and x.exp.q % 2) return rv.xreplace(n1pow)
def plot(): maclaurinPolynomial = maclaurin(degree) maclaurinText.set_text("Maclaurin Series: " + str( maclaurinPolynomial.xreplace( Transform(lambda x: x.round(degree), lambda x: isinstance(x, Float))))) f = lambdify(x, maclaurinPolynomial, 'numpy') fx = f(xvals) if np.all(fx == 0): maclaurinGraph.set_ydata(np.zeros(50)) else: maclaurinGraph.set_ydata(fx) fig.canvas.draw_idle()
def __call__(self, _q=None): if _q is None: q = self.q_ else: q = _q self.m0j_[0] = self.mij_[0](q[0]) for i, mij in enumerate(self.mij_[1:], start=1): self.m0j_[i] = self.m0j_[i - 1] * mij(q[i]) res = self.m0j_[-1] * self.mee for i in range(3): for j in range(4): res[i, j] = res[i, j].xreplace( Transform(lambda x: x.round(8), lambda x: isinstance(x, Float))) return res
def jac(self, _q=None): if _q is None: q = self.q_ else: q = _q pe = self(q)[:3, -1] jac = sp.zeros(6, self.dim_) axis = sp.Matrix([0.0, 0.0, 1.0]) p = sp.Matrix([0.0, 0.0, 0.0]) for j in range(0, self.dim_): jac[:3, j] = axis.cross(pe - p).doit() jac[3:, j] = axis axis = self.m0j_[j][:3, 2] p = self.m0j_[j][:3, -1] for i in range(6): for j in range(self.dim_): jac[i, j] = jac[i, j].xreplace( Transform(lambda x: x.round(8), lambda x: isinstance(x, Float))) return jac
def powdenest(eq, force=False, polar=False): r""" Collect exponents on powers as assumptions allow. Explanation =========== Given ``(bb**be)**e``, this can be simplified as follows: * if ``bb`` is positive, or * ``e`` is an integer, or * ``|be| < 1`` then this simplifies to ``bb**(be*e)`` Given a product of powers raised to a power, ``(bb1**be1 * bb2**be2...)**e``, simplification can be done as follows: - if e is positive, the gcd of all bei can be joined with e; - all non-negative bb can be separated from those that are negative and their gcd can be joined with e; autosimplification already handles this separation. - integer factors from powers that have integers in the denominator of the exponent can be removed from any term and the gcd of such integers can be joined with e Setting ``force`` to ``True`` will make symbols that are not explicitly negative behave as though they are positive, resulting in more denesting. Setting ``polar`` to ``True`` will do simplifications on the Riemann surface of the logarithm, also resulting in more denestings. When there are sums of logs in exp() then a product of powers may be obtained e.g. ``exp(3*(log(a) + 2*log(b)))`` - > ``a**3*b**6``. Examples ======== >>> from sympy.abc import a, b, x, y, z >>> from sympy import Symbol, exp, log, sqrt, symbols, powdenest >>> powdenest((x**(2*a/3))**(3*x)) (x**(2*a/3))**(3*x) >>> powdenest(exp(3*x*log(2))) 2**(3*x) Assumptions may prevent expansion: >>> powdenest(sqrt(x**2)) sqrt(x**2) >>> p = symbols('p', positive=True) >>> powdenest(sqrt(p**2)) p No other expansion is done. >>> i, j = symbols('i,j', integer=True) >>> powdenest((x**x)**(i + j)) # -X-> (x**x)**i*(x**x)**j x**(x*(i + j)) But exp() will be denested by moving all non-log terms outside of the function; this may result in the collapsing of the exp to a power with a different base: >>> powdenest(exp(3*y*log(x))) x**(3*y) >>> powdenest(exp(y*(log(a) + log(b)))) (a*b)**y >>> powdenest(exp(3*(log(a) + log(b)))) a**3*b**3 If assumptions allow, symbols can also be moved to the outermost exponent: >>> i = Symbol('i', integer=True) >>> powdenest(((x**(2*i))**(3*y))**x) ((x**(2*i))**(3*y))**x >>> powdenest(((x**(2*i))**(3*y))**x, force=True) x**(6*i*x*y) >>> powdenest(((x**(2*a/3))**(3*y/i))**x) ((x**(2*a/3))**(3*y/i))**x >>> powdenest((x**(2*i)*y**(4*i))**z, force=True) (x*y**2)**(2*i*z) >>> n = Symbol('n', negative=True) >>> powdenest((x**i)**y, force=True) x**(i*y) >>> powdenest((n**i)**x, force=True) (n**i)**x """ from sympy.simplify.simplify import posify if force: def _denest(b, e): if not isinstance(b, (Pow, exp)): return b.is_positive, Pow(b, e, evaluate=False) return _denest(b.base, b.exp * e) reps = [] for p in eq.atoms(Pow, exp): if isinstance(p.base, (Pow, exp)): ok, dp = _denest(*p.args) if ok is not False: reps.append((p, dp)) if reps: eq = eq.subs(reps) eq, reps = posify(eq) return powdenest(eq, force=False, polar=polar).xreplace(reps) if polar: eq, rep = polarify(eq) return unpolarify(powdenest(unpolarify(eq, exponents_only=True)), rep) new = powsimp(sympify(eq)) return new.xreplace( Transform(_denest_pow, filter=lambda m: m.is_Pow or isinstance(m, exp)))
def simplify(expr, ratio=1.7, measure=count_ops, rational=False): # type: (object, object, object, object) -> object """ Simplifies the given expression. Simplification is not a well defined term and the exact strategies this function tries can change in the future versions of SymPy. If your algorithm relies on "simplification" (whatever it is), try to determine what you need exactly - is it powsimp()?, radsimp()?, together()?, logcombine()?, or something else? And use this particular function directly, because those are well defined and thus your algorithm will be robust. Nonetheless, especially for interactive use, or when you don't know anything about the structure of the expression, simplify() tries to apply intelligent heuristics to make the input expression "simpler". For example: >>> from sympy import simplify, cos, sin >>> from sympy.abc import x, y >>> a = (x + x**2)/(x*sin(y)**2 + x*cos(y)**2) >>> a (x**2 + x)/(x*sin(y)**2 + x*cos(y)**2) >>> simplify(a) x + 1 Note that we could have obtained the same result by using specific simplification functions: >>> from sympy import trigsimp, cancel >>> trigsimp(a) (x**2 + x)/x >>> cancel(_) x + 1 In some cases, applying :func:`simplify` may actually result in some more complicated expression. The default ``ratio=1.7`` prevents more extreme cases: if (result length)/(input length) > ratio, then input is returned unmodified. The ``measure`` parameter lets you specify the function used to determine how complex an expression is. The function should take a single argument as an expression and return a number such that if expression ``a`` is more complex than expression ``b``, then ``measure(a) > measure(b)``. The default measure function is :func:`count_ops`, which returns the total number of operations in the expression. For example, if ``ratio=1``, ``simplify`` output can't be longer than input. :: >>> from sympy import sqrt, simplify, count_ops, oo >>> root = 1/(sqrt(2)+3) Since ``simplify(root)`` would result in a slightly longer expression, root is returned unchanged instead:: >>> simplify(root, ratio=1) == root True If ``ratio=oo``, simplify will be applied anyway:: >>> count_ops(simplify(root, ratio=oo)) > count_ops(root) True Note that the shortest expression is not necessary the simplest, so setting ``ratio`` to 1 may not be a good idea. Heuristically, the default value ``ratio=1.7`` seems like a reasonable choice. You can easily define your own measure function based on what you feel should represent the "size" or "complexity" of the input expression. Note that some choices, such as ``lambda expr: len(str(expr))`` may appear to be good metrics, but have other problems (in this case, the measure function may slow down simplify too much for very large expressions). If you don't know what a good metric would be, the default, ``count_ops``, is a good one. For example: >>> from sympy import symbols, log >>> a, b = symbols('a b', positive=True) >>> g = log(a) + log(b) + log(a)*log(1/b) >>> h = simplify(g) >>> h log(a*b**(-log(a) + 1)) >>> count_ops(g) 8 >>> count_ops(h) 5 So you can see that ``h`` is simpler than ``g`` using the count_ops metric. However, we may not like how ``simplify`` (in this case, using ``logcombine``) has created the ``b**(log(1/a) + 1)`` term. A simple way to reduce this would be to give more weight to powers as operations in ``count_ops``. We can do this by using the ``visual=True`` option: >>> print(count_ops(g, visual=True)) 2*ADD + DIV + 4*LOG + MUL >>> print(count_ops(h, visual=True)) 2*LOG + MUL + POW + SUB >>> from sympy import Symbol, S >>> def my_measure(expr): ... POW = Symbol('POW') ... # Discourage powers by giving POW a weight of 10 ... count = count_ops(expr, visual=True).subs(POW, 10) ... # Every other operation gets a weight of 1 (the default) ... count = count.replace(Symbol, type(S.One)) ... return count >>> my_measure(g) 8 >>> my_measure(h) 14 >>> 15./8 > 1.7 # 1.7 is the default ratio True >>> simplify(g, measure=my_measure) -log(a)*log(b) + log(a) + log(b) Note that because ``simplify()`` internally tries many different simplification strategies and then compares them using the measure function, we get a completely different result that is still different from the input expression by doing this. If rational=True, Floats will be recast as Rationals before simplification. If rational=None, Floats will be recast as Rationals but the result will be recast as Floats. If rational=False(default) then nothing will be done to the Floats. """ expr = sympify(expr) try: return expr._eval_simplify(ratio=ratio, measure=measure) except AttributeError: pass original_expr = expr = signsimp(expr) from sympy.simplify.hyperexpand import hyperexpand from sympy.functions.special.bessel import BesselBase from sympy import Sum, Product if not isinstance(expr, Basic) or not expr.args: # XXX: temporary hack return expr if not isinstance(expr, (Add, Mul, Pow, ExpBase)): if isinstance(expr, Function) and hasattr(expr, "inverse"): if len(expr.args) == 1 and len(expr.args[0].args) == 1 and \ isinstance(expr.args[0], expr.inverse(argindex=1)): return simplify(expr.args[0].args[0], ratio=ratio, measure=measure, rational=rational) return expr.func(*[simplify(x, ratio=ratio, measure=measure, rational=rational) for x in expr.args]) # TODO: Apply different strategies, considering expression pattern: # is it a purely rational function? Is there any trigonometric function?... # See also https://github.com/sympy/sympy/pull/185. def shorter(*choices): '''Return the choice that has the fewest ops. In case of a tie, the expression listed first is selected.''' if not has_variety(choices): return choices[0] return min(choices, key=measure) # rationalize Floats floats = False if rational is not False and expr.has(Float): floats = True expr = nsimplify(expr, rational=True) expr = bottom_up(expr, lambda w: w.normal()) expr = Mul(*powsimp(expr).as_content_primitive()) _e = cancel(expr) expr1 = shorter(_e, _mexpand(_e).cancel()) # issue 6829 expr2 = shorter(together(expr, deep=True), together(expr1, deep=True)) if ratio is S.Infinity: expr = expr2 else: expr = shorter(expr2, expr1, expr) if not isinstance(expr, Basic): # XXX: temporary hack return expr expr = factor_terms(expr, sign=False) # hyperexpand automatically only works on hypergeometric terms expr = hyperexpand(expr) expr = piecewise_fold(expr) if expr.has(BesselBase): expr = besselsimp(expr) if expr.has(TrigonometricFunction, HyperbolicFunction): expr = trigsimp(expr, deep=True) if expr.has(log): expr = shorter(expand_log(expr, deep=True), logcombine(expr)) if expr.has(CombinatorialFunction, gamma): # expression with gamma functions or non-integer arguments is # automatically passed to gammasimp expr = combsimp(expr) if expr.has(Sum): expr = sum_simplify(expr) if expr.has(Product): expr = product_simplify(expr) short = shorter(powsimp(expr, combine='exp', deep=True), powsimp(expr), expr) short = shorter(short, cancel(short)) short = shorter(short, factor_terms(short), expand_power_exp(expand_mul(short))) if short.has(TrigonometricFunction, HyperbolicFunction, ExpBase): short = exptrigsimp(short) # get rid of hollow 2-arg Mul factorization hollow_mul = Transform( lambda x: Mul(*x.args), lambda x: x.is_Mul and len(x.args) == 2 and x.args[0].is_Number and x.args[1].is_Add and x.is_commutative) expr = short.xreplace(hollow_mul) numer, denom = expr.as_numer_denom() if denom.is_Add: n, d = fraction(radsimp(1/denom, symbolic=False, max_terms=1)) if n is not S.One: expr = (numer*n).expand()/d if expr.could_extract_minus_sign(): n, d = fraction(expr) if d != 0: expr = signsimp(-n/(-d)) if measure(expr) > ratio*measure(original_expr): expr = original_expr # restore floats if floats and rational is None: expr = nfloat(expr, exponent=False) return expr
axDegree = plt.axes([0.25, .1, 0.65, 0.03], facecolor='lightgoldenrodyellow') degreeSlider = Slider(axDegree, 'Degree', 0, 18, valinit=6, valstep=2, color='goldenrod') def update(val): global degree degree = val plot() degreeSlider.on_changed(update) ax.plot(xvals, yvals, 'k-') maclaurinText = axDegree.text( -3.2, 1.5, "Maclaurin Series: " + str( maclaurin(degree).xreplace( Transform(lambda x: x.round(2), lambda x: isinstance(x, Float))))) maclaurinGraph, = ax.plot(xvals, lambdify(x, maclaurin(degree), 'numpy')(xvals), color='red') plt.show()
from sympy import * init_printing() # Need the following to fold the conjugates. See # https://stackoverflow.com/questions/48754975/simplification-of-derivative-of-square-using-sympy from sympy.core.rules import Transform fold_conjugates = Transform( lambda f: 2 * re(f.args[0]), lambda f: isinstance(f, Add) and len(f.args) == 2 and f.args[1] == f.args[0].conjugate()) fold_conjugates_2 = Transform( lambda f: f.args[0] + 2 * re(f.args[1]), lambda f: isinstance(f, Add) and len(f.args) == 3 and f.args[2] == f.args[1].conjugate()) S, l, m, n = symbols('S l m n', real=True) u, v, w, wt = symbols('u v w wt', real=True) Vobs, Vres0 = symbols('Vobs Vres', complex=True) Vres = Vobs - S * exp(-I * 2 * pi * (u * l + v * m)) J = Vres * wt * conjugate(Vres) axes = [S, l, m] grad = derive_by_array(J, axes) hess = derive_by_array(grad, axes) print("J = ", J) for axis in range(3): print( "grad[%d] = %s" % (axis, grad[axis].subs(Vres, Vres0).conjugate().subs( Vres, Vres0).conjugate().xreplace(fold_conjugates)))