def pow_to_mul(expr): if expr.is_Atom or expr.is_Indexed: return expr elif expr.is_Pow: base, exp = expr.as_base_exp() if exp <= 0 or not exp.is_integer: # Cannot handle powers containing non-integer non-positive exponents return expr else: return sympy.Mul(*[base] * exp, evaluate=False) else: return expr.func(*[pow_to_mul(i) for i in expr.args], evaluate=False)
def my_sympify(expr, normphase=False, matrix=False, abcsym=False, do_qubit=False, symtab=None): # make all lowercase real? if symtab: varset = symtab else: varset = {'p': sympy.Symbol('p'), 'g': sympy.Symbol('g'), 'e': sympy.E, # for exp 'i': sympy.I, # lowercase i is also sqrt(-1) 'Q': sympy.Symbol('Q'), # otherwise it is a sympy "ask key" 'I': sympy.Symbol('I'), # otherwise it is sqrt(-1) 'N': sympy.Symbol('N'), # or it is some kind of sympy function #'X':sympy.sympify('Matrix([[0,1],[1,0]])'), #'Y':sympy.sympify('Matrix([[0,-I],[I,0]])'), #'Z':sympy.sympify('Matrix([[1,0],[0,-1]])'), 'ZZ': sympy.Symbol('ZZ'), # otherwise it is the PythonIntegerRing 'XI': sympy.Symbol('XI'), # otherwise it is the capital \XI 'hat': sympy.Function('hat'), # for unit vectors (8.02) } if do_qubit: # turn qubit(...) into Qubit instance varset.update({'qubit': sympy.physics.quantum.qubit.Qubit, 'Ket': sympy.physics.quantum.state.Ket, 'dot': dot, 'bit': sympy.Function('bit'), }) if abcsym: # consider all lowercase letters as real symbols, in the parsing for letter in string.lowercase: if letter in varset: # exclude those already done continue varset.update({letter: sympy.Symbol(letter, real=True)}) sexpr = sympify(expr, locals=varset) if normphase: # remove overall phase if sexpr is a list if type(sexpr) == list: if sexpr[0].is_number: ophase = sympy.sympify('exp(-I*arg(%s))' % sexpr[0]) sexpr = [sympy.Mul(x, ophase) for x in sexpr] def to_matrix(x): # if x is a list of lists, and is rectangular, then return Matrix(x) if not type(x) == list: return x for row in x: if (not type(row) == list): return x rdim = len(x[0]) for row in x: if not len(row) == rdim: return x return sympy.Matrix(x) if matrix: sexpr = to_matrix(sexpr) return sexpr
def convert_mp(mp): if hasattr(mp, 'mp'): mp_left = mp.mp(0) mp_right = mp.mp(1) else: mp_left = mp.mp_nofunc(0) mp_right = mp.mp_nofunc(1) if mp.MUL() or mp.CMD_TIMES() or mp.CMD_CDOT(): lh = convert_mp(mp_left) rh = convert_mp(mp_right) return sympy.Mul(lh, rh, evaluate=False) elif mp.DIV() or mp.CMD_DIV() or mp.COLON(): lh = convert_mp(mp_left) rh = convert_mp(mp_right) return sympy.Mul(lh, sympy.Pow(rh, -1, evaluate=False), evaluate=False) else: if hasattr(mp, 'unary'): return convert_unary(mp.unary()) else: return convert_unary(mp.unary_nofunc())
def element_to_sympy(elem): if isinstance(elem, formula.Frac): return sympy.Mul(elementlist_to_sympy(elem.numerator), sympy.Pow(elementlist_to_sympy(elem.denominator), -1)) elif isinstance(elem, formula.Abs): return sympy.Abs(elementlist_to_sympy(elem.argument)) elif isinstance(elem, formula.Radical): index = elementlist_to_sympy(elem.index) or 2 return sympy.Pow(elementlist_to_sympy(elem.radicand), sympy.Pow(index, -1)) else: raise NotImplementedError
def expand_mul(expr): assert isinstance(expr, sp.Mul) commutative, other = split_commutative(expr) commutative = [(apply_characteristic(v) if isinstance(v, sp.Number) else v) for v in commutative] commutative = sp.Mul(*commutative) if commutative == 0: return S.Zero terms = [expand_with_transformers_impl(term) for term in other] for tr in config['mul']: terms = apply_transformer_termwise(terms, tr) def catch_zeros(expr): s = str(expr) for z in zeros_mul: if z in s: return S.Zero for z in zeros_pow: if z in s: return S.Zero return expr def postprocess(expr): # TODO: are these actually needed? # expr = sp.powsimp(expr) # expr = sp.expand_mul(expr) # TODO: get rid of this expr = catch_zeros(expr) return expr # FIXME: THIS COULD BE A BUG if one of the transformers yielded something # like an Add whose part could be matched by catch_zeros and thus the whole # expression would be marked as zero, which it is not. Currently there are no # such transformers in mul, but there may be. # Anyway, catch_zeros is evil and should be abandoned. return commutative * postprocess(sp.Mul(*terms))
def out_add_f(expr01, cof_list, cof_dict, vector_add): if isinstance(expr01, sympy.Add): wiss = [sympy.Symbol("W%s" % i) for i, j in enumerate(expr01.args)] args_new = [(wi, sympy.Mul(wi, ei)) if not ei.is_number else (None, ei) for ei, wi in zip(expr01.args, wiss)] wis, we = zip(*args_new) cof_list.extend([wi for wi in wis if wi is not None]) argss = sympy.Add(*we) expr01 = argss elif isinstance(expr01, M3): exprin1 = expr01.args[0] conu = expr01.conu if isinstance(exprin1, sympy.Add): wiss = [sympy.Symbol("W%s" % i) for i, j in enumerate(exprin1.args)] args_new = [(wi, sympy.Mul(wi, ei)) if not ei.is_number else (None, ei) for ei, wi in zip(exprin1.args, wiss)] wis, we = zip(*args_new) cof_list.extend([wi for wi in wis if wi is not None]) argss = sympy.Add(*we) expr01 = expr01.func(argss) if vector_add: if conu > 1: Wi = sympy.Symbol("V") arg = expr01.args[0] expr02 = expr01.func(sympy.Mul(Wi, arg)) cof_dict[Wi] = conu expr01 = expr02 else: A = sympy.Symbol("A") expr01 = sympy.Mul(expr01, A) cof_list.append(A) else: A = sympy.Symbol("A") expr01 = sympy.Mul(expr01, A) cof_list.append(A) return expr01
def eval(cls, A, B): if not A != B: return sp.S.Zero if A.is_commutative or B.is_commutative: return sp.S.Zero if isinstance(A, sp.Add): sargs = [] for term in A.args: sargs.append(Corxet(term, B)) return sp.Add(*sargs) if isinstance(B, sp.Add): sargs = [] for term in B.args: sargs.append(Corxet(A, term)) return sp.Add(*sargs) cA, ncA = A.args_cnc() cB, ncB = B.args_cnc() c_part = cA + cB if c_part: return sp.Mul(sp.Mul(*c_part), cls(sp.Mul._from_args(ncA), sp.Mul._from_args(ncB))) if A.compare(B) == 1: return sp.S.NegativeOne * cls.eval(cls, B, A) i, j, k, l = A.i, A.j, B.i, B.j if A.t != B.t: printe("Els objectes %s i %s no pertanyen a la mateixa base." % (A, B)) exit(-1) if A.t == "E": ll = rl.corxetErel(i, j, k, l) elif A.t == "Z": ll = rl.corxetZrel(i, j, k, l) else: printe("No hi ha cap base definida amb %s." % (A.t)) exit(-1) args = [] for it in ll: elem = sp.Mul(sp.Rational(it[0], it[1]), Eel(it[2], it[3], A.t)) args.append(elem) return sp.Add(*args)
def _arg_func_from_proto( func: v2.program_pb2.ArgFunction, *, arg_function_language: str, required_arg_name: Optional[str] = None, ) -> Optional[ARG_LIKE]: supported = SUPPORTED_FUNCTIONS_FOR_LANGUAGE.get(arg_function_language) if supported is None: raise ValueError(f'Unrecognized arg_function_language: {arg_function_language!r}') if func.type not in supported: raise ValueError( f'Unrecognized function type {func.type!r} ' f'for arg_function_language={arg_function_language!r}' ) if func.type == 'add': return sympy.Add( *[ arg_from_proto( a, arg_function_language=arg_function_language, required_arg_name='An addition argument', ) for a in func.args ] ) if func.type == 'mul': return sympy.Mul( *[ arg_from_proto( a, arg_function_language=arg_function_language, required_arg_name='A multiplication argument', ) for a in func.args ] ) if func.type == 'pow': return sympy.Pow( *[ arg_from_proto( a, arg_function_language=arg_function_language, required_arg_name='A power argument', ) for a in func.args ] ) return None
def get_spontaneous_decay_rate(self, z=sp.Symbol('Z', real=True), mu=sp.Symbol('mu', real=True), algo="auto"): """ Get the spontaneous decay rate of the transition :param z: atomic number (int) :param mu: reduced mass (float) :return: the spontaneous decay rate (float) """ # check if spontaneous_decay_rate is already calculated if self.spontaneous_decay_rate is not None: return self.spontaneous_decay_rate elif self.repr_without_spin( ) in Transition.n_ell_m_ell_state_to_rs.keys(): self.spontaneous_decay_rate = Transition.n_ell_m_ell_state_to_rs[ self.repr_without_spin()] return self.spontaneous_decay_rate r, theta, phi = sp.Symbol("r", real=True, positive=True), sp.Symbol("theta", real=True),\ sp.Symbol("phi", real=True) coeff = (4 * const.alpha * (self.get_delta_energy(z, mu)**3)) / (3 * (const.hbar**3) * (const.c**2)) psi = self._initial_quantum_state.get_wave_function(z, mu) psi_prime = self._ending_quantum_state.get_wave_function(z, mu) if algo == "auto": if self._initial_quantum_state.hydrogen and self._ending_quantum_state.hydrogen: algo = "sympy_ns" else: algo = "scipy_nquad" # \Vec{r} = x + y + z r_operator = r * (sp.sin(theta) * sp.cos(phi) + sp.sin(theta) * sp.sin(phi) + sp.cos(theta)) # Process the integral with algo bracket_product = QuantumFactory.bracket_product( psi, psi_prime, r_operator, algo) bracket_product_norm_square = sp.Mul(sp.conjugate(bracket_product), bracket_product).evalf() # print(bracket_product_norm_square) self.spontaneous_decay_rate = sp.Float(coeff * bracket_product_norm_square) # updating Transition static attribute Transition.n_ell_m_ell_state_to_rs[ self.repr_without_spin()] = self.spontaneous_decay_rate return self.spontaneous_decay_rate
def f1(x, xT, P, A): """ :param x: matrix :param xT: transpose of x :param P: matrix :param A: matrix :return: x^T (A^T P + P A) x """ AT = sp.Transpose(A) e0 = sp.Mul(AT, P, evaluate=False) e1 = sp.Mul(P, A, evaluate=False) e2 = sp.Add(e0, e1, evaluate=False) e = sp.Mul(xT, e2, evaluate=False) e = sp.Mul(e, x, evaluate=False) m = { str(P[r, c]): P[r, c] for r in range(P.shape[0]) for c in range(P.shape[0]) } m.update({str(x): x for x in x}) e = parse_expr(str(e), local_dict=m) # res = sp.expand((xT * (AT * P + P * A) * x)[0]) return sp.expand(e[0])
def pow_to_mul(expr): if expr.is_Atom or expr.is_Indexed: return expr elif expr.is_Pow: base, exp = expr.as_base_exp() if exp > 10 or exp < -10 or int(exp) != exp or exp == 0: # Large and non-integer powers remain untouched return expr elif exp == -1: # Reciprocals also remain untouched, but we traverse the base # looking for other Pows return expr.func(pow_to_mul(base), exp, evaluate=False) elif exp > 0: return sympy.Mul(*[base]*int(exp), evaluate=False) else: # SymPy represents 1/x as Pow(x,-1). Also, it represents # 2/x as Mul(2, Pow(x, -1)). So we shouldn't end up here, # but just in case SymPy changes its internal conventions... posexpr = sympy.Mul(*[base]*(-int(exp)), evaluate=False) return sympy.Pow(posexpr, -1, evaluate=False) else: return expr.func(*[pow_to_mul(i) for i in expr.args], evaluate=False)
def convert_add(add): if add.ADD(): lh = convert_add(add.additive(0)) rh = convert_add(add.additive(1)) return sympy.Add(lh, rh, evaluate=False) elif add.SUB(): lh = convert_add(add.additive(0)) rh = convert_add(add.additive(1)) # return sympy.Add(lh, -1 * rh, evaluate=False) # just keep the origin expression, don't simplify return sympy.Add(lh, sympy.Mul(-1, rh, evaluate=False), evaluate=False) else: return convert_mp(add.mp())
def ma(self): """Return the mass action monomial associated to the complex. :Example: >>> c1 = Complex({'S': 2, 'E': 1}) >>> c1.ma() E*S**2 :rtype: sympy expression. """ if self == {}: return 1 return sp.Mul(*(sp.Symbol(r)**self[r] for r in self))
def hack_simplify_sum(expr): # https://stackoverflow.com/questions/62679575/why-cant-sympy-simplify-these-sum-expressions-of-indexed-variables # https://github.com/sympy/sympy/issues/19685 if expr.func is sym.concrete.summations.Sum: body, (idx, lower, upper) = expr.args if idx not in body.free_symbols: factor = (upper + 1) - lower return factor * body else: if body.func is sym.Mul: factor_out = [] factor_in = [] for sub_arg in body.args: if idx in sub_arg.free_symbols: factor_in.append(sub_arg) else: factor_out.append(sub_arg) outer = sym.Mul(*factor_out) return outer * sym.summation(sym.Mul(*factor_in), (idx, lower, upper)) return expr
def residue(self, pole, poles): """Determine residue for given pole.""" expr = self.expr var = self.var # Remove occurrence of pole; sym.cancel # doesn't always work, for example, for complex poles. occurrences = [] for p in poles: occurrences += [p.n - 1 if p.expr == pole else p.n] numer, denom = expr.as_numer_denom() Dpoly = sym.Poly(denom, var) K = Dpoly.LC() D = [(var - p.expr)**o for p, o in zip(poles, occurrences)] denom = sym.Mul(K, *D) # Could calculate all residues simultaneously using # system of linear equations. def method1(numer, denom, var, pole): d = sym.limit(denom, var, pole) if d != 0: tmp = (numer / denom).simplify() # Sometimes this takes ages... return sym.limit(tmp, var, pole) # Use l'Hopital's rule tmp = numer / denom tmp = sym.diff(tmp, var) return sym.limit(tmp, var, pole) def method2(numer, denom, var, pole): d = denom.subs(var, pole) n = numer.subs(var, pole) if d != 0: return n / d ddenom = sym.diff(denom, var) return n / ddenom.subs(pole) m2 = method2(numer, denom, var, pole) return m2.cancel()
def _parse_reaction(model, line, reaction_cache): """Parse a 'reaction' line from a BNGL net file.""" (number, reactants, products, rate, rule) = line.strip().split(' ', 4) # the -1 is to switch from one-based to zero-based indexing reactants = tuple(int(r) - 1 for r in reactants.split(',') if r != '0') products = tuple(int(p) - 1 for p in products.split(',') if p != '0') rate = rate.rsplit('*') (rule_list, unit_conversion) = re.match( r'#([\w,\(\)]+)(?: unit_conversion=(.*))?\s*$', rule).groups() rule_list = rule_list.split(',') # BNG lists all rules that generate a rxn # Support new (BNG 2.2.6-stable or greater) and old BNG naming convention # for reverse rules rule_name, is_reverse = zip( *[re.subn('^_reverse_|\(reverse\)$', '', r) for r in rule_list]) is_reverse = tuple(bool(i) for i in is_reverse) r_names = ['__s%d' % r for r in reactants] rate_param = [ model.parameters.get(r) or model.expressions.get(r) or model._derived_parameters.get(r) or model._derived_expressions.get(r) or float(r) for r in rate ] combined_rate = sympy.Mul(*[sympy.S(t) for t in r_names + rate_param]) reaction = { 'reactants': reactants, 'products': products, 'rate': combined_rate, 'rule': rule_name, 'reverse': is_reverse, } model.reactions.append(reaction) # bidirectional reactions key = (reactants, products) key_reverse = (products, reactants) if key in reaction_cache: reaction_bd = reaction_cache.get(key) reaction_bd['rate'] += combined_rate reaction_bd['rule'] += tuple(r for r in rule_name if r not in reaction_bd['rule']) elif key_reverse in reaction_cache: reaction_bd = reaction_cache.get(key_reverse) reaction_bd['reversible'] = True reaction_bd['rate'] -= combined_rate reaction_bd['rule'] += tuple(r for r in rule_name if r not in reaction_bd['rule']) else: # make a copy of the reaction dict reaction_bd = dict(reaction) # default to false until we find a matching reverse reaction reaction_bd['reversible'] = False reaction_cache[key] = reaction_bd model.reactions_bidirectional.append(reaction_bd)
def std_latex_array(self, out_var=None): l_scalar, r_scalar = self.get_scalar() l_part = [] r_part = [sympy.latex(r_scalar)] for variable in self.variables: l_coeff, r_coeff = self.get_coeff(variable) substitution = self.substitutions.get(variable, variable) if l_coeff != 0: l_part.append(sympy.latex(sympy.Mul(l_coeff, substitution, evaluate=False))) if r_coeff < 0: r_part.append("-") r_part.append(sympy.latex(sympy.Mul(-r_coeff, substitution, evaluate=False))) elif r_coeff > 0: r_part.append("+") r_part.append(sympy.latex(sympy.Mul(r_coeff, substitution, evaluate=False))) elif out_var: if variable in out_var: r_part += ["", ""] else: pass else: r_part += ["", ""] l_part = " & ".join(l_part) r_part = " & ".join(r_part) comp = { 'LEQ' : r"""\leq""", 'EQ' : r"""=""", 'GEQ' : r"""\geq""", }[self.comp] return l_part + " & " + comp + " & " + r_part + r"""\\"""
def parse_term(self, expr): syms = [] cons = [] if type(expr) == sy.Symbol: syms.append(expr) cons.append(1) elif type(expr) == sy.Pow: var, exponent = expr.args if type(var) == sy.Symbol: syms.append(expr) cons.append(1) else: cons.append(expr) else: for arg in expr.args: if type(arg) == sy.Symbol: syms.append(arg) elif type(arg) == sy.Pow: var, exponent = arg.args if type(var) == sy.Symbol: syms.append(arg) else: cons.append(arg) else: cons.append(arg) const_term = 1 syms_term = None if len(cons) == 1: const_term = cons[0] elif len(cons) > 1: const_term = sy.Mul(*cons) if len(syms) == 1: syms_term = syms[0] elif len(syms) > 0: syms_term = sy.Mul(*syms) return const_term, syms_term
def add_coefficient(expr01, inter_add=True, inner_add=False, vector_add=False, out_add=False, flat_add=False): """ Try add the placeholder coefficient to sympy expression. 1. Add Wi,A,B normal coefficients to expression. 2. Add V, Vi vector coefficients to expression, for this type of coefficient , there should be with expr01.conu for Function("MAdd"), Function("MSub"). more details can be found in ..translate.simple Parameters ---------- expr01: Expr sympy expressions inter_add: bool bool inner_add: bool bool vector_add:bool bool flat_add:bool bool out_add:bool bool Returns ------- expr """ cof_list = [] cof_dict = {} assert len([i for i in [inner_add, out_add, flat_add] if i is True]) <= 1, \ "For the 'out_add','flat_add'and 'out_add', you should just choose one of them." if out_add: # out layer expr01 = out_add_f(expr01, cof_list, cof_dict, vector_add) elif inner_add: # out and inner layer each add and Madd... expr01 = inner_add_f(expr01, cof_list, cof_dict, vector_add) elif flat_add: # out and inner layer each add and Madd... just open by add. expr01 = flatten_add_f(expr01, cof_list, cof_dict, vector_add) else: A = sympy.Symbol("A") expr01 = sympy.Mul(expr01, A) cof_list.append(A) if inter_add: # intercept B = sympy.Symbol("B") expr01 = sympy.Add(expr01, B) cof_list.append(B) return expr01, cof_list, cof_dict
def oneEpsAsDeltas(eps, **tempOverride): '''Takes an instance of Eps and rewrites it as Deltas''' dim, indexRange = delta.getTempDimAndIndexRange(**tempOverride) if not isinstance(eps, Eps): raise TypeError('Error: input must be an Eps(*indecis)') if not len(eps.index) == dim: raise TypeError('Error: Eps must have dim number of indices') termList = [] for perm in permute_all(eps.index): factorList = [perm['parity']] for (pos, index) in enumerate(perm['perm']): factorList.append(delta.Delta(pos + 1, index)) termList.append(sympy.Mul(*factorList)) return sympy.Add(*termList)
def _print_Pow(self, expr): result = self._scalarFallback('_print_Pow', expr) if result: return result one = self.instruction_set['makeVecConst'].format(1.0, **self._kwargs) if expr.exp.is_integer and expr.exp.is_number and 0 < expr.exp < 8: return "(" + self._print(sp.Mul(*[expr.base] * expr.exp, evaluate=False)) + ")" elif expr.exp == -1: one = self.instruction_set['makeVecConst'].format(1.0, **self._kwargs) return self.instruction_set['/'].format(one, self._print(expr.base), **self._kwargs) elif expr.exp == 0.5: return self.instruction_set['sqrt'].format(self._print(expr.base), **self._kwargs) elif expr.exp == -0.5: root = self.instruction_set['sqrt'].format(self._print(expr.base), **self._kwargs) return self.instruction_set['/'].format(one, root, **self._kwargs) elif expr.exp.is_integer and expr.exp.is_number and - 8 < expr.exp < 0: return self.instruction_set['/'].format(one, self._print(sp.Mul(*[expr.base] * (-expr.exp), evaluate=False)), **self._kwargs) else: raise ValueError("Generic exponential not supported: " + str(expr))
def pow_to_mul(expr): """ Convert integer powers in an expression to Muls, like a**2 => a*a. """ pows = list(expr.atoms(sympy.Pow)) if any(not e.is_Integer for b, e in (i.as_base_exp() for i in pows)): raise ValueError("A power contains a non-integer exponent") print(pows) for b, e in (i.as_base_exp() for i in pows): print(b, e) repl = zip(pows, (sympy.Mul(*[b] * e, evaluate=False) for b, e in (i.as_base_exp() for i in pows))) #print repl return expr.subs(repl)
def zeros_to_coeffs(*z_list, **kwargs): """ calculates the coeffs corresponding to a poly with provided zeros """ s = sp.Symbol("s") p = sp.Mul(*[s-s0 for s0 in z_list]) real_coeffs = kwargs.get("real_coeffs", True) c = np.array(coeffs(p, s), dtype=np.float) if real_coeffs: c = np.real(c) return c
def distribute(e, x): """Helper method to apply distributive multiplication. This helps by allowing the use of 'subs' instead of 'limit' in special circumstances """ # traverse the operations graph if e.is_Add: return sp.Add(*[distribute(a, x) for a in e.args]) elif e.is_Mul: o = sp.Integer(1) done = False for a in e.args: if x in a.atoms() and not done: # prefer multiply where x is found # seek for simplification o = sp.Mul(o, distribute(a, x)) done = True else: o = sp.Mul(o, a) return o if done else sp.Mul(o, x) else: return sp.Mul(e, x)
def _interpolate_Function(expr): path = 'None' factor = 'None' change = False summand_0 = 'None' summand_1 = 'None' res = expr for i in np.arange(len(expr.args)): argument = sympy.expand(expr.args[i]) if argument.func == sympy.Add: for j in np.arange(len(argument.args)): summand = argument.args[j] if summand.func == sympy.Mul: for k in np.arange(len(summand.args)): temp = 0 if summand.args[k] == sympy.Symbol('a'): temp = sympy.Mul(sympy.Mul(*summand.args[:k]), sympy.Mul(*summand.args[k + 1:])) #print(temp) if not temp == int(temp): #print('found one') factor = (temp) path = np.array([i, j, k]) if not factor == 'None': change = True sign = np.sign(factor) offsets = np.array([int(factor), sign * (int(sign * factor) + 1)]) weights = 1 / np.abs(offsets - factor) weights = weights / np.sum(weights) res = (weights[0] * _interchange(expr, offsets[0] * sympy.Symbol('a'), path[:-1]) + weights[1] * _interchange(expr, offsets[1] * sympy.Symbol('a'), path[:-1])) return sympy.expand(res), change
def expected(expr): cls = expr.__class__ if cls == sp.Add: return sp.Add(*[expected(elem) for elem in expr.args]) if cls == sp.Mul: return sp.Mul(*[expected(elem) for elem in expr.args]) if cls == sp.Pow and isinstance(expr.args[0],RandomVar): if (not expr.args[1].is_integer): raise Exception("Can't do expected values of non-integer powers") if expr.args[1]<0: raise Exception("Can't do expected values of negative powers (including division)") return moment(expr.args[0], expr.args[1]) if isinstance(expr, RandomVar): return moment(expr, 1) return expr
def expand_tp(expr): l, r = expr.args l = expand_with_transformers_impl(l) r = expand_with_transformers_impl(r) if l == 0 or r == 0: return S.Zero if isinstance(l, sp.Add): expr = sp.Add(*[TP(arg, r) for arg in l.args]) return expand_with_transformers_impl(expr) if isinstance(r, sp.Add): expr = sp.Add(*[TP(l, arg) for arg in r.args]) return expand_with_transformers_impl(expr) lc, lnc = split_commutative(l) if isinstance(l, sp.Mul) else ([S.One], [l]) rc, rnc = split_commutative(r) if isinstance(r, sp.Mul) else ([S.One], [r]) lnc = sp.Mul(*lnc) rnc = sp.Mul(*rnc) commutative = sp.Mul(*(lc + rc)) tp = TP(lnc, rnc) return commutative * tp
def convert_frac(frac): diff_op = False partial_op = False lower_itv = frac.lower.getSourceInterval() lower_itv_len = lower_itv[1] - lower_itv[0] + 1 if (frac.lower.start == frac.lower.stop and frac.lower.start.type == PSLexer.DIFFERENTIAL): wrt = get_differential_var_str(frac.lower.start.text) diff_op = True elif (lower_itv_len == 2 and frac.lower.start.type == PSLexer.SYMBOL and frac.lower.start.text == '\\partial' and (frac.lower.stop.type == PSLexer.LETTER_NO_E or frac.lower.stop.type == PSLexer.SYMBOL)): partial_op = True wrt = frac.lower.stop.text if frac.lower.stop.type == PSLexer.SYMBOL: wrt = wrt[1:] if diff_op or partial_op: wrt = sympy.Symbol(wrt, real=True, positive=True) if (diff_op and frac.upper.start == frac.upper.stop and frac.upper.start.type == PSLexer.LETTER_NO_E and frac.upper.start.text == 'd'): return [wrt] elif (partial_op and frac.upper.start == frac.upper.stop and frac.upper.start.type == PSLexer.SYMBOL and frac.upper.start.text == '\\partial'): return [wrt] upper_text = rule2text(frac.upper) expr_top = None if diff_op and upper_text.startswith('d'): expr_top = process_sympy(upper_text[1:]) elif partial_op and frac.upper.start.text == '\\partial': expr_top = process_sympy(upper_text[len('\\partial'):]) if expr_top: return sympy.Derivative(expr_top, wrt) expr_top = convert_expr(frac.upper) expr_bot = convert_expr(frac.lower) if expr_top.is_Matrix or expr_bot.is_Matrix: return sympy.MatMul(expr_top, sympy.Pow(expr_bot, -1, evaluate=False), evaluate=False) else: return sympy.Mul(expr_top, sympy.Pow(expr_bot, -1, evaluate=False), evaluate=False)
def check_filter_equations(self): made_changes = False # Expand, and remove instances of '0 = 0' and 'non-zero number != 0' len_cl, len_op = len(self.cl_eqs), len(self.op_eqs) self.cl_eqs = list({ sp.expand(e) for e in self.cl_eqs if e != 0 }) self.op_eqs = list({ sp.expand(e) for e in self.op_eqs if not e.is_complex or e == 0 }) if len(self.cl_eqs) != len_cl or len(self.op_eqs) != len_op: made_changes = True # If any equation is of the form 'x = 0', we can solve for x = 0 and continue with the remaining system for x in [ eq for eq in self.cl_eqs if eq.is_Symbol and eq in self.vars ]: self.vars = self.vars.difference({x,}) self.cl_eqs = [ e.subs(x, 0) for e in self.cl_eqs ] self.op_eqs = [ e.subs(x, 0) for e in self.op_eqs ] made_changes = True for eq in self.cl_eqs: eq_factor = sp.factor(eq) # If any equation is of the form '(...)^n = 0', we can simply substitute with '(...) = 0' (provided n is positive) if eq_factor.is_Pow: if eq_factor.args[1] < 0: return 0 self.cl_eqs = [ eq_factor.args[0] if e == eq else e for e in self.cl_eqs] # If any equation is a product, we can remove all denominators and all numeric factors. Also, one can remove all higher multiplicities if eq_factor.is_Mul: unnecessary_factors = [ a for a in eq_factor.args if a.is_complex or (a.is_Pow and a.args[1] < 0) ] higher_multiplicity = [ a for a in eq_factor.args if a.is_Pow and a.args[1] > 0 ] if unnecessary_factors or higher_multiplicity: replacement = sp.Mul(*( f.args[0] if f in higher_multiplicity else f for f in eq_factor.args if f not in unnecessary_factors )) self.cl_eqs = [ replacement if e == eq else e for e in self.cl_eqs ] made_changes = True for eq in self.op_eqs: eq_factor = sp.factor(eq) # If an equation is of the form '(u) * ... * (v) != 0', replace by '(u) != 0 & ... & (v) != 0' if eq_factor.is_Mul: self.op_eqs = [ e for e in self.op_eqs if e != eq ] + [ f for f in eq_factor.args if not f.is_complex] made_changes = True if made_changes: return self.compute_class() return None
def seperate_coeff(big_term): coefficients = [] terms = [] for term in big_term: if term.func == sympy.Pow: coefficients.append(1) mul2 = [term.args[0]] * term.args[1] else: mul2 = [] for arg in term.args: if arg.is_Integer is True: coefficients.append(arg) else: mul2.append(arg) terms.append(sympy.Mul(*mul2)) return (terms, coefficients)