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 cancel_terms(sym, x_term, coef): if coef.is_Add: for arg_c in coef.args: sym = cancel_terms(sym, x_term, arg_c) else: terms = Add.make_args(sym) return Add.fromiter(t for t in terms if t != x_term*coef)
def test_gcd_terms(): f = 2*(x + 1)*(x + 4)/(5*x**2 + 5) + (2*x + 2)*(x + 5)/(x**2 + 1)/5 + (2*x + 2)*(x + 6)/(5*x**2 + 5) assert _gcd_terms(f) == ((S(6)/5)*((1 + x)/(1 + x**2)), 5 + x, 1) assert _gcd_terms(Add.make_args(f)) == ((S(6)/5)*((1 + x)/(1 + x**2)), 5 + x, 1) assert gcd_terms(f) == (S(6)/5)*((1 + x)*(5 + x)/(1 + x**2)) assert gcd_terms(Add.make_args(f)) == (S(6)/5)*((1 + x)*(5 + x)/(1 + x**2)) assert gcd_terms((2*x + 2)**3 + (2*x + 2)**2) == 4*(x + 1)**2*(2*x + 3) assert gcd_terms(0) == 0 assert gcd_terms(1) == 1 assert gcd_terms(x) == x assert gcd_terms(2 + 2*x) == Mul(2, 1 + x, evaluate=False) arg = x*(2*x + 4*y) garg = 2*x*(x + 2*y) assert gcd_terms(arg) == garg assert gcd_terms(sin(arg)) == sin(garg) # issue 3040-like alpha, alpha1, alpha2, alpha3 = symbols('alpha:4') a = alpha**2 - alpha*x**2 + alpha + x**3 - x*(alpha + 1) rep = (alpha, (1 + sqrt(5))/2 + alpha1*x + alpha2*x**2 + alpha3*x**3) s = (a/(x - alpha)).subs(*rep).series(x, 0, 1) assert simplify(collect(s, x)) == -sqrt(5)/2 - S(3)/2 + O(x) # issue 2818 assert _gcd_terms([S.Zero, S.Zero]) == (0, 0, 1) assert _gcd_terms([2*x + 4]) == (2, x + 2, 1)
def test_lookup_table(): from random import uniform, randrange from sympy import Add from sympy.integrals.meijerint import z as z_dummy table = {} _create_lookup_table(table) for _, l in sorted(table.items()): for formula, terms, cond, hint in sorted(l, key=default_sort_key): subs = {} for a in list(formula.free_symbols) + [z_dummy]: if hasattr(a, "properties") and a.properties: # these Wilds match positive integers subs[a] = randrange(1, 10) else: subs[a] = uniform(1.5, 2.0) if not isinstance(terms, list): terms = terms(subs) # First test that hyperexpand can do this. expanded = [hyperexpand(g) for (_, g) in terms] assert all(x.is_Piecewise or not x.has(meijerg) for x in expanded) # Now test that the meijer g-function is indeed as advertised. expanded = Add(*[f * x for (f, x) in terms]) a, b = formula.n(subs=subs), expanded.n(subs=subs) r = min(abs(a), abs(b)) if r < 1: assert abs(a - b).n() <= 1e-10 else: assert (abs(a - b) / r).n() <= 1e-10
def test_as_ordered_terms(): f, g = symbols("f,g", cls=Function) assert x.as_ordered_terms() == [x] assert (sin(x) ** 2 * cos(x) + sin(x) * cos(x) ** 2 + 1).as_ordered_terms() == [ sin(x) ** 2 * cos(x), sin(x) * cos(x) ** 2, 1, ] args = [f(1), f(2), f(3), f(1, 2, 3), g(1), g(2), g(3), g(1, 2, 3)] expr = Add(*args) assert expr.as_ordered_terms() == args assert (1 + 4 * sqrt(3) * pi * x).as_ordered_terms() == [4 * pi * x * sqrt(3), 1] assert (2 + 3 * I).as_ordered_terms() == [2, 3 * I] assert (-2 + 3 * I).as_ordered_terms() == [-2, 3 * I] assert (2 - 3 * I).as_ordered_terms() == [2, -3 * I] assert (-2 - 3 * I).as_ordered_terms() == [-2, -3 * I] assert (4 + 3 * I).as_ordered_terms() == [4, 3 * I] assert (-4 + 3 * I).as_ordered_terms() == [-4, 3 * I] assert (4 - 3 * I).as_ordered_terms() == [4, -3 * I] assert (-4 - 3 * I).as_ordered_terms() == [-4, -3 * I] f = x ** 2 * y ** 2 + x * y ** 4 + y + 2 assert f.as_ordered_terms(order="lex") == [x ** 2 * y ** 2, x * y ** 4, y, 2] assert f.as_ordered_terms(order="grlex") == [x * y ** 4, x ** 2 * y ** 2, y, 2] assert f.as_ordered_terms(order="rev-lex") == [2, y, x * y ** 4, x ** 2 * y ** 2] assert f.as_ordered_terms(order="rev-grlex") == [2, y, x ** 2 * y ** 2, x * y ** 4]
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 atomic_ordering_energy(self, dbe): """ Return the atomic ordering contribution in symbolic form. Description follows Servant and Ansara, Calphad, 2001. """ phase = dbe.phases[self.phase_name] ordered_phase_name = phase.model_hints.get("ordered_phase", None) disordered_phase_name = phase.model_hints.get("disordered_phase", None) if phase.name != ordered_phase_name: return S.Zero disordered_model = self.__class__(dbe, self.components, disordered_phase_name) constituents = [ sorted(set(c).intersection(self.components)) for c in dbe.phases[ordered_phase_name].constituents ] # Fix variable names variable_rename_dict = {} for atom in disordered_model.energy.atoms(v.SiteFraction): # Replace disordered phase site fractions with mole fractions of # ordered phase site fractions. # Special case: Pure vacancy sublattices all_species_in_sublattice = dbe.phases[disordered_phase_name].constituents[atom.sublattice_index] if atom.species == "VA" and len(all_species_in_sublattice) == 1: # Assume: Pure vacancy sublattices are always last vacancy_subl_index = len(dbe.phases[ordered_phase_name].constituents) - 1 variable_rename_dict[atom] = v.SiteFraction(ordered_phase_name, vacancy_subl_index, atom.species) else: # All other cases: replace site fraction with mole fraction variable_rename_dict[atom] = self.mole_fraction( atom.species, ordered_phase_name, constituents, dbe.phases[ordered_phase_name].sublattices ) # Save all of the ordered energy contributions # This step is why this routine must be called _last_ in build_phase ordered_energy = Add(*list(self.models.values())) self.models.clear() # Copy the disordered energy contributions into the correct bins for name, value in disordered_model.models.items(): self.models[name] = value.xreplace(variable_rename_dict) # All magnetic parameters will be defined in the disordered model self.TC = self.curie_temperature = disordered_model.TC self.TC = self.curie_temperature = self.TC.xreplace(variable_rename_dict) molefraction_dict = {} # Construct a dictionary that replaces every site fraction with its # corresponding mole fraction in the disordered state for sitefrac in ordered_energy.atoms(v.SiteFraction): all_species_in_sublattice = dbe.phases[ordered_phase_name].constituents[sitefrac.sublattice_index] if sitefrac.species == "VA" and len(all_species_in_sublattice) == 1: # pure-vacancy sublattices should not be replaced # this handles cases like AL,NI,VA:AL,NI,VA:VA and # ensures the VA's don't get mixed up continue molefraction_dict[sitefrac] = self.mole_fraction( sitefrac.species, ordered_phase_name, constituents, dbe.phases[ordered_phase_name].sublattices ) return ordered_energy - ordered_energy.subs(molefraction_dict, simultaneous=True)
def test_gcd_terms(): f = 2*(x + 1)*(x + 4)/(5*x**2 + 5) + (2*x + 2)*(x + 5)/(x**2 + 1)/5 + \ (2*x + 2)*(x + 6)/(5*x**2 + 5) assert _gcd_terms(f) == ((S(6)/5)*((1 + x)/(1 + x**2)), 5 + x, 1) assert _gcd_terms(Add.make_args(f)) == \ ((S(6)/5)*((1 + x)/(1 + x**2)), 5 + x, 1) newf = (S(6)/5)*((1 + x)*(5 + x)/(1 + x**2)) assert gcd_terms(f) == newf args = Add.make_args(f) # non-Basic sequences of terms treated as terms of Add assert gcd_terms(list(args)) == newf assert gcd_terms(tuple(args)) == newf assert gcd_terms(set(args)) == newf # but a Basic sequence is treated as a container assert gcd_terms(Tuple(*args)) != newf assert gcd_terms(Basic(Tuple(1, 3*y + 3*x*y), Tuple(1, 3))) == \ Basic((1, 3*y*(x + 1)), (1, 3)) # but we shouldn't change keys of a dictionary or some may be lost assert gcd_terms(Dict((x*(1 + y), 2), (x + x*y, y + x*y))) == \ Dict({x*(y + 1): 2, x + x*y: y*(1 + x)}) assert gcd_terms((2*x + 2)**3 + (2*x + 2)**2) == 4*(x + 1)**2*(2*x + 3) assert gcd_terms(0) == 0 assert gcd_terms(1) == 1 assert gcd_terms(x) == x assert gcd_terms(2 + 2*x) == Mul(2, 1 + x, evaluate=False) arg = x*(2*x + 4*y) garg = 2*x*(x + 2*y) assert gcd_terms(arg) == garg assert gcd_terms(sin(arg)) == sin(garg) # issue 6139-like alpha, alpha1, alpha2, alpha3 = symbols('alpha:4') a = alpha**2 - alpha*x**2 + alpha + x**3 - x*(alpha + 1) rep = (alpha, (1 + sqrt(5))/2 + alpha1*x + alpha2*x**2 + alpha3*x**3) s = (a/(x - alpha)).subs(*rep).series(x, 0, 1) assert simplify(collect(s, x)) == -sqrt(5)/2 - S(3)/2 + O(x) # issue 5917 assert _gcd_terms([S.Zero, S.Zero]) == (0, 0, 1) assert _gcd_terms([2*x + 4]) == (2, x + 2, 1) eq = x/(x + 1/x) assert gcd_terms(eq, fraction=False) == eq eq = x/2/y + 1/x/y assert gcd_terms(eq, fraction=True, clear=True) == \ (x**2 + 2)/(2*x*y) assert gcd_terms(eq, fraction=True, clear=False) == \ (x**2/2 + 1)/(x*y) assert gcd_terms(eq, fraction=False, clear=True) == \ (x + 2/x)/(2*y) assert gcd_terms(eq, fraction=False, clear=False) == \ (x/2 + 1/x)/y
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_as_ordered_terms(): f, g = symbols('f,g', cls=Function) assert x.as_ordered_terms() == [x] assert (sin(x)**2*cos(x) + sin(x)*cos(x)**2 + 1).as_ordered_terms() == [sin(x)**2*cos(x), sin(x)*cos(x)**2, 1] expr = Add(*[f(1), f(2), f(3), f(1, 2, 3), g(1), g(2), g(3), g(1, 2, 3)]) assert expr.as_ordered_terms() == \ [f(1), f(2), f(3), f(1, 2, 3), g(1), g(2), g(3), g(1, 2, 3)] assert (1 + 4*sqrt(3)*pi*x).as_ordered_terms() == [4*pi*x*sqrt(3), 1]
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 test_gcd_terms(): f = 2*(x + 1)*(x + 4)/(5*x**2 + 5) + (2*x + 2)*(x + 5)/(x**2 + 1)/5 + (2*x + 2)*(x + 6)/(5*x**2 + 5) assert _gcd_terms(f) == ((S(6)/5)*((1 + x)/(1 + x**2)), 5 + x, 1) assert _gcd_terms(Add.make_args(f)) == ((S(6)/5)*((1 + x)/(1 + x**2)), 5 + x, 1) assert gcd_terms(f) == (S(6)/5)*((1 + x)*(5 + x)/(1 + x**2)) assert gcd_terms(Add.make_args(f)) == (S(6)/5)*((1 + x)*(5 + x)/(1 + x**2)) assert gcd_terms(0) == 0 assert gcd_terms(1) == 1 assert gcd_terms(x) == x
def _add_reaction_dual_constraint(self, reaction, coefficient, maximization, prefix): """Add a dual constraint corresponding to the reaction's objective coefficient""" stoichiometry = {self.solver.variables["lambda_" + m.id]: c for m, c in six.iteritems(reaction.metabolites)} if maximization: constraint = self.solver.interface.Constraint( Add._from_args(tuple(c * v for v, c in six.iteritems(stoichiometry))), name="r_%s_%s" % (reaction.id, prefix), lb=coefficient) else: constraint = self._dual_solver.interface.Constraint( Add._from_args(tuple(c * v for v, c in six.iteritems(stoichiometry))), name="r_%s_%s" % (reaction.id, prefix), ub=coefficient) self.solver._add_constraint(constraint)
def _inverse_mellin_transform(F, s, x_, strip, as_meijerg=False): """ A helper for the real inverse_mellin_transform function, this one here assumes x to be real and positive. """ from sympy import (expand, expand_mul, hyperexpand, meijerg, And, Or, arg, pi, re, factor, Heaviside, gamma, Add) x = _dummy('t', 'inverse-mellin-transform', F, positive=True) # Actually, we won't try integration at all. Instead we use the definition # of the Meijer G function as a fairly general inverse mellin transform. F = F.rewrite(gamma) for g in [factor(F), expand_mul(F), expand(F)]: if g.is_Add: # do all terms separately ress = [_inverse_mellin_transform(G, s, x, strip, as_meijerg, noconds=False) \ for G in g.args] conds = [p[1] for p in ress] ress = [p[0] for p in ress] res = Add(*ress) if not as_meijerg: res = factor(res, gens=res.atoms(Heaviside)) return res.subs(x, x_), And(*conds) try: a, b, C, e, fac = _rewrite_gamma(g, s, strip[0], strip[1]) except IntegralTransformError: continue G = meijerg(a, b, C/x**e) if as_meijerg: h = G else: h = hyperexpand(G) if h.is_Piecewise and len(h.args) == 3: # XXX we break modularity here! h = Heaviside(x - abs(C))*h.args[0].args[0] \ + Heaviside(abs(C) - x)*h.args[1].args[0] # We must ensure that the intgral along the line we want converges, # and return that value. # See [L], 5.2 cond = [abs(arg(G.argument)) < G.delta*pi] # Note: we allow ">=" here, this corresponds to convergence if we let # limits go to oo symetrically. ">" corresponds to absolute convergence. cond += [And(Or(len(G.ap) != len(G.bq), 0 >= re(G.nu) + 1), abs(arg(G.argument)) == G.delta*pi)] cond = Or(*cond) if cond is False: raise IntegralTransformError('Inverse Mellin', F, 'does not converge') return (h*fac).subs(x, x_), cond raise IntegralTransformError('Inverse Mellin', F, '')
def sampling_E(condition, given=None, numsamples=1, evalf=True, **kwargs): """ Sampling version of E See Also ======== P sampling_P """ samples = sample_iter(condition, given, numsamples=numsamples, **kwargs) result = Add(*list(samples)) / numsamples if evalf: return result.evalf() else: return result
def test_gcd_terms(): f = 2*(x + 1)*(x + 4)/(5*x**2 + 5) + (2*x + 2)*(x + 5)/(x**2 + 1)/5 + (2*x + 2)*(x + 6)/(5*x**2 + 5) assert _gcd_terms(f) == ((S(6)/5)*((1 + x)/(1 + x**2)), 5 + x, 1) assert _gcd_terms(Add.make_args(f)) == ((S(6)/5)*((1 + x)/(1 + x**2)), 5 + x, 1) assert gcd_terms(f) == (S(6)/5)*((1 + x)*(5 + x)/(1 + x**2)) assert gcd_terms(Add.make_args(f)) == (S(6)/5)*((1 + x)*(5 + x)/(1 + x**2)) assert gcd_terms((2*x + 2)**3 + (2*x + 2)**2) == 4*(x + 1)**2*(2*x + 3) assert gcd_terms(0) == 0 assert gcd_terms(1) == 1 assert gcd_terms(x) == x assert gcd_terms(2 + 2*x) == Mul(2, 1 + x, evaluate=False)
def calc_part(expr, nexpr): from sympy import Add nint = int(to_int(nexpr, rnd)) n, c, p, b = nexpr if (c != 1 and p != 0) or p < 0: expr = Add(expr, -nint, evaluate=False) x, _, x_acc, _ = evalf(expr, 10, options) try: check_target(expr, (x, None, x_acc, None), 3) except PrecisionExhausted: if not expr.equals(0): raise PrecisionExhausted x = fzero nint += int(no*(mpf_cmp(x or fzero, fzero) == no)) nint = from_int(nint) return nint, fastlog(nint) + 10
def __new__(cls, *args): args = map(matrixify, args) args = [arg for arg in args if arg!=0] if not all(arg.is_Matrix for arg in args): raise ValueError("Mix of Matrix and Scalar symbols") # Check that the shape of the args is consistent A = args[0] for B in args[1:]: if A.shape != B.shape: raise ShapeError("Matrices %s and %s are not aligned"%(A,B)) expr = Add.__new__(cls, *args) if expr == S.Zero: return ZeroMatrix(*args[0].shape) expr = matrixify(expr) if expr.is_Mul: return MatMul(*expr.args) # Clear out Identities # Any zeros around? if expr.is_Add and any(M.is_ZeroMatrix for M in expr.args): newargs = [M for M in expr.args if not M.is_ZeroMatrix] # clear out if len(newargs)==0: # Did we lose everything? return ZeroMatrix(*args[0].shape) if expr.args != newargs: # Removed some 0's but not everything? return MatAdd(*newargs) # Repeat with simpler expr return expr
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 _as_ordered_terms(self, expr, order=None): """A compatibility function for ordering terms in Add. """ order = order or self.order if order == 'old': return sorted(Add.make_args(expr), key=cmp_to_key(Basic._compare_pretty)) else: return expr.as_ordered_terms(order=order)
def _print_Add(self, expr): if len(expr.args) != 2: return "add({}, {})".format( self._print(expr.args[0]), self._print(Add.fromiter(expr.args[1:])) ) return "add({}, {})".format( self._print(expr.args[0]), self._print(expr.args[1]), )
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_terms(): f, g = symbols('f,g', cls=Function) assert x.as_ordered_terms() == [x] assert (sin(x)**2*cos(x) + sin(x)*cos(x)**2 + 1).as_ordered_terms() == [sin(x)**2*cos(x), sin(x)*cos(x)**2, 1] args = [f(1), f(2), f(3), f(1, 2, 3), g(1), g(2), g(3), g(1, 2, 3)] expr = Add(*args) assert expr.as_ordered_terms() == args assert (1 + 4*sqrt(3)*pi*x).as_ordered_terms() == [4*pi*x*sqrt(3), 1] assert ( 2 + 3*I).as_ordered_terms() == [ 2, 3*I] assert (-2 + 3*I).as_ordered_terms() == [-2, 3*I] assert ( 2 - 3*I).as_ordered_terms() == [ 2, -3*I] assert (-2 - 3*I).as_ordered_terms() == [-2, -3*I] assert ( 4 + 3*I).as_ordered_terms() == [ 4, 3*I] assert (-4 + 3*I).as_ordered_terms() == [-4, 3*I] assert ( 4 - 3*I).as_ordered_terms() == [ 4, -3*I] assert (-4 - 3*I).as_ordered_terms() == [-4, -3*I]
def dot(vect1, vect2): """ Returns dot product of two vectors. Examples ======== >>> from sympy.vector import CoordSys3D >>> from sympy.vector.vector import dot >>> R = CoordSys3D('R') >>> v1 = R.i + R.j + R.k >>> v2 = R.x * R.i + R.y * R.j + R.z * R.k >>> dot(v1, v2) R.x + R.y + R.z """ if isinstance(vect1, Add): return Add.fromiter(dot(i, vect2) for i in vect1.args) if isinstance(vect2, Add): return Add.fromiter(dot(vect1, i) for i in vect2.args) if isinstance(vect1, BaseVector) and isinstance(vect2, BaseVector): if vect1._sys == vect2._sys: return S.One if vect1 == vect2 else S.Zero try: from .functions import express return dot(vect1, express(vect2, vect1._sys)) except: return Dot(vect1, vect2) if isinstance(vect1, VectorZero) or isinstance(vect2, VectorZero): return S.Zero if isinstance(vect1, VectorMul): v1, m1 = next(iter(vect1.components.items())) return m1*dot(v1, vect2) if isinstance(vect2, VectorMul): v2, m2 = next(iter(vect2.components.items())) return m2*dot(vect1, v2) return Dot(vect1, vect2)
def analyze(self, expr): """Rewrite an expression as sorted list of terms. """ gens, terms = set([]), [] for term in Add.make_args(expr): coeff, cpart, ncpart = [], {}, [] for factor in Mul.make_args(term): if not factor.is_commutative: ncpart.append(factor) else: if factor.is_Number: coeff.append(factor) else: base, exp = _analyze_power(*factor.as_base_exp()) cpart[base] = exp gens.add(base) terms.append((coeff, cpart, ncpart, term)) gens = sorted(gens, Basic._compare_pretty) k, indices = len(gens), {} for i, g in enumerate(gens): indices[g] = i result = [] for coeff, cpart, ncpart, term in terms: monom = [0]*k for base, exp in cpart.iteritems(): monom[indices[base]] = exp result.append((coeff, monom, ncpart, term)) if self.order is None: return sorted(result, Basic._compare_pretty) else: return sorted(result, self._compare_terms)
def test_doit(): a = OperationsOnlyMatrix([[Add(x, x, evaluate=False)]]) assert a[0] != 2 * x assert a.doit() == Matrix([[2 * x]])
def test_identity_removal(): assert Add.make_args(x + 0) == (x,) assert Mul.make_args(x*1) == (x,)
def _dict_from_basic_no_gens(ex, **args): """Figure out generators and convert `ex` to a multinomial. """ domain = args.get('domain') if domain is not None: def _is_coeff(factor): return factor in domain else: extension = args.get('extension') if extension is True: def _is_coeff(factor): return ask(factor, 'algebraic') else: greedy = args.get('greedy', True) if greedy is True: def _is_coeff(factor): return False else: def _is_coeff(factor): return factor.is_number gens, terms = set([]), [] for term in Add.make_args(ex): coeff, elements = [], {} for factor in Mul.make_args(term): if factor.is_Number or _is_coeff(factor): coeff.append(factor) else: base, exp = _analyze_power(*factor.as_Pow()) elements[base] = exp gens.add(base) terms.append((coeff, elements)) if not gens: raise GeneratorsNeeded("specify generators to give %s a meaning" % ex) gens = _sort_gens(gens, **args) k, indices = len(gens), {} for i, g in enumerate(gens): indices[g] = i result = {} for coeff, term in terms: monom = [0]*k for base, exp in term.iteritems(): monom[indices[base]] = exp monom = tuple(monom) if result.has_key(monom): result[monom] += Mul(*coeff) else: result[monom] = Mul(*coeff) return result, tuple(gens)
def u(expr, x): from sympy import Add, exp, exp_polar r = _rewrite_single(expr, x) e = Add(*[res[0] * res[2] for res in r[0]]).replace(exp_polar, exp) # XXX Hack? assert verify_numerically(e, expr, x)
def get_max_coef(sym, x_term): return Add.fromiter( get_max_coef_mul(s, x_term) for s in Add.make_args(sym) )
def test_dim_simplify_add(): assert dim_simplify(Add(L, L)) == L assert dim_simplify(L + L) == L
from sympy import Add, Mul from commons import P1, L1, TF, render_eqn, H2, G1, H1, G2, Delta1, Delta, L2 P1_ = G1 * G2 render_eqn(P1, P1_, "P1", mul_symbol=".") L1_ = -H1 render_eqn(L1, L1_, "L1", mul_symbol=".") L2_ = -G1 * G2 * H2 render_eqn(L2, L2_, "L1", mul_symbol=".") delta1_ = 1 render_eqn(Delta1, delta1_, "delta1_", mul_symbol=".") delta_ = Add(1, Mul(-1, Add(L1, L2, evaluate=False), evaluate=False), evaluate=False) render_eqn(Delta, delta_, "delta_", mul_symbol=".", order="none") delta_ = 1 - (L1_ + L2_) render_eqn(Delta, delta_, "delta_", mul_symbol=".") render_eqn(TF, P1 * Delta1 / Delta, "TF1", mul_symbol=".") Tf_ = (delta1_ * P1_) / delta_ render_eqn(P1 * Delta1 / Delta, Tf_, "TF2", mul_symbol=".")
def test_cancellation(): assert NS(Add(pi, Rational(1, 10**1000), -pi, evaluate=False), 15, maxn=1200) == '1.00000000000000e-1000'
def evaluate_pauli_product(arg): '''Help function to evaluate Pauli matrices product with symbolic objects Parameters ========== arg: symbolic expression that contains Paulimatrices Examples ======== >>> from sympy.physics.paulialgebra import Pauli, evaluate_pauli_product >>> from sympy import I >>> evaluate_pauli_product(I*Pauli(1)*Pauli(2)) -sigma3 >>> from sympy.abc import x >>> evaluate_pauli_product(x**2*Pauli(2)*Pauli(1)) -I*x**2*sigma3 ''' start = arg end = arg if isinstance(arg, Pow) and isinstance(arg.args[0], Pauli): if arg.args[1].is_odd: return arg.args[0] else: return 1 if isinstance(arg, Add): return Add(*[evaluate_pauli_product(part) for part in arg.args]) if isinstance(arg, TensorProduct): return TensorProduct( *[evaluate_pauli_product(part) for part in arg.args]) elif not (isinstance(arg, Mul)): return arg while ((not (start == end)) | ((start == arg) & (end == arg))): start = end tmp = start.as_coeff_mul() sigma_product = 1 com_product = 1 keeper = 1 for el in tmp[1]: if isinstance(el, Pauli): sigma_product *= el elif not (el.is_commutative): if isinstance(el, Pow) and isinstance(el.args[0], Pauli): if el.args[1].is_odd: sigma_product *= el.args[0] elif isinstance(el, TensorProduct): keeper = keeper*sigma_product*\ TensorProduct( *[evaluate_pauli_product(part) for part in el.args] ) sigma_product = 1 else: keeper = keeper * sigma_product * el sigma_product = 1 else: com_product *= el end = (tmp[0] * keeper * sigma_product * com_product) if end == arg: break return end
def test_qsimplify_rec(): q3 = Q(2, s) assert qsimplify(Mul(Add(q1, q2), q3)) == q1.add(q2).mul(q3)
def replace_kronecker_delta(e, L, _n=0): """ Look for Integral of the form L ∫ sin(n*pi*x/L) * sin(m*pi*x/L) dx 0 or L ∫ cos(n*pi*x/L) * cos(m*pi*x/L) dx 0 and replace with L/2 * KroneckerDelta(n, m) if both n and m are positive integers. In addition, look for Integral of the form L ∫ sin(n*pi*x/L) * cos(m*pi*x/L) dx 0 and replace with 0 if both n and m are positive integers. """ if _n > 20: warnings.warn("Too high level or recursion, aborting") return e if isinstance(e, Add): return Add( *[replace_kronecker_delta(arg, L=L, _n=_n + 1) for arg in e.args]) if isinstance(e, Mul): return Mul( *[replace_kronecker_delta(arg, L=L, _n=_n + 1) for arg in e.args]) if isinstance(e, Sum): nargs = [replace_kronecker_delta(e.function, L=L, _n=_n + 1)] for lim in e.limits: nargs.append(lim) return Sum(*nargs) if isinstance(e, Integral): func = e.function lims = e.limits if len(lims) == 1 and (isinstance(func, Mul) and len(func.args) == 2 and len(lims[0]) == 3): # works only for definite integrals funcs = func.args dvar, xa, xb = lims[0] if (xa, xb) == (0, L): if ((all([isinstance(f, sin) for f in funcs]) or all([isinstance(f, cos) for f in funcs])) and all([dvar in f.args[0].args for f in funcs])): n = [(f.args[0] * L / (dvar * pi)) for f in funcs] if all([m.is_integer and m.is_positive for m in n]): return L * KroneckerDelta(n[0], n[1]) / 2 if (((isinstance(funcs[0], sin) and isinstance(funcs[1], cos)) or (isinstance(funcs[0], cos) and isinstance(funcs[1], sin))) and all([dvar in f.args[0].args for f in funcs])): n = [(f.args[0] * L / (dvar * pi)) for f in funcs] if all([m.is_integer and m.is_positive for m in n]): return 0 else: nargs = [replace_kronecker_delta(e.function, L=L, _n=_n + 1)] for lim in e.limits: nargs.append(lim) return Integral(*nargs) return e
def _Add(a, b): return Add(a, b, evaluate=False)
def thetas_alphas_to_expr_complex(thetas, alphas, alpha0): return alpha0 + 2*customre(Add(*[alpha/(t - theta) for theta, alpha in zip(thetas, alphas) if im(theta) >= 0]))
def test_cse_single(): # Simple substitution. e = Add(Pow(x + y, 2), sqrt(x + y)) substs, reduced = cse([e], optimizations=[]) assert substs == [(x0, x + y)] assert reduced == [sqrt(x0) + x0**2]
def test_qsimplify_add(): assert qsimplify(Add(q1, q2)) == q1.add(q2)
def test_nested_substitution(): # Substitution within a substitution. e = Add(Pow(w * x + y, 2), sqrt(w * x + y)) substs, reduced = cse([e], optimizations=[]) assert substs == [(x0, w * x + y)] assert reduced == [sqrt(x0) + x0**2]
def test_dim_simplify_rec(): assert dim_simplify(Mul(Add(L, L), T)) == L.mul(T) assert dim_simplify((L + L) * T) == L.mul(T)
def pdf(self, *syms): alpha = self.alpha B = Mul.fromiter(map(gamma, alpha)) / gamma(Add(*alpha)) return Mul.fromiter([sym**(a_k - 1) for a_k, sym in zip(alpha, syms)]) / B
def test_fps__operations(): f1, f2 = fps(sin(x)), fps(cos(x)) fsum = f1 + f2 assert fsum.function == sin(x) + cos(x) assert fsum.truncate( ) == 1 + x - x**2 / 2 - x**3 / 6 + x**4 / 24 + x**5 / 120 + O(x**6) fsum = f1 + 1 assert fsum.function == sin(x) + 1 assert fsum.truncate() == 1 + x - x**3 / 6 + x**5 / 120 + O(x**6) fsum = 1 + f2 assert fsum.function == cos(x) + 1 assert fsum.truncate() == 2 - x**2 / 2 + x**4 / 24 + O(x**6) assert (f1 + x) == Add(f1, x) assert -f2.truncate() == -1 + x**2 / 2 - x**4 / 24 + O(x**6) assert (f1 - f1) is S.Zero fsub = f1 - f2 assert fsub.function == sin(x) - cos(x) assert fsub.truncate( ) == -1 + x + x**2 / 2 - x**3 / 6 - x**4 / 24 + x**5 / 120 + O(x**6) fsub = f1 - 1 assert fsub.function == sin(x) - 1 assert fsub.truncate() == -1 + x - x**3 / 6 + x**5 / 120 + O(x**6) fsub = 1 - f2 assert fsub.function == -cos(x) + 1 assert fsub.truncate() == x**2 / 2 - x**4 / 24 + O(x**6) raises(ValueError, lambda: f1 + fps(exp(x), dir=-1)) raises(ValueError, lambda: f1 + fps(exp(x), x0=1)) fm = f1 * 3 assert fm.function == 3 * sin(x) assert fm.truncate() == 3 * x - x**3 / 2 + x**5 / 40 + O(x**6) fm = 3 * f2 assert fm.function == 3 * cos(x) assert fm.truncate() == 3 - 3 * x**2 / 2 + x**4 / 8 + O(x**6) assert (f1 * f2) == Mul(f1, f2) assert (f1 * x) == Mul(f1, x) fd = f1.diff() assert fd.function == cos(x) assert fd.truncate() == 1 - x**2 / 2 + x**4 / 24 + O(x**6) fd = f2.diff() assert fd.function == -sin(x) assert fd.truncate() == -x + x**3 / 6 - x**5 / 120 + O(x**6) fd = f2.diff().diff() assert fd.function == -cos(x) assert fd.truncate() == -1 + x**2 / 2 - x**4 / 24 + O(x**6) f3 = fps(exp(sqrt(x))) fd = f3.diff() assert fd.truncate().expand() == (1 / (2 * sqrt(x)) + S.Half + x / 12 + x**2 / 240 + x**3 / 10080 + x**4 / 725760 + x**5 / 79833600 + sqrt(x) / 4 + x**Rational(3, 2) / 48 + x**Rational(5, 2) / 1440 + x**Rational(7, 2) / 80640 + x**Rational(9, 2) / 7257600 + x**Rational(11, 2) / 958003200 + O(x**6)) assert f1.integrate((x, 0, 1)) == -cos(1) + 1 assert integrate(f1, (x, 0, 1)) == -cos(1) + 1 fi = integrate(f1, x) assert fi.function == -cos(x) assert fi.truncate() == -1 + x**2 / 2 - x**4 / 24 + O(x**6) fi = f2.integrate(x) assert fi.function == sin(x) assert fi.truncate() == x - x**3 / 6 + x**5 / 120 + O(x**6)
def _visit_Add(self, expr, **kwargs): args = [self._visit(i) for i in expr.args] return Add(*args)
def test_2127(): assert Add(evaluate=False) == 0 assert Mul(evaluate=False) == 1 assert Mul(x + y, evaluate=False).is_Add
def cse(exprs, symbols=None, optimizations=None): """ Perform common subexpression elimination on an expression. Parameters ========== exprs : list of sympy expressions, or a single sympy expression The expressions to reduce. symbols : infinite iterator yielding unique Symbols The symbols used to label the common subexpressions which are pulled out. The ``numbered_symbols`` generator is useful. The default is a stream of symbols of the form "x0", "x1", etc. This must be an infinite iterator. optimizations : list of (callable, callable) pairs, optional The (preprocessor, postprocessor) pairs. If not provided, ``sympy.simplify.cse.cse_optimizations`` is used. Returns ======= replacements : list of (Symbol, expression) pairs All of the common subexpressions that were replaced. Subexpressions earlier in this list might show up in subexpressions later in this list. reduced_exprs : list of sympy expressions The reduced expressions with all of the replacements above. """ if symbols is None: symbols = numbered_symbols() else: # In case we get passed an iterable with an __iter__ method instead of # an actual iterator. symbols = iter(symbols) seen_subexp = set() muls = set() adds = set() to_eliminate = [] to_eliminate_ops_count = [] if optimizations is None: # Pull out the default here just in case there are some weird # manipulations of the module-level list in some other thread. optimizations = list(cse_optimizations) # Handle the case if just one expression was passed. if isinstance(exprs, Basic): exprs = [exprs] # Preprocess the expressions to give us better optimization opportunities. exprs = [preprocess_for_cse(e, optimizations) for e in exprs] # Find all of the repeated subexpressions. def insert(subtree): '''This helper will insert the subtree into to_eliminate while maintaining the ordering by op count and will skip the insertion if subtree is already present.''' ops_count = subtree.count_ops() index_to_insert = bisect.bisect(to_eliminate_ops_count, ops_count) # all i up to this index have op count <= the current op count # so check that subtree is not yet present from this index down # (if necessary) to zero. for i in xrange(index_to_insert - 1, -1, -1): if to_eliminate_ops_count[i] == ops_count and \ subtree == to_eliminate[i]: return # already have it to_eliminate_ops_count.insert(index_to_insert, ops_count) to_eliminate.insert(index_to_insert, subtree) for expr in exprs: pt = preorder_traversal(expr) for subtree in pt: if subtree.is_Atom: # Exclude atoms, since there is no point in renaming them. continue if subtree in seen_subexp: insert(subtree) pt.skip() continue if subtree.is_Mul: muls.add(subtree) elif subtree.is_Add: adds.add(subtree) seen_subexp.add(subtree) # process adds - any adds that weren't repeated might contain # subpatterns that are repeated, e.g. x+y+z and x+y have x+y in common adds = [set(a.args) for a in adds] for i in xrange(len(adds)): for j in xrange(i + 1, len(adds)): com = adds[i].intersection(adds[j]) if len(com) > 1: insert(Add(*com)) # remove this set of symbols so it doesn't appear again adds[i] = adds[i].difference(com) adds[j] = adds[j].difference(com) for k in xrange(j + 1, len(adds)): if not com.difference(adds[k]): adds[k] = adds[k].difference(com) # process muls - any muls that weren't repeated might contain # subpatterns that are repeated, e.g. x*y*z and x*y have x*y in common # use SequenceMatcher on the nc part to find the longest common expression # in common between the two nc parts sm = difflib.SequenceMatcher() muls = [a.args_cnc() for a in muls] for i in xrange(len(muls)): if muls[i][1]: sm.set_seq1(muls[i][1]) for j in xrange(i + 1, len(muls)): # the commutative part in common ccom = muls[i][0].intersection(muls[j][0]) # the non-commutative part in common if muls[i][1] and muls[j][1]: # see if there is any chance of an nc match ncom = set(muls[i][1]).intersection(set(muls[j][1])) if len(ccom) + len(ncom) < 2: continue # now work harder to find the match sm.set_seq2(muls[j][1]) i1, _, n = sm.find_longest_match(0, len(muls[i][1]), 0, len(muls[j][1])) ncom = muls[i][1][i1:i1 + n] else: ncom = [] com = list(ccom) + ncom if len(com) < 2: continue insert(Mul(*com)) # remove ccom from all if there was no ncom; to update the nc part # would require finding the subexpr and then replacing it with a # dummy to keep bounding nc symbols from being identified as a # subexpr, e.g. removing B*C from A*B*C*D might allow A*D to be # identified as a subexpr which would not be right. if not ncom: muls[i][0] = muls[i][0].difference(ccom) for k in xrange(j, len(muls)): if not ccom.difference(muls[k][0]): muls[k][0] = muls[k][0].difference(ccom) # Substitute symbols for all of the repeated subexpressions. replacements = [] reduced_exprs = list(exprs) for i, subtree in enumerate(to_eliminate): sym = symbols.next() replacements.append((sym, subtree)) # Make the substitution in all of the target expressions. for j, expr in enumerate(reduced_exprs): reduced_exprs[j] = expr.subs(subtree, sym) # Make the substitution in all of the subsequent substitutions. for j in range(i + 1, len(to_eliminate)): to_eliminate[j] = to_eliminate[j].subs(subtree, sym) # Postprocess the expressions to return the expressions to canonical form. for i, (sym, subtree) in enumerate(replacements): subtree = postprocess_for_cse(subtree, optimizations) replacements[i] = (sym, subtree) reduced_exprs = [ postprocess_for_cse(e, optimizations) for e in reduced_exprs ] return replacements, reduced_exprs
def eval(cls, expr): types = (VectorTestFunction, ScalarTestFunction, DifferentialOperator, ScalarField, VectorField) if isinstance(expr, _logical_partial_derivatives): atom = get_atom_logical_derivatives(expr) indices = get_index_logical_derivatives(expr) if cls in _logical_partial_derivatives: indices[cls.coordinate] += 1 for i, n in enumerate(list(indices.values())[::-1]): d = _logical_partial_derivatives[-i - 1] for _ in range(n): atom = d(atom, evaluate=False) if cls in _partial_derivatives: atom = cls(atom, evaluate=False) elif cls not in _logical_partial_derivatives: raise NotImplementedError('TODO') return atom if isinstance(expr, (VectorTestFunction, VectorField)): n = expr.shape[0] args = [cls(expr[i], evaluate=False) for i in range(0, n)] args = Tuple(*args) return Matrix([args]) elif isinstance(expr, (list, tuple, Tuple, Matrix, ImmutableDenseMatrix)): args = [cls(i, evaluate=True) for i in expr] args = Tuple(*args) return Matrix([args]) elif isinstance( expr, (IndexedTestTrial, IndexedVectorField, DifferentialOperator)): return cls(expr, evaluate=False) elif isinstance(expr, (ScalarField, ScalarTestFunction)): return cls(expr, evaluate=False) elif isinstance(expr, (minus, plus)): return cls(expr, evaluate=False) elif isinstance(expr, Indexed) and isinstance(expr.base, BasicMapping): return cls(expr, evaluate=False) elif not has(expr, types): if expr.is_number: return S.Zero elif isinstance(expr, Expr): x = Symbol(cls.coordinate) if cls.logical: M = expr.atoms(Mapping) if len(M) > 0: M = list(M)[0] expr_primes = [diff(expr, M[i]) for i in range(M.rdim)] Jj = Jacobian(M)[:, cls.grad_index] expr_prime = sum( [ei * Jji for ei, Jji in zip(expr_primes, Jj)]) return expr_prime + diff(expr, x) return diff(expr, x) if isinstance(expr, Add): args = [cls(a, evaluate=True) for a in expr.args] v = Add(*args) return v elif isinstance(expr, Mul): coeffs = [a for a in expr.args if isinstance(a, _coeffs_registery)] vectors = [a for a in expr.args if not (a in coeffs)] c = S.One if coeffs: c = Mul(*coeffs) V = S.Zero if vectors: if len(vectors) == 1: # do we need to use Mul? V = cls(vectors[0], evaluate=True) elif len(vectors) == 2: a = vectors[0] b = vectors[1] fa = cls(a, evaluate=True) fb = cls(b, evaluate=True) V = a * fb + fa * b else: a = vectors[0] b = Mul(*vectors[1:]) fa = cls(a, evaluate=True) fb = cls(b, evaluate=True) V = a * fb + fa * b v = Mul(c, V) return v elif isinstance(expr, Pow): b = expr.base e = expr.exp v = (log(b) * cls(e, evaluate=True) + e * cls(b, evaluate=True) / b) * b**e return v else: msg = '{expr} of type {type}'.format(expr=expr, type=type(expr)) raise NotImplementedError(msg)
def test_unify_iter(): expr = Add(1, 2, 3, evaluate=False) a, b, c = map(Symbol, 'abc') pattern = Add(a, c, evaluate=False) assert is_associative(deconstruct(pattern)) assert is_commutative(deconstruct(pattern)) result = list(unify(expr, pattern, {}, (a, c))) expected = [{a: 1, c: Add(2, 3, evaluate=False)}, {a: 1, c: Add(3, 2, evaluate=False)}, {a: 2, c: Add(1, 3, evaluate=False)}, {a: 2, c: Add(3, 1, evaluate=False)}, {a: 3, c: Add(1, 2, evaluate=False)}, {a: 3, c: Add(2, 1, evaluate=False)}, {a: Add(1, 2, evaluate=False), c: 3}, {a: Add(2, 1, evaluate=False), c: 3}, {a: Add(1, 3, evaluate=False), c: 2}, {a: Add(3, 1, evaluate=False), c: 2}, {a: Add(2, 3, evaluate=False), c: 1}, {a: Add(3, 2, evaluate=False), c: 1}] assert iterdicteq(result, expected)
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))
def convert_to(expr, target_units): """ Convert ``expr`` to the same expression with all of its units and quantities represented as factors of ``target_units``, whenever the dimension is compatible. ``target_units`` may be a single unit/quantity, or a collection of units/quantities. Examples ======== >>> from sympy.physics.units import speed_of_light, meter, gram, second, day >>> from sympy.physics.units import mile, newton, kilogram, atomic_mass_constant >>> from sympy.physics.units import kilometer, centimeter >>> from sympy.physics.units import convert_to >>> convert_to(mile, kilometer) 25146*kilometer/15625 >>> convert_to(mile, kilometer).n() 1.609344*kilometer >>> convert_to(speed_of_light, meter/second) 299792458*meter/second >>> convert_to(day, second) 86400*second >>> 3*newton 3*newton >>> convert_to(3*newton, kilogram*meter/second**2) 3*kilogram*meter/second**2 >>> convert_to(atomic_mass_constant, gram) 1.66053904e-24*gram Conversion to multiple units: >>> convert_to(speed_of_light, [meter, second]) 299792458*meter/second >>> convert_to(3*newton, [centimeter, gram, second]) 300000*centimeter*gram/second**2 Conversion to Planck units: >>> from sympy.physics.units import gravitational_constant, hbar >>> convert_to(atomic_mass_constant, [gravitational_constant, speed_of_light, hbar]).n() 7.62950196312651e-20*gravitational_constant**(-0.5)*hbar**0.5*speed_of_light**0.5 """ if not isinstance(target_units, (collections.Iterable, Tuple)): target_units = [target_units] if isinstance(expr, Add): return Add.fromiter(convert_to(i, target_units) for i in expr.args) expr = sympify(expr) if not isinstance(expr, Quantity) and expr.has(Quantity): expr = expr.replace(lambda x: isinstance(x, Quantity), lambda x: x.convert_to(target_units)) def get_total_scale_factor(expr): if isinstance(expr, Mul): return reduce(lambda x, y: x * y, [get_total_scale_factor(i) for i in expr.args]) elif isinstance(expr, Pow): return get_total_scale_factor(expr.base) ** expr.exp elif isinstance(expr, Quantity): return expr.scale_factor return expr depmat = _get_conversion_matrix_for_expr(expr, target_units) if depmat is None: return expr expr_scale_factor = get_total_scale_factor(expr) return expr_scale_factor * Mul.fromiter((1/get_total_scale_factor(u) * u) ** p for u, p in zip(target_units, depmat))
from __future__ import print_function, division from sympy.integrals.meijerint import _create_lookup_table from sympy import latex, Eq, meijerg, Add, Symbol t = {} _create_lookup_table(t) doc = "" for about, category in sorted(t.items()): if about == (): doc += 'Elementary functions:\n\n' else: doc += 'Functions involving ' + ', '.join( '`%s`' % latex(list(category[0][0].atoms(func))[0]) for func in about) + ':\n\n' for formula, gs, cond, hint in category: if not isinstance(gs, list): g = Symbol('\\text{generated}') else: g = Add(*[fac * f for (fac, f) in gs]) obj = Eq(formula, g) if cond is True: cond = "" else: cond = ',\\text{ if } %s' % latex(cond) doc += ".. math::\n %s%s\n\n" % (latex(obj), cond) __doc__ = doc
def test_evaluate_false(): for no in [0, False, None]: 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_series(): from sympy.abc import x i = Integral(cos(x)) e = i.lseries(x) assert i.nseries(x, n=8).removeO() == Add(*[e.next() for j in range(4)])
def variance_prop(expr, consts=(), include_covar=False): r"""Symbolically propagates variance (`\sigma^2`) for expressions. This is computed as as seen in [1]_. Parameters ========== expr : Expr A sympy expression to compute the variance for. consts : sequence of Symbols, optional Represents symbols that are known constants in the expr, and thus have zero variance. All symbols not in consts are assumed to be variant. include_covar : bool, optional Flag for whether or not to include covariances, default=False. Returns ======= var_expr : Expr An expression for the total variance of the expr. The variance for the original symbols (e.g. x) are represented via instance of the Variance symbol (e.g. Variance(x)). Examples ======== >>> from sympy import symbols, exp >>> from sympy.stats.error_prop import variance_prop >>> x, y = symbols('x y') >>> variance_prop(x + y) Variance(x) + Variance(y) >>> variance_prop(x * y) x**2*Variance(y) + y**2*Variance(x) >>> variance_prop(exp(2*x)) 4*exp(4*x)*Variance(x) References ========== .. [1] https://en.wikipedia.org/wiki/Propagation_of_uncertainty """ args = expr.args if len(args) == 0: if expr in consts: return S.Zero elif isinstance(expr, RandomSymbol): return Variance(expr).doit() elif isinstance(expr, Symbol): return Variance(RandomSymbol(expr)).doit() else: return S.Zero nargs = len(args) var_args = list( map(variance_prop, args, repeat(consts, nargs), repeat(include_covar, nargs))) if isinstance(expr, Add): var_expr = Add(*var_args) if include_covar: terms = [2 * Covariance(_arg0_or_var(x), _arg0_or_var(y)).doit() \ for x, y in combinations(var_args, 2)] var_expr += Add(*terms) elif isinstance(expr, Mul): terms = [v / a**2 for a, v in zip(args, var_args)] var_expr = simplify(expr**2 * Add(*terms)) if include_covar: terms = [2*Covariance(_arg0_or_var(x), _arg0_or_var(y)).doit()/(a*b) \ for (a, b), (x, y) in zip(combinations(args, 2), combinations(var_args, 2))] var_expr += Add(*terms) elif isinstance(expr, Pow): b = args[1] v = var_args[0] * (expr * b / args[0])**2 var_expr = simplify(v) elif isinstance(expr, exp): var_expr = simplify(var_args[0] * expr**2) else: # unknown how to proceed, return variance of whole expr. var_expr = Variance(expr) return var_expr
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_Pow 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_Pow and y.exp.is_integer: a.append((y, S.One)) else: raise NotImplementedError continue sifted = sift(y.args, is_sqrt) a.append((Mul(*sifted[False]), Mul(*sifted[True])**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 show_first_few_terms(e, n=10): if isinstance(e, Add): e_args_trunc = e.args[0:n] e = Add(*(e_args_trunc)) return Latex("$" + latex(e).replace("dag", "dagger") + r"+ \dots$")
def drop_const(expr, x): if expr.is_Add: return Add(*[arg for arg in expr.args if arg.has(x)]) else: return expr
def recurse_expr(expr, index_ranges={}): if expr.is_Mul: nonmatargs = [] pos_arg = [] pos_ind = [] dlinks = {} link_ind = [] counter = 0 args_ind = [] for arg in expr.args: retvals = recurse_expr(arg, index_ranges) assert isinstance(retvals, list) if isinstance(retvals, list): for i in retvals: args_ind.append(i) else: args_ind.append(retvals) for arg_symbol, arg_indices in args_ind: if arg_indices is None: nonmatargs.append(arg_symbol) continue if isinstance(arg_symbol, MatrixElement): arg_symbol = arg_symbol.args[0] pos_arg.append(arg_symbol) pos_ind.append(arg_indices) link_ind.append([None]*len(arg_indices)) for i, ind in enumerate(arg_indices): if ind in dlinks: other_i = dlinks[ind] link_ind[counter][i] = other_i link_ind[other_i[0]][other_i[1]] = (counter, i) dlinks[ind] = (counter, i) counter += 1 counter2 = 0 lines = {} while counter2 < len(link_ind): for i, e in enumerate(link_ind): if None in e: line_start_index = (i, e.index(None)) break cur_ind_pos = line_start_index cur_line = [] index1 = pos_ind[cur_ind_pos[0]][cur_ind_pos[1]] while True: d, r = cur_ind_pos if pos_arg[d] != 1: if r % 2 == 1: cur_line.append(transpose(pos_arg[d])) else: cur_line.append(pos_arg[d]) next_ind_pos = link_ind[d][1-r] counter2 += 1 # Mark as visited, there will be no `None` anymore: link_ind[d] = (-1, -1) if next_ind_pos is None: index2 = pos_ind[d][1-r] lines[(index1, index2)] = cur_line break cur_ind_pos = next_ind_pos ret_indices = list(j for i in lines for j in i) lines = {k: MatMul.fromiter(v) if len(v) != 1 else v[0] for k, v in lines.items()} return [(Mul.fromiter(nonmatargs), None)] + [ (MatrixElement(a, i, j), (i, j)) for (i, j), a in lines.items() ] elif expr.is_Add: res = [recurse_expr(i) for i in expr.args] d = collections.defaultdict(list) for res_addend in res: scalar = 1 for elem, indices in res_addend: if indices is None: scalar = elem continue indices = tuple(sorted(indices, key=default_sort_key)) d[indices].append(scalar*remove_matelement(elem, *indices)) scalar = 1 return [(MatrixElement(Add.fromiter(v), *k), k) for k, v in d.items()] elif isinstance(expr, KroneckerDelta): i1, i2 = expr.args if dimensions is not None: identity = Identity(dimensions[0]) else: identity = S.One return [(MatrixElement(identity, i1, i2), (i1, i2))] elif isinstance(expr, MatrixElement): matrix_symbol, i1, i2 = expr.args if i1 in index_ranges: r1, r2 = index_ranges[i1] if r1 != 0 or matrix_symbol.shape[0] != r2+1: raise ValueError("index range mismatch: {0} vs. (0, {1})".format( (r1, r2), matrix_symbol.shape[0])) if i2 in index_ranges: r1, r2 = index_ranges[i2] if r1 != 0 or matrix_symbol.shape[1] != r2+1: raise ValueError("index range mismatch: {0} vs. (0, {1})".format( (r1, r2), matrix_symbol.shape[1])) if (i1 == i2) and (i1 in index_ranges): return [(trace(matrix_symbol), None)] return [(MatrixElement(matrix_symbol, i1, i2), (i1, i2))] elif isinstance(expr, Sum): return recurse_expr( expr.args[0], index_ranges={i[0]: i[1:] for i in expr.args[1:]} ) else: return [(expr, None)]
def _expansion_search(e, rep_list, N): """ Search for and substitute terms that match a series expansion of fundamental math functions. e: expression rep_list: list containing dummy variables """ if e.find(I): is_complex = True else: is_complex = False if debug: print("_expansion_search: ", e) try: dummy = Dummy() flist0 = [exp, lambda x: exp(-x), cos, cosh] flist1 = [ lambda x: (exp(x) - 1) / x, lambda x: (1 - exp(-x)) / x, lambda x: sin(x) / x, lambda x: sinh(x) / x ] flist2 = [ lambda x: (1 - cos(x)) / (x**2 / 2), lambda x: (cosh(x) - 1) / (x**2 / 2) ] if is_complex: iflist0 = [lambda x: exp(I * x), lambda x: exp(-I * x)] iflist1 = [ lambda x: (exp(I * x) - 1) / (I * x), lambda x: (1 - exp(-I * x)) / (I * x) ] flist0 = iflist0 + flist0 flist1 = iflist1 + flist1 flist = [flist0, flist1, flist2] fseries = {} if isinstance(e, Mul): e_args = [e] elif isinstance(e, Add): e_args = e.args else: return e newargs = [] for e in e_args: if isinstance(e, Mul): c, nc = e.args_cnc() if nc and c: c_expr = Mul(*c).expand() d, d_order = _lowest_order_term(c_expr) c_expr_normal = (c_expr / d).expand() c_expr_subs = c_expr_normal for alpha in rep_list: if alpha not in c_expr_subs.free_symbols: continue for f in flist[d_order]: if f not in fseries.keys(): fseries[f] = f(dummy).series( dummy, n=N - d_order).removeO() c_expr_subs = c_expr_subs.subs( fseries[f].subs(dummy, alpha), f(alpha)) if c_expr_subs != c_expr_normal: break if c_expr_subs != c_expr_normal: break newargs.append(d * c_expr_subs * Mul(*nc)) else: newargs.append(e) else: newargs.append(e) return Add(*newargs) except Exception as e: print("Failed to identify series expansions: " + str(e)) return e