def t(a, b, arg, n): from sympy import Mul m1 = meijerg(a, b, arg) m2 = Mul(*_inflate_g(m1, n)) # NOTE: (the random number)**9 must still be on the principal sheet. # Thus make b&d small to create random numbers of small imaginary part. return verify_numerically(m1.subs(subs), m2.subs(subs), x, b=0.1, d=-0.1)
def _add_switches(self, reactions): logger.info("Adding switches.") y_vars = list() switches = list() self._exchanges = list() for reaction in reactions: if reaction.id.startswith('DM_'): # demand reactions don't need integer switches self._exchanges.append(reaction) continue y = self.model.solver.interface.Variable('y_' + reaction.id, lb=0, ub=1, type='binary') y_vars.append(y) # The following is a complicated but efficient way to write the following constraints # switch_lb = self.model.solver.interface.Constraint(y * reaction.lower_bound - reaction.flux_expression, # name='switch_lb_' + reaction.id, ub=0) # switch_ub = self.model.solver.interface.Constraint(y * reaction.upper_bound - reaction.flux_expression, # name='switch_ub_' + reaction.id, lb=0) forward_var_term = Mul._from_args((RealNumber(-1), reaction.forward_variable)) reverse_var_term = Mul._from_args((RealNumber(-1), reaction.reverse_variable)) switch_lb_y_term = Mul._from_args((RealNumber(reaction.lower_bound), y)) switch_ub_y_term = Mul._from_args((RealNumber(reaction.upper_bound), y)) switch_lb = self.model.solver.interface.Constraint( Add._from_args((switch_lb_y_term, forward_var_term, reverse_var_term)), name='switch_lb_' + reaction.id, ub=0, sloppy=True) switch_ub = self.model.solver.interface.Constraint( Add._from_args((switch_ub_y_term, forward_var_term, reverse_var_term)), name='switch_ub_' + reaction.id, lb=0, sloppy=True) switches.extend([switch_lb, switch_ub]) self.model.solver.add(y_vars) self.model.solver.add(switches, sloppy=True) logger.info("Setting minimization of switch variables as objective.") self.model.objective = self.model.solver.interface.Objective(Add(*y_vars), direction='min') self._y_vars_ids = [var.name for var in y_vars]
def quantity_simplify(expr): if expr.is_Atom: return expr if not expr.is_Mul: return expr.func(*map(quantity_simplify, expr.args)) if expr.has(Prefix): coeff, args = expr.as_coeff_mul(Prefix) args = list(args) for arg in args: if isinstance(arg, Pow): coeff = coeff * (arg.base.scale_factor ** arg.exp) else: coeff = coeff * arg.scale_factor expr = coeff coeff, args = expr.as_coeff_mul(Quantity) args_pow = [arg.as_base_exp() for arg in args] quantity_pow, other_pow = sift(args_pow, lambda x: isinstance(x[0], Quantity), binary=True) quantity_pow_by_dim = sift(quantity_pow, lambda x: x[0].dimension) # Just pick the first quantity: ref_quantities = [i[0][0] for i in quantity_pow_by_dim.values()] new_quantities = [ Mul.fromiter( (quantity*i.scale_factor/quantity.scale_factor)**p for i, p in v) if len(v) > 1 else v[0][0]**v[0][1] for quantity, (k, v) in zip(ref_quantities, quantity_pow_by_dim.items())] return coeff*Mul.fromiter(other_pow)*Mul.fromiter(new_quantities)
def test_combine_inverse(): x, y = symbols("x y") assert Mul._combine_inverse(x*I*y, x*I) == y assert Mul._combine_inverse(x*I*y, y*I) == x assert Mul._combine_inverse(oo*I*y, y*I) == oo assert Mul._combine_inverse(oo*I*y, oo*I) == y assert Add._combine_inverse(oo, oo) == S(0) assert Add._combine_inverse(oo*I, oo*I) == S(0)
def test_as_ordered_factors(): f, g = symbols("f,g", cls=Function) assert x.as_ordered_factors() == [x] assert (2 * x * x ** n * sin(x) * cos(x)).as_ordered_factors() == [Integer(2), x, x ** n, sin(x), cos(x)] args = [f(1), f(2), f(3), f(1, 2, 3), g(1), g(2), g(3), g(1, 2, 3)] expr = Mul(*args) assert expr.as_ordered_factors() == args
def test__combine_inverse(): x, y = symbols("x y") assert Mul._combine_inverse(x*I*y, x*I) == y assert Mul._combine_inverse(x*I*y, y*I) == x assert Mul._combine_inverse(oo*I*y, y*I) == oo assert Mul._combine_inverse(oo*I*y, oo*I) == y assert Add._combine_inverse(oo, oo) == S(0) assert Add._combine_inverse(oo*I, oo*I) == S(0) assert Add._combine_inverse(x*oo, x*oo) == S(0) assert Add._combine_inverse(-x*oo, -x*oo) == S(0) assert Add._combine_inverse((x - oo)*(x + oo), -oo)
def test_make_args(): assert Add.make_args(x) == (x,) assert Mul.make_args(x) == (x,) assert Add.make_args(x*y*z) == (x*y*z,) assert Mul.make_args(x*y*z) == (x*y*z).args assert Add.make_args(x + y + z) == (x + y + z).args assert Mul.make_args(x + y + z) == (x + y + z,) assert Add.make_args((x + y)**z) == ((x + y)**z,) assert Mul.make_args((x + y)**z) == ((x + y)**z,)
def remove_infeasible_cycles(model, fluxes, fix=()): """Remove thermodynamically infeasible cycles from a flux distribution. Arguments --------- model : cobra.Model The model that generated the flux distribution. fluxes : dict The flux distribution containing infeasible loops. Returns ------- dict A cycle free flux distribution. References ---------- .. [1] A. A. Desouki, F. Jarre, G. Gelius-Dietrich, and M. J. Lercher, “CycleFreeFlux: efficient removal of thermodynamically infeasible loops from flux distributions.” """ with model: # make sure the original object is restored exchange_reactions = model.boundary exchange_ids = [exchange.id for exchange in exchange_reactions] internal_reactions = [reaction for reaction in model.reactions if reaction.id not in exchange_ids] for exchange in exchange_reactions: exchange_flux = fluxes[exchange.id] exchange.bounds = (exchange_flux, exchange_flux) cycle_free_objective_list = [] for internal_reaction in internal_reactions: internal_flux = fluxes[internal_reaction.id] if internal_flux >= 0: cycle_free_objective_list.append(Mul._from_args((FloatOne, internal_reaction.forward_variable))) internal_reaction.bounds = (0, internal_flux) else: # internal_flux < 0: cycle_free_objective_list.append(Mul._from_args((FloatOne, internal_reaction.reverse_variable))) internal_reaction.bounds = (internal_flux, 0) cycle_free_objective = model.solver.interface.Objective( Add._from_args(cycle_free_objective_list), direction="min", sloppy=True ) model.objective = cycle_free_objective for reaction_id in fix: reaction_to_fix = model.reactions.get_by_id(reaction_id) reaction_to_fix.bounds = (fluxes[reaction_id], fluxes[reaction_id]) try: solution = model.optimize(raise_error=True) except OptimizationError as e: logger.warning("Couldn't remove cycles from reference flux distribution.") raise e result = solution.fluxes return result
def test_as_ordered_factors(): f, g = symbols("f,g", cls=Function) assert x.as_ordered_factors() == [x] assert (2 * x * x ** n * sin(x) * cos(x)).as_ordered_factors() == [Integer(2), x, x ** n, sin(x), cos(x)] args = [f(1), f(2), f(3), f(1, 2, 3), g(1), g(2), g(3), g(1, 2, 3)] expr = Mul(*args) assert expr.as_ordered_factors() == args A, B = symbols("A,B", commutative=False) assert (A * B).as_ordered_factors() == [A, B] assert (B * A).as_ordered_factors() == [B, A]
def linear_expand(expr): """ If a sympy 'Expr' is of the form: expr = expr_0 + expr_1*a_1 + ... + expr_n*a_n where all the a_j are noncommuting symbols in basis then (expr_0, ..., expr_n) and (1, a_1, ..., a_n) are returned. Note that expr_j*a_j does not have to be of that form, but rather can be any Mul with a_j as a factor (it doen not have to be a postmultiplier). expr_0 is the scalar part of the expression. """ expr = expand(expr) if expr.is_commutative: # commutative expr only contains expr_0 return (expr, ), (S.One, ) if isinstance(expr, Mul): # expr only contains one term (coefs, bases) = expr.args_cnc() coefs = Mul(*coefs) bases = bases[0] elif isinstance(expr, Symbol): # term is Symbol coefs = S.One bases = expr elif isinstance(expr, Add): # expr has multiple terms coefs = [] bases = [] for arg in expr.args: term = arg.args_cnc() coef = Mul(*term[0]) base = term[1][0] if base in bases: # increment coefficient of base ibase = list(bases).index(base) # Python 2.5 coefs[ibase] += coef else: # add base to list coefs.append(coef) bases.append(base) else: raise NotImplementedError("linear_expand for type %s" % type(expr)) if not isinstance(coefs, list): # convert single coef to list coefs = [coefs] if not isinstance(bases, list): # convert single base to list bases = [bases] coefs = tuple(coefs) bases = tuple(bases) return coefs, bases
def multiply(expr, mrow): from sympy.simplify import fraction numer, denom = fraction(expr) if denom is not S.One: frac = self.dom.createElement('mfrac') xnum = self._print(numer) xden = self._print(denom) frac.appendChild(xnum) frac.appendChild(xden) return frac coeff, terms = expr.as_coeff_mul() if coeff is S.One and len(terms) == 1: return self._print(terms[0]) if self.order != 'old': terms = Mul._from_args(terms).as_ordered_factors() if(coeff != 1): x = self._print(coeff) y = self.dom.createElement('mo') y.appendChild(self.dom.createTextNode(self.mathml_tag(expr))) mrow.appendChild(x) mrow.appendChild(y) for term in terms: x = self._print(term) mrow.appendChild(x) if not term == terms[-1]: y = self.dom.createElement('mo') y.appendChild(self.dom.createTextNode(self.mathml_tag(expr))) mrow.appendChild(y) return mrow
def trig_replace(self, M, angle, name): """Replaces trigonometric expressions cos(x) and sin(x) by CX and SX Parameters ========== M: var or Matrix Object of substitution angle: var symbol that stands for the angle value name: int or string brief name X for the angle Notes ===== The cos(x) and sin(x) will be replaced by CX and SX, where X is the name and x is the angle """ if not isinstance(angle, Expr) or angle.is_number: return M cos_sym, sin_sym = tools.cos_sin_syms(name) sym_list = [(cos_sym, cos(angle)), (sin_sym, sin(angle))] subs_dict = {} for sym, sym_old in sym_list: if -1 in Mul.make_args(sym_old): sym_old = -sym_old subs_dict[sym_old] = sym self.add_to_dict(sym, sym_old) for i1 in xrange(M.shape[0]): for i2 in xrange(M.shape[1]): M[i1, i2] = M[i1, i2].subs(subs_dict) return M
def multiply(expr, mrow): from sympy.simplify import fraction numer, denom = fraction(expr) if denom is not S.One: frac = self.dom.createElement('mfrac') if self._settings["fold_short_frac"] and len(str(expr)) < 7: frac.setAttribute('bevelled', 'true') xnum = self._print(numer) xden = self._print(denom) frac.appendChild(xnum) frac.appendChild(xden) mrow.appendChild(frac) return mrow coeff, terms = expr.as_coeff_mul() if coeff is S.One and len(terms) == 1: mrow.appendChild(self._print(terms[0])) return mrow if self.order != 'old': terms = Mul._from_args(terms).as_ordered_factors() if coeff != 1: x = self._print(coeff) y = self.dom.createElement('mo') y.appendChild(self.dom.createTextNode(self.mathml_tag(expr))) mrow.appendChild(x) mrow.appendChild(y) for term in terms: x = self._print(term) mrow.appendChild(x) if not term == terms[-1]: y = self.dom.createElement('mo') y.appendChild(self.dom.createTextNode(self.mathml_tag(expr))) mrow.appendChild(y) return mrow
def _dict_from_basic_if_gens(ex, gens, **args): """Convert `ex` to a multinomial given a generators list. """ k, indices = len(gens), {} for i, g in enumerate(gens): indices[g] = i result = {} for term in Add.make_args(ex): coeff, monom = [], [0]*k for factor in Mul.make_args(term): if factor.is_Number: coeff.append(factor) else: try: base, exp = _analyze_power(*factor.as_Pow()) monom[indices[base]] = exp except KeyError: if not factor.has(*gens): coeff.append(factor) else: raise PolynomialError("%s contains an element of the generators set" % factor) monom = tuple(monom) if result.has_key(monom): result[monom] += Mul(*coeff) else: result[monom] = Mul(*coeff) return result
def _print_Mul(self, expr): if _coeff_isneg(expr): x = self.dom.createElement('apply') x.appendChild(self.dom.createElement('minus')) x.appendChild(self._print_Mul(-expr)) return x from sympy.simplify import fraction numer, denom = fraction(expr) if denom is not S.One: x = self.dom.createElement('apply') x.appendChild(self.dom.createElement('divide')) x.appendChild(self._print(numer)) x.appendChild(self._print(denom)) return x coeff, terms = expr.as_coeff_mul() if coeff is S.One and len(terms) == 1: # XXX since the negative coefficient has been handled, I don't # think a coeff of 1 can remain return self._print(terms[0]) if self.order != 'old': terms = Mul._from_args(terms).as_ordered_factors() x = self.dom.createElement('apply') x.appendChild(self.dom.createElement('times')) if(coeff != 1): x.appendChild(self._print(coeff)) for term in terms: x.appendChild(self._print(term)) return x
def test_issue_3268(): z = -5*sqrt(2)/(2*sqrt(2*sqrt(29) + 29)) + sqrt(-sqrt(29)/29 + S(1)/2) assert Mul(*[powsimp(a) for a in Mul.make_args(z.normal())]) == 0 assert powsimp(z.normal()) == 0 assert simplify(z) == 0 assert powsimp(sqrt(2 + sqrt(3))*sqrt(2 - sqrt(3)) + 1) == 2 assert powsimp(z) != 0
def _print_Mul(self, expr): if len(expr.args) >= 2: return "mul({}, {})".format( self._print(expr.args[0]), self._print(Mul.fromiter(expr.args[1:])), ) else: return self._print(expr.args[0])
def test_zoo(): b = Symbol('b', bounded=True) nz = Symbol('nz', nonzero=True) p = Symbol('p', positive=True) n = Symbol('n', negative=True) im = Symbol('i', imaginary=True) c = Symbol('c', complex=True) pb = Symbol('pb', positive=True, bounded=True) nb = Symbol('nb', negative=True, bounded=True) imb = Symbol('ib', imaginary=True, bounded=True) for i in [I, S.Infinity, S.NegativeInfinity, S.Zero, S.One, S.Pi, S.Half, S(3), log(3), b, nz, p, n, im, pb, nb, imb, c]: if i.is_bounded and (i.is_real or i.is_imaginary): assert i + zoo is zoo assert i - zoo is zoo assert zoo + i is zoo assert zoo - i is zoo elif i.is_bounded is not False: assert (i + zoo).is_Add assert (i - zoo).is_Add assert (zoo + i).is_Add assert (zoo - i).is_Add else: assert (i + zoo) is S.NaN assert (i - zoo) is S.NaN assert (zoo + i) is S.NaN assert (zoo - i) is S.NaN if i.is_nonzero and (i.is_real or i.is_imaginary): assert i*zoo is zoo assert zoo*i is zoo elif i.is_zero: assert i*zoo is S.NaN assert zoo*i is S.NaN else: assert (i*zoo).is_Mul assert (zoo*i).is_Mul if (1/i).is_nonzero and (i.is_real or i.is_imaginary): assert zoo/i is zoo elif (1/i).is_zero: assert zoo/i is S.NaN elif i.is_zero: assert zoo/i is zoo else: assert (zoo/i).is_Mul assert (I*oo).is_Mul # allow directed infinity assert zoo + zoo is S.NaN assert zoo * zoo is zoo assert zoo - zoo is S.NaN assert zoo/zoo is S.NaN assert zoo**zoo is S.NaN assert zoo**0 is S.One assert zoo**2 is zoo assert 1/zoo is S.Zero assert Mul.flatten([S(-1), oo, S(0)]) == ([S.NaN], [], None)
def eval(cls, a, b): if not (a and b): return S.Zero if a == b: return Integer(2)*a**2 if a.is_commutative or b.is_commutative: return Integer(2)*a*b # [xA,yB] -> xy*[A,B] # from sympy.physics.qmul import QMul ca, nca = a.args_cnc() cb, ncb = b.args_cnc() c_part = ca + cb if c_part: return Mul(Mul(*c_part), cls(Mul._from_args(nca), Mul._from_args(ncb))) # Canonical ordering of arguments #The Commutator [A,B] is on canonical form if A < B. if a.compare(b) == 1: return cls(b,a)
def flatten(cls, args): # TODO: disallow nested TensorProducts. c_part = [] nc_parts = [] for arg in args: cp, ncp = arg.args_cnc() c_part.extend(list(cp)) nc_parts.append(Mul._from_args(ncp)) return c_part, nc_parts
def eval(cls, a, b): if not (a and b): return S.Zero if a == b: return S.Zero if a.is_commutative or b.is_commutative: return S.Zero # [xA,yB] -> xy*[A,B] ca, nca = a.args_cnc() cb, ncb = b.args_cnc() c_part = ca + cb if c_part: return Mul(Mul(*c_part), cls(Mul._from_args(nca), Mul._from_args(ncb))) # Canonical ordering of arguments # The Commutator [A, B] is in canonical form if A < B. if a.compare(b) == 1: return S.NegativeOne*cls(b, a)
def eval(cls, a, b): """The Commutator [A,B] is on canonical form if A < B. """ if not (a and b): return S.Zero if a == b: return S.Zero if a.is_commutative or b.is_commutative: return S.Zero # [xA,yB] -> xy*[A,B] # from sympy.physics.qmul import QMul ca, nca = a.args_cnc() cb, ncb = b.args_cnc() c_part = list(ca) + list(cb) if c_part: return Mul(Mul(*c_part), cls(Mul._from_args(nca), Mul._from_args(ncb))) # Canonical ordering of arguments if a.compare(b) == 1: return S.NegativeOne*cls(b,a)
def _print_MatMul(self, expr): from sympy.matrices.expressions import MatrixExpr mat_args = [arg for arg in expr.args if isinstance(arg, MatrixExpr)] args = [arg for arg in expr.args if arg not in mat_args] if args: return "%s*%s" % ( self.parenthesize(Mul.fromiter(args), PRECEDENCE["Mul"]), self._expand_fold_binary_op("tensorflow.matmul", mat_args) ) else: return self._expand_fold_binary_op("tensorflow.matmul", mat_args)
def simp(self, sym): sym = factor(sym) new_sym = tools.ONE for expr in Mul.make_args(sym): if expr.is_Pow: expr, pow_val = expr.args else: pow_val = 1 expr = self.C2S2_simp(expr) expr = self.CS12_simp(expr, silent=True) new_sym *= expr**pow_val return new_sym
def simp(self, sym): sym = factor(sym) new_sym = ONE for e in Mul.make_args(sym): if e.is_Pow: e, p = e.args else: p = 1 e = self.C2S2_simp(e) e = self.CS12_simp(e, silent=True) new_sym *= e**p return new_sym
def _eval_expand_covariance(self, **hints): A, B = self.args[0], self.args[1] # <A + B, C> = <A, C> + <B, C> if isinstance(A, Add): return Add(*(Covariance(a, B, self.is_normal_order).expand() for a in A.args)) # <A, B + C> = <A, B> + <A, C> if isinstance(B, Add): return Add(*(Covariance(A, b, self.is_normal_order).expand() for b in B.args)) if isinstance(A, Mul): A = A.expand() cA, ncA = A.args_cnc() return Mul(Mul(*cA), Covariance(Mul._from_args(ncA), B, self.is_normal_order).expand()) if isinstance(B, Mul): B = B.expand() cB, ncB = B.args_cnc() return Mul(Mul(*cB), Covariance(A, Mul._from_args(ncB), self.is_normal_order).expand()) if isinstance(A, Integral): # <∫adx, B> -> ∫<a, B>dx func, lims = A.function, A.limits new_args = [Covariance(func, B, self.is_normal_order).expand()] for lim in lims: new_args.append(lim) return Integral(*new_args) if isinstance(B, Integral): # <A, ∫bdx> -> ∫<A, b>dx func, lims = B.function, B.limits new_args = [Covariance(A, func, self.is_normal_order).expand()] for lim in lims: new_args.append(lim) return Integral(*new_args) return self
def _print_Mul(self, expr): "Copied from sympy StrPrinter and modified to remove division." 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: # Thermo-Calc's parser can't handle division operators return sign + '*'.join(a_str) + "*%s" % self.parenthesize(b[0]**(-1), prec) else: # TODO: Make this Thermo-Calc compatible by removing division operation return sign + '*'.join(a_str) + "/(%s)" % '*'.join(b_str)
def doit(self, **hints): from sympy.assumptions import ask, Q from sympy import Transpose, Mul, MatMul vector = self._vector # This accounts for shape (1, 1) and identity matrices, among others: if ask(Q.diagonal(vector)): return vector if vector.is_MatMul: matrices = [arg for arg in vector.args if arg.is_Matrix] scalars = [arg for arg in vector.args if arg not in matrices] if scalars: return Mul.fromiter(scalars)*DiagonalizeVector(MatMul.fromiter(matrices).doit()).doit() if isinstance(vector, Transpose): vector = vector.arg return DiagonalizeVector(vector)
def get_max_coef_mul(sym, x_term): k, ex = x_term.as_coeff_Mul() coef = sym / k pow_x = ex.as_powers_dict() pow_c = coef.as_powers_dict() pow_c[-1] = 0 for j, pow_j in pow_x.iteritems(): num_j = -j if j in pow_c and pow_c[j] >= pow_j: pow_c[j] -= pow_j elif num_j in pow_c and pow_c[num_j] >= pow_j: pow_c[num_j] -= pow_j if pow_j % 2: pow_c[-1] += 1 else: return ZERO return Mul.fromiter(c**p for c, p in pow_c.iteritems())
def check_dimensions(expr): """Return expr if there are not unitless values added to dimensional quantities, else raise a ValueError.""" from sympy.solvers.solveset import _term_factors # the case of adding a number to a dimensional quantity # is ignored for the sake of SymPy core routines, so this # function will raise an error now if such an addend is # found. # Also, when doing substitutions, multiplicative constants # might be introduced, so remove those now adds = expr.atoms(Add) DIM_OF = dimsys_default.get_dimensional_dependencies for a in adds: deset = set() for ai in a.args: if ai.is_number: deset.add(()) continue dims = [] skip = False for i in Mul.make_args(ai): if i.has(Quantity): i = Dimension(Quantity.get_dimensional_expr(i)) if i.has(Dimension): dims.extend(DIM_OF(i).items()) elif i.free_symbols: skip = True break if not skip: deset.add(tuple(sorted(dims))) if len(deset) > 1: raise ValueError( "addends have incompatible dimensions") # clear multiplicative constants on Dimensions which may be # left after substitution reps = {} for m in expr.atoms(Mul): if any(isinstance(i, Dimension) for i in m.args): reps[m] = m.func(*[ i for i in m.args if not i.is_number]) return expr.xreplace(reps)
def test_variable_percentage(): assert_equal( "\\variable{x}\\%", Mul(Symbol('x' + hashlib.md5('x'.encode()).hexdigest(), real=True), Pow(100, -1, evaluate=False), evaluate=False))
def poly_factor(polynome, variable, corps=None, approchee=None): u"""Factorise un polynome à une variable. Le corps peut être R ou C. Par défaut, le corps de factorisation est celui des coefficients.""" from .sympy_functions import simplifier_racines if approchee is None: # Paramètre utilisé en interne par 'l'interpreteur' de commandes # (cf. méth. evaluer() de la classe Interprete(), dans custom_objects.py) approchee = getattr(param, 'calcul_approche', False) if polynome.is_Mul: return reduce(lambda x, y: x * y, [ poly_factor(fact, variable, corps=corps) for fact in polynome.args ], 1) sym_poly = polynome.as_poly(variable) coeffs = sym_poly.all_coeffs() if any(_is_num(coeff) for coeff in coeffs): approchee = True racines_brutes = {}.fromkeys(nroots(coeffs), 1) else: if corps == "R": if not all(coeff.is_real for coeff in coeffs): raise ValueError, "factorisation dans 'R' impossible." elif corps is None: if all(coeff.is_real for coeff in coeffs): corps = "R" else: corps = "C" racines_brutes = roots(polynome, variable, cubics=True, quartics=True) racines = list((simplifier_racines(racine), mult) for racine, mult in racines_brutes.iteritems()) if approchee: nbr_racines = sum(multiplicite for racine, multiplicite in racines) if nbr_racines < sym_poly.degree(): # On cherche une approximation des racines manquantes sol_approchees = list(nroots(coeffs)) # On associe à chaque racine l'approximation qui lui correspond for racine, multiplicite in racines: distances = [(sol, abs(complex(racine) - sol)) for sol in sol_approchees] distances.sort(key=lambda x: x[1]) for i in range(multiplicite): distances.pop(0) # Les racines approchées qui restent ne correspondent à aucune racine exacte sol_approchees = [sol for sol, distance in distances] racines.extend((sympify(sol), sol_approchees.count(sol)) for sol in set(sol_approchees)) coefficient = coeffs[0] produit = 1 if corps == "R": racines_en_stock = [] multiplicites_en_stock = [] for racine, multiplicite in racines: if not isinstance(racine, Basic): racine = sympify(racine) reel = racine.is_real if not reel: # is_real n'est pas fiable (26/11/2009) # cf. ((54*6**(1/3)*93**(1/2) - 162*I*6**(1/3)*31**(1/2) - 522*6**(1/3) + 6*6**(2/3)*(-522 + 54*93**(1/2))**(1/3) + 522*I*3**(1/2)*6**(1/3) + 6*I*3**(1/2)*6**(2/3)*(-522 + 54*93**(1/2))**(1/3) - 24*(-522 + 54*93**(1/2))**(2/3))/(36*(-522 + 54*93**(1/2))**(2/3))).is_real re, im = racine.expand(complex=True).as_real_imag() reel = im.is_zero or im.evalf(80).epsilon_eq(0, '10e-80') if reel: racine = re # Approximation utile (?) pour la factorisation de certains polynômes de degrés 3 et 4 # De toute manière, une vérification de la factorisation par division euclidienne # a lieu à la fin de l'algorithme. if reel: produit *= (variable - racine)**multiplicite else: conjuguee = racine.conjugate() if conjuguee in racines_en_stock: produit *= (variable**2 - 2 * re * variable + re**2 + im**2)**multiplicite i = racines_en_stock.index(conjuguee) racines_en_stock.pop(i) multiplicites_en_stock.pop(i) else: racines_en_stock.append(racine) multiplicites_en_stock.append(multiplicite) if racines_en_stock: # Il reste des racines qu'on n'a pas réussi à appareiller. P = 1 for racine, multiplicite in zip(racines_en_stock, multiplicites_en_stock): P *= (variable - racine)**multiplicite produit *= P.expand() else: for racine, multiplicite in racines: produit *= (variable - racine)**multiplicite # print produit quotient, reste = div(polynome, coefficient * produit, variable) if reste != 0 and not approchee: raise NotImplementedError poly_factorise = coefficient * produit * quotient if isinstance(poly_factorise, Mul) and poly_factorise.args[0] == 1.: poly_factorise = Mul(*poly_factorise.args[1:]) # sinon, poly_factor(x**2+2.5*x+1,x) donne 1.0*(x + 0.5)*(x + 2.0) return poly_factorise
def test_issue_6611a(): assert Mul.flatten([3**Rational(1, 3), Pow(-Rational(1, 9), Rational(2, 3), evaluate=False)]) == \ ([Rational(1, 3), (-1)**Rational(2, 3)], [], None)
def test_signsimp(): e = x * (-x + 1) + x * (x - 1) assert signsimp(Eq(e, 0)) is S.true assert Abs(x - 1) == Abs(1 - x) assert signsimp(y - x) == y - x assert signsimp(y - x, evaluate=False) == Mul(-1, x - y, evaluate=False)
def test_simplify_expr(): x, y, z, k, n, m, w, s, A = symbols('x,y,z,k,n,m,w,s,A') f = Function('f') assert all(simplify(tmp) == tmp for tmp in [I, E, oo, x, -x, -oo, -E, -I]) e = 1 / x + 1 / y assert e != (x + y) / (x * y) assert simplify(e) == (x + y) / (x * y) e = A**2 * s**4 / (4 * pi * k * m**3) assert simplify(e) == e e = (4 + 4 * x - 2 * (2 + 2 * x)) / (2 + 2 * x) assert simplify(e) == 0 e = (-4 * x * y**2 - 2 * y**3 - 2 * x**2 * y) / (x + y)**2 assert simplify(e) == -2 * y e = -x - y - (x + y)**(-1) * y**2 + (x + y)**(-1) * x**2 assert simplify(e) == -2 * y e = (x + x * y) / x assert simplify(e) == 1 + y e = (f(x) + y * f(x)) / f(x) assert simplify(e) == 1 + y e = (2 * (1 / n - cos(n * pi) / n)) / pi assert simplify(e) == (-cos(pi * n) + 1) / (pi * n) * 2 e = integrate(1 / (x**3 + 1), x).diff(x) assert simplify(e) == 1 / (x**3 + 1) e = integrate(x / (x**2 + 3 * x + 1), x).diff(x) assert simplify(e) == x / (x**2 + 3 * x + 1) f = Symbol('f') A = Matrix([[2 * k - m * w**2, -k], [-k, k - m * w**2]]).inv() assert simplify((A * Matrix([0, f]))[1] - (-f * (2 * k - m * w**2) / (k**2 - (k - m * w**2) * (2 * k - m * w**2)))) == 0 f = -x + y / (z + t) + z * x / (z + t) + z * a / (z + t) + t * x / (z + t) assert simplify(f) == (y + a * z) / (z + t) # issue 10347 expr = -x * (y**2 - 1) * ( 2 * y**2 * (x**2 - 1) / (a * (x**2 - y**2)**2) + (x**2 - 1) / (a * (x**2 - y**2))) / (a * (x**2 - y**2)) + x * ( -2 * x**2 * sqrt(-x**2 * y**2 + x**2 + y**2 - 1) * sin(z) / (a * (x**2 - y**2)**2) - x**2 * sqrt(-x**2 * y**2 + x**2 + y**2 - 1) * sin(z) / (a * (x**2 - 1) * (x**2 - y**2)) + (x**2 * sqrt((-x**2 + 1) * (y**2 - 1)) * sqrt(-x**2 * y**2 + x**2 + y**2 - 1) * sin(z) / (x**2 - 1) + sqrt( (-x**2 + 1) * (y**2 - 1)) * (x * (-x * y**2 + x) / sqrt(-x**2 * y**2 + x**2 + y**2 - 1) + sqrt(-x**2 * y**2 + x**2 + y**2 - 1)) * sin(z)) / (a * sqrt( (-x**2 + 1) * (y**2 - 1)) * (x**2 - y**2)) ) * sqrt(-x**2 * y**2 + x**2 + y**2 - 1) * sin(z) / ( a * (x**2 - y**2)) + x * ( -2 * x**2 * sqrt(-x**2 * y**2 + x**2 + y**2 - 1) * cos(z) / (a * (x**2 - y**2)**2) - x**2 * sqrt(-x**2 * y**2 + x**2 + y**2 - 1) * cos(z) / (a * (x**2 - 1) * (x**2 - y**2)) + (x**2 * sqrt((-x**2 + 1) * (y**2 - 1)) * sqrt(-x**2 * y**2 + x**2 + y**2 - 1) * cos(z) / (x**2 - 1) + x * sqrt( (-x**2 + 1) * (y**2 - 1)) * (-x * y**2 + x) * cos(z) / sqrt(-x**2 * y**2 + x**2 + y**2 - 1) + sqrt( (-x**2 + 1) * (y**2 - 1)) * sqrt(-x**2 * y**2 + x**2 + y**2 - 1) * cos(z)) / (a * sqrt((-x**2 + 1) * (y**2 - 1)) * (x**2 - y**2)) ) * sqrt(-x**2 * y**2 + x**2 + y**2 - 1) * cos(z) / ( a * (x**2 - y**2)) - y * sqrt((-x**2 + 1) * (y**2 - 1)) * ( -x * y * sqrt(-x**2 * y**2 + x**2 + y**2 - 1) * sin(z) / (a * (x**2 - y**2) * (y**2 - 1)) + 2 * x * y * sqrt(-x**2 * y**2 + x**2 + y**2 - 1) * sin(z) / (a * (x**2 - y**2)**2) + (x * y * sqrt((-x**2 + 1) * (y**2 - 1)) * sqrt(-x**2 * y**2 + x**2 + y**2 - 1) * sin(z) / (y**2 - 1) + x * sqrt( (-x**2 + 1) * (y**2 - 1)) * (-x**2 * y + y) * sin(z) / sqrt(-x**2 * y**2 + x**2 + y**2 - 1)) / (a * sqrt( (-x**2 + 1) * (y**2 - 1)) * (x**2 - y**2)) ) * sin(z) / (a * (x**2 - y**2)) + y * (x**2 - 1) * ( -2 * x * y * (x**2 - 1) / (a * (x**2 - y**2)**2) + 2 * x * y / (a * (x**2 - y**2)) ) / (a * (x**2 - y**2)) + y * (x**2 - 1) * (y**2 - 1) * ( -x * y * sqrt(-x**2 * y**2 + x**2 + y**2 - 1) * cos(z) / (a * (x**2 - y**2) * (y**2 - 1)) + 2 * x * y * sqrt(-x**2 * y**2 + x**2 + y**2 - 1) * cos(z) / (a * (x**2 - y**2)**2) + (x * y * sqrt((-x**2 + 1) * (y**2 - 1)) * sqrt(-x**2 * y**2 + x**2 + y**2 - 1) * cos(z) / (y**2 - 1) + x * sqrt( (-x**2 + 1) * (y**2 - 1)) * (-x**2 * y + y) * cos(z) / sqrt(-x**2 * y**2 + x**2 + y**2 - 1)) / (a * sqrt((-x**2 + 1) * (y**2 - 1)) * (x**2 - y**2))) * cos(z) / (a * sqrt( (-x**2 + 1) * (y**2 - 1)) * (x**2 - y**2)) - x * sqrt( (-x**2 + 1) * (y**2 - 1) ) * sqrt(-x**2 * y**2 + x**2 + y**2 - 1) * sin( z)**2 / (a**2 * (x**2 - 1) * (x**2 - y**2) * (y**2 - 1)) - x * sqrt( (-x**2 + 1) * (y**2 - 1)) * sqrt( -x**2 * y**2 + x**2 + y**2 - 1) * cos(z)**2 / ( a**2 * (x**2 - 1) * (x**2 - y**2) * (y**2 - 1)) assert simplify(expr) == 2 * x / (a**2 * (x**2 - y**2)) #issue 17631 assert simplify('((-1/2)*Boole(True)*Boole(False)-1)*Boole(True)') == \ Mul(sympify('(2 + Boole(True)*Boole(False))'), sympify('-Boole(True)/2')) A, B = symbols('A,B', commutative=False) assert simplify(A * B - B * A) == A * B - B * A assert simplify(A / (1 + y / x)) == x * A / (x + y) assert simplify(A * (1 / x + 1 / y)) == A / x + A / y #(x + y)*A/(x*y) assert simplify(log(2) + log(3)) == log(6) assert simplify(log(2 * x) - log(2)) == log(x) assert simplify(hyper([], [], x)) == exp(x)
def tensor_product_simp_Mul(e): """Simplify a Mul with TensorProducts. Current the main use of this is to simplify a ``Mul`` of ``TensorProduct``s to a ``TensorProduct`` of ``Muls``. It currently only works for relatively simple cases where the initial ``Mul`` only has scalars and raw ``TensorProduct``s, not ``Add``, ``Pow``, ``Commutator``s of ``TensorProduct``s. Parameters ========== e : Expr A ``Mul`` of ``TensorProduct``s to be simplified. Returns ======= e : Expr A ``TensorProduct`` of ``Mul``s. Examples ======== This is an example of the type of simplification that this function performs:: >>> from sympsi.tensorproduct import \ tensor_product_simp_Mul, TensorProduct >>> from sympy import Symbol >>> A = Symbol('A',commutative=False) >>> B = Symbol('B',commutative=False) >>> C = Symbol('C',commutative=False) >>> D = Symbol('D',commutative=False) >>> e = TensorProduct(A,B)*TensorProduct(C,D) >>> e AxB*CxD >>> tensor_product_simp_Mul(e) (A*C)x(B*D) """ # TODO: This won't work with Muls that have other composites of # TensorProducts, like an Add, Pow, Commutator, etc. # TODO: This only works for the equivalent of single Qbit gates. if not isinstance(e, Mul): return e c_part, nc_part = e.args_cnc() n_nc = len(nc_part) if n_nc == 0 or n_nc == 1: return e elif e.has(TensorProduct): current = nc_part[0] if not isinstance(current, TensorProduct): raise TypeError('TensorProduct expected, got: %r' % current) n_terms = len(current.args) new_args = list(current.args) for next in nc_part[1:]: # TODO: check the hilbert spaces of next and current here. if isinstance(next, TensorProduct): if n_terms != len(next.args): raise QuantumError( 'TensorProducts of different lengths: %r and %r' % (current, next)) for i in range(len(new_args)): new_args[i] = new_args[i] * next.args[i] else: # this won't quite work as we don't want next in the # TensorProduct for i in range(len(new_args)): new_args[i] = new_args[i] * next current = next return Mul(*c_part) * TensorProduct(*new_args) else: return e
def __rmul__(self, other): return Mul(other, self)
def test_issue_5460(): u = Mul(2, (1 + x), evaluate=False) assert (2 + u).args == (2, u)
def test_2127(): assert Add(evaluate=False) == 0 assert Mul(evaluate=False) == 1 assert Mul(x+y, evaluate=False).is_Add
def gate_simp(circuit): """Simplifies gates symbolically It first sorts gates using gate_sort. It then applies basic simplification rules to the circuit, e.g., XGate**2 = Identity """ # Bubble sort out gates that commute. circuit = gate_sort(circuit) # Do simplifications by subing a simplification into the first element # which can be simplified. We recursively call gate_simp with new circuit # as input more simplifications exist. if isinstance(circuit, Add): return sum(gate_simp(t) for t in circuit.args) elif isinstance(circuit, Mul): circuit_args = circuit.args elif isinstance(circuit, Pow): b, e = circuit.as_base_exp() circuit_args = (gate_simp(b)**e, ) else: return circuit # Iterate through each element in circuit, simplify if possible. for i in xrange(len(circuit_args)): # H,X,Y or Z squared is 1. # T**2 = S, S**2 = Z if isinstance(circuit_args[i], Pow): if isinstance(circuit_args[i].base, (HadamardGate, XGate, YGate, ZGate))\ and isinstance(circuit_args[i].exp, Number): # Build a new circuit taking replacing the # H,X,Y,Z squared with one. newargs = (circuit_args[:i] +\ (circuit_args[i].base**(circuit_args[i].exp % 2),) +\ circuit_args[i+1:]) # Recursively simplify the new circuit. circuit = gate_simp(Mul(*newargs)) break elif isinstance(circuit_args[i].base, PhaseGate): # Build a new circuit taking old circuit but splicing # in simplification. newargs = circuit_args[:i] # Replace PhaseGate**2 with ZGate. newargs = newargs + (ZGate(circuit_args[i].base.args[0])**\ (Integer(circuit_args[i].exp/2)), circuit_args[i].base**\ (circuit_args[i].exp % 2)) # Append the last elements. newargs = newargs + circuit_args[i + 1:] # Recursively simplify the new circuit. circuit = gate_simp(Mul(*newargs)) break elif isinstance(circuit_args[i].base, TGate): # Build a new circuit taking all the old elements. newargs = circuit_args[:i] # Put an Phasegate in place of any TGate**2. newargs = newargs + (PhaseGate(circuit_args[i].base.args[0])**\ Integer(circuit_args[i].exp/2), circuit_args[i].base**\ (circuit_args[i].exp % 2)) # Append the last elements. newargs = newargs + circuit_args[i + 1:] # Recursively simplify the new circuit. circuit = gate_simp(Mul(*newargs)) break return circuit
def _eval_expand_commutator(self, **hints): A = self.args[0] B = self.args[1] if isinstance(A, Add): # [A + B, C] -> [A, C] + [B, C] sargs = [] for term in A.args: comm = Commutator(term, B) if isinstance(comm, Commutator): comm = comm._eval_expand_commutator() sargs.append(comm) return Add(*sargs) elif isinstance(B, Add): # [A, B + C] -> [A, B] + [A, C] sargs = [] for term in B.args: comm = Commutator(A, term) if isinstance(comm, Commutator): comm = comm._eval_expand_commutator() sargs.append(comm) return Add(*sargs) elif isinstance(A, Mul): # [A*B, C] -> A*[B, C] + [A, C]*B a = A.args[0] b = Mul(*A.args[1:]) c = B comm1 = Commutator(b, c) comm2 = Commutator(a, c) if isinstance(comm1, Commutator): comm1 = comm1._eval_expand_commutator() if isinstance(comm2, Commutator): comm2 = comm2._eval_expand_commutator() first = Mul(a, comm1) second = Mul(comm2, b) return Add(first, second) elif isinstance(B, Mul): # [A, B*C] -> [A, B]*C + B*[A, C] a = A b = B.args[0] c = Mul(*B.args[1:]) comm1 = Commutator(a, b) comm2 = Commutator(a, c) if isinstance(comm1, Commutator): comm1 = comm1._eval_expand_commutator() if isinstance(comm2, Commutator): comm2 = comm2._eval_expand_commutator() first = Mul(comm1, c) second = Mul(b, comm2) return Add(first, second) elif isinstance(A, Integral): # [∫adx, B] -> ∫[a, B]dx func, lims = A.function, A.limits new_args = [Commutator(func, B)] for lim in lims: new_args.append(lim) return Integral(*new_args) elif isinstance(B, Integral): # [A, ∫bdx] -> ∫[A, b]dx func, lims = B.function, B.limits new_args = [Commutator(A, func)] for lim in lims: new_args.append(lim) return Integral(*new_args) # No changes, so return self return self
def _minpoly_compose(ex, x, dom): """ Computes the minimal polynomial of an algebraic element using operations on minimal polynomials Examples ======== >>> from sympy import minimal_polynomial, sqrt, Rational >>> from sympy.abc import x, y >>> minimal_polynomial(sqrt(2) + 3*Rational(1, 3), x, compose=True) x**2 - 2*x - 1 >>> minimal_polynomial(sqrt(y) + 1/y, x, compose=True) x**2*y**2 - 2*x*y - y**3 + 1 """ if ex.is_Rational: return ex.q * x - ex.p if ex is I: _, factors = factor_list(x**2 + 1, x, domain=dom) return x**2 + 1 if len(factors) == 1 else x - I if hasattr(dom, 'symbols') and ex in dom.symbols: return x - ex if dom.is_QQ and _is_sum_surds(ex): # eliminate the square roots ex -= x while 1: ex1 = _separate_sq(ex) if ex1 is ex: return ex else: ex = ex1 if ex.is_Add: res = _minpoly_add(x, dom, *ex.args) elif ex.is_Mul: f = Factors(ex).factors r = sift(f.items(), lambda itx: itx[0].is_Rational and itx[1].is_Rational) if r[True] and dom == QQ: ex1 = Mul(*[bx**ex for bx, ex in r[False] + r[None]]) r1 = dict(r[True]) dens = [y.q for y in r1.values()] lcmdens = reduce(lcm, dens, 1) neg1 = S.NegativeOne expn1 = r1.pop(neg1, S.Zero) nums = [base**(y.p * lcmdens // y.q) for base, y in r1.items()] ex2 = Mul(*nums) mp1 = minimal_polynomial(ex1, x) # use the fact that in SymPy canonicalization products of integers # raised to rational powers are organized in relatively prime # bases, and that in ``base**(n/d)`` a perfect power is # simplified with the root # Powers of -1 have to be treated separately to preserve sign. mp2 = ex2.q * x**lcmdens - ex2.p * neg1**(expn1 * lcmdens) ex2 = neg1**expn1 * ex2**Rational(1, lcmdens) res = _minpoly_op_algebraic_element(Mul, ex1, ex2, x, dom, mp1=mp1, mp2=mp2) else: res = _minpoly_mul(x, dom, *ex.args) elif ex.is_Power: res = _minpoly_pow(ex.base, ex.exp, x, dom) elif ex.__class__ is sin: res = _minpoly_sin(ex, x) elif ex.__class__ is cos: res = _minpoly_cos(ex, x) elif ex.__class__ is exp: res = _minpoly_exp(ex, x) elif ex.__class__ is CRootOf: res = _minpoly_rootof(ex, x) else: raise NotAlgebraic("%s doesn't seem to be an algebraic element" % ex) return res
def test_powsimp(): x, y, z, n = symbols('x,y,z,n') f = Function('f') assert powsimp(4**x * 2**(-x) * 2**(-x)) == 1 assert powsimp((-4)**x * (-2)**(-x) * 2**(-x)) == 1 assert powsimp(f(4**x * 2**(-x) * 2**(-x))) == f(4**x * 2**(-x) * 2**(-x)) assert powsimp(f(4**x * 2**(-x) * 2**(-x)), deep=True) == f(1) assert exp(x) * exp(y) == exp(x) * exp(y) assert powsimp(exp(x) * exp(y)) == exp(x + y) assert powsimp(exp(x) * exp(y) * 2**x * 2**y) == (2 * E)**(x + y) assert powsimp(exp(x)*exp(y)*2**x*2**y, combine='exp') == \ exp(x + y)*2**(x + y) assert powsimp(exp(x)*exp(y)*exp(2)*sin(x) + sin(y) + 2**x*2**y) == \ exp(2 + x + y)*sin(x) + sin(y) + 2**(x + y) assert powsimp(sin(exp(x) * exp(y))) == sin(exp(x) * exp(y)) assert powsimp(sin(exp(x) * exp(y)), deep=True) == sin(exp(x + y)) assert powsimp(x**2 * x**y) == x**(2 + y) # This should remain factored, because 'exp' with deep=True is supposed # to act like old automatic exponent combining. assert powsimp((1 + E*exp(E))*exp(-E), combine='exp', deep=True) == \ (1 + exp(1 + E))*exp(-E) assert powsimp((1 + E*exp(E))*exp(-E), deep=True) == \ (1 + exp(1 + E))*exp(-E) assert powsimp((1 + E * exp(E)) * exp(-E)) == (1 + exp(1 + E)) * exp(-E) assert powsimp((1 + E*exp(E))*exp(-E), combine='exp') == \ (1 + exp(1 + E))*exp(-E) assert powsimp((1 + E*exp(E))*exp(-E), combine='base') == \ (1 + E*exp(E))*exp(-E) x, y = symbols('x,y', nonnegative=True) n = Symbol('n', real=True) assert powsimp(y**n * (y / x)**(-n)) == x**n assert powsimp(x**(x**(x*y)*y**(x*y))*y**(x**(x*y)*y**(x*y)), deep=True) \ == (x*y)**(x*y)**(x*y) assert powsimp(2**(2**(2 * x) * x), deep=False) == 2**(2**(2 * x) * x) assert powsimp(2**(2**(2 * x) * x), deep=True) == 2**(x * 4**x) assert powsimp( exp(-x + exp(-x)*exp(-x*log(x))), deep=False, combine='exp') == \ exp(-x + exp(-x)*exp(-x*log(x))) assert powsimp( exp(-x + exp(-x)*exp(-x*log(x))), deep=False, combine='exp') == \ exp(-x + exp(-x)*exp(-x*log(x))) assert powsimp((x + y) / (3 * z), deep=False, combine='exp') == (x + y) / (3 * z) assert powsimp((x / 3 + y / 3) / z, deep=True, combine='exp') == (x / 3 + y / 3) / z assert powsimp(exp(x)/(1 + exp(x)*exp(y)), deep=True) == \ exp(x)/(1 + exp(x + y)) assert powsimp(x * y**(z**x * z**y), deep=True) == x * y**(z**(x + y)) assert powsimp((z**x * z**y)**x, deep=True) == (z**(x + y))**x assert powsimp(x * (z**x * z**y)**x, deep=True) == x * (z**(x + y))**x p = symbols('p', positive=True) assert powsimp((1 / x)**log(2) / x) == (1 / x)**(1 + log(2)) assert powsimp((1 / p)**log(2) / p) == p**(-1 - log(2)) # coefficient of exponent can only be simplified for positive bases assert powsimp(2**(2 * x)) == 4**x assert powsimp((-1)**(2 * x)) == (-1)**(2 * x) i = symbols('i', integer=True) assert powsimp((-1)**(2 * i)) == 1 assert powsimp((-1)**(-x)) != (-1)**x # could be 1/((-1)**x), but is not # force=True overrides assumptions assert powsimp((-1)**(2 * x), force=True) == 1 # rational exponents allow combining of negative terms w, n, m = symbols('w n m', negative=True) e = i / a # not a rational exponent if `a` is unknown ex = w**e * n**e * m**e assert powsimp(ex) == m**(i / a) * n**(i / a) * w**(i / a) e = i / 3 ex = w**e * n**e * m**e assert powsimp(ex) == (-1)**i * (-m * n * w)**(i / 3) e = (3 + i) / i ex = w**e * n**e * m**e assert powsimp(ex) == (-1)**(3 * e) * (-m * n * w)**e eq = x**(a * Rational(2, 3)) # eq != (x**a)**(2/3) (try x = -1 and a = 3 to see) assert powsimp(eq).exp == eq.exp == a * Rational(2, 3) # powdenest goes the other direction assert powsimp(2**(2 * x)) == 4**x assert powsimp(exp(p / 2)) == exp(p / 2) # issue 6368 eq = Mul(*[sqrt(Dummy(imaginary=True)) for i in range(3)]) assert powsimp(eq) == eq and eq.is_Mul assert all(powsimp(e) == e for e in (sqrt(x**a), sqrt(x**2))) # issue 8836 assert str(powsimp(exp(I * pi / 3) * root(-1, 3))) == '(-1)**(2/3)' # issue 9183 assert powsimp(-0.1**x) == -0.1**x # issue 10095 assert powsimp((1 / (2 * E))**oo) == (exp(-1) / 2)**oo # PR 13131 eq = sin(2 * x)**2 * sin(2.0 * x)**2 assert powsimp(eq) == eq # issue 14615 assert powsimp( x**2 * y**3 * (x * y**2)**Rational(3, 2)) == x * y * (x * y**2)**Rational(5, 2)
def test_evalf_bugs(): assert NS(sin(1) + exp(-10**10), 10) == NS(sin(1), 10) assert NS(exp(10**10) + sin(1), 10) == NS(exp(10**10), 10) assert NS('expand_log(log(1+1/10**50))', 20) == '1.0000000000000000000e-50' assert NS('log(10**100,10)', 10) == '100.0000000' assert NS('log(2)', 10) == '0.6931471806' assert NS('(sin(x)-x)/x**3', 15, subs={x: '1/10**50'}) == '-0.166666666666667' assert NS(sin(1) + Rational(1, 10**100) * I, 15) == '0.841470984807897 + 1.00000000000000e-100*I' assert x.evalf() == x assert NS((1 + I)**2 * I, 6) == '-2.00000' d = { n: (-1)**Rational(6, 7), y: (-1)**Rational(4, 7), x: (-1)**Rational(2, 7) } assert NS((x * (1 + y * (1 + n))).subs(d).evalf(), 6) == '0.346011 + 0.433884*I' assert NS(((-I - sqrt(2) * I)**2).evalf()) == '-5.82842712474619' assert NS((1 + I)**2 * I, 15) == '-2.00000000000000' # issue 4758 (1/2): assert NS(pi.evalf(69) - pi) == '-4.43863937855894e-71' # issue 4758 (2/2): With the bug present, this still only fails if the # terms are in the order given here. This is not generally the case, # because the order depends on the hashes of the terms. assert NS(20 - 5008329267844 * n**25 - 477638700 * n**37 - 19 * n, subs={n: .01}) == '19.8100000000000' assert NS( ((x - 1) * ((1 - x))** 1000).n()) == '(1.00000000000000 - x)**1000*(x - 1.00000000000000)' assert NS((-x).n()) == '-x' assert NS((-2 * x).n()) == '-2.00000000000000*x' assert NS((-2 * x * y).n()) == '-2.00000000000000*x*y' assert cos(x).n(subs={x: 1 + I}) == cos(x).subs(x, 1 + I).n() # issue 6660. Also NaN != mpmath.nan # In this order: # 0*nan, 0/nan, 0*inf, 0/inf # 0+nan, 0-nan, 0+inf, 0-inf # >>> n = Some Number # n*nan, n/nan, n*inf, n/inf # n+nan, n-nan, n+inf, n-inf assert (0 * E**(oo)).n() is S.NaN assert (0 / E**(oo)).n() is S.Zero assert (0 + E**(oo)).n() is S.Infinity assert (0 - E**(oo)).n() is S.NegativeInfinity assert (5 * E**(oo)).n() is S.Infinity assert (5 / E**(oo)).n() is S.Zero assert (5 + E**(oo)).n() is S.Infinity assert (5 - E**(oo)).n() is S.NegativeInfinity #issue 7416 assert as_mpmath(0.0, 10, {'chop': True}) == 0 #issue 5412 assert ((oo * I).n() == S.Infinity * I) assert ((oo + oo * I).n() == S.Infinity + S.Infinity * I) #issue 11518 assert NS(2 * x**2.5, 5) == '2.0000*x**2.5000' #issue 13076 assert NS(Mul(Max(0, y), x, evaluate=False).evalf()) == 'x*Max(0, y)'
def test_unevaluated_mul(): eq = Mul(x + y, x + y, evaluate=False) assert cse(eq) == ([(x0, x + y)], [x0**2])
def pdf(self, *x): n, p = self.n, self.p term_1 = factorial(n)/Mul.fromiter([factorial(x_k) for x_k in x]) term_2 = Mul.fromiter([p_k**x_k for p_k, x_k in zip(p, x)]) return Piecewise((term_1 * term_2, Eq(sum(x), n)), (0, True))
def test_Pow_as_content_primitive(): assert (x**y).as_content_primitive() == (1, x**y) assert ((2*x + 2)**y).as_content_primitive() == \ (1, (Mul(2, (x + 1), evaluate=False))**y) assert ((2 * x + 2)**3).as_content_primitive() == (8, (x + 1)**3)
def _eval_expand_basic(self, deep=True, **hints): if isinstance(self.args[0], Mul): return Mul(*map(Transpose, reversed(self.args[0].args))) if isinstance(self.args[0], Add): return Add(*map(Transpose, self.args[0].args)) return self
def test_evaluate_false(): for no in [0, False]: assert Add(3, 2, evaluate=no).is_Add assert Mul(3, 2, evaluate=no).is_Mul assert Pow(3, 2, evaluate=no).is_Pow assert Pow(y, 2, evaluate=True) - Pow(y, 2, evaluate=True) == 0
def test_pow_im(): for m in (-2, -1, 2): for d in (3, 4, 5): b = m * I for i in range(1, 4 * d + 1): e = Rational(i, d) assert (b**e - b.n()**e.n()).n(2, chop=1e-10) == 0 e = Rational(7, 3) assert ( 2 * x * I)**e == 4 * 2**Rational(1, 3) * (I * x)**e # same as Wolfram Alpha im = symbols('im', imaginary=True) assert (2 * im * I)**e == 4 * 2**Rational(1, 3) * (I * im)**e args = [I, I, I, I, 2] e = Rational(1, 3) ans = 2**e assert Mul(*args, evaluate=False)**e == ans assert Mul(*args)**e == ans args = [I, I, I, 2] e = Rational(1, 3) ans = 2**e * (-I)**e assert Mul(*args, evaluate=False)**e == ans assert Mul(*args)**e == ans args.append(-3) ans = (6 * I)**e assert Mul(*args, evaluate=False)**e == ans assert Mul(*args)**e == ans args.append(-1) ans = (-6 * I)**e assert Mul(*args, evaluate=False)**e == ans assert Mul(*args)**e == ans args = [I, I, 2] e = Rational(1, 3) ans = (-2)**e assert Mul(*args, evaluate=False)**e == ans assert Mul(*args)**e == ans args.append(-3) ans = (6)**e assert Mul(*args, evaluate=False)**e == ans assert Mul(*args)**e == ans args.append(-1) ans = (-6)**e assert Mul(*args, evaluate=False)**e == ans assert Mul(*args)**e == ans assert Mul(Pow(-1, Rational(3, 2), evaluate=False), I, I) == I assert Mul(I * Pow(I, S.Half, evaluate=False)) == (-1)**Rational(3, 4)
def residue(expr, x, x0): """ Finds the residue of ``expr`` at the point x=x0. The residue is defined as the coefficient of 1/(x-x0) in the power series expansion about x=x0. Examples ======== >>> from sympy import Symbol, residue, sin >>> x = Symbol("x") >>> residue(1/x, x, 0) 1 >>> residue(1/x**2, x, 0) 0 >>> residue(2/sin(x), x, 0) 2 This function is essential for the Residue Theorem [1]. References ========== 1. http://en.wikipedia.org/wiki/Residue_theorem """ # The current implementation uses series expansion to # calculate it. A more general implementation is explained in # the section 5.6 of the Bronstein's book {M. Bronstein: # Symbolic Integration I, Springer Verlag (2005)}. For purely # rational functions, the algorithm is much easier. See # sections 2.4, 2.5, and 2.7 (this section actually gives an # algorithm for computing any Laurent series coefficient for # a rational function). The theory in section 2.4 will help to # understand why the resultant works in the general algorithm. # For the definition of a resultant, see section 1.4 (and any # previous sections for more review). from sympy import collect, Mul, Order, S expr = sympify(expr) if x0 != 0: expr = expr.subs(x, x + x0) for n in [0, 1, 2, 4, 8, 16, 32]: if n == 0: s = expr.series(x, n=0) else: s = expr.nseries(x, n=n) if s.has(Order) and s.removeO() == 0: # bug in nseries continue if not s.has(Order) or s.getn() >= 0: break if s.has(Order) and s.getn() < 0: raise NotImplementedError('Bug in nseries?') s = collect(s.removeO(), x) if s.is_Add: args = s.args else: args = [s] res = S(0) for arg in args: c, m = arg.as_coeff_mul(x) m = Mul(*m) if not (m == 1 or m == x or (m.is_Pow and m.exp.is_Integer)): raise NotImplementedError('term of unexpected form: %s' % m) if m == 1 / x: res += c return res
def test_zoo(): b = Symbol('b', bounded=True) nz = Symbol('nz', nonzero=True) p = Symbol('p', positive=True) n = Symbol('n', negative=True) im = Symbol('i', imaginary=True) c = Symbol('c', complex=True) pb = Symbol('pb', positive=True, bounded=True) nb = Symbol('nb', negative=True, bounded=True) imb = Symbol('ib', imaginary=True, bounded=True) for i in [ I, S.Infinity, S.NegativeInfinity, S.Zero, S.One, S.Pi, S.Half, S(3), log(3), b, nz, p, n, im, pb, nb, imb, c ]: if i.is_bounded and (i.is_real or i.is_imaginary): assert i + zoo is zoo assert i - zoo is zoo assert zoo + i is zoo assert zoo - i is zoo elif i.is_bounded is not False: assert (i + zoo).is_Add assert (i - zoo).is_Add assert (zoo + i).is_Add assert (zoo - i).is_Add else: assert (i + zoo) is S.NaN assert (i - zoo) is S.NaN assert (zoo + i) is S.NaN assert (zoo - i) is S.NaN if i.is_nonzero and (i.is_real or i.is_imaginary): assert i * zoo is zoo assert zoo * i is zoo elif i.is_zero: assert i * zoo is S.NaN assert zoo * i is S.NaN else: assert (i * zoo).is_Mul assert (zoo * i).is_Mul if (1 / i).is_nonzero and (i.is_real or i.is_imaginary): assert zoo / i is zoo elif (1 / i).is_zero: assert zoo / i is S.NaN elif i.is_zero: assert zoo / i is zoo else: assert (zoo / i).is_Mul assert (I * oo).is_Mul # allow directed infinity assert zoo + zoo is S.NaN assert zoo * zoo is zoo assert zoo - zoo is S.NaN assert zoo / zoo is S.NaN assert zoo**zoo is S.NaN assert zoo**0 is S.One assert zoo**2 is zoo assert 1 / zoo is S.Zero assert Mul.flatten([S(-1), oo, S(0)]) == ([S.NaN], [], None)
def pdf(self, *k): k0, p = self.k0, self.p term_1 = (gamma(k0 + sum(k))*(1 - sum(p))**k0)/gamma(k0) term_2 = Mul.fromiter([pi**ki/factorial(ki) for pi, ki in zip(p, k)]) return term_1 * term_2
def test_as_powers_dict(): assert x.as_powers_dict() == {x: 1} assert (x**y*z).as_powers_dict() == {x: y, z: 1} assert Mul(2, 2, **dict(evaluate=False)).as_powers_dict() == {S(2): S(2)}
def _normal_ordered_form_factor(product, independent=False, recursive_limit=10, _recursive_depth=0): """ Helper function for normal_ordered_form_factor: Write multiplication expression with bosonic or fermionic operators on normally ordered form, using the bosonic and fermionic commutation relations. The resulting operator expression is equivalent to the argument, but will in general be a sum of operator products instead of a simple product. """ factors = _expand_powers(product) new_factors = [] n = 0 while n < len(factors) - 1: if isinstance(factors[n], BosonOp): # boson if not isinstance(factors[n + 1], BosonOp): new_factors.append(factors[n]) elif factors[n].is_annihilation == factors[n + 1].is_annihilation: if (independent and str(factors[n].name) > str(factors[n + 1].name)): new_factors.append(factors[n + 1]) new_factors.append(factors[n]) n += 1 else: new_factors.append(factors[n]) elif not factors[n].is_annihilation: new_factors.append(factors[n]) else: if factors[n + 1].is_annihilation: new_factors.append(factors[n]) else: if factors[n].args[0] != factors[n + 1].args[0]: if independent: c = 0 else: c = Commutator(factors[n], factors[n + 1]) new_factors.append(factors[n + 1] * factors[n] + c) else: c = Commutator(factors[n], factors[n + 1]) new_factors.append(factors[n + 1] * factors[n] + c.doit()) n += 1 elif isinstance(factors[n], FermionOp): # fermion if not isinstance(factors[n + 1], FermionOp): new_factors.append(factors[n]) elif factors[n].is_annihilation == factors[n + 1].is_annihilation: if (independent and str(factors[n].name) > str(factors[n + 1].name)): new_factors.append(factors[n + 1]) new_factors.append(factors[n]) n += 1 else: new_factors.append(factors[n]) elif not factors[n].is_annihilation: new_factors.append(factors[n]) else: if factors[n + 1].is_annihilation: new_factors.append(factors[n]) else: if factors[n].args[0] != factors[n + 1].args[0]: if independent: c = 0 else: c = AntiCommutator(factors[n], factors[n + 1]) new_factors.append(-factors[n + 1] * factors[n] + c) else: c = AntiCommutator(factors[n], factors[n + 1]) new_factors.append(-factors[n + 1] * factors[n] + c.doit()) n += 1 elif isinstance(factors[n], Operator): if isinstance(factors[n + 1], (BosonOp, FermionOp)): new_factors.append(factors[n + 1]) new_factors.append(factors[n]) n += 1 else: new_factors.append(factors[n]) else: new_factors.append(factors[n]) n += 1 if n == len(factors) - 1: new_factors.append(factors[-1]) if new_factors == factors: return product else: expr = Mul(*new_factors).expand() return normal_ordered_form(expr, recursive_limit=recursive_limit, _recursive_depth=_recursive_depth + 1, independent=independent)
def test_ops(): k0 = Ket(0) k1 = Ket(1) k = 2 * I * k0 - (x / sqrt(2)) * k1 assert k == Add(Mul(2, I, k0), Mul(Rational(-1, 2), x, Pow(2, Rational(1, 2)), k1))
x = [1, 2, 3, 4, 5] y = [2, 5, 7, 8, 9] wvar = random.random() bvar = random.random() w, b = symbols('w b', imaginary=True) cost = 0 for i in range(len(x)): cost = cost + (y[i] - (x[i] * w + b))**2 cost = cost / len(x) gradient_w = diff(cost, w) gradient_b = diff(cost, b) n = int(input("iteration: ")) lr = input("learning rate: ") print(gradient_w, gradient_b) for i in range(n): wvar = Add(sympify(wvar), -Mul(sympify(lr), gradient_w.subs({ w: wvar, b: bvar }))) bvar = Add(sympify(bvar), -Mul(sympify(lr), gradient_b.subs({ w: wvar, b: bvar }))) if (i % 100 == 0): print(i) print('{0:.3g}'.format(wvar) + "x+ " + '{0:.3g}'.format(bvar) + "b")
def test_issue_17811(): a = Function('a') assert sympify('a(x)*5', evaluate=False) == Mul(a(x), 5, evaluate=False)
def _separate_sq(p): """ helper function for ``_minimal_polynomial_sq`` It selects a rational ``g`` such that the polynomial ``p`` consists of a sum of terms whose surds squared have gcd equal to ``g`` and a sum of terms with surds squared prime with ``g``; then it takes the field norm to eliminate ``sqrt(g)`` See simplify.simplify.split_surds and polytools.sqf_norm. Examples ======== >>> from sympy import sqrt >>> from sympy.abc import x >>> from sympy.polys.numberfields import _separate_sq >>> p= -x + sqrt(2) + sqrt(3) + sqrt(7) >>> p = _separate_sq(p); p -x**2 + 2*sqrt(3)*x + 2*sqrt(7)*x - 2*sqrt(21) - 8 >>> p = _separate_sq(p); p -x**4 + 4*sqrt(7)*x**3 - 32*x**2 + 8*sqrt(7)*x + 20 >>> p = _separate_sq(p); p -x**8 + 48*x**6 - 536*x**4 + 1728*x**2 - 400 """ from sympy.utilities.iterables import sift def is_sqrt(expr): return expr.is_Power and expr.exp is S.Half # p = c1*sqrt(q1) + ... + cn*sqrt(qn) -> a = [(c1, q1), .., (cn, qn)] a = [] for y in p.args: if not y.is_Mul: if is_sqrt(y): a.append((S.One, y**2)) elif y.is_Atom: a.append((y, S.One)) elif y.is_Power and y.exp.is_integer: a.append((y, S.One)) else: raise NotImplementedError continue T, F = sift(y.args, is_sqrt, binary=True) a.append((Mul(*F), Mul(*T)**2)) a.sort(key=lambda z: z[1]) if a[-1][1] is S.One: # there are no surds return p surds = [z for y, z in a] for i in range(len(surds)): if surds[i] != 1: break g, b1, b2 = _split_gcd(*surds[i:]) a1 = [] a2 = [] for y, z in a: if z in b1: a1.append(y * z**S.Half) else: a2.append(y * z**S.Half) p1 = Add(*a1) p2 = Add(*a2) p = _mexpand(p1**2) - _mexpand(p2**2) return p
def test_identity_removal(): assert Add.make_args(x + 0) == (x,) assert Mul.make_args(x*1) == (x,)