I am now making an ODE solver using Sympy. It can solve = Separable, Linear, Bernoulli, Second-Order Homogenous, Exact and Non Exact Equation, Nth Order Homogenous DE, Lagrange, Clairaut, 2nd and 3rd Order Nonhomogenous Diff. Eq, Can use undetermined coeff. in the form of: exp(x), cos(x), sin(x), x**n, exp(x)cos(x).
But for 2 * cos(x), 3 * exp(x) the code does not understand when the code is multiplied by a number. Here is my question. How can I remove every coefficients. Are there any function or method? Thanks in advance.
There are lots of ways depending on exactly what you are doing but e.g.:
In [124]: f = 2 * cos(x)
In [125]: f
Out[125]: 2⋅cos(x)
In [126]: c, m = f.as_coeff_Mul()
In [127]: c
Out[127]: 2
In [128]: m
Out[128]: cos(x)
Related
I am not pratice in Sympy manipulation.
I need to find roots on particular poly:
-4x**(11/2)-24x**(9/2)-16x**(7/2)+2x**(5/2)+16x**(5)+23x**(4)+5x**(3)-x**(2)
I verified that I have 2 real solution and I find one of them with Sympy function
nsolve(mypoly,x,1).
Why the previous step doesn't look the other?
How can I proceed to find ALL roots?
Thank you to all for assistance
A.
To my knowledge, nsolve looks in the proximity of the provided initial guess to find one root for each equations.
I would plot the expression to find suitable initial guesses:
from sympy import *
from sympy.plotting import PlotGrid
expr = -4*x**(S(11)/2)-24*x**(S(9)/2)-16*x**(S(7)/2)+2*x**(S(5)/2)+16*x**(5)+23*x**(4)+5*x**(3)-x**(2)
p1 = plot(expr, (x, 0, 0.5), adaptive=False, n=1000, ylim=(-0.01, 0.05), show=False)
p2 = plot(expr, (x, 0, 5), adaptive=False, n=1000, ylim=(-200, 200), show=False)
PlotGrid(1, 2, p1, p2)
Now, we can do:
nsolve(expr, x, 0.2)
# out: 0.169003536680445
nsolve(expr, x, 4)
# out: 4.28968831654177
EDIT: to find all roots (even the complex one), we can:
compute the derivative of the expression.
convert both the expression and the derivative to numerical functions with sympy's lambdify.
visually inspect the expression in the complex plane to determine good initial values for the root finding algorithm. I'm going to use this plotting module, SymPy Plotting Backend which exposes a very handy function, plot_complex, to generate domain coloring plots. In particular, I will plot alternating black and white stripes corresponding to modulus.
use scipy's newton method to compute the actual roots. EDIT: I just discovered that nsolve works too :)
# step 1 and 2
f = lambdify(x, expr)
f_der = lambdify(x, expr.diff(x))
# step 3
from spb import plot_complex
r = (x, -1-0.8j, 4.5+0.8j)
w = r[1].real - r[2].real
h = r[1].imag - r[2].imag
# number of discretization points, watch out memory usage
n1 = 1500
n2 = int(h / w * n1)
plot_complex(expr, r, {"interpolation": "spline36"}, grid=False, coloring="e", n1=n1, n2=n2, size=(10, 5))
In the above picture we see circular stripes getting bigger and deforming. The center of these circular stripes represent a pole or a zero. But this is an easy case: there are no poles. So, from the above pictures we count 7 zeros. We already know 3, the two computed above and the value 0. Let's find the others:
from scipy.optimize import newton
r1 = newton(f, x0=-0.9+0.1j, fprime=f_der)
r2 = newton(f, x0=-0.9-0.1j, fprime=f_der)
r3 = newton(f, x0=0.6+0.6j, fprime=f_der)
r4 = newton(f, x0=0.6-0.6j, fprime=f_der)
for r in (r1, r2, r3, r4):
print(r, ": is it a zero?", expr.subs(x, r).evalf())
# out:
# (-0.9202719950522663+0.09010409402273806j) : is it a zero? -8.21787666002984e-15 + 2.06697764417957e-15*I
# (-0.9202719950522663-0.09010409402273806j) : is it a zero? -8.21787666002984e-15 - 2.06697764417957e-15*I
# (0.6323265751497729+0.6785871500619469j) : is it a zero? -2.2103533615688e-15 - 2.77549897301442e-15*I
# (0.6323265751497729-0.6785871500619469j) : is it a zero? -2.2103533615688e-15 + 2.77549897301442e-15*I
As you can see, inserting those values into the original expression get values very very close to zero. It is perfectly normal to see these kind of errors.
I just discovered that you can use also use nsolve instead of newton to compute complex roots. This makes step 1 and 2 unnecessary.
nsolve(expr, x, -0.9+0.1j)
# out: −0.920271995052266+0.0901040940227375𝑖
In Sympy one can obtain the representation of a polynomial's reduction by a Grobner basis:
from sympy import groebner, expand
from sympy.abc import x, y
f = 2*x**4 - x**2 + y**3 + y**2
G = groebner([x**3 - x, y**3 - y])
Q, r = G.reduce(f)
assert f == expand(sum(q*g for q, g in zip(Q, G)) + r)
But what I'm looking for is a way to get the expression of the elements of a Groebner basis in terms of the polynomials defining it, essentially just storing the computations performed in the Buchberger algorithm used in producing the basis.
For example
groebner([2*x+3*y+5, 3*x+5*y+2, 5*x+2*y+3]) # GroebnerBasis([1], x, y, domain='ZZ', order='lex')
It indicates that these three polynomials generate the unit ideal, but I would like an explicit combination of these polynomials that equals 1. In the example given it is a linear combination, but I would like a method that works with nonlinear as well.
In the first example I obtained Q,r. In the second example I obtained the analog of the remainder r but I would like the polynomials Q realizing it.
Similarly, the method G.contains() will indicate if the ideal contains the polynomial, but it won't tell you how to produce it. Is there a way to do this too?
Motivation. It is well known that generating function for Catalan numbers satisfies quadratic equation. I would like to have first several coefficients of a function, implicitly defined by an algebraic equation (not necessarily a quadratic one!).
Example.
import sympy as sp
sp.init_printing() # math as latex
from IPython.display import display
z = sp.Symbol('z')
F = sp.Function('F')(z)
equation = 1 + z * F**2 - F
display(equation)
solution = sp.solve(equation, F)[0]
display(solution)
display(sp.series(solution))
Question. The approach where we explicitly solve the equation and then expand it as power series, works only for low-degree equations. How to obtain first coefficients of formal power series for more complicated algebraic equations?
Related.
Since algebraic and differential framework may behave differently, I posted another question.
Sympy: how to solve differential equation in formal power series?
I don't know a built-in way, but plugging in a polynomial for F and equating the coefficients works well enough. Although one should not try to find all coefficients at once from a large nonlinear system; those will give SymPy trouble. I take iterative approach, first equating the free term to zero and solving for c0, then equating 2nd and solving for c1, etc.
This assumes a regular algebraic equation, in which the coefficient of z**k in the equation involves the k-th Taylor coefficient of F, and does not involve higher-order coefficients.
from sympy import *
z = Symbol('z')
d = 10 # how many coefficients to find
c = list(symbols('c:{}'.format(d))) # undetermined coefficients
for k in range(d):
F = sum([c[n]*z**n for n in range(k+1)]) # up to z**k inclusive
equation = 1 + z * F**2 - F
coeff_eqn = Poly(series(equation, z, n=k+1).removeO(), z).coeff_monomial(z**k)
c[k] = solve(coeff_eqn, c[k])[0]
sol = sum([c[n]*z**n for n in range(d)]) # solution
print(series(sol + z**d, z, n=d)) # add z**d to get SymPy to print as a series
This prints
1 + z + 2*z**2 + 5*z**3 + 14*z**4 + 42*z**5 + 132*z**6 + 429*z**7 + 1430*z**8 + 4862*z**9 + O(z**10)
Using Eigen, I have a Matrix3Xd (3 rows, n columns). I would like to get the squared norm of all columns
to be clearer, lets say I have
Matrix3Xd a =
1 3 2 1
2 1 1 4
I would like to get the squared norm of each column
squaredNorms =
5 10 5 17
I wanted to take advantage of matrix computation instead of going through a for loop doing the computation myself.
What I though of was
squaredNorms = (A.transpose() * A).diagonal()
This works, but I am afraid of performance issues: A.transpose() * A will be a nxn matrix (potentially million of elements), when I only need the diagonal.
Is Eigen clever enough to compute only the coefficients I need?
What would be the most efficient way to achieve squareNorm computation on each column?
The case of (A.transpose() * A).diagonal() is explicitly handled by Eigen to enforce lazy evaluation of the product expression nested in a diagonal-view. Therefore, only the n required diagonal coefficients will be computed.
That said, it's simpler to call A.colwise().squaredNorm() as well noted by Eric.
This will do what you want.
squaredNorms = A.colwise().squaredNorm();
https://eigen.tuxfamily.org/dox/group__QuickRefPage.html
Eigen provides several reduction methods such as: minCoeff() , maxCoeff() , sum() , prod() , trace() *, norm() *, squaredNorm() *, all() , and any() . All reduction operations can be done matrix-wise, column-wise or row-wise .
Please suggest subroutine program to evaluate the polynomial ax 3 + bx 2 + cx + d with minimum number of operations for given values of a,b,c and d.
If using bisection method is there any way to guess limit values dynamically.
The fastest method to evaluate f(x)=ax³+bx²+cx+d is the Horner scheme which uses parantheses to transform the expression to
f(x) = ((a*x+b)*x+c)*x+d
For finding roots note that at x=-R and x=+R where
R = 1+max(abs(b), abs(c), abs(d))/abs(a)
the polynomial will have non-zero values of opposite sign. Use bisection or better regula-falsi with the Illinois-anti-stalling modification.