How to get repeating roots in sympy? - python

from sympy import Symbol
from sympy.solvers import solveset
x = Symbol('x')
equation = x**2 - 2*x + 1
result = solveset(equation, x)
Here, result evaluates to FiniteSet(1).
Since this is a quadratic equation, there must be 2 roots.
But also, since the two roots are the same (1 in this case), the result returns it only once.
For the purpose of solving linear recurrences, I need to know the repeated roots, and how many times did each one of them repeat.
How to do that?

You can convert it into a polynomial and then use the roots function, which will return a dictionary that has the roots as keys and the multiplicities as values, like so:
from sympy import roots
poly = equation.as_poly()
roots(poly)
# returns {1: 2}
Unlike nroots, this works with polynomials with symbolic coefficients as well:
from sympy.abc import a, b, c
poly = (a * x ** 2 - 2 * sqrt(a * c) * x + c).as_poly(x)
roots(poly, x)
# returns {sqrt(a*c)/a: 2}

Related

How to substitute an equation in python?

from sympy import symbols, Eq, solve, sin, sqrt
x = symbols('x')
D = symbols('d')
C = symbols('c')
eq1 = 2*sin(x)+sqrt(1-sin^2(x))+D*sin(x/2)-sin(2*x)-1-C
sol = solve(eq1)
print(sol)
Actually in the equation eq1=0. And I was trying to find a function for x which I couldn't find by mathematics. So I was thinking if it is possible in Python. My friend was saying that we actually deal with numbers in Python so he said it would be good if he can get some value of x. In that equation C and D is constant. He was saying that they are height. So we can consider that C,D=1 to 1000 (we can choose whatever we wish). Is there really possible way to substitute that function to find a value of x?
You can use fsolve to numerically solve the non-linear equation. The subs attribute of a sympy expression can be used to substitute a value to a variable.
from sympy import symbols, Eq, solve, sin, sqrt
from scipy.optimize import fsolve
x = symbols('x')
D = symbols('d')
C = symbols('c')
eq1 = 2*sin(x)+sqrt(1-(sin(x))**2)+D*sin(x/2)-sin(2*x)-1-C
values = {
C: 500,
D: 1000
}
eq1_in_x = eq1.subs(values)
def f(y):
return float(eq1_in_x.subs(x,y[0]))
sol = fsolve(f,1) # Here, 1 is an initial guess.
print(sol)
Outout:
[1.04635456]
So, 1.04635456 is a value of x that satisfies the equation with C and D values being 500 and 1000, respectively.
Take a look at sympy tutorial: https://docs.sympy.org/latest/tutorial/index.html
also Itk this should solve your problem: With #Oscar Benjamin advice:
from sympy import nsolve, sin, sqrt
from sympy.abc import x, C, D
eq1 = 2*sin(x)+sqrt(1-sin(x)**2)+C*sin(x/2)-sin(2*x)-1-D
sol = nsolve(eq1.subs({C: C_value, D: D_value}, x0)
print(sol)
x0 is the initialization of x, depending on the value of x0 you can end with different value of x verifying eq = 0.

Using the BFGS method to find roots of few equations

I am trying to use the BFGS method to find the roots of these equations.
ax[0]^2 - bx[1]^2
a = 35; b = 25; d = 15
import numpy as np
from scipy import optimize
def f(x):
return a*x[0]^2 - b*x[1]^2
optimize.fmin_bfgs(f,[0.55,0.65])
The output I am getting is,
Warning: Desired error not necessarily achieved due to precision loss.
Current function value: -2791745.308471
Iterations: 3
Function evaluations: 196
Gradient evaluations: 46
array([ 300.41455833, 2439.35586751])
The output is of course not desirable. I want to add two more equations and want the roots x[0], x[1], x[2]. Is it possible in BFGS, if so, how?
The two more equations are like,
b*x[2]^2 - x[1]^2 == 0
d *x[0]x[2](x[2] + x[0]) - x[1]^2 == 0
The BFGS algorithm tries to find a local minimum of the given function, as the method name fmin_bfgs indicates. You can use scipy.optimize.root to find the root of the function F: R^n -> R^n of n variables:
import numpy as np
from scipy.optimize import root
a = 35; b = 25; d = 15
def F(x):
return np.array([a*x[0]**2 - b*x[1]**2, 0])
# res.x contains your root
res = root(F, x0=np.ones(2))
In order to solve a*x[0]**2 - b*x[1]**2 == 0 we added the equation 0 == 0, since root expects 2 equations for a function of 2 variables. When adding your two other equations, we have a function of three variables, i.e:
def F(x):
eq1 = a*x[0]**2 - b*x[1]**2
eq2 = b*x[1]**2 - x[0]**2
eq3 = d*x[0]*x[2]*(x[2] + x[0]) - x[1]**2
return np.array([eq1, eq2, eq3])
# res.x contains your root
res = root(F, x0=np.ones(3))
Note also that in Python, the ^ operator denotes the bitwise XOR. Use x[0]**2 to denote the power of two of x[0].

Best way to take a function (lambda) as input, and also have the variable within the computation itself?

I have a function that should compute an integral, taking in some function as input. I'd like the code to compute a definite integral of: <some function, in terms of x. e.g., 3*x or 3*x*(1-x), etc.> * np.sin(np.pi * x)). I'm using scipy for this:
import scipy.integrate as integrate
def calculate(a):
test = integrate.quad(a*np.sin(np.pi * x), 0, 1)
return test
a = lambda x: 3*x
calculate(a)
Now this implementation will fail because of the discrepancy between a and x. I tried defining x as x = lambda x: x, but that won't work because I get an error of multiplying a float by a function.
Any suggestions?
Since you are trying to combine two symbolic expressions before computing the definite integral numerically, I think this might be a good application for sympy's symbolic manipulation tools.
from sympy import symbols, Integral, sin, pi
def calculate(a_exp):
test = Integral(a_exp * sin(pi * x), (x, 0, 1)).evalf()
return test
x = symbols('x')
a_exp = 3*x
print(calculate(a_exp))
# 0.954929658551372
Note: I changed the name of a to a_exp to make it clear that this is an expression rather than a function.
If you decide to use sympy then note that you might also be able to compute the expression for the integral symbolically as well.
Update: Importing Sympy might be overkill for this
If computation speed is more important than precision, you can easily calculate the integral approximately using some simple discretized method.
For example, the functions below calculate the integral approximately with increasingly sophisticated methods. The accuracy of the first two will improve as n is increased and also depends on the nature of a_func etc.
import numpy as np
from scipy.integrate import trapz, quad
def calculate2(a_func, n=100):
dx = 1/n
x = np.linspace(0, 1-dx, n)
y = a_func(x) * np.sin(np.pi*x)
return np.sum(y) * dx
def calculate3(a_func, n=100):
x = np.linspace(0, 1, n+1)
y = a_func(x) * np.sin(np.pi*x)
return trapz(y, x)
def calculate4(a_func):
f = lambda x: a_func(x) * np.sin(np.pi*x)
return quad(f, 0, 1)
a_func = lambda x: 3*x
print(calculate2(a_func))
# 0.9548511174430737
print(calculate3(a_func))
# 0.9548511174430737
print(calculate4(a_func)[0])
# 0.954929658551372
I'm not an expert on numerical integration so there may be better ways to do this than these.

In Sympy, what is equivalent to Mathematica's symbolic minimize function?

Mathematica has a symbolic solver for quadratic (and maybe other) functions, e.g.:
Minimize[2 x^2 - y x + 5, {x}]
will yield the following solution:
{1/8 (40-y^2),{x->y/4}}
Is this feature supported in SymPy or a derivative library? Or I have to implement it myself?
Thanks a lot for your opinion!
I'm not sure about the generality of this approach, but the following code:
import sympy
from sympy.solvers import solve
x = sympy.var('x')
y = sympy.var('y')
f = 2*x**2 - y*x + 5
r = solve(f.diff(x), x)
f = f.subs(x, r[0])
print(f)
print(r)
Outputs:
-y**2/8 + 5
[y/4]
The first line of output (-y**2/8 + 5) is equivalent to Mathematica's 1/8 (40-y^2), just ordered differently.
The second line ([y/4]) is similar to Mathematica's {x->y/4} (solve returns a list of roots)
The idea is that we first take the partial derivative of f with respect to x, then substitute it into the original function.

numpy.poly1d , root-finding optimization, shifting polynom on x-axis

it is commonly an easy task to build an n-th order polynomial
and find the roots with numpy:
import numpy
f = numpy.poly1d([1,2,3])
print numpy.roots(f)
array([-1.+1.41421356j, -1.-1.41421356j])
However, suppose you want a polynomial of type:
f(x) = a*(x-x0)**0 + b(x-x0)**1 + ... + n(x-x0)**n
Is there a simple way to construct a numpy.poly1d type function
and find the roots ? I've tried scipy.fsolve but it is very unstable as it depends highly on the choice of the starting values
in my particular case.
Thanks in advance
Best Regards
rrrak
EDIT: Changed "polygon"(wrong) to "polynomial"(correct)
First of all, surely you mean polynomial, not polygon?
In terms of providing an answer, are you using the same value of "x0" in all the terms? If so, let y = x - x0, solve for y and get x using x = y + x0.
You could even wrap it in a lambda function if you want. Say, you want to represent
f(x) = 1 + 3(x-1) + (x-1)**2
Then,
>>> g = numpy.poly1d([1,3,1])
>>> f = lambda x:g(x-1)
>>> f(0.0)
-1.0
The roots of f are given by:
f.roots = numpy.roots(g) + 1
In case x0 are different by power, such as:
f(x) = 3*(x-0)**0 + 2*(x-2)**1 + 3*(x-1)**2 + 2*(x-2)**3
You can use polynomial operation to calculate the finally expanded polynomial:
import numpy as np
import operator
ks = [3,2,3,2]
offsets = [0,2,1,2]
p = reduce(operator.add, [np.poly1d([1, -x0])**i * c for i, (c, x0) in enumerate(zip(ks, offsets))])
print p
The result is:
3 2
2 x - 9 x + 20 x - 14

Categories

Resources