def test_D(): s = symbols('s') C = Rational(3, 2) L = Rational(1, 3) r = Rational(1, 2) # series L, shunt C C0 = Cascade.Series(L * s) C1 = Cascade.Series(1 / (C * s)) C2 = Cascade.Shunt(1 / r) print("test_D") print(C0) print(C1) print(C2) print(C1.hit(C0)) print(C2.hit(C1.hit(C0))) Y = ratsimp(1 / C2.hit(C1.hit(C0)).terminate(0)) print(Y) Z = ratsimp(1 / (Y - 2)) print(Z) Y = ratsimp(Z - s / 3) print(Y)
def heuristics(e, z, z0, dir): rv = None if abs(z0) is S.Infinity: rv = limit(e.subs(z, 1 / z), z, S.Zero, "+" if z0 is S.Infinity else "-") if isinstance(rv, Limit): return elif e.is_Mul or e.is_Add or e.is_Pow or e.is_Function: r = [] for a in e.args: l = limit(a, z, z0, dir) if l.has(S.Infinity) and l.is_finite is None: return elif isinstance(l, Limit): return elif l is S.NaN: return else: r.append(l) if r: rv = e.func(*r) if rv is S.NaN: try: rat_e = ratsimp(e) except PolynomialError: return if rat_e is S.NaN or rat_e == e: return return limit(rat_e, z, z0, dir) return rv
def heuristics(e, z, z0, dir): """Computes the limit of an expression term-wise. Parameters are the same as for the ``limit`` function. Works with the arguments of expression ``e`` one by one, computing the limit of each and then combining the results. This approach works only for simple limits, but it is fast. """ from sympy.calculus.util import AccumBounds rv = None if abs(z0) is S.Infinity: rv = limit(e.subs(z, 1/z), z, S.Zero, "+" if z0 is S.Infinity else "-") if isinstance(rv, Limit): return elif e.is_Mul or e.is_Add or e.is_Pow or e.is_Function: r = [] for a in e.args: l = limit(a, z, z0, dir) if l.has(S.Infinity) and l.is_finite is None: if isinstance(e, Add): m = factor_terms(e) if not isinstance(m, Mul): # try together m = together(m) if not isinstance(m, Mul): # try factor if the previous methods failed m = factor(e) if isinstance(m, Mul): return heuristics(m, z, z0, dir) return return elif isinstance(l, Limit): return elif l is S.NaN: return else: r.append(l) if r: rv = e.func(*r) if rv is S.NaN and e.is_Mul and any(isinstance(rr, AccumBounds) for rr in r): r2 = [] e2 = [] for ii in range(len(r)): if isinstance(r[ii], AccumBounds): r2.append(r[ii]) else: e2.append(e.args[ii]) if len(e2) > 0: e3 = Mul(*e2).simplify() l = limit(e3, z, z0, dir) rv = l * Mul(*r2) if rv is S.NaN: try: rat_e = ratsimp(e) except PolynomialError: return if rat_e is S.NaN or rat_e == e: return return limit(rat_e, z, z0, dir) return rv
def heuristics(e, z, z0, dir): rv = None if abs(z0) is S.Infinity: rv = limit(e.subs(z, 1/z), z, S.Zero, "+" if z0 is S.Infinity else "-") if isinstance(rv, Limit): return elif e.is_Mul or e.is_Add or e.is_Pow or e.is_Function: r = [] for a in e.args: l = limit(a, z, z0, dir) if l.has(S.Infinity) and l.is_finite is None: return elif isinstance(l, Limit): return elif l is S.NaN: return else: r.append(l) if r: rv = e.func(*r) if rv is S.NaN: try: rat_e = ratsimp(e) except PolynomialError: return if rat_e is S.NaN or rat_e == e: return return limit(rat_e, z, z0, dir) return rv
def heuristics(e, z, z0, dir): """Computes the limit of an expression term-wise. Parameters are the same as for the ``limit`` function. Works with the arguments of expression ``e`` one by one, computing the limit of each and then combining the results. This approach works only for simple limits, but it is fast. """ from sympy.calculus.util import AccumBounds rv = None if abs(z0) is S.Infinity: rv = limit(e.subs(z, 1/z), z, S.Zero, "+" if z0 is S.Infinity else "-") if isinstance(rv, Limit): return elif e.is_Mul or e.is_Add or e.is_Pow or e.is_Function: r = [] for a in e.args: l = limit(a, z, z0, dir) if l.has(S.Infinity) and l.is_finite is None: if isinstance(e, Add): m = factor_terms(e) if not isinstance(m, Mul): # try together m = together(m) if not isinstance(m, Mul): # try factor if the previous methods failed m = factor(e) if isinstance(m, Mul): return heuristics(m, z, z0, dir) return return elif isinstance(l, Limit): return elif l is S.NaN: return else: r.append(l) if r: rv = e.func(*r) if rv is S.NaN and e.is_Mul and any(isinstance(rr, AccumBounds) for rr in r): r2 = [] e2 = [] for ii in range(len(r)): if isinstance(r[ii], AccumBounds): r2.append(r[ii]) else: e2.append(e.args[ii]) if len(e2) > 0: e3 = Mul(*e2).simplify() l = limit(e3, z, z0, dir) rv = l * Mul(*r2) if rv is S.NaN: try: rat_e = ratsimp(e) except PolynomialError: return if rat_e is S.NaN or rat_e == e: return return limit(rat_e, z, z0, dir) return rv
def test_C(): s = symbols('s') C = Rational(3, 2) L = Rational(1, 3) r = Rational(1, 2) # series L, shunt C C0 = Cascade.Shunt(1 / (1 / (C * s) + L * s)) print(ratsimp(C0.terminate(r))) X = ratsimp(1 / C0.terminate(r)) print(X) Y = ratsimp(1 / (X - 2)) print(Y) Z = ratsimp(Y - s / 3) print(Z)
def test_pmint_logexp(): if ON_TRAVIS: # See https://github.com/sympy/sympy/pull/12795 skip("Too slow for travis.") f = (1 + x + x * exp(x)) * (x + log(x) + exp(x) - 1) / (x + log(x) + exp(x))**2 / x g = log(x + exp(x) + log(x)) + 1 / (x + exp(x) + log(x)) assert ratsimp(heurisch(f, x)) == g
def test_F(): "Hazony example 5.2.2" s = symbols('s') print("test_F") Z = (s**2 + s + 1) / (s**2 + 2 * s + 2) print(f"Z: {Z}") min_r = (3 - sympy.sqrt(2)) / 4 Z1 = ratsimp(Z - min_r) print(f"Z1: {Z1}") #plot_real_part( sympy.lambdify(s, Z1, "numpy")) Y1 = ratsimp(1 / Z - 1) print(f"Y1: {Y1}") C = Cascade.Shunt(1) Z2 = ratsimp(1 / Y1 - s) print(f"Z2: {Z2}") C = C.hit(Cascade.Series(s)) Y3 = ratsimp(1 / Z2 - s - 1) print(f"Y3: {Y3}") Ytotal = C.hit(Cascade.Shunt(1).hit( Cascade.Shunt(s))).terminate_with_admittance(0) assert sympy.Eq(0, ratsimp(1 / Ytotal - Z)) assert sympy.Eq(1, ratsimp(Ytotal * Z)) Ytotal = C.hit(Cascade.Shunt(s)).terminate_with_admittance(1) assert sympy.Eq(0, ratsimp(1 / Ytotal - Z)) assert sympy.Eq(1, ratsimp(Ytotal * Z)) Ytotal = C.terminate_with_admittance(1 + s) assert sympy.Eq(0, ratsimp(1 / Ytotal - Z)) assert sympy.Eq(1, ratsimp(Ytotal * Z))
def find_riccati_ode(ratfunc, x, yf): y = ratfunc yp = y.diff(x) q1 = rand_rational_function(x, 1, 3) q2 = rand_rational_function(x, 1, 3) while q2 == 0: q2 = rand_rational_function(x, 1, 3) q0 = ratsimp(yp - q1 * y - q2 * y**2) eq = Eq(yf.diff(), q0 + q1 * yf + q2 * yf**2) sol = Eq(yf, y) assert checkodesol(eq, sol) == (True, 0) return eq, q0, q1, q2
def heuristics(e, z, z0, dir): from sympy.calculus.util import AccumBounds rv = None if abs(z0) is S.Infinity: rv = limit(e.subs(z, 1/z), z, S.Zero, "+" if z0 is S.Infinity else "-") if isinstance(rv, Limit): return elif e.is_Mul or e.is_Add or e.is_Pow or e.is_Function: r = [] for a in e.args: l = limit(a, z, z0, dir) if l.has(S.Infinity) and l.is_finite is None: if isinstance(e, Add): m = factor_terms(e) if not isinstance(m, Mul): # try together m = together(m) if not isinstance(m, Mul): # try factor if the previous methods failed m = factor(e) if isinstance(m, Mul): return heuristics(m, z, z0, dir) return return elif isinstance(l, Limit): return elif l is S.NaN: return else: r.append(l) if r: rv = e.func(*r) if rv is S.NaN and e.is_Mul and any(isinstance(rr, AccumBounds) for rr in r): r2 = [] e2 = [] for ii in range(len(r)): if isinstance(r[ii], AccumBounds): r2.append(r[ii]) else: e2.append(e.args[ii]) if len(e2) > 0: e3 = Mul(*e2).simplify() l = limit(e3, z, z0, dir) rv = l * Mul(*r2) if rv is S.NaN: try: rat_e = ratsimp(e) except PolynomialError: return if rat_e is S.NaN or rat_e == e: return return limit(rat_e, z, z0, dir) return rv
def test_pmint_rat(): # TODO: heurisch() is off by a constant: -3/4. Possibly different permutation # would give the optimal result? def drop_const(expr, x): if expr.is_Add: return Add(*[arg for arg in expr.args if arg.has(x)]) else: return expr f = (x**7 - 24 * x**4 - 4 * x**2 + 8 * x - 8) / (x**8 + 6 * x**6 + 12 * x**4 + 8 * x**2) g = (4 + 8 * x**2 + 6 * x + 3 * x**3) / (x**5 + 4 * x**3 + 4 * x) + log(x) assert drop_const(ratsimp(heurisch(f, x)), x) == g
def test_E(): "Chop Chop example" s = symbols('s') print("test_E") Z = (2 * s**2 + 2 * s + 1) / (s * (s**2 + s + 1)) print(f"Z: {Z}") Z = ratsimp(Z) print(f"Z: {Z}") Z = ratsimp(Z - 1 / s) print(f"Z-1/s: {Z}") C = Cascade.Series(1 / s) Y = ratsimp(1 / Z - s) print(f"Y: {Y}") C = C.hit(Cascade.Shunt(s)) Z = ratsimp(1 / Y) print(f"Z: {Z-1-s}") C = C.hit(Cascade.Series(1 + s)).terminate(0) print(ratsimp(C))
def heuristics(e, z, z0, dir): rv = None if abs(z0) is S.Infinity: rv = limit(e.subs(z, 1 / z), z, S.Zero, "+" if z0 is S.Infinity else "-") if isinstance(rv, Limit): return elif e.is_Mul or e.is_Add or e.is_Pow or e.is_Function: r = [] for a in e.args: l = limit(a, z, z0, dir) if l.has(S.Infinity) and l.is_finite is None: if isinstance(e, Add): m = factor_terms(e) if not isinstance(m, Mul): # try together m = together(m) if not isinstance( m, Mul): # try factor if the previous methods failed m = factor(e) if isinstance(m, Mul): return heuristics(m, z, z0, dir) return return elif isinstance(l, Limit): return elif l is S.NaN: return else: r.append(l) if r: rv = e.func(*r) if rv is S.NaN: try: rat_e = ratsimp(e) except PolynomialError: return if rat_e is S.NaN or rat_e == e: return return limit(rat_e, z, z0, dir) return rv
def heuristics(e, z, z0, dir): rv = None if abs(z0) is S.Infinity: rv = limit(e.subs(z, 1/z), z, S.Zero, "+" if z0 is S.Infinity else "-") if isinstance(rv, Limit): return elif e.is_Mul or e.is_Add or e.is_Pow or e.is_Function: r = [] for a in e.args: l = limit(a, z, z0, dir) if l.has(S.Infinity) and l.is_finite is None: if isinstance(e, Add): m = factor_terms(e) if not isinstance(m, Mul): # try together m = together(m) if not isinstance(m, Mul): # try factor if the previous methods failed m = factor(e) if isinstance(m, Mul): return heuristics(m, z, z0, dir) return return elif isinstance(l, Limit): return elif l is S.NaN: return else: r.append(l) if r: rv = e.func(*r) if rv is S.NaN: try: rat_e = ratsimp(e) except PolynomialError: return if rat_e is S.NaN or rat_e == e: return return limit(rat_e, z, z0, dir) return rv
def test_ratsimp(): f, g = 1 / x + 1 / y, (x + y) / (x * y) assert f != g and ratsimp(f) == g f, g = 1 / (1 + 1 / x), 1 - 1 / (x + 1) assert f != g and ratsimp(f) == g f, g = x / (x + y) + y / (x + y), 1 assert f != g and ratsimp(f) == g f, g = -x - y - y**2 / (x + y) + x**2 / (x + y), -2 * y assert f != g and ratsimp(f) == g f = (a * c * x * y + a * c * z - b * d * x * y - b * d * z - b * t * x * y - b * t * x - b * t * z + e * x) / (x * y + z) G = [ a * c - b * d - b * t + (-b * t * x + e * x) / (x * y + z), a * c - b * d - b * t - (b * t * x - e * x) / (x * y + z) ] assert f != g and ratsimp(f) in G A = sqrt(pi) B = log(erf(x) - 1) C = log(erf(x) + 1) D = 8 - 8 * erf(x) f = A * B / D - A * C / D + A * C * erf(x) / D - A * B * erf( x) / D + 2 * A / D assert ratsimp(f) == A * B / 8 - A * C / 8 - A / (4 * erf(x) - 4)
def test_pmint_erf(): f = exp(-x**2) * erf(x) / (erf(x)**3 - erf(x)**2 - erf(x) + 1) g = sqrt(pi) * log(erf(x) - 1) / 8 - sqrt(pi) * log(erf(x) + 1) / 8 - sqrt( pi) / (4 * erf(x) - 4) assert ratsimp(heurisch(f, x)) == g
def test_I(): "Hazony problem 5.3.a" s, k = symbols('s k') w = symbols('w', real=True) pprint("test_I") Z = (s**3 + 3 * s**2 + s + 1) / (s**3 + s**2 + 3 * s + 1) pprint(f"Z: {Z}") #plot_real_part( sympy.lambdify(s, Z, "numpy")) real_part = cancel(sympy.re(Z.subs({s: sympy.I * w}))) print(f"real_part: {real_part}") roots = sympy.solveset(real_part, w) print(f"roots for w: {roots}") #plot( sympy.lambdify(w, real_part, "numpy")) w0 = 1 target0 = radsimp(Z.subs({s: sympy.I * w0}) / (sympy.I * w0)) print(f"target: {target0}") target1 = radsimp(Z.subs({s: sympy.I * w0}) * (sympy.I * w0)) print(f"target: {target1}") assert target0 > 0 eq = sympy.Eq(Z.subs({s: k}) / k, target0) #assert target1 > 0 #eq = sympy.Eq( Z.subs({s:k})*k, target1) roots = sympy.solveset(eq, k) print(f"roots for k: {roots}") k0 = Rational(1, 1) Z_k0 = Z.subs({s: k0}) print(k0, Z_k0) print(k0.evalf(), Z_k0.evalf()) den = cancel((k0 * Z_k0 - s * Z)) print(f"den factored: {sympy.factor(den)}") num = cancel((k0 * Z - s * Z_k0)) print(f"num factored: {sympy.factor(num)}") eta = cancel(num / den) print(k0, Z_k0, eta) print("normal") Z0 = eta * Z_k0 print(f"Z0: {Z0}") Y1 = ratsimp(1 / Z0 - 1) print(f"Y1: {Y1}") C = Cascade.Shunt(1) Z2 = ratsimp(1 / Y1 - s / 2 - 1 / (2 * s)) print(f"Z2: {Z2}") C = C.hit(Cascade.Series(s / 2)) C = C.hit(Cascade.Series(1 / (2 * s))) eta_Z_k0 = cancel(C.terminate(0)) print(f"eta_Z_k0: {eta_Z_k0}") assert sympy.Eq(cancel(eta_Z_k0 - Z0), 0) print("recip") Z0 = cancel(Z_k0 / eta) print(f"Z0: {Z0}") Z1 = ratsimp(Z0 - 1) print(f"Z1: {Z1}") C = Cascade.Series(1) Y2 = ratsimp(1 / Z1 - s / 2 - 1 / (2 * s)) print(f"Y2: {Y2}") C = C.hit(Cascade.Shunt(s / 2)) C = C.hit(Cascade.Shunt(1 / (2 * s))) eta_over_Z_k0 = cancel(1 / C.terminate_with_admittance(0)) print(f"eta_over_Z_k0: {eta_over_Z_k0}") assert sympy.Eq(cancel(eta_over_Z_k0 - Z0), 0) def p(a, b): return a * b / (a + b) constructed_Z = cancel( p(eta_Z_k0, (k0 * Z_k0) / s) + p(eta_over_Z_k0, (Z_k0 * s) / k0)) print(f"constructed_Z: {constructed_Z}") assert sympy.Eq(cancel(constructed_Z - Z), 0)
def test_J(): "Second problem in Guillemin" s, k = symbols('s k') w = symbols('w', real=True) pprint("test_I") Z = (s**2 + s + 8) / (s**2 + 2 * s + 2) pprint(f"Z: {Z}") Y = 1 / Z #plot_real_part( sympy.lambdify(s, Y, "numpy")) real_part = cancel(sympy.re(Y.subs({s: sympy.I * w}))) print(f"real_part: {real_part}") roots = sympy.solveset(real_part, w) print(f"roots for w: {roots}") #plot( sympy.lambdify(w, real_part, "numpy")) w0 = 2 target0 = radsimp(Y.subs({s: sympy.I * w0}) / (sympy.I * w0)) print(f"target: {target0.evalf()}") target0 = Rational(1, 2) target1 = radsimp(Y.subs({s: sympy.I * w0}) * (sympy.I * w0)) print(f"target: {target1.evalf()}") target1 = Rational(2, 1) assert target0 > 0 eq = sympy.Eq(Y.subs({s: k}) / k, target0) #assert target1 > 0 #eq = sympy.Eq( Z.subs({s:k})*k, target1) roots = sympy.solveset(eq, k) print(f"roots for k: {roots}") k0 = Rational(1, 1) Y_k0 = Y.subs({s: k0}) print(k0, Y_k0) print(k0.evalf(), Y_k0.evalf()) den = cancel((k0 * Y_k0 - s * Y)) print(f"den factored: {sympy.factor(den)}") num = cancel((k0 * Y - s * Y_k0)) print(f"num factored: {sympy.factor(num)}") eta = cancel(num / den) print(k0, Y_k0, eta) print("normal") Y0 = eta * Y_k0 print(f"Y0: {Y0}") Z1 = ratsimp(1 / Y0 - 4) print(f"Z1: {Z1}") C = Cascade.Series(4) Y2 = ratsimp(1 / Z1) print(f"Y2: {Y2}") C = C.hit(Cascade.Shunt(s / 10)) C = C.hit(Cascade.Shunt(2 / (5 * s))) eta_Y_k0 = cancel(C.terminate_with_admittance(0)) print(f"eta_Y_k0: {eta_Y_k0}") assert sympy.Eq(cancel(eta_Y_k0 - Y0), 0) print("recip") Y0 = ratsimp(Y_k0 / eta) print(f"Y0: {Y0}") Y1 = ratsimp(Y0 - 1) print(f"Y1: {Y1}") C = Cascade.Shunt(1) Z2 = ratsimp(1 / Y1 - 2 * s / 5 - 8 / (5 * s)) print(f"Z2: {Z2}") C = C.hit(Cascade.Series(2 * s / 5)) C = C.hit(Cascade.Series(8 / (5 * s))) eta_over_Y_k0 = cancel(1 / C.terminate(0)) print(f"eta_over_Y_k0: {eta_over_Y_k0}") assert sympy.Eq(cancel(eta_over_Y_k0 - Y0), 0) def p(a, b): return a * b / (a + b) constructed_Y = cancel( p(eta_Y_k0, (k0 * Y_k0) / s) + p(eta_over_Y_k0, (Y_k0 * s) / k0)) print(f"constructed_Y: {constructed_Y}") assert sympy.Eq(cancel(constructed_Y - Y), 0)
def test_ratsimp(): assert ratsimp(A*B - B*A) == A*B - B*A