Sympy simplification of polynomial with complex coefficients - python

Working on a problem with polynomials with complex coefficients,
I am stuck with the following problem:
Let's say I have a polynomial P = λ^16*z + λ^15*z^2, where λ is complex.
I want to simplify having the following constraint: λ^14 = 1.
So, plugging in, we should get:
P = λ^2*z + λ*z^2.
I have tried P.subs(λ**14,1) but it doesn't work, because it assumes λ is real I guess. So it returns the original expression: P = λ^16*z + λ^15*z^2, without factoring out λ^14...

I don't know any simple way to achieve what you want in sympy, but you could substitute each value explicitly:
p = (λ**16)*z + (λ**15)*(z**2)
p = p.subs(λ**16, λ**2).subs(λ**15, λ**1)
>>> z**2*λ + z*λ**2
Why subs fails to work here:
subs only substitutes an expression x**m in x**n when m is a factor of n, e.g.:
p.subs(λ, 1)
>>> z**2 + z
p.subs(λ**2, 1)
>>> z**2*λ**15 + z
p.subs(λ**3, 1)
>>> z**2 + z*λ**16
p.subs(λ**6, 1)
>>> z**2*λ**15 + z*λ**16
etc.

If you assume that λ is real, this works:
lambda_, z = sym.symbols('lambda z', real=True)
print((lambda_**16*z + lambda_**15*z**2).subs(lambda_**14, 1))
z**2 + z
Edit:
It shouldn't actually work anyway because λ may be negative. What you want is only true if λ is a positive number.

You can use the ratsimpmodprime() function to reduce a polynomial modulo a set of other polynomials. There is also the reduce() function, which does something similar.
>>> P = λ**16*z + λ**15*z**2
>>> ratsimpmodprime(P, [λ**14 - 1])
z**2*λ + z*λ**2

This works:
P.simplify().subs(λ**15,1).expand()

Related

symbolic solution of linear equations using Sympy

Basically I have [5x5][5x1]=[0] and would like to have the symbolic expression of the solution.
Here is my code.
from sympy import symbols, solve
gm1, gm2, gm4 = symbols(['gm1', 'gm2', 'gm4'])
gds1, gds2, gds3, gds4, gds5 = symbols(['gds1', 'gds2', 'gds3', 'gds4', 'gds5'])
s = symbols(['s'])
Cd, CF , Cin, Ct = symbols(['Cd', 'CF', 'Cin', 'Ct'])
K = symbols(['K'])
vb, vc, ve, vout, iin = symbols(['vb', 'vc', 've', 'vout', 'iin'])
sol = solve([-(gds1+gds3+(s*Cd))*vb + (gm1+gds1)*ve + -gm1*vout, \
-gm4*vb + (gds4-gds2-(s*Cin)-(s*CF))*vc + (gds2+gm2)*ve + s*CF*vout + iin, \
gds1*vb + gds2*vc + (-(s*Ct)-gds5-gds1-gm1-gm2-gds2)*ve + gm1*vout, \
K*vc + vout], [vout])
print(sol)
but, I got this error
TypeError: can't multiply sequence by non-int of type 'Symbol'
From here, symbolic multiplication seems working just fine.
I am not sure whether I describe my problem in a way that does not comply with Sympy or something else.
What did I miss here?
The problem is in the assignment of the single symbols s and K. If instead you do:
s, K = symbols(['s', 'K'])
Or:
s = symbols('s')
K = symbols('K')
Whether you get the right answer or not is another matter :)
When you pass a list to symbols you get a list back. You can unpack that like [s] = symbols(['s']) or you can just pass a string of space or comma separated strings like x, y = symbols('x y') or x, y = symbols(','.join(['x', 'y']).
If you select manual=True you will get a solution vout=K*vc which sets the 4th equation to 0. But that was almost obvious, right? And you didn't need the other 3 equations to tell you that. So go ahead and pick up to 3 other variables for which you want to solve. There are lots of possibilities:
>>> from sympy.functions.combinatorial.numbers import nC
>>> allsym = Tuple(*eqs).free_symbols
>>> nfree = len(allsym) - 1 # always take vout
>>> print(nC(nfree, 3)) # want 3 others
816
For example, selecting (vout, gds4, gm1, gds5) gives a solution of
[{gds4: (CF*K*s*vc + CF*s*vc + Cin*s*vc + gds2*vc -
gds2*ve - gm2*ve + gm4*vb - iin)/vc,
gm1: (Cd*s*vb + gds1*vb - gds1*ve + gds3*vb)/(K*vc + ve),
gds5: -(Cd*s*vb + Ct*s*ve - gds2*vc + gds2*ve + gds3*vb + gm2*ve)/ve,
vout: -K*vc}]

How to order terms in polynomial expression (sympy, python) according to increasing degree (univariate case)?

In sympy (python) it seems that, by default, terms in univarate polynomials are ordered according to decreasing degrees: highest degree first, then second to highest, and so on. So, for example, a polynomial like
x + 1 + x^3 + 3x^6
will be printed out as 3x^6 + x^3 + x + 1.
I would like to reverse this order of polynomial terms in sympy to be increasing in the degrees. For the same example, the print-out should read 1 + x + x^3 + 3x^6. A solution that globally changes some parameter in program preamble is preferred but other options are also welcome.
Here is an MWE to play around with. It is different from the actual program I am working with. One part of the actual program (not the MWE) is printing out a list of recursively defined polynomials, e.g., P_n(x) = P_(n-1)(x) + a_n * x^n. It is easier for me to compare them when they are ordered by increasing degree. This is the motivation to change the order; doing it globally would probably just keep the code more readable (aesthetically pleasing). But the MWE is just for the same simple polynomial given in example above.
import sympy as sym
from sympy import *
x = sym.Symbol('x')
polynomial = x + 1 + x**3 + 3*x**6
print(polynomial)
Output of MWE:
>>> 3*x**6 + x**3 + x + 1
Desired output for MWE:
>>> 1 + x + x**3 + 3*x**6
You can get the leading term using sympy.polys.polytools.LT:
LT(3x ** 6 + x ** 3 + x + 1) == 3x**6
So at least you can churn out terms recursively and print it in your own way.
Unfortunately I’ve been trying to find some way to print the terms in some fix order for a long while and find no solution better than this
It's seems that there isn't an explicit way to do that and I found this approach to the problem:
to modify the print-representation of the object you can subclass its type and override the corresponding printing method (for LaTeX, MathML, ...) see documentation.
In this case _sympystr is used to "generates readable representations of SymPy expressions."
Here a basic implementation:
from sympy import Poly, symbols, latex
class UPoly(Poly):
"""Modified univariative polynomial"""
def _sympystr(self, printer) -> str:
"""increasing order of powers"""
if self.is_multivariate: # or: not self.is_univariate
raise Exception('Error, Polynomial is not univariative')
x = next(iter(expr.free_symbols))
poly_print = ""
for deg, coef in sorted(self.terms()):
term = coef * x**deg[0]
if coef.is_negative:
term = -term # fix sign
poly_print += " - "
else:
poly_print += " + "
poly_print += printer._print(term)
return poly_print.lstrip(" +-")
def _latex(self, printer):
return latex(self._sympystr(printer)) # keep the order
x = symbols('x')
expr = 2*x + 6 - x**5
up = UPoly(expr)
print(up)
#6 + 2*x - x**5
print(latex(up))
#6 + 2 x - x^{5}

Sympy - got two solutions from trigonometric equation, I was expecting only one

I'm trying to solve a trigonometric equation with sympy. I'm having issues understanding what sympy is doing: I was expecting only one solution, instead I got two. Here is the code:
import sympy as sp
sp.var("a, b, c, d, z")
myeq = sp.Eq(c * sp.sin(a * (b / 2 - z)) + d * sp.cos(a * (b / 2 - z)), 0)
sol = sp.solve(myeq, z)
print(sol)
Output: [(a*b - 4*atan((c - sqrt(c**2 + d**2))/d))/(2*a), (a*b - 4*atan((c + sqrt(c**2 + d**2))/d))/(2*a)]
The solution I was expecting is: [b / 2 + atan(c / d) / a]
What am I missing? For this specific case, is it possible to obtain a single solution?
If you rearrange your equation to combine the sin and cos into tan you will get what you are looking for:
>>> solve(c/d*tan(a*(b/2-z))-1,z)
[b/2 - atan(d/c)/a]
If you don't, SymPy will rewrite and solve in terms of exp...and in that case, as you can verify, it will be quadratic in exp(l*a*z).
An attempt at rewriting a two-arg sum as a ratio could be done like this:
>>> def ratio(eq):
... if isinstance(eq, Eq):
... eq=eq.rewrite(Add)
... A, B = eq.as_two_terms()
... if not A.is_Add and not B.is_Add:
... return Eq(A/B, 1)
>>> trigsimp(ratio(eq))
Eq(c*tan(a*b/2 - a*z)/d, 1)
(The function returns None if there aren't two terms to work with.) As you can see, in this case you get a new equation which will solve as you desired.

Smart rewriting of expressions in sympy

I found this to be tricky to explain, but I'll do my best through an example.
Consider the expression assigned to the variable grad below
from sympy import *
a, x, b = symbols("a x b")
y_pred = a * x
loss = log(1 + exp(- b * y_pred))
grad = diff(loss, x, 1)
grad has the following expression:
-a*b*exp(-a*b*x)/(1 + exp(-a*b*x))
Now I want to manipulate grad in two ways.
1) I want sympy to try rewrite the expression grad such that none of its terms look like
exp(-a*b*x)/(1 + exp(-a*b*x)).
2) I also want it to try to rewrite the expression such that it has at least one term that look like this 1./(1 + exp(a*b*x)).
So at the end, grad becomes:
-a*b/(1 + exp(a*b*x)
Note that 1./(1 + exp(a*b*x)) is equivalent to exp(-a*b*x)/(1 + exp(-a*b*x)) but I don't want to mention that to sympy explicitly :).
I'm not sure if this is feasible at all, but it would be interesting to know whether it's possible to do this to some extent.
cancel does this
In [16]: cancel(grad)
Out[16]:
-a⋅b
──────────
a⋅b⋅x
ℯ + 1
This works because it sees the expression as -a*b*(1/A)/(1 + 1/A), where A = exp(a*b*x), and cancel rewrites rational functions as canceled p/q (see the section on cancel in the SymPy tutorial for more information).
Note that this only works because it uses A = exp(a*b*x) instead of A = exp(-a*b*x). So for instance, cancel won't do the similar simplification here
In [17]: cancel(-a*b*exp(a*b*x)/(1 + exp(a*b*x)))
Out[17]:
a⋅b⋅x
-a⋅b⋅ℯ
────────────
a⋅b⋅x
ℯ + 1
Are you just looking for simplify?
>>> grad
-a*b*exp(-a*b*x)/(1 + exp(-a*b*x))
>>> simplify(grad)
-a*b/(exp(a*b*x) + 1)

Differentiation in python using Sympy

How do i implement this kind of equation in python dC/dt = r + kI - dC where the left hand side are constants and the right hand side are varibles?
i am relatively new to python and as such can't really do much.
from sympy.solvers import ode
r=float(input("enter r:"))
k=float(input("enter k:"))
I=float(input("enter I:"))
d=float(input("enter d:"))
C=float(input("enter C:"))
dC/dt=x
x=r + kI-dC
print(x)
what it just does equate the values of x and not any differential, would like help getting this to work.
if possible i would like to get answer specifying the using of sympy,
but all answers are truly appreciated.
You asigned values to all the variables that are on the rhs of x so when you show x you see the value that it took on with the variables that you defined. Rather than input values, why not try solve the ode symbolically if possible?
>>> from sympy import *
>>> var('r k I d C t')
(r, k, I, d, C, t)
>>> eq = Eq(C(t).diff(t), r + k*I + d*C(t)) # note d*C(t) not d*C
>>> ans = dsolve(eq); ans
C(t) == (-I*k - r + exp(d*(C1 + t)))/d
Now you can substitute in values for the variables to see the result:
>>> ans.subs({k: 0})
C(t) == (-r + exp(d*(C1 + t)))/d

Categories