def collectDenom(expr, subsDict): """ collect input expression in terms of common denominators """ commons = {} for arg in expr.args: if sy.denom(arg) in commons: commons[sy.denom(arg)] += sy.numer(arg) else: commons[sy.denom(arg)] = sy.numer(arg) return sum([ sy.simplify(commons[denom]).subs(subsDict) / denom for denom in commons ])
def __new__(cls, b, e, evaluate=True): from sympy.functions.elementary.exponential import exp_polar from sympy.functions import log # don't optimize "if e==0; return 1" here; it's better to handle that # in the calling routine so this doesn't get called b = _sympify(b) e = _sympify(e) if evaluate: if e is S.Zero: return S.One elif e is S.One: return b elif S.NaN in (b, e): if b is S.One: # already handled e == 0 above return S.One return S.NaN else: if e.func == log: if len(e.args) == 2: lbase = e.args[1] else: lbase = S.Exp1 if lbase == b: return e.args[0] if e is Mul and e.args[1].func == log: if len(e.args[1].args) == 2: lbase = e.args[1].args[1] else: lbase = S.Exp1 if lbase == b: return e.args[1].args[0] ** e.args[0] # recognize base as E if not e.is_Atom and b is not S.Exp1 and b.func is not exp_polar: from sympy import numer, denom, log, sign, im, factor_terms c, ex = factor_terms(e, sign=False).as_coeff_Mul() den = denom(ex) if den.func is log and den.args[0] == b: return S.Exp1**(c*numer(ex)) elif den.is_Add: s = sign(im(b)) if s.is_Number and s and den == \ log(-factor_terms(b, sign=False)) + s*S.ImaginaryUnit*S.Pi: return S.Exp1**(c*numer(ex)) obj = b._eval_power(e) if obj is not None: return obj obj = Expr.__new__(cls, b, e) obj.is_commutative = (b.is_commutative and e.is_commutative) return obj
def entropy_of_value(value): """Returns "min entropy" that would give probability of getting this value.""" if isinstance(value, display.Decimal): return entropy_of_value(sympy.numer(value)) if is_non_integer_rational(value): numer = sympy.numer(value) denom = sympy.denom(value) return entropy_of_value(numer) + entropy_of_value(denom) elif not is_integer(value): raise ValueError('Unhandled value: {}'.format(value)) # Note: we sample integers in a range of size approx 10**entropy about zero, # so assume that `abs(value)` is about half of the upper range. return math.log10(5 * abs(value) + 1)
def normalize_poly(poly): poly = sp.simplify(poly) num = sp.Poly(sp.expand(sp.numer(poly))) den = sp.Poly(sp.expand(sp.denom(poly))) num /= den.coeffs()[0] den /= den.coeffs()[0] return num / den
def e2nd(expression): """ basic helper function that accepts a sympy expression, expands it, attempts to simplify it, and returns a numerator and denomenator pair for the instantiation of a scipy LTI system object. """ expression = expression.expand().cancel() n = sympy.Poly(sympy.numer(expression), s).all_coeffs() d = sympy.Poly(sympy.denom(expression), s).all_coeffs() return ([float(x) for x in n], [float(x) for x in d])
def _div_op(value, sample_args, rationals_allowed): """Returns sampled args for `ops.Div`.""" assert rationals_allowed # should be True if this function gets invoked entropy, sample_args = sample_args.peel() numer = sympy.numer(value) denom = sympy.denom(value) if sample_args.count == 1: mult = number.integer(entropy, signed=True, min_abs=1) op_args = [numer * mult, denom * mult] elif sample_args.count == 2: if numer == 0 or random.choice([False, True]): x = number.integer(entropy, signed=True, min_abs=1, coprime_to=denom) op_args = [sympy.Rational(x * numer, denom), x] else: x = number.integer(entropy, signed=True, min_abs=1, coprime_to=numer) op_args = [x, sympy.Rational(x * denom, numer)] else: assert sample_args.count >= 3 p2, p1 = _split_factors(numer) q1, q2 = _split_factors(denom) entropy -= _entropy_of_factor_split(numer) + _entropy_of_factor_split(denom) entropy_r = random.uniform(0, entropy) entropy_s = entropy - entropy_r r = number.integer(entropy_r, signed=True, min_abs=1, coprime_to=q1*p2) s = number.integer(entropy_s, signed=False, min_abs=1, coprime_to=p1*q2) op_args = [sympy.Rational(r*p1, s*q1), sympy.Rational(r*q2, s*p2)] return ops.Div, op_args, sample_args
def simplify(self): self._eqn = sympy.factor(sympy.numer(sympy.factor(self._eqn))) if isinstance(self._eqn, sympy.Mul): def is_not_constant(ex): sym = ex.free_symbols return x in sym or y in sym or z in sym self._eqn = sympy.Mul(*(filter(is_not_constant, self._eqn.args)))
def pxhatsqrd_Ci_polylike_eqn(self, sub_: Dict, pzhat_: float) -> Eq: r"""Define polynomial-form equation for :math:`\hat{p}_x^2`.""" tmp = (self.H_Ci_eqn.rhs.subs({ pzhat: pzhat_, H: Rational(1, 2), mu: eta / 2 }).subs(omitdict(sub_, [Ci])))**2 return Eq(4 * numer(tmp) - denom(tmp), 0)
def __new__(cls, b, e, evaluate=None): if evaluate is None: evaluate = global_evaluate[0] from sympy.functions.elementary.exponential import exp_polar b = _sympify(b) e = _sympify(e) if evaluate: if e is S.Zero: return S.One elif e is S.One: return b elif e.is_integer and _coeff_isneg(b): if e.is_even: b = -b elif e.is_odd: return -Pow(-b, e) if b is S.One: if e in (S.NaN, S.Infinity, -S.Infinity): return S.NaN return S.One elif S.NaN in ( b, e): # XXX S.NaN**x -> S.NaN under assumption that x != 0 return S.NaN else: # recognize base as E if not e.is_Atom and b is not S.Exp1 and b.func is not exp_polar: from sympy import numer, denom, log, sign, im, factor_terms c, ex = factor_terms(e, sign=False).as_coeff_Mul() den = denom(ex) if den.func is log and den.args[0] == b: return S.Exp1**(c * numer(ex)) elif den.is_Add: s = sign(im(b)) if s.is_Number and s and den == \ log(-factor_terms(b, sign=False)) + s*S.ImaginaryUnit*S.Pi: return S.Exp1**(c * numer(ex)) obj = b._eval_power(e) if obj is not None: return obj obj = Expr.__new__(cls, b, e) obj.is_commutative = (b.is_commutative and e.is_commutative) return obj
def complexity_rat(N): ''' Compute the complexity of a rational number. ''' a, b = int(sp.numer(N)), int(sp.denom(N)) C_A = complexity_integer(a) C_B = complexity_integer(b) C_M = max(a, b) return 0.5 * (C_A + C_B) + 0.5 * C_M
def __new__(cls, b, e, evaluate=None): if evaluate is None: evaluate = global_evaluate[0] from sympy.functions.elementary.exponential import exp_polar b = _sympify(b) e = _sympify(e) if evaluate: if e is S.Zero: return S.One elif e is S.One: return b elif e.is_integer and _coeff_isneg(b): if e.is_even: b = -b elif e.is_odd: return -Pow(-b, e) if b is S.One: if e in (S.NaN, S.Infinity, -S.Infinity): return S.NaN return S.One elif S.NaN in (b, e): # XXX S.NaN**x -> S.NaN under assumption that x != 0 return S.NaN else: # recognize base as E if not e.is_Atom and b is not S.Exp1 and b.func is not exp_polar: from sympy import numer, denom, log, sign, im, factor_terms c, ex = factor_terms(e, sign=False).as_coeff_Mul() den = denom(ex) if den.func is log and den.args[0] == b: return S.Exp1**(c*numer(ex)) elif den.is_Add: s = sign(im(b)) if s.is_Number and s and den == \ log(-factor_terms(b, sign=False)) + s*S.ImaginaryUnit*S.Pi: return S.Exp1**(c*numer(ex)) obj = b._eval_power(e) if obj is not None: return obj obj = Expr.__new__(cls, b, e) obj.is_commutative = (b.is_commutative and e.is_commutative) return obj
def e2nd(expression): """ basic helper function that accepts a sympy expression, expands it, attempts to simplify it, and returns a numerator and denomenator pair for the instantiation of a scipy LTI system object. """ expression = expression.expand() expression = expression.cancel() n = sympy.Poly(sympy.numer(expression), s).all_coeffs() d = sympy.Poly(sympy.denom(expression), s).all_coeffs() n = map(float, n) d = map(float, d) return (n, d)
def __new__(cls, b, e, evaluate=None): if evaluate is None: evaluate = global_evaluate[0] from sympy.functions.elementary.exponential import exp_polar # don't optimize "if e==0; return 1" here; it's better to handle that # in the calling routine so this doesn't get called b = _sympify(b) e = _sympify(e) if evaluate: if e is S.Zero: return S.One elif e is S.One: return b elif b is S.One: if e in (S.NaN, S.Infinity, -S.Infinity): return S.NaN return S.One elif S.NaN in (b, e): return S.NaN else: # recognize base as E if not e.is_Atom and b is not S.Exp1 and b.func is not exp_polar: from sympy import numer, denom, log, sign, im, factor_terms c, ex = factor_terms(e, sign=False).as_coeff_Mul() den = denom(ex) if den.func is log and den.args[0] == b: return S.Exp1**(c * numer(ex)) elif den.is_Add: s = sign(im(b)) if s.is_Number and s and den == \ log(-factor_terms(b, sign=False)) + s*S.ImaginaryUnit*S.Pi: return S.Exp1**(c * numer(ex)) obj = b._eval_power(e) if obj is not None: return obj obj = Expr.__new__(cls, b, e) obj.is_commutative = (b.is_commutative and e.is_commutative) return obj
def sympy_to_tf(G, data): """convert a discrete transfer function in sympy to a contorl.tf""" z = sympy.symbols('z') Gs = G.subs(data) try: num = np.array(sympy.Poly(sympy.numer(Gs), z).all_coeffs(), dtype=float) den = np.array(sympy.Poly(sympy.denom(Gs), z).all_coeffs(), dtype=float) except Exception: raise TypeError('failed to convert expression to float polynomials: ', Gs) return control.tf(num, den, 1.0 / data['f_s'])
def tustin(tf, sRate): s = getMapping(tf)['s'] T = 1 / sRate poles = sympy.roots(sympy.denom(tf), s, multiple=True) centroid = np.mean(np.abs(poles)) invz = sympy.Symbol('invz', real=True) # normalized center frequency derived from poles of filter SISO transfer function w0 = 2 * np.pi * centroid / (sRate * 2 * np.pi) # modified bilinear transform w/ frequency warping bt = w0 / sympy.tan(w0 * T / 2) * ((1 - invz) / (1 + invz)) dt = sympy.simplify(tf.subs({s: bt})) b = sympy.Poly(sympy.numer(dt)).all_coeffs()[::-1] a = sympy.Poly(sympy.denom(dt)).all_coeffs()[::-1] normalize = lambda x: float(x / a[0]) return (map(normalize, b), map(normalize, a))
def tustin(tf, sRate): s = getMapping(tf)['s'] T = 1/sRate poles = sympy.roots(sympy.denom(tf), s, multiple=True) centroid = np.mean(np.abs(poles)) invz = sympy.Symbol('invz', real=True) # normalized center frequency derived from poles of filter SISO transfer function w0 = 2*np.pi*centroid/(sRate*2*np.pi) # modified bilinear transform w/ frequency warping bt = w0/sympy.tan(w0*T/2) * ((1-invz)/(1+invz)) dt = sympy.simplify(tf.subs({s: bt})) b = sympy.Poly(sympy.numer(dt)).all_coeffs()[::-1] a = sympy.Poly(sympy.denom(dt)).all_coeffs()[::-1] normalize = lambda x: float(x/a[0]) return (map(normalize, b), map(normalize, a))
def mutate_rat(value, *, keep_sign=True, mutate_up=None): '''Mutate rational number''' r = random.random() numer, denom = sp.numer(value), sp.denom(value) # swap numerator and denominator if r < 0.20: numer, denom = (mutate_int(denom, mutate_up=mutate_up, keep_sign=keep_sign), mutate_int(numer, mutate_up=mutate_up)) # mutate numerator elif r < 0.65: numer = mutate_int(numer, mutate_up=mutate_up, keep_sign=keep_sign) # mutate denominator else: denom = mutate_int(denom, mutate_up=mutate_up, keep_sign=keep_sign) return sp.Rational(numer, denom or 1)
def _rational_to_string(self, rational): """Converts a rational to words, e.g., "two thirds".""" numer = sympy.numer(rational) denom = sympy.denom(rational) numer_words = self._to_string(numer) if denom == 1: return numer_words if denom <= 0 or denom >= len(_PLURAL_DENOMINATORS): raise ValueError('Unsupported denominator {}.'.format(denom)) if numer == 1: denom_word = _SINGULAR_DENOMINATORS[denom] else: denom_word = _PLURAL_DENOMINATORS[denom] return '{} {}'.format(numer_words, denom_word)
def __init__(self, value): """Initializes a `Decimal`. Args: value: (Sympy) value to display as a decimal. Raises: ValueError: If `value` cannot be represented as a non-terminating decimal. """ self._value = sympy.Rational(value) numer = int(sympy.numer(self._value)) denom = int(sympy.denom(self._value)) denom_factors = list(sympy.factorint(denom).keys()) for factor in denom_factors: if factor not in [2, 5]: raise ValueError('Cannot represent {} as a non-recurring decimal.' .format(value)) self._decimal = decimal.Decimal(numer) / decimal.Decimal(denom)
def _delta_invariant(g,u,v,u0,v0): """ Returns the delta invariant corresponding to the singular point `singular_pt` = [alpha, beta, gamma] on the plane algebraic curve f(x,y) = 0. """ # compute Puiseux expansions at u=u0 and filter out only those # with v(t=0) == v0. We only chose one y=y(x) Puiseux series for # each place as a representative to prevent over-counting by using # the "grouped=True" flag in Puiseux P = puiseux(g,u,v,u0,nterms=0,parametric=_t,grouped=True) P_x = puiseux(g,u,v,u0,nterms=0,parametric=False,grouped=True) P_x_v0 = [] for i in range(len(P)): X,Y = P[i] p = P_x[i][0] if Y.subs(_t,0).simplify() == v0: # store the index as well so we know which parametric form # corresponds to this puiseux series. P_x_v0.append((p,i)) # now obtain ungrouped series P_x = puiseux(g,u,v,u0,nterms=0,parametric=False) # for each place compute its contribution to the delta invariant delta = sympy.Rational(0,1) for i in range(len(P_x_v0)): yhat, place_index = P_x_v0[i] j = P_x.index(yhat) IntPj = Int(j,P_x,u,u0) # obtain the ramification index by retreiving the # corresponding parametric form. By definition, this # parametric series satisfies Y(t=0) = v0 X,Y = P[place_index] rj = (X-u0).as_coeff_exponent(_t)[1] delta += sympy.Rational(rj * IntPj - rj + 1, 2) return sympy.numer(delta)
def poleres2pz(poles,residues,offset,slope, maxsteps=500): """ Convert a pole-resiude representation of a TF -- f(s) = Sum [r/(s-p)] + k + s * h to a pole zero representation f(s) = Sum[s-z] / Sum[s-p] """ from sympy import Symbol, together, expand, numer, denom, nroots x = Symbol('x') f = sum([r/(x-p) for p,r in zip(poles, residues)]) f += offset + slope*x ft = together(f) nf = expand(numer(ft)) zeros = nroots(nf,maxsteps=maxsteps) return np.array([complex(xx) for xx in poles]), np.array([complex(xx) for xx in zeros])
def _mul_op(value, sample_args, rationals_allowed): """Returns sampled args for `ops.Mul`.""" if sample_args.count >= 3: _, op_args, sample_args = _div_op(value, sample_args, rationals_allowed) op_args = [op_args[0], sympy.Integer(1) / op_args[1]] elif sample_args.count == 1: entropy, sample_args = sample_args.peel() assert _entropy_of_factor_split(value) >= entropy op_args = _split_factors(value) else: assert sample_args.count == 2 entropy, sample_args = sample_args.peel() numer = sympy.numer(value) denom = sympy.denom(value) p1, p2 = _split_factors(numer) entropy -= _entropy_of_factor_split(numer) mult = number.integer(entropy, signed=True, min_abs=1, coprime_to=p1) op_args = [p1 / (mult * denom), p2 * mult] if random.choice([False, True]): op_args = list(reversed(op_args)) return ops.Mul, op_args, sample_args
def symmetryDetection(allVariables, diffEquations, observables, obsFunctions, initFunctions, predictions, predFunctions, ansatz='uni', pMax=2, inputs=[], fixed=[], parallel=1, allTrafos=False, timeTrans=False, pretty=True, suffix=''): n = len(allVariables) m = len(diffEquations) h = len(observables) ########################################################################################### ############################# prepare equations #################################### ########################################################################################### sys.stdout.write('Preparing equations...') sys.stdout.flush() # make infinitesimal ansatz infis, diffInfis, rs = makeAnsatz(ansatz, allVariables, m, len(inputs), pMax, fixed) # get infinitesimals of time transformation if timeTrans: rs.append(spy.var('r_T_1')) diffInfiT = rs[-1] allVariables += [T] else: diffInfiT = None # and convert to polynomial infis, diffInfis = transformInfisToPoly(infis, diffInfis, allVariables, rs, parallel, ansatz) diffInfiT = Apoly(diffInfiT, allVariables, rs) ### extract numerator and denominator of equations #differential equations numerators = [0] * m denominators = [0] * m for k in range(m): rational = spy.together(diffEquations[k]) numerators[k] = Apoly(spy.numer(rational), allVariables, None) denominators[k] = Apoly(spy.denom(rational), allVariables, None) #observation functions obsNumerators = [0] * h obsDenominatros = [0] * h for k in range(h): rational = spy.together(obsFunctions[k]) obsNumerators[k] = Apoly(spy.numer(rational), allVariables, None) obsDenominatros[k] = Apoly(spy.denom(rational), allVariables, None) #initial functions if len(initFunctions) != 0: initNumerators = [0] * m initDenominatros = [0] * m for k in range(m): rational = spy.together(initFunctions[k]) initNumerators[k] = Apoly(spy.numer(rational), allVariables, None) initDenominatros[k] = Apoly(spy.denom(rational), allVariables, None) else: initNumerators = [] initDenominatros = [] ### calculate numerator of derivatives of equations #differential equatioins derivativesNum = [0] * m for i in range(m): derivativesNum[i] = [0] * n for k in range(m): for l in range(n): derivativesNum[k][l] = Apoly(None, allVariables, None) derivativesNum[k][l].add(numerators[k].diff(l).mul( denominators[k])) derivativesNum[k][l].sub(numerators[k].mul( denominators[k].diff(l))) #observation functions obsDerivativesNum = [0] * h for i in range(h): obsDerivativesNum[i] = [0] * n for k in range(h): for l in range(n): obsDerivativesNum[k][l] = Apoly(None, allVariables, None) obsDerivativesNum[k][l].add(obsNumerators[k].diff(l).mul( obsDenominatros[k])) obsDerivativesNum[k][l].sub(obsNumerators[k].mul( obsDenominatros[k].diff(l))) #initial functions if len(initFunctions) != 0: initDerivativesNum = [0] * len(initFunctions) for i in range(m): initDerivativesNum[i] = [0] * n for k in range(m): for l in range(n): initDerivativesNum[k][l] = Apoly(None, allVariables, None) initDerivativesNum[k][l].add(initNumerators[k].diff(l).mul( initDenominatros[k])) initDerivativesNum[k][l].sub(initNumerators[k].mul( initDenominatros[k].diff(l))) else: initDerivativesNum = [] sys.stdout.write('\rPreparing equations...done\n') sys.stdout.flush() ########################################################################################### ############################ build linear system ################################### ########################################################################################### sys.stdout.write('\nBuilding system...') sys.stdout.flush() rSystem = buildSystem(numerators, denominators, derivativesNum, obsDerivativesNum, initDenominatros, initDerivativesNum, initFunctions, infis, diffInfis, diffInfiT, allVariables, rs, parallel, ansatz) sys.stdout.write('done\n') sys.stdout.flush() ########################################################################################### ############################## solve system ######################################## ########################################################################################### sys.stdout.write('\nSolving system of size ' + str(rSystem.shape[0]) + 'x' +\ str(rSystem.shape[1]) + '...') sys.stdout.flush() #get LU decomposition from scipy rSystem = scipy.linalg.lu(rSystem, permute_l=True)[1] #calculate reduced row echelon form rSystem, pivots = getrref(rSystem) sys.stdout.write('done\n') sys.stdout.flush() ########################################################################################### ############################# process results ###################################### ########################################################################################### sys.stdout.write('\nProcessing results...') sys.stdout.flush() # calculate solution space sys.stdout.write('\n calculating solution space') sys.stdout.flush() baseMatrix = nullSpace(rSystem, pivots) #substitute solutions into infinitesimals #(and remove the ones with common parameter factors) sys.stdout.write('\n substituting solutions') sys.stdout.flush() infisAll = [] for l in range(baseMatrix.shape[1]): infisTmp = [0] * n for i in range(len(infis)): infisTmp[i] = infis[i].getCopy() infisTmp[i].rs = baseMatrix[:, l] infisTmp[i] = infisTmp[i].as_expr() if timeTrans: infisTmp.append(baseMatrix[-1, l] * T) if allTrafos: infisAll.append(infisTmp) else: if not checkForCommonFactor(infisTmp, allVariables, m): infisAll.append(infisTmp) print('') sys.stdout.write('done\n') sys.stdout.flush() # print transformations print('\n\n') if len(infisAll) != 0: printTransformations(infisAll, allVariables, pretty, suffix) ########################################################################################### ############################ check predictions ##################################### ########################################################################################### if predictions != False: checkPredictions(predictions, predFunctions, infisAll, allVariables) print( time.strftime('\nTotal time: %Hh:%Mm:%Ss', time.gmtime(time.time() - t0)))
def ratfun(self, expr, z, n, **kwargs): expr = expr / z # Handle special case 1 / (z**m * (z - 1)) since this becomes u[n - m] # The default method produces u[n] - delta[n] for u[n-1]. This is correct # but can be simplified. # In general, 1 / (z**m * (z - a)) becomes a**n * u[n - m] if (len(expr.args) == 2 and expr.args[1].is_Pow and expr.args[1].args[0].is_Add and expr.args[1].args[0].args[0] == -1 and expr.args[1].args[0].args[1] == z): delay = None if expr.args[0] == z: delay = 1 elif expr.args[0].is_Pow and expr.args[0].args[0] == z: a = expr.args[0].args[1] if a.is_positive: warn('Dodgy z-transform 1. Have advance of unit step.') elif not a.is_negative: warn( 'Dodgy z-transform 2. May have advance of unit step.') delay = -a elif (expr.args[0].is_Pow and expr.args[0].args[0].is_Pow and expr.args[0].args[0].args[0] == z and expr.args[0].args[0].args[1] == -1): a = expr.args[0].args[1] if a.is_negative: warn('Dodgy z-transform 3. Have advance of unit step.') elif not a.is_positive: warn( 'Dodgy z-transform 4. May have advance of unit step.') delay = a if delay is not None: return UnitStep(n - delay), sym.S.Zero zexpr = Ratfun(expr, z) Q, M, D, delay, undef = zexpr.as_QMA() cresult = sym.S.Zero uresult = sym.S.Zero if Q: Qpoly = sym.Poly(Q, z) C = Qpoly.all_coeffs() for m, c in enumerate(C): cresult += c * UnitImpulse(n - len(C) + m + 1) # There is problem with determining residues if # have 1/(z*(-a/z + 1)) instead of 1/(-a + z). Hopefully, # simplify will fix things... expr = (M / D).simplify() # M and D may contain common factors before simplification, so redefine M and D M = sym.numer(expr) D = sym.denom(expr) for factor in expr.as_ordered_factors(): if factor == sym.oo: return factor, factor zexpr = Ratfun(expr, z, **kwargs) poles = zexpr.poles(damping=kwargs.get('damping', None)) poles_dict = {} for pole in poles: # Replace cos()**2-1 by sin()**2 pole.expr = TR6(sym.expand(pole.expr)) pole.expr = sym.simplify(pole.expr) # Remove abs value from sin() pole.expr = pole.expr.subs(sym.Abs, sym.Id) poles_dict[pole.expr] = pole.n # Juergen Weizenecker HsKa # Make two dictionaries in order to handle them differently and make # pretty expressions if kwargs.get('pairs', True): pole_pair_dict, pole_single_dict = pair_conjugates(poles_dict) else: pole_pair_dict, pole_single_dict = {}, poles_dict # Make n (=number of poles) different denominators to speed up # calculation and avoid sym.limit. The different denominators are # due to shortening of poles after multiplying with (z-z1)**o if not (M.is_polynomial(z) and D.is_polynomial(z)): print("Numerator or denominator may contain 1/z terms: ", M, D) n_poles = len(poles) # Leading coefficient of denominator polynom a_0 = sym.LC(D, z) # The canceled denominator (for each (z-p)**o) shorten_denom = {} for i in range(n_poles): shorten_term = sym.prod([(z - poles[j].expr)**(poles[j].n) for j in range(n_poles) if j != i], a_0) shorten_denom[poles[i].expr] = shorten_term # Run through single poles real or complex, order 1 or higher for pole in pole_single_dict: p = pole # Number of occurrences of the pole. o = pole_single_dict[pole] # X(z)/z*(z-p)**o after shortening. expr2 = M / shorten_denom[p] if o == 0: continue if o == 1: r = sym.simplify(sym.expand(expr2.subs(z, p))) if p == 0: cresult += r * UnitImpulse(n) else: uresult += r * p**n continue # Handle repeated poles. all_derivatives = [expr2] for i in range(1, o): all_derivatives += [sym.diff(all_derivatives[i - 1], z)] bino = 1 sum_p = 0 for i in range(1, o + 1): m = o - i derivative = all_derivatives[m] # Derivative at z=p derivative = sym.expand(derivative.subs(z, p)) r = sym.simplify(derivative) / sym.factorial(m) if p == 0: cresult += r * UnitImpulse(n - i + 1) else: sum_p += r * bino * p**(1 - i) / sym.factorial(i - 1) bino *= n - i + 1 uresult += sym.simplify(sum_p * p**n) # Run through complex pole pairs for pole in pole_pair_dict: p1 = pole[0] p2 = pole[1] # Number of occurrences of the pole pair o1 = pole_pair_dict[pole] # X(z)/z*(z-p)**o after shortening expr_1 = M / shorten_denom[p1] expr_2 = M / shorten_denom[p2] # Oscillation parameter lam = sym.sqrt(sym.simplify(p1 * p2)) p1_n = sym.simplify(p1 / lam) # term is of form exp(j*arg()) if len(p1_n.args ) == 1 and p1_n.is_Function and p1_n.func == sym.exp: omega_0 = sym.im(p1_n.args[0]) # term is of form cos() + j sin() elif p1_n.is_Add and sym.re(p1_n).is_Function and sym.re( p1_n).func == sym.cos: p1_n = p1_n.rewrite(sym.exp) omega_0 = sym.im(p1_n.args[0]) # general form else: omega_0 = sym.simplify(sym.arg(p1_n)) if o1 == 1: r1 = expr_1.subs(z, p1) r2 = expr_2.subs(z, p2) r1_re = sym.re(r1).simplify() r1_im = sym.im(r1).simplify() # if pole pairs is selected, r1=r2* # Handle real part uresult += 2 * TR9(r1_re) * lam**n * sym.cos(omega_0 * n) uresult -= 2 * TR9(r1_im) * lam**n * sym.sin(omega_0 * n) else: bino = 1 sum_b = 0 # Compute first all derivatives needed all_derivatives_1 = [expr_1] for i in range(1, o1): all_derivatives_1 += [ sym.diff(all_derivatives_1[i - 1], z) ] # Loop through the binomial series for i in range(1, o1 + 1): m = o1 - i # m th derivative at z=p1 derivative = all_derivatives_1[m] r1 = derivative.subs(z, p1) / sym.factorial(m) # prefactors prefac = bino * lam**(1 - i) / sym.factorial(i - 1) # simplify r1 r1 = r1.rewrite(sym.exp).simplify() # sum sum_b += prefac * r1 * sym.exp(sym.I * omega_0 * (1 - i)) # binomial coefficient bino *= n - i + 1 # take result = lam**n * (sum_b*sum_b*exp(j*omega_0*n) + cc) aa = sym.simplify(sym.re(sum_b)) bb = sym.simplify(sym.im(sum_b)) uresult += 2 * (aa * sym.cos(omega_0 * n) - bb * sym.sin(omega_0 * n)) * lam**n # cresult is a sum of Dirac deltas and its derivatives so is known # to be causal. return cresult, uresult
def ALGO4(As,Bs,Cs,Ds,do_test): #-------------------STEP 1------------------------------ if not is_row_proper(As): Us,Ast=row_proper(As) else: Us,Ast=eye(As.rows),As Bst=Us*Bs Bst=expand(Bst) r=Ast.cols #-------------------STEP 2------------------------------ K=simplify(Ast.inv()*Bst) #very important Ys=zeros(K.shape) for i,j in product(range(K.rows),range(K.cols)): Ys[i,j],q=div(numer(K[i,j]),denom(K[i,j])) B_hat=Bst-Ast*Ys #-------------------END STEP 2------------------------------ #-------------------STEP 3------------------------------ Psi=diag(*[[s**( mc.row_degrees(Ast,s)[j] -i -1) for i in range( mc.row_degrees(Ast,s)[j])] for j in range(r)]).T S=diag(*[s**(rho) for rho in mc.row_degrees(Ast,s)]) Ahr=mc.highest_row_degree_matrix(Ast,s) Help=Ast-S*Ahr SOL={} numvar=Psi.rows*Psi.cols alr=symbols('a0:%d'%numvar) Alr=Matrix(Psi.cols,Psi.rows,alr) RHS=Psi*Alr for i,j in product(range(Help.rows),range(Help.cols)): #diagonal explain later SOL.update(solve_undetermined_coeffs(Eq(Help[i,j],RHS[i,j]),alr,s)) Alr=Alr.subs(SOL) #substitute(SOL) Aoc=Matrix(BlockDiagMatrix(*[Matrix(rho, rho, lambda i,j: KroneckerDelta(i+1,j))for rho in mc.row_degrees(Ast,s)])) Boc=eye(sum(mc.row_degrees(Ast,s))) Coc=Matrix(BlockDiagMatrix(*[SparseMatrix(1,rho,{(x,0):1 if x==0 else 0 for x in range(rho)}) for rho in mc.row_degrees(Ast,s)])) A0=Aoc-Alr*Ahr.inv()*Matrix(Coc) C0=Ahr.inv()*Coc SOL={} numvar=Psi.cols*Bst.cols b0=symbols('b0:%d'%numvar) B0=Matrix(Psi.cols,Bst.cols,b0) RHS=Psi*B0 for i,j in product(range(B_hat.rows),range(B_hat.cols)): #diagonal explain later SOL.update(solve_undetermined_coeffs(Eq(B_hat[i,j],RHS[i,j]),b0,s)) B0=B0.subs(SOL) #substitute(SOL) LHS_matrix=simplify(Cs*C0) #left hand side of the equation (1) sI_A=s*eye(A0.cols)- A0 max_degree=mc.find_degree(LHS_matrix,s) #get the degree of the matrix at the LHS #which is also the maximum degree for the coefficients of Λ(s) #---------------------------Creating Matrices Λ(s) and C ------------------------------------- Lamda=[] numvar=((max_degree))*A0.cols a=symbols('a0:%d'%numvar) for i in range(A0.cols): # paratirisi den douleuei to prin giat;i otra oxi diagonios p=sum(a[n +i*(max_degree)]*s**n for n in range(max_degree)) # we want variables one degree lower because we are multiplying by first order monomials Lamda.append(p) Lamda=Matrix(Cs.rows,A0.cols,Lamda) #convert the list to Matrix c=symbols('c0:%d'%(Lamda.rows*Lamda.cols)) C=Matrix(Lamda.rows,Lamda.cols,c) #----------------------------------------- RHS_matrix=Lamda*sI_A +C #right hand side of the equation (1) ''' -----------Converting equation (1) to a system of linear ----------- -----------equations, comparing the coefficients of the ----------- -----------polynomials in both sides of the equation (1) ----------- ''' EQ=[Eq(LHS_matrix[i,j],expand(RHS_matrix[i,j])) for i,j in product(range(LHS_matrix.rows),range(LHS_matrix.cols)) ]
def ac_analysis(param_d, param_l, instance, file_sufix): """ Performs ac analysis param_d: substitutions for symbols, or named parameters for plot param_l: expresions to plot format is: .ac expresion0 [expresion1 expresion2 ...] sweep = parameter_to_sweep [symmbol_or_option0 = value0 symmbol_or_option1 = value1 ...] expresions are on positiona parameters list can hold expresions containing parameters or functions of nodal voltages [v(node)] and element and port currents [i(element) isub(port)] named parameters (param_d) can contain options for analysis or substitutions for symbols, substituions will be done as they are without any parsing, be aware of symbol and option names clashes. Config options: fstart: first value of frequency for AC analysis [float] fstop: last value of frequency for AC analysis [float] fscale: scale for frequency points [linear | log] npoints: numbers of points for ac analysis [integer] yscale: scale for y-axis to being displayed on [linear or log] hold: hold plot for next analysis and don't save it to file [yes | no] show_poles: show poles of function on plot [yes | no] show_zeroes: show zeros of function on plot [yes | no] title: display title above ac plot [string] show_legend: show legend on plot [yes | no] xkcd: style plot to be xkcd like scetch """ warnings.filterwarnings('ignore') # Just getting rid of those fake casting from complex warnings s, w = sympy.symbols(('s', 'w')) config = {'fstart': 1, 'fstop': 1e6, 'fscale': 'log', 'npoints': 100, 'yscale': 'log', 'type': 'amp', 'hold': 'no', 'show_poles': 'yes', 'show_zeros': 'yes', 'title': None, 'show_legend': 'no', 'xkcd': 'no'} for config_name in config.keys(): if config_name in param_d: config.update({config_name: param_d[config_name]}) param_d.pop(config_name) subst = [] for symbol, value in param_d.iteritems(): tokens = scs_parser.parse_param_expresion(value) try: value = float(sympy.sympify(scs_parser.params2values(tokens, instance.paramsd),sympy.abc._clash)) except ValueError: raise scs_errors.ScsAnalysisError("Passed subsitution for %s is not a number") subst.append((symbol, value)) if config['fscale'] == 'log': fs = np.logspace(np.log10(float(config['fstart'])), np.log10(float(config['fstop'])), int(config['npoints'])) elif config['fscale'] == 'linear': fs = np.linspace(float(config['fstart']), float(config['fstop']), int(config['npoints'])) else: raise scs_errors.ScsAnalysisError(("Option %s for fscale invalid!" % config['yscale'])) if config['yscale'] != 'log' and config['yscale'] != 'linear': raise scs_errors.ScsAnalysisError(("Option %s for yscale invalid!" % config['fscale'])) filename = "%s.results" % file_sufix with open(filename, 'a') as fil: if config['xkcd'] == 'yes': plt.xkcd() plt.hold(True) for expresion in param_l: fil.write("%s: %s \n---------------------\n" % ('AC analysis of', expresion)) tokens = scs_parser.parse_analysis_expresion(expresion) value0 = sympy.factor(sympy.sympify(scs_parser.results2values(tokens, instance),sympy.abc._clash), s).simplify() fil.write("%s = %s \n\n" % (expresion, str(value0))) denominator = sympy.denom(value0) numerator = sympy.numer(value0) poles = sympy.solve(denominator, s) zeros = sympy.solve(numerator, s) poles_r = sympy.roots(denominator, s) zeros_r = sympy.roots(numerator, s) gdc = str(value0.subs(s, 0).simplify()) fil.write('G_DC = %s\n\n' % gdc) p = 0 titled = 1 for pole, degree in poles_r.iteritems(): if pole == 0: titled *= s ** degree else: titled *= (s / sympy.symbols("\\omega_p%d" % p) + 1) p += 1 z = 0 titlen = 1 for zero, degree in zeros_r.iteritems(): if zero == 0: titlen *= s ** degree else: titlen *= (s / sympy.symbols("\\omega_z%d" % z) + 1) z += 1 # title = sympy.symbols("G_DC") * (titlen / titled) value = value0.subs(subst) f = sympy.symbols('f', real=True) value = value.subs(s, sympy.sympify('2*pi*I').evalf() * f) tf = sympy.lambdify(f, abs(sympy.numer(value)) / abs(sympy.denom(value))) phf = sympy.lambdify(f, sympy.arg(value)) if config['type'] == 'amp': zf = tf ylabel = '|T(f)|' elif config['type'] == 'phase': zf = phf ylabel = 'ph(T(f))' else: raise scs_errors.ScsAnalysisError("Option %s for type invalid!" % config['type']) try: ys = [float(zf(f)) for f in fs] except (ValueError, TypeError): raise scs_errors.ScsAnalysisError( "Numeric error while evaluating expresions: %s. Not all values where subsituted?" % value0) plt.plot(fs, ys, label=expresion) plt.title(r'$%s$' % config['title'] if config['title'] else ' ', y=1.05) try: plt.xscale(config['fscale']) plt.yscale(config['yscale']) except ValueError, e: raise scs_errors.ScsAnalysisError(e) plt.xlabel('f [Hz]') plt.ylabel(ylabel) if len(poles): fil.write('Poles: \n') p = 0 for pole in poles: try: pole_value = pole.subs(subst) pole_value_f = abs(np.float64(-abs(pole_value) / sympy.sympify('2*pi').evalf())) pole_s = (-pole).simplify() polestr = str(pole_s) fil.write('wp_%d = %s\n\n' % (p, polestr)) p += 1 if pole_value_f > float(config['fstop']) \ or pole_value_f < float(config['fstart']) \ or np.isnan(zf(pole_value_f)): continue if config['show_poles'] == 'yes': pole_label = r'$\omega_{p%d} $' % (p - 1) plt.plot(pole_value_f, zf(pole_value_f), 'o', label=pole_label) plt.text(pole_value_f, zf(pole_value_f), pole_label) plt.axvline(pole_value_f, linestyle='dashed') except: pass z = 0 for zero in zeros: try: zero_value = zero.subs(subst) zero_value_f = abs(np.float64(-abs(zero_value) / sympy.sympify('2*pi').evalf())) zero_s = (-zero).simplify() zerostr = str(zero_s) fil.write('wz_%d = %s\n\n' % (z, zerostr)) z += 1 if zero_value_f > float(config['fstop']) \ or zero_value_f < float(config['fstart']) \ or np.isnan(zf(zero_value_f)): continue if config['show_zeros'] == 'yes': zero_label = r'$\omega_{z%d} $' % (z - 1) plt.plot(zero_value_f, zf(zero_value_f), '*', label=zero_label) plt.axvline(zero_value_f, linestyle='dashed') plt.text(zero_value_f, zf(zero_value_f), zero_label) except: pass if config['show_legend'] == 'yes': plt.legend() if config['hold'] == 'no': plt.hold(False) plt.savefig('%s_%d.png' % (file_sufix, PlotNumber.plot_num)) plt.clf() PlotNumber.plot_num += 1
def solve_u_eqn_rect(self): u3_eqn = self.ucubed_dynamic_eqn.subs(theta,sy.pi/2).args[1] u2_eqn = sy.simplify(((2*d+w)*(u**2-u3_eqn)).subs(d,Q/(w*u))/u) return Eq(u,sy.solve(Eq(sy.numer(u2_eqn)),u)[1])
#pdf A_lp, b_lp, V_lp = lowpass(10000, 10000, 1e-9, 1e-9, 1.586, 1) Vo_lp = V_lp[3] hf_lp = lambdify(s, Vo_lp, 'numpy') bode_output_lp = hf_lp(ss) plt.loglog(ww, abs(bode_output_lp), lw=2) plt.title("bode plot of lowpass filter") plt.xlabel('frequency') plt.ylabel('H(jw)') plt.grid(True) plt.show() numerator_lp = [ float(numer(Vo_lp.simplify()).coeff(s, 2)), float(numer(Vo_lp.simplify()).coeff(s, 1)), float(numer(Vo_lp.simplify()).coeff(s, 0)) ] denominator_lp = [ float(denom(Vo_lp.simplify()).coeff(s, 2)), float(denom(Vo_lp.simplify()).coeff(s, 1)), float(denom(Vo_lp.simplify()).coeff(s, 0)) ] #1 v, t = sp.step([numerator_lp, denominator_lp], None, np.arange(0, 1e-3, 1e-6)) plt.plot(v, t) plt.title("Step response of lowpass filter") plt.grid(True) plt.xlabel('t')
def _split_value_equally(delta, count): """Splits an integer or rational into roughly equal parts.""" numer = sympy.numer(delta) denom = sympy.denom(delta) return [int(math.floor((numer + i) / count)) / denom for i in range(count)]
def parametric_differentiation(f, g, dependent_variable, n, simplification_method='None'): ''' Performs differentiation on two parametric equations. Parameters ---------- f: Sympy Mul A Sympy Mul object containing the first parametric equation. g: Sympy Mul A Sympy Mul object containing the second parametric equation. dependent_variable: Sympy Symbol Dependent variable. n: integer Order of differentiation. simplification_method: str (or list if method is 'collect'), optional Simplification method to be applied to the final answer. Example ------- >> t = sym.symbols('t') >> x = t ** 3 - 3 * t ** 2 >> y = t ** 4 - 8 * t ** 2 >> parametric_differentiation(f = x, g = y, dependent_variable = t, n = 3) >> t = sym.symbols('t') >> x = sin(t) >> y = cos(t) >> parametric_differentiation(f = x, g = y, dependent_variable = t, n = 2, simplification_method = 'simplify') ''' t = dependent_variable # check that a positive integer if np.mod(n, 1) != 0 or n < 0: raise ValueError('n must be a positive integer') else: if n == 1: para_derivative = sym.diff(g, t) / sym.diff(f, t) else: # perform the normal differentiation recurssively para_derivative = sym.diff( parametric_differentiation(g, f, t, n - 1), t) / sym.diff( f, t) numerator, denominator = sym.numer(para_derivative), sym.denom( para_derivative) # perform simplification according to the simplification method specfied if simplification_method == 'None': result = sym.factor(numerator) / sym.factor(denominator) elif simplification_method == 'simplify': result = sym.simplify(numerator) / sym.simplify(denominator) elif simplification_method == 'factor': result = sym.factor(numerator) / sym.factor(denominator) elif simplification_method == 'expand': result = sym.expand(numerator) / sym.expand(denominator) elif 'collect' in simplification_method: # stop and return an error if simplification method is not a list if not isinstance(simplification_method, list): raise ValueError( 'Specifiy the simplification_method argument as a list.') result = sym.collect(numerator, simplification_method[1]) / sym.collect( denominator, simplification_method[1]) elif simplification_method == 'together': result = sym.together(numerator) / sym.together(denominator) elif simplification_method == 'cancel': result = sym.cancel(numerator) / sym.cancel(denominator) else: raise ValueError( "%s is an invalid value for the argument 'simplification_method'" % (simplification_method)) return result
def f2nd(function: Basic) -> Tuple[Basic, Basic]: function = together(function) return numer(function), denom(function)
def define_tanbeta_eqns(self) -> None: r""" Define equations for surface tilt angle :math:`\beta`. Attributes: tanbeta_alpha_eqns (list) : :math:`\left[ \tan{\left(\beta \right)} \ = \dfrac{\eta - \sqrt{\eta^{2} - 4 \eta \tan^{2}{\left(\alpha \right)} - 2 \eta + 1} - 1} {2 \tan{\left(\alpha \right)}}, \tan{\left(\beta \right)} = \dfrac{\eta + \sqrt{\eta^{2} - 4 \eta \tan^{2}{\left(\alpha \right)} - 2 \eta + 1} - 1} {2 \tan{\left(\alpha \right)}}\right]` tanbeta_alpha_eqn (:class:`~sympy.core.relational.Equality`): :math:`\tan{\left(\beta \right)} = \dfrac{\eta - \sqrt{\eta^{2} - 4 \eta \tan^{2}{\left(\alpha \right)} - 2 \eta + 1} - 1} {2 \tan{\left(\alpha \right)}}` tanalpha_ext_eqns (list) : :math:`\left[ \tan{\left(\alpha_c \right)} = - \frac{\sqrt{\eta - 2 + \frac{1}{\eta}}}{2}, \tan{\left(\alpha_c \right)} = \frac{\sqrt{\eta - 2 + \frac{1}{\eta}}}{2}\right]` tanalpha_ext_eqn (:class:`~sympy.core.relational.Equality`): :math:`\tan{\left(\alpha_c \right)} = \dfrac{\eta - 1}{2 \sqrt{\eta}}` tanbeta_crit_eqns (list) : :math:`\left[ \tan{\left(\beta_c \right)} = - \dfrac{\eta - 1}{\sqrt{\eta - 2 + \frac{1}{\eta}}}, \tan{\left(\beta_c \right)} = \dfrac{\eta - 1}{\sqrt{\eta - 2 + \frac{1}{\eta}}}\right]` tanbeta_crit_eqn (:class:`~sympy.core.relational.Equality`): :math:`\tan{\left(\beta_c \right)} = \sqrt{\eta}` tanbeta_rdotxz_pz_eqn (:class:`~sympy.core.relational.Equality`): :math:`\tan{\left(\beta \right)} = \dfrac{v^{z} - \frac{1}{p_{z}}}{v^{x}}` tanbeta_rdotxz_xiv_eqn (:class:`~sympy.core.relational.Equality`): :math:`\tan{\left(\beta \right)} = \dfrac{\xi^{\downarrow} + v^{z}}{v^{x}}` """ logging.info("gme.core.angles.define_tanbeta_eqns") # eta_sub = {eta: self.eta_} if self.eta_ == 1 and self.beta_type == "sin": logging.info(r"Cannot compute all $\beta$ equations " + r"for $\sin\beta$ model and $\eta=1$") return solns = solve(self.tanalpha_beta_eqn.subs({tan(alpha): ta}), tan(beta)) self.tanbeta_alpha_eqns = [ Eq(tan(beta), soln.subs({ta: tan(alpha)})) for soln in solns ] # Bit of a hack - extracts the square root term in tan(beta) # as a fn of tan(alpha), which then gives the critical alpha root_terms = [[ arg_ for arg__ in arg_.args if isinstance(arg__, sy.core.power.Pow) or isinstance(arg_, sy.core.power.Pow) ] for arg_ in numer(self.tanbeta_alpha_eqns[0].rhs).args if isinstance(arg_, (sy.core.mul.Mul, sy.core.power.Pow)) ] self.tanalpha_ext_eqns = [ Eq(tan(alpha_ext), soln) for soln in solve(Eq(root_terms[0][0], 0), tan(alpha)) ] tac_lt1 = simplify( (factor(simplify(self.tanalpha_ext_eqns[0].rhs * sqrt(eta))) / sqrt(eta)).subs({Abs(eta - 1): 1 - eta})) tac_gt1 = simplify( (factor(simplify(self.tanalpha_ext_eqns[1].rhs * sqrt(eta))) / sqrt(eta)).subs({Abs(eta - 1): eta - 1})) self.tanalpha_ext_eqn = Eq( tan(alpha_ext), Piecewise((tac_lt1, eta < 1), (tac_gt1, True))) self.tanbeta_crit_eqns = [ factor( tanbeta_alpha_eqn_.subs({ beta: beta_crit, alpha: alpha_ext }).subs(e2d(tanalpha_ext_eqn_))) for tanalpha_ext_eqn_, tanbeta_alpha_eqn_ in zip( self.tanalpha_ext_eqns, self.tanbeta_alpha_eqns) ] # This is a hack, because SymPy simplify can't handle it self.tanbeta_crit_eqn = Eq( tan(beta_crit), sqrt(simplify((self.tanbeta_crit_eqns[0].rhs)**2))) self.tanbeta_rdotxz_pz_eqn = Eq(tan(beta), (rdotz - 1 / pz) / rdotx) self.tanbeta_rdotxz_xiv_eqn = self.tanbeta_rdotxz_pz_eqn.subs( {pz: self.pz_xiv_eqn.rhs}) self.tanalpha_ext = float( N(self.tanalpha_ext_eqn.rhs.subs({eta: self.eta_}))) self.tanbeta_crit = float( N(self.tanbeta_crit_eqn.rhs.subs({eta: self.eta_})))
def round(self, ndigits=0): """Returns a new `Decimal` rounded to this many decimal places.""" scale = sympy.Integer(10 ** ndigits) numer = sympy.numer(self.value) * scale denom = sympy.denom(self.value) return Decimal(int(round(numer / denom)) / scale)
def differential_constants(model, p1, p2, p3): """ Description: This function calculates the differential constants u and q necessary to calculate the tip sample interaction force. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Parameters: :param model: string Model name, e.g. 'Gen. Kelvin Voigt', 'Gen. Maxwell' :param p1: float Either Ge or Jg :param p2: array of floats Either G or J :param pe: array of floats tau - charactersitic times - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Return, function output: retrun: u: array of floats differential constants u0, u1, ... un q: array of floats differential constants q0, q1, ... qn """ s = sym.symbols('s') if model == 'Gen. Kelvin-Voigt': if len(p2) == len(p3): # checks J and tau are same lenght U = p1 + sum(p2[:] / (1.0 + p3[:] * s)) U_n = (U).normal() # writes retardance with common denominator u_n = sym.numer(U_n) # selects the numerator u_n = sym.expand(u_n) # expands each term u_n = sym.collect( u_n, s) # collect the terms with the same exponent of s q_n = sym.denom(U_n) # selects the denominator q_n = sym.expand(q_n) # expands each term q_n = sym.collect( q_n, s) # collect the terms with the same exponent of s q_arr = np.zeros( len(p2) + 1) # initializes array with lenght J, tau + 1 to store q u_arr = np.zeros( len(p2) + 1) # initializes array with lenght J, tau + 1 to store u for i in range(len(p2) + 1): q_arr[i] = q_n.coeff( s, i ) # selects the terms multiplied by s^n which are synonymus for q0, .., qn u_arr[i] = u_n.coeff( s, i ) # selects the terms multiplied by s^n which are synonymus for u0, .., un else: print('input arrays have unequal length') if model == 'Gen. Maxwell': if len(p2) == len(p3): Q = p1 + sum((p2[:] * p3[:]) / (1.0 + p3[:] * s)) Q_n = (Q).normal() # writes retardance with common denominator u_n = sym.denom(Q_n) # selects the denominator u_n = sym.expand(u_n) # expands each term u_n = sym.collect( u_n, s) # collect the terms with the same exponent of s q_n = sym.numer(Q_n) # selects the numerator q_n = sym.expand(q_n) # expands each term q_n = sym.collect( q_n, s) # collect the terms with the same exponent of s q_arr = np.zeros( len(p2) + 1) # initializes array with lenght J, tau + 1 to store q u_arr = np.zeros( len(p2) + 1) # initializes array with lenght J, tau + 1 to store u for i in range(len(p2) + 1): q_arr[i] = q_n.coeff( s, i ) # selects the terms multiplied by s^n which are synonymus for q0, .., qn u_arr[i] = u_n.coeff( s, i ) # selects the terms multiplied by s^n which are synonymus for u0, .., un else: print('input arrays have unequal length') return u_arr, q_arr
def export(self, x): return float(sp.numer(x)) / sp.denom(x)
def zeros(G=None, A=None, B=None, C=None, D=None): ''' Return the zeros of a multivariable transfer function system for with transfer functions or state-space. For transfer functions, Theorem 4.5 (p139) is used. For state-space, the method from Equations 4.66 and 4.67 (p138) is applied. Parameters ---------- G : numpy matrix (n x n) The transfer function G(s) of the system. A, B, C, D : numpy matrix State space parameters Returns ------- pole : array List of poles. Example ------- >>> def G(s): ... return 1 / (s + 2) * numpy.matrix([[s - 1, 4], ... [4.5, 2 * (s - 1)]]) >>> zeros(G) [4.00000000000000] Note ---- Not applicable for a non-squared plant, yet. It is assumed that B,C,D will have values if A is defined. ''' # TODO create a beter function to accept paramters and switch between tf and ss if not G is None: s = sympy.Symbol('s') G = sympy.Matrix(G(s)) # convert to sympy matrix object det = sympy.simplify(G.det()) zero = sympy.solve(sympy.numer(det)) elif not A is None: z = sympy.Symbol('z') top = numpy.hstack((A, B)) bot = numpy.hstack((C, D)) m = numpy.vstack((top, bot)) M = numpy.matrix(m) [rowsA, colsA] = numpy.shape(A) [rowsB, colsB] = numpy.shape(B) [rowsC, colsC] = numpy.shape(C) [rowsD, colsD] = numpy.shape(D) p1 = numpy.eye(rowsA) p2 = numpy.zeros((rowsB, colsB)) p3 = numpy.zeros((rowsC, colsC)) p4 = numpy.zeros((rowsD, colsD)) top = numpy.hstack((p1, p2)) bot = numpy.hstack((p3, p4)) p = numpy.vstack((top, bot)) Ig = sympy.Matrix(p) zIg = z * Ig f = zIg - M zf = f.det() zero = sympy.solve(zf, z) return zero
def apart_fact(Fs): S=0 Ls = apart(Fs).as_ordered_terms() for l in Ls: S += numer(l)/factor(denom(l)) return expand_mul(S)
def define_px_poly_eqn( self, eta_choice: Rational = None, do_ndim: bool = False ) -> None: r""" Define :math:`p_x` polynomial. TODO: remove ref to xiv_0 Define polynomial form of function combining normal-slowness covector components :math:`(p_x,p_z)` (where the latter is given in terms of the vertical erosion rate :math:`\xi^{\downarrow} = -\dfrac{1}{p_z}`) and the erosion model flow component :math:`\varphi(\mathbf{r})` Args: eta_choice (:class:`~sympy.core.numbers.Rational`): value of :math:`\eta` to use instead value given at instantiation; otherwise the latter value is used Attributes: poly_px_xiv_varphi_eqn (:class:`~sympy.polys.polytools.Poly`): :math:`\operatorname{Poly}{\left( \left(\xi^{\downarrow}\right)^{4} \varphi^{4}{\left(\mathbf{r} \right)} p_{x}^{6} - \left(\xi^{\downarrow}\right)^{4} p_{x}^{2} - \left(\xi^{\downarrow}\right)^{2}, p_{x}, domain=\mathbb{Z}\left[\varphi{\left(\mathbf{r} \right)}, \xi^{\downarrow}\right] \right)}` poly_px_xiv_eqn (:class:`~sympy.core.relational.Equality`): :math:`\varphi_0^{4} \left(\xi^{\downarrow{0}}\right)^{4} p_{x}^{6} \left(\varepsilon + \left(\frac{x_{1} - {r}^x}{x_{1}}\right)^{2 \mu}\right)^{4} - \left(\xi^{\downarrow{0}}\right)^{4} p_{x}^{2} - \left(\xi^{\downarrow{0}}\right)^{2} = 0` """ logging.info(f"gme.core.pxpoly.define_px_poly_eqn (ndim={do_ndim})") if do_ndim: # Non-dimensionalized version varphi0_solns = solve( self.sinCi_xih0_eqn.subs({eta: eta_choice}), varphi_0 ) varphi0_eqn = Eq(varphi_0, varphi0_solns[0]) if eta_choice is not None and eta_choice <= 1: tmp_eqn = separatevars( simplify( self.px_xiv_varphi_eqn.subs({eta: eta_choice}) .subs({varphi_r(rvec): self.varphi_rxhat_eqn.rhs}) .subs(e2d(self.px_pxhat_eqn)) .subs(e2d(varphi0_eqn)) ) ) self.poly_pxhat_xiv_eqn = simplify( Eq( ( numer(tmp_eqn.lhs) - denom(tmp_eqn.lhs) * (tmp_eqn.rhs) ) / xiv ** 2, 0, ) ) self.poly_pxhat_xiv0_eqn = self.poly_pxhat_xiv_eqn.subs( {xiv: xiv_0} ).subs(e2d(self.xiv0_xih0_Ci_eqn)) else: tmp_eqn = separatevars( simplify( self.px_xiv_varphi_eqn.subs({eta: eta_choice}) .subs({varphi_r(rvec): self.varphi_rxhat_eqn.rhs}) .subs(e2d(self.px_pxhat_eqn)) .subs(e2d(varphi0_eqn)) ) ) self.poly_pxhat_xiv_eqn = simplify( Eq( ( numer(tmp_eqn.lhs) - denom(tmp_eqn.lhs) * (tmp_eqn.rhs) ) / xiv ** 2, 0, ) ) self.poly_pxhat_xiv0_eqn = simplify( Eq( self.poly_pxhat_xiv_eqn.lhs.subs({xiv: xiv_0}).subs( e2d(self.xiv0_xih0_Ci_eqn) ) / xih_0 ** 2, 0, ) ) else: # Dimensioned version tmp_eqn = simplify(self.px_xiv_varphi_eqn.subs({eta: eta_choice})) if eta_choice is not None and eta_choice <= 1: self.poly_px_xiv_varphi_eqn = poly(tmp_eqn.lhs, px) else: self.poly_px_xiv_varphi_eqn = poly( numer(tmp_eqn.lhs) - denom(tmp_eqn.lhs) * (tmp_eqn.rhs), px ) self.poly_px_xiv_eqn = Eq( self.poly_px_xiv_varphi_eqn.subs(e2d(self.varphi_rx_eqn)), 0 )
def prep_geodesic_eqns(self, parameters: Dict = None): r""" Define geodesic equations. Args: parameters: dictionary of model parameter values to be used for equation substitutions Attributes: gstar_ij_tanbeta_mat (`Matrix`_): :math:`\dots` g_ij_tanbeta_mat (`Matrix`_): :math:`\dots` tanbeta_poly_eqn (:class:`~sympy.core.relational.Equality`): :math:`\dots` where :math:`a := \tan\alpha` tanbeta_eqn (:class:`~sympy.core.relational.Equality`): :math:`\tan{\left(\beta \right)} = \dots` where :math:`a := \tan\alpha` gstar_ij_tanalpha_mat (`Matrix`_): a symmetric tensor with components (using shorthand :math:`a := \tan\alpha`) :math:`g^*[1,1] = \dots` :math:`g^*[1,2] = g^*[2,1] = \dots` :math:`g^*[2,2] = \dots` gstar_ij_mat (`Matrix`_): a symmetric tensor with components (using shorthand :math:`a := \tan\alpha`, and with a particular choice of model parameters) :math:`g^*[1,1] = \dots` :math:`g^*[1,2] = g^*[2,1] = \dots` :math:`g^*[2,2] = \dots` g_ij_tanalpha_mat (`Matrix`_): a symmetric tensor with components (using shorthand :math:`a := \tan\alpha`) :math:`g[1,1] = \dots` :math:`g[1,2] = g[2,1] = \dots` :math:`g[2,2] = \dots` g_ij_mat (`Matrix`_): a symmetric tensor with components (using shorthand :math:`a := \tan\alpha`, and with a particular choice of model parameters) :math:`g[1,1] =\dots` :math:`g[1,2] = g[2,1] = \dots` :math:`g[2,2] = \dots` g_ij_mat_lambdified (function) : lambdified version of `g_ij_mat` gstar_ij_mat_lambdified (function) : lambdified version of `gstar_ij_mat` """ logging.info("gme.core.geodesic.prep_geodesic_eqns") self.gstar_ij_tanbeta_mat = None self.g_ij_tanbeta_mat = None self.tanbeta_poly_eqn = None self.tanbeta_eqn = None self.gstar_ij_tanalpha_mat = None self.gstar_ij_mat = None self.g_ij_tanalpha_mat = None self.g_ij_mat = None self.g_ij_mat_lambdified = None self.gstar_ij_mat_lambdified = None mu_eta_sub = {mu: self.mu_, eta: self.eta_} # if parameters is None: return H_ = self.H_eqn.rhs.subs(mu_eta_sub) # Assume indexing here ranges in [1,2] def p_i_lambda(i): return [px, pz][i - 1] # r_i_lambda = lambda i: [rx, rz][i-1] # rdot_i_lambda = lambda i: [rdotx, rdotz][i-1] def gstar_ij_lambda(i, j): return simplify( Rational(2, 2) * diff(diff(H_, p_i_lambda(i)), p_i_lambda(j))) gstar_ij_mat = Matrix([ [gstar_ij_lambda(1, 1), gstar_ij_lambda(2, 1)], [gstar_ij_lambda(1, 2), gstar_ij_lambda(2, 2)], ]) gstar_ij_pxpz_mat = gstar_ij_mat.subs({varphi_r(rvec): varphi}) g_ij_pxpz_mat = gstar_ij_mat.inv().subs({varphi_r(rvec): varphi}) cosbeta_eqn = Eq(cos(beta), 1 / sqrt(1 + tan(beta)**2)) sinbeta_eqn = Eq(sin(beta), sqrt(1 - 1 / (1 + tan(beta)**2))) sintwobeta_eqn = Eq(sin(2 * beta), cos(beta)**2 - sin(beta)**2) self.gstar_ij_tanbeta_mat = expand_trig( simplify(gstar_ij_pxpz_mat.subs(e2d( self.px_pz_tanbeta_eqn)))).subs(e2d(cosbeta_eqn)) self.g_ij_tanbeta_mat = expand_trig( simplify(g_ij_pxpz_mat.subs(e2d(self.px_pz_tanbeta_eqn)))).subs( e2d(cosbeta_eqn)) tanalpha_beta_eqn = self.tanalpha_beta_eqn.subs(mu_eta_sub) tanbeta_poly_eqn = Eq( numer(tanalpha_beta_eqn.rhs) - tanalpha_beta_eqn.lhs * denom(tanalpha_beta_eqn.rhs), 0, ).subs({tan(alpha): ta}) tanbeta_eqn = Eq(tan(beta), solve(tanbeta_poly_eqn, tan(beta))[0]) self.tanbeta_poly_eqn = tanbeta_poly_eqn self.tanbeta_eqn = tanbeta_eqn # Replace all refs to beta with refs to alpha self.gstar_ij_tanalpha_mat = (self.gstar_ij_tanbeta_mat.subs( e2d(sintwobeta_eqn)).subs(e2d(sinbeta_eqn)).subs( e2d(cosbeta_eqn)).subs(e2d(tanbeta_eqn))).subs(mu_eta_sub) self.gstar_ij_mat = (self.gstar_ij_tanalpha_mat.subs({ ta: tan(alpha) }).subs(e2d(self.tanalpha_rdot_eqn)).subs( e2d(self.varphi_rx_eqn.subs( {varphi_r(rvec): varphi}))).subs(parameters)).subs(mu_eta_sub) self.g_ij_tanalpha_mat = (expand_trig(self.g_ij_tanbeta_mat).subs( e2d(sintwobeta_eqn)).subs(e2d(sinbeta_eqn)).subs( e2d(cosbeta_eqn)).subs(e2d(tanbeta_eqn))).subs(mu_eta_sub) self.g_ij_mat = (self.g_ij_tanalpha_mat.subs({ ta: rdotz / rdotx }).subs(e2d(self.varphi_rx_eqn.subs( {varphi_r(rvec): varphi}))).subs(parameters)).subs(mu_eta_sub) self.g_ij_mat_lambdified = lambdify((rx, rdotx, rdotz, varepsilon), self.g_ij_mat, "numpy") self.gstar_ij_mat_lambdified = lambdify((rx, rdotx, rdotz, varepsilon), self.gstar_ij_mat, "numpy")
# importar libreria matemática simbólica import sympy as sp # Numeros y variables sp.numer(numero) # Numero sp.Symbol('numero') # Numero sp.Symbol('nombre_constante') # Constante sp.Symbol('nombre_variable') # Variable sp.Rational(num1, num2) # Numero racional # Construcción de expresiones con numeros y varaibles x = sp.Symbol('x') y = sp.Symbol('y') -x # Inverso x + y # Suma x - y # Resta x * y # Multiplicación x / y # División x**y # Potencia # Operación de expresiones sp.expand(expresión) # Expandir expresión sp.simplify(expresión) # Simplificar expresión sp.factor(expresión) # Factorizar expresión sp.N(expresión) # Resolver expresión expresión.evalf() # Resolver expresión sp.solve( expresión, variable ) # Solucionar ecuación igualada a 0 (Pueden ser ecuaciones trasendentales) sp.solve( [exp1, exp2, expN], [var1, var2, varN]
def symmetryDetection(allVariables, diffEquations, observables, obsFunctions, initFunctions, predictions, predFunctions, ansatz = 'uni', pMax = 2, inputs = [], fixed = [], parallel = 1, allTrafos = False, timeTrans = False, pretty = True, suffix=''): n = len(allVariables) m = len(diffEquations) h = len(observables) ########################################################################################### ############################# prepare equations #################################### ########################################################################################### sys.stdout.write('Preparing equations...') sys.stdout.flush() # make infinitesimal ansatz infis, diffInfis, rs = makeAnsatz(ansatz, allVariables, m, len(inputs), pMax, fixed) # get infinitesimals of time transformation if timeTrans: rs.append(spy.var('r_T_1')) diffInfiT = rs[-1] allVariables += [T] else: diffInfiT = None # and convert to polynomial infis, diffInfis = transformInfisToPoly(infis, diffInfis, allVariables, rs, parallel, ansatz) diffInfiT = Apoly(diffInfiT, allVariables, rs) ### extract numerator and denominator of equations #differential equations numerators = [0]*m denominators = [0]*m for k in range(m): rational = spy.together(diffEquations[k]) numerators[k] = Apoly(spy.numer(rational), allVariables, None) denominators[k] = Apoly(spy.denom(rational), allVariables, None) #observation functions obsNumerators = [0]*h obsDenominatros = [0]*h for k in range(h): rational = spy.together(obsFunctions[k]) obsNumerators[k] = Apoly(spy.numer(rational), allVariables, None) obsDenominatros[k] = Apoly(spy.denom(rational), allVariables, None) #initial functions if len(initFunctions) != 0: initNumerators = [0]*m initDenominatros = [0]*m for k in range(m): rational = spy.together(initFunctions[k]) initNumerators[k] = Apoly(spy.numer(rational), allVariables, None) initDenominatros[k] = Apoly(spy.denom(rational), allVariables, None) else: initNumerators = [] initDenominatros = [] ### calculate numerator of derivatives of equations #differential equatioins derivativesNum = [0]*m for i in range(m): derivativesNum[i] = [0]*n for k in range(m): for l in range(n): derivativesNum[k][l] = Apoly(None, allVariables, None) derivativesNum[k][l].add(numerators[k].diff(l).mul(denominators[k])) derivativesNum[k][l].sub(numerators[k].mul(denominators[k].diff(l))) #observation functions obsDerivativesNum = [0]*h for i in range(h): obsDerivativesNum[i] = [0]*n for k in range(h): for l in range(n): obsDerivativesNum[k][l] = Apoly(None, allVariables, None) obsDerivativesNum[k][l].add(obsNumerators[k].diff(l).mul(obsDenominatros[k])) obsDerivativesNum[k][l].sub(obsNumerators[k].mul(obsDenominatros[k].diff(l))) #initial functions if len(initFunctions) != 0: initDerivativesNum = [0]*len(initFunctions) for i in range(m): initDerivativesNum[i] = [0]*n for k in range(m): for l in range(n): initDerivativesNum[k][l] = Apoly(None, allVariables, None) initDerivativesNum[k][l].add(initNumerators[k].diff(l).mul(initDenominatros[k])) initDerivativesNum[k][l].sub(initNumerators[k].mul(initDenominatros[k].diff(l))) else: initDerivativesNum = [] sys.stdout.write('\rPreparing equations...done\n') sys.stdout.flush() ########################################################################################### ############################ build linear system ################################### ########################################################################################### sys.stdout.write('\nBuilding system...') sys.stdout.flush() rSystem = buildSystem(numerators, denominators, derivativesNum, obsDerivativesNum, initDenominatros, initDerivativesNum, initFunctions, infis, diffInfis, diffInfiT, allVariables, rs, parallel, ansatz) sys.stdout.write('done\n') sys.stdout.flush() ########################################################################################### ############################## solve system ######################################## ########################################################################################### sys.stdout.write('\nSolving system of size ' + str(rSystem.shape[0]) + 'x' +\ str(rSystem.shape[1]) + '...') sys.stdout.flush() #get LU decomposition from scipy rSystem = scipy.linalg.lu(rSystem, permute_l=True)[1] #calculate reduced row echelon form rSystem, pivots = getrref(rSystem) sys.stdout.write('done\n') sys.stdout.flush() ########################################################################################### ############################# process results ###################################### ########################################################################################### sys.stdout.write('\nProcessing results...') sys.stdout.flush() # calculate solution space sys.stdout.write('\n calculating solution space') sys.stdout.flush() baseMatrix = nullSpace(rSystem, pivots) #substitute solutions into infinitesimals #(and remove the ones with common parameter factors) sys.stdout.write('\n substituting solutions') sys.stdout.flush() infisAll = [] for l in range(baseMatrix.shape[1]): infisTmp = [0]*n for i in range(len(infis)): infisTmp[i] = infis[i].getCopy() infisTmp[i].rs = baseMatrix[:,l] infisTmp[i] = infisTmp[i].as_expr() if timeTrans: infisTmp.append(baseMatrix[-1,l] * T) if allTrafos: infisAll.append(infisTmp) else: if not checkForCommonFactor(infisTmp, allVariables, m): infisAll.append(infisTmp) print('') sys.stdout.write('done\n') sys.stdout.flush() # print transformations print('\n\n') if len(infisAll) != 0: printTransformations(infisAll, allVariables, pretty,suffix) ########################################################################################### ############################ check predictions ##################################### ########################################################################################### if predictions != False: checkPredictions(predictions, predFunctions, infisAll, allVariables) print(time.strftime('\nTotal time: %Hh:%Mm:%Ss', time.gmtime(time.time()-t0)))
res_freq = 1 / s.sqrt(Ls * Cs) imp_at_approx_res = s.simplify(Z.subs(o, res_freq)) imp_at_approx_res # Note that this is a decent thing to do, since we are at least somewhat close to resonance, and we're getting an idea of what our impedance is like near resonance: s.re(imp_at_approx_res).simplify() # So, as we expect, the $C_{ratio}$ does allow us to adjust the real part of our impedance (so we can target 50 $\Omega$), but the value we want will depend very strongly on the built-in resistances in the circuit, which we don't really control. Cn = s.symbols('C_{new}', positive=True, real=True) # Cn = (Cr+1)/Cs s.numer(s.im(Z).subs(Cr, Cn * Cs - 1).simplify()) # ### One ratio per tune # Finally, I give the impedance in terms of the ratio and the tune capacitance Z = -1j / o / Cm + Rm + 1 / (1 / (1j * o * Ls + Rt) + 1 / (-1j / Ct / o + Rt)) Z = Z.subs(Cm, Cr * Ct).simplify() Z # We can solve to find that there is only one ratio that will allow us to tune -- again, this depends not only on the inductance, frequency, and tuning capacitance, but also on the resistance in the tuning circuit soln = s.solve(s.Eq(s.im(Z).simplify(), 0), Cr) assert len(soln) == 1 soln = soln[0] soln