def _separatevars(expr, force): if len(expr.free_symbols) == 1: return expr # don't destroy a Mul since much of the work may already be done if expr.is_Mul: args = list(expr.args) changed = False for i, a in enumerate(args): args[i] = separatevars(a, force) changed = changed or args[i] != a if changed: expr = expr.func(*args) return expr # get a Pow ready for expansion if expr.is_Pow: expr = Pow(separatevars(expr.base, force=force), expr.exp) # First try other expansion methods expr = expr.expand(mul=False, multinomial=False, force=force) _expr, reps = posify(expr) if force else (expr, {}) expr = factor(_expr).subs(reps) if not expr.is_Add: return expr # Find any common coefficients to pull out args = list(expr.args) commonc = args[0].args_cnc(cset=True, warn=False)[0] for i in args[1:]: commonc &= i.args_cnc(cset=True, warn=False)[0] commonc = Mul(*commonc) commonc = commonc.as_coeff_Mul()[1] # ignore constants commonc_set = commonc.args_cnc(cset=True, warn=False)[0] # remove them for i, a in enumerate(args): c, nc = a.args_cnc(cset=True, warn=False) c = c - commonc_set args[i] = Mul(*c)*Mul(*nc) nonsepar = Add(*args) if len(nonsepar.free_symbols) > 1: _expr = nonsepar _expr, reps = posify(_expr) if force else (_expr, {}) _expr = (factor(_expr)).subs(reps) if not _expr.is_Add: nonsepar = _expr return commonc*nonsepar
def eval(self): f, i, a, b = self.f, self.i, self.a, self.b # Exploit the linearity of the sum if not f.has(i): return f*(b-a+1) if isinstance(f, Mul): L, R = getab(f) if not L.has(i): return L*Sum2(R, (i, a, b)) if not R.has(i): return R*Sum2(L, (i, a, b)) if isinstance(f, Add): L, R = getab(f) lsum = Sum2(L, (i,a,b)) rsum = Sum2(R, (i,a,b)) if not isinstance(lsum, Sum2) and not isinstance(rsum, Sum2): return lsum + rsum # Polynomial terms with Faulhaber's formula if f == i: f = Pow(i, 1, evaluate=False) # TODO: match should handle this p = Wild('p') e = f.match(i**p) if e != None: c = p.subs_dict(e) B = Basic.bernoulli if c.is_integer and c >= 0: s = (B(c+1, b+1) - B(c+1, a))/(c+1) return s.expand() # Geometric terms if isinstance(f, Pow): r, k = f[:] if not r.has(i) and k == i: # TODO: Pow should be able to simplify x**oo depending # on whether |x| < 1 or |x| > 1 for non-rational x if b == oo and isinstance(r, Rational) and abs(r) < 1: return r**a / (1-r) else: return (r**a - r**(b+1)) / (1-r) # Should nothing else works, use brute force if possible if isinstance(a, Rational) and a.is_integer and \ isinstance(b, Rational) and b.is_integer: s = 0 for j in range(a, b+1): s += f.subs(i, j) return s return self
def _dyad_div(one, other): """ Helper for division involving dyadics """ if isinstance(one, Dyadic) and isinstance(other, Dyadic): raise TypeError("Cannot divide two dyadics") elif isinstance(one, Dyadic): return DyadicMul(one, Pow(other, S.NegativeOne)) else: raise TypeError("Cannot divide by a dyadic")
def _print_Mul(self, expr): prec = precedence(expr) c, e = expr.as_coeff_Mul() if c < 0: expr = _keep_coeff(-c, e) sign = "-" else: sign = "" a = [] # items in the numerator b = [] # items that are in the denominator (if any) if self.order not in ('old', 'none'): args = expr.as_ordered_factors() else: # use make_args in case expr was something like -x -> x args = Mul.make_args(expr) # Gather args for numerator/denominator for item in args: if item.is_commutative and item.is_Pow and item.exp.is_Rational and item.exp.is_negative: if item.exp != -1: b.append(Pow(item.base, -item.exp, evaluate=False)) else: b.append(Pow(item.base, -item.exp)) elif item.is_Rational and item is not S.Infinity: if item.p != 1: a.append(Rational(item.p)) if item.q != 1: b.append(Rational(item.q)) else: a.append(item) a = a or [S.One] a_str = [self.parenthesize(x, prec) for x in a] b_str = [self.parenthesize(x, prec) for x in b] if len(b) == 0: return sign + '*'.join(a_str) elif len(b) == 1: return sign + '*'.join(a_str) + "/" + b_str[0] else: return sign + '*'.join(a_str) + "/(%s)" % '*'.join(b_str)
def test_pow_as_base_exp(): x = Symbol('x') assert (S.Infinity**(2 - x)).as_base_exp() == (S.Infinity, 2 - x) assert (S.Infinity**(x - 2)).as_base_exp() == (S.Infinity, x - 2) p = S.Half**x assert p.base, p.exp == p.as_base_exp() == (S(2), -x) # issue 8344: assert Pow(1, 2, evaluate=False).as_base_exp() == (S.One, S(2))
def _real_to_rational(expr, tolerance=None): """ Replace all reals in expr with rationals. >>> from sympy import nsimplify >>> from sympy.abc import x >>> nsimplify(.76 + .1*x**.5, rational=True) sqrt(x)/10 + 19/25 """ inf = Float('inf') p = expr reps = {} reduce_num = None if tolerance is not None and tolerance < 1: reduce_num = ceiling(1 / tolerance) for float in p.atoms(Float): key = float if reduce_num is not None: r = Rational(float).limit_denominator(reduce_num) elif (tolerance is not None and tolerance >= 1 and float.is_Integer is False): r = Rational(tolerance * round(float / tolerance)).limit_denominator( int(tolerance)) else: r = nsimplify(float, rational=False) # e.g. log(3).n() -> log(3) instead of a Rational if float and not r: r = Rational(float) elif not r.is_Rational: if float == inf or float == -inf: r = S.ComplexInfinity elif float < 0: float = -float d = Pow(10, int((mpmath.log(float) / mpmath.log(10)))) r = -Rational(str(float / d)) * d elif float > 0: d = Pow(10, int((mpmath.log(float) / mpmath.log(10)))) r = Rational(str(float / d)) * d else: r = Integer(0) reps[key] = r return p.subs(reps, simultaneous=True)
def _print_Mul(self, expr): prec = precedence(expr) c, e = expr.as_coeff_Mul() if c < 0: expr = _keep_coeff(-c, e) sign = "-" else: sign = "" a = [] # items in the numerator b = [] # items that are in the denominator (if any) if self.order not in ('old', 'none'): args = expr.as_ordered_factors() else: # use make_args in case expr was something like -x -> x args = Mul.make_args(expr) # Gather args for numerator/denominator for item in args: if item.is_commutative and item.is_Pow and item.exp.is_Rational and item.exp.is_negative: if item.exp != -1: b.append(Pow(item.base, -item.exp, evaluate=False)) else: b.append(Pow(item.base, -item.exp)) else: a.append(item) a = a or [S.One] a_str = map(lambda x: self.parenthesize(x, prec), a) b_str = map(lambda x: self.parenthesize(x, prec), b) if len(b) == 0: return sign + '*'.join(a_str) elif len(b) == 1: if len(a) == 1 and not (a[0].is_Atom or a[0].is_Add): return sign + "%s/" % a_str[0] + '*'.join(b_str) else: return sign + '*'.join(a_str) + "/%s" % b_str[0] else: return sign + '*'.join(a_str) + "/(%s)" % '*'.join(b_str)
def ratsimp(expr): """ == Usage == ratsimp(expr) -> joins two rational expressions and returns the simples form == Notes == Currently can simplify only simple expressions, for this to be really usefull multivariate polynomial algorithms are needed == Examples == >>> from sympy import * >>> x = Symbol('x') >>> y = Symbol('y') >>> e = ratsimp(1/x + 1/y) """ expr = sympify(expr) if expr.is_Pow: return Pow(ratsimp(expr.base), ratsimp(expr.exp)) elif expr.is_Mul: res = [] for x in expr.args: res.append(ratsimp(x)) return Mul(*res) elif expr.is_Function: return expr.func(*[ratsimp(t) for t in expr.args]) #elif expr.is_Function: # return type(expr)( ratsimp(expr[0]) ) elif not expr.is_Add: return expr def get_num_denum(x): """Matches x = a/b and returns a/b.""" a, b = map(Wild, 'ab') r = x.match(a / b) if r is not None and len(r) == 2: return r[a], r[b] return x, S.One x = expr.args[0] y = Add(*expr.args[1:]) a, b = get_num_denum(ratsimp(x)) c, d = get_num_denum(ratsimp(y)) num = a * d + b * c denum = b * d # Check to see if the numerator actually expands to 0 if num.expand() == 0: return 0 return num / denum
def test_Pow(): assert maple_code(x ** 3) == "x^3" assert maple_code(x ** (y ** 3)) == "x^(y^3)" assert maple_code((x ** 3) ** y) == "(x^3)^y" assert maple_code(x ** Rational(2, 3)) == 'x^(2/3)' g = implemented_function('g', Lambda(x, 2 * x)) assert maple_code(1 / (g(x) * 3.5) ** (x - y ** x) / (x ** 2 + y)) == \ "(3.5*2*x)^(-x + y^x)/(x^2 + y)" # For issue 14160 assert maple_code(Mul(-2, x, Pow(Mul(y, y, evaluate=False), -1, evaluate=False), evaluate=False)) == '-2*x/(y*y)'
def test_NumPyPrinter(): from sympy.core.function import Lambda from sympy.matrices.expressions.adjoint import Adjoint from sympy.matrices.expressions.diagonal import (DiagMatrix, DiagonalMatrix, DiagonalOf) from sympy.matrices.expressions.funcmatrix import FunctionMatrix from sympy.matrices.expressions.hadamard import HadamardProduct from sympy.matrices.expressions.kronecker import KroneckerProduct from sympy.matrices.expressions.special import (OneMatrix, ZeroMatrix) from sympy.abc import a, b p = NumPyPrinter() assert p.doprint(sign(x)) == 'numpy.sign(x)' A = MatrixSymbol("A", 2, 2) B = MatrixSymbol("B", 2, 2) C = MatrixSymbol("C", 1, 5) D = MatrixSymbol("D", 3, 4) assert p.doprint(A**(-1)) == "numpy.linalg.inv(A)" assert p.doprint(A**5) == "numpy.linalg.matrix_power(A, 5)" assert p.doprint(Identity(3)) == "numpy.eye(3)" u = MatrixSymbol('x', 2, 1) v = MatrixSymbol('y', 2, 1) assert p.doprint(MatrixSolve(A, u)) == 'numpy.linalg.solve(A, x)' assert p.doprint(MatrixSolve(A, u) + v) == 'numpy.linalg.solve(A, x) + y' assert p.doprint(ZeroMatrix(2, 3)) == "numpy.zeros((2, 3))" assert p.doprint(OneMatrix(2, 3)) == "numpy.ones((2, 3))" assert p.doprint(FunctionMatrix(4, 5, Lambda((a, b), a + b))) == \ "numpy.fromfunction(lambda a, b: a + b, (4, 5))" assert p.doprint(HadamardProduct(A, B)) == "numpy.multiply(A, B)" assert p.doprint(KroneckerProduct(A, B)) == "numpy.kron(A, B)" assert p.doprint(Adjoint(A)) == "numpy.conjugate(numpy.transpose(A))" assert p.doprint(DiagonalOf(A)) == "numpy.reshape(numpy.diag(A), (-1, 1))" assert p.doprint(DiagMatrix(C)) == "numpy.diagflat(C)" assert p.doprint(DiagonalMatrix(D)) == "numpy.multiply(D, numpy.eye(3, 4))" # Workaround for numpy negative integer power errors assert p.doprint(x**-1) == 'x**(-1.0)' assert p.doprint(x**-2) == 'x**(-2.0)' expr = Pow(2, -1, evaluate=False) assert p.doprint(expr) == "2**(-1.0)" assert p.doprint(S.Exp1) == 'numpy.e' assert p.doprint(S.Pi) == 'numpy.pi' assert p.doprint(S.EulerGamma) == 'numpy.euler_gamma' assert p.doprint(S.NaN) == 'numpy.nan' assert p.doprint(S.Infinity) == 'numpy.PINF' assert p.doprint(S.NegativeInfinity) == 'numpy.NINF'
def test_power_dispatcher(): class NewBase(Expr): pass class NewPow(NewBase, Pow): pass a, b = Symbol('a'), NewBase() @power.register(Expr, NewBase) @power.register(NewBase, Expr) @power.register(NewBase, NewBase) def _(a, b): return NewPow(a, b) # Pow called as fallback assert power(2, 3) == 8*S.One assert power(a, 2) == Pow(a, 2) assert power(a, a) == Pow(a, a) # NewPow called by dispatch assert power(a, b) == NewPow(a, b) assert power(b, a) == NewPow(b, a) assert power(b, b) == NewPow(b, b)
def _find_opts(expr): if not isinstance(expr, Basic): return if expr.is_Atom or expr.is_Order: return if iterable(expr): list(map(_find_opts, expr)) return if expr in seen_subexp: return expr seen_subexp.add(expr) list(map(_find_opts, expr.args)) if _coeff_isneg(expr): neg_expr = -expr if not neg_expr.is_Atom: opt_subs[expr] = Mul(S.NegativeOne, neg_expr, evaluate=False) seen_subexp.add(neg_expr) expr = neg_expr if isinstance(expr, (Mul, MatMul)): muls.add(expr) elif isinstance(expr, (Add, MatAdd)): adds.add(expr) elif isinstance(expr, (Pow, MatPow)): if _coeff_isneg(expr.exp): opt_subs[expr] = Pow(Pow(expr.base, -expr.exp), S.NegativeOne, evaluate=False)
def _print_Mul(self, expr): coeff, terms = expr.as_coeff_mul() if coeff.is_negative: coeff = -coeff if coeff is not S.One: terms = (coeff, ) + terms sign = "-" else: terms = (coeff, ) + terms sign = "" a = [] # items in the numerator b = [] # items that are in the denominator (if any) if self.order not in ('old', 'none'): args = expr._new_rawargs(*terms).as_ordered_factors() else: args = terms # Gather args for numerator/denominator for item in args: if item.is_commutative and item.is_Pow and item.exp.is_Rational and item.exp.is_negative: b.append(Pow(item.base, -item.exp)) elif item.is_Rational and item is not S.Infinity: if item.p != 1: a.append(Rational(item.p)) if item.q != 1: b.append(Rational(item.q)) else: a.append(item) if len(a) == 0: a = [S.One] prec = precedence(expr) a_str = map(lambda x: self.parenthesize(x, prec), a) b_str = map(lambda x: self.parenthesize(x, prec), b) if len(b) == 0: return sign + '*'.join(a_str) elif len(b) == 1: if len(a) == 1 and not (a[0].is_Atom or a[0].is_Add): return sign + "%s/" % a_str[0] + '*'.join(b_str) else: return sign + '*'.join(a_str) + "/%s" % b_str[0] else: return sign + '*'.join(a_str) + "/(%s)" % '*'.join(b_str)
def __rpow__(self, other): if other.is_real and other.is_extended_nonnegative and ( self.max - self.min).is_extended_positive: if other is S.One: return S.One if other.is_extended_positive: a, b = [other**i for i in self.args] if min(a, b) != a: a, b = b, a return self.func(a, b) if other.is_zero: if self.min.is_zero: return self.func(0, 1) if self.min.is_extended_positive: return S.Zero return Pow(other, self, evaluate=False)
def test_idempotence(): x = Symbol('x', idempotent=True) n = Symbol('n', positive=True) y = Symbol('y') # positive powers equal the element assert x**2 == x assert x**125 == x assert x**n == x assert x**(n + 1) == x # empty product assert x**0 == 1 # not-necessarily-positive powers are left untouched assert x**y == Pow(x, y, evaluate=False) assert x**y != x
def _parallel_dict_from_expr_if_gens(exprs, opt): """Transform expressions into a multinomial form given generators. """ k, indices = len(opt.gens), {} for i, g in enumerate(opt.gens): indices[g] = i polys = [] for expr in exprs: poly = {} for term in Add.make_args(expr): coeff, monom = [], [0] * k for factor in Mul.make_args(term): if factor.is_Number: coeff.append(factor) else: try: base, exp = decompose_power(factor) if exp < 0: exp, base = -exp, Pow(base, -S.One) monom[indices[base]] = exp except KeyError: if not factor.has(*opt.gens): coeff.append(factor) else: raise PolynomialError( "%s contains an element of the generators set" % factor) monom = tuple(monom) if monom in poly: poly[monom] += Mul(*coeff) else: poly[monom] = Mul(*coeff) polys.append(poly) return polys, opt.gens
def test_ccode_Pow(): assert ccode(x ** 3) == "pow(x, 3)" assert ccode(x ** (y ** 3)) == "pow(x, pow(y, 3))" g = implemented_function("g", Lambda(x, 2 * x)) assert ( ccode(1 / (g(x) * 3.5) ** (x - y ** x) / (x ** 2 + y)) == "pow(3.5*2*x, -x + pow(y, x))/(pow(x, 2) + y)" ) assert ccode(x ** -1.0) == "1.0/x" assert ccode(x ** Rational(2, 3)) == "pow(x, 2.0/3.0)" assert ( ccode(x ** Rational(2, 3), type_aliases={real: float80}) == "powl(x, 2.0L/3.0L)" ) _cond_cfunc = [ (lambda base, exp: exp.is_integer, "dpowi"), (lambda base, exp: not exp.is_integer, "pow"), ] assert ccode(x ** 3, user_functions={"Pow": _cond_cfunc}) == "dpowi(x, 3)" assert ccode(x ** 0.5, user_functions={"Pow": _cond_cfunc}) == "pow(x, 0.5)" assert ( ccode(x ** Rational(16, 5), user_functions={"Pow": _cond_cfunc}) == "pow(x, 16.0/5.0)" ) _cond_cfunc2 = [ (lambda base, exp: base == 2, lambda base, exp: "exp2(%s)" % exp), (lambda base, exp: base != 2, "pow"), ] # Related to gh-11353 assert ccode(2 ** x, user_functions={"Pow": _cond_cfunc2}) == "exp2(x)" assert ccode(x ** 2, user_functions={"Pow": _cond_cfunc2}) == "pow(x, 2)" # For issue 14160 assert ( ccode( Mul( -2, x, Pow(Mul(y, y, evaluate=False), -1, evaluate=False), evaluate=False, ) ) == "-2*x/(y*y)" )
def is_nilpotent_number(n): """ Check whether `n` is a nilpotent number. A number `n` is said to be nilpotent if and only if every finite group of order `n` is nilpotent. For more information see [1]_. Examples ======== >>> from sympy.combinatorics.group_numbers import is_nilpotent_number >>> from sympy import randprime >>> is_nilpotent_number(21) False >>> is_nilpotent_number(randprime(1, 30)**12) True References ========== .. [1] Pakianathan, J., Shankar, K., *Nilpotent Numbers*, The American Mathematical Monthly, 107(7), 631-634. """ if n <= 0 or int(n) != n: raise ValueError("n must be a positive integer, not %i" % n) n = Integer(n) prime_factors = list(factorint(n).items()) is_nilpotent = True for p_j, a_j in prime_factors: for p_i, a_i in prime_factors: if any([Mod(Pow(p_i, k), p_j) == 1 for k in range(1, a_i + 1)]): is_nilpotent = False break if not is_nilpotent: break return is_nilpotent
def perform_operation(self, lhs, rhs, op): """Performs operation supported by the SymPy core Returns ======= combined_variable: list contains variable content and type of variable """ lhs_value = self.get_expr_for_operand(lhs) rhs_value = self.get_expr_for_operand(rhs) if op == '+': return [Add(lhs_value, rhs_value), 'expr'] if op == '-': return [Add(lhs_value, -rhs_value), 'expr'] if op == '*': return [Mul(lhs_value, rhs_value), 'expr'] if op == '/': return [Mul(lhs_value, Pow(rhs_value, Integer(-1))), 'expr'] if op == '%': return [Mod(lhs_value, rhs_value), 'expr'] if op in ['<', '<=', '>', '>=', '==', '!=']: return [Rel(lhs_value, rhs_value, op), 'expr'] if op == '&&': return [ And(as_Boolean(lhs_value), as_Boolean(rhs_value)), 'expr' ] if op == '||': return [ Or(as_Boolean(lhs_value), as_Boolean(rhs_value)), 'expr' ] if op == '=': return [Assignment(Variable(lhs_value), rhs_value), 'expr'] if op in ['+=', '-=', '*=', '/=', '%=']: return [ aug_assign(Variable(lhs_value), op[0], rhs_value), 'expr' ]