How to make sympy simplify a radical expression equaling zero - sympy

The three (real) roots of the polynomial x^3 - 3x + 1 sum up to 0. But sympy does not seem to be able to simplify this sum of roots:
>>> from sympy import *
>>> from sympy.abc import x
>>> rr = real_roots(x**3 -3*x + 1)
>>> sum(rr)
CRootOf(x**3 - 3*x + 1, 0) + CRootOf(x**3 - 3*x + 1, 1) + CRootOf(x**3 - 3*x + 1, 2)
The functions simplify and radsimp cannot simplify this expression. The minimal polynomial, however, is computed correctly:
>>> minimal_polymial(sum(rr))
_x
From this we can conclude that the sum is 0. Is there a direct way of making sympy simplify this sum of roots?

The following function computes the rational number equal to an algebraic term if possible:
import sympy as sp
# try to simplify an algebraic term to a rational number
def try_simplify_to_rational(expr):
try:
float(expr) # does the expression evaluate to a real number?
minPoly = sp.poly(sp.minimal_polynomial(expr))
print('minimal polynomial:', minPoly)
if len(minPoly.monoms()) == 1: # minPoly == x
return 0
if minPoly.degree() == 1: # minPoly == a*x + b
a,b = minPoly.coeffs()
return sp.Rational(-b, a)
except TypeError:
pass # expression does not evaluate to a real number
except sp.polys.polyerrors.NotAlgebraic:
pass # expression does not evaluate to an algebraic number
except Exception as exc:
print("unexpected exception:", str(exc))
print('simplification to rational number not successful')
return expr # simplification not successful
See the working example:
x = sp.symbols('x')
rr = sp.real_roots(x**3 - 3*x + 1)
# sum of roots equals (-1)*coefficient of x^2, here 0
print(sp.simplify(sum(rr)))
print(try_simplify_to_rational(sum(rr))) # -> 0
A more elaborate function computing also simple radical expressions is proposed in sympy issue #19726.

Related

sympy solve( ) with complex numbers

I have a hard time getting sympy to work with complex numbers.
Take the following example:
from sympy import *
x = Symbol("x")
expr = sqrt(x) # note that this is imaginary for x<0
# Find all solutions such that |expr| < 1
print( solve( abs(expr)<1, x ) )
This, however, only finds 0<=x<1.
It misses the negative x region -1<x.
How can I make this work?
Since abs(sqrt(x)) = sqrt(x**2) for real numbers, you could solve sqrt(x**2)<1 instead.
>>> solve(sqrt(x**2)<1)
(-1 < x) & (x < 1)
You can perhaps find the boundaries of the solution by replacing your argument of the sqrt with a negative or nonnegative symbol:
>>> solve(abs(sqrt(n))-1)
[-1]
>>> var('nn',nonnegative=1)
nn
>>> solve(abs(sqrt(nn))-1)
[1]
Could you get the boundaries numerically?
>>> [nsolve((abs(x**2+2*x-sqrt(x+5)))-1,i) for i in (-3,-1,0,1)]
[-2.86080585311170, 0.533751168755204, 0.533751168755204, 1.11490754147676]

How in sympy Disable unnecessary parenthesis?

Tell me please, How to forbid to open brackets? For example,
8 * (x + 1) It should be that way, not 8 * x + 8
Using evaluate = False doesn't help
The global evaluate flag will allow you to do this in the most natural manner:
>>> with evaluate(False):
... 8*(x+1)
...
8*(x + 1)
Otherwise, Mul(8, x + 1, evaluate=False) is a lower level way to do this. And conversion from a string (already in that form) is possible as
>>> S('8*(x+1)',evaluate=False)
8*(x + 1)
In general, SymPy will convert the expression to its internal format, which includes some minimal simplifications. For example, sqrt is represented internally as Pow(x,1/2). Also, some reordering of terms may happen.
In your specific case, you could try:
from sympy import factor
from sympy.abc import x, y
y = x + 1
g = 8 * y
g = factor(g)
print(g) # "8 * (x + 1)"
But, if for example you have g = y * y, SymPy will either represent it as a second power ((x + 1)**2), or expand it to x**2 + 2*x + 1.
PS: See also this answer by SymPy's maintainer for some possible workarounds. (It might complicate things later when you would like to evaluate or simplify this expression in other calculations.)
How about sympy.collect_const(sympy.S("8 * (x + 1)"), 8)?
In general you might be interested in some of these expression manipulations: https://docs.sympy.org/0.7.1/modules/simplify/simplify.html

Matrix multiplication with Python

I have a numerical analysis assignment and I need to find some coefficients by multiplying matrices. We were given an example in Mathcad, but now we have to do it in another programming language so I chose Python.
The problem is, that I get different results by multiplying matrices in respective environments. Here's the function in Python:
from numpy import *
def matrica(C, n):
N = len(C) - 1
m = N - n
A = [[0] * (N + 1) for i in range(N+1)]
A[0][0] = 1
for i in range(0, n + 1):
A[i][i] = 1
for j in range(1, m + 1):
for i in range(0, N + 1):
if i + j <= N:
A[i+j][n+j] = A[i+j][n+j] - C[i]/2
A[int(abs(i - j))][n+j] = A[int(abs(i - j))][n+j] - C[i]/2
M = matrix(A)
x = matrix([[x] for x in C])
return [float(y) for y in M.I * x]
As you can see I am using numpy library. This function is consistent with its analog in Mathcad until return statement, the part where matrices are multiplied, to be more specific. One more observation: this function returns correct matrix if N = 1.
I'm not sure I understand exactly what your code do. Could you explain a little more, like what math stuff you're actually computing. But if you want a plain regular product and if you use a numpy.matrix, why don't you use the already written matrix product?
a = numpy.matrix(...)
b = numpy.matrix(...)
p = a * b #matrix product

Quadratic Equations Factored Form

I'm a beginner with python as my first language trying to factor a
quadratic where the equation provides the result in
factor form for example:
x^2+5x+4
Output to be (or any factors in parenthesis)
(x+4)(x+1)
So far this only gives me x but not a correct value either
CODE
def quadratic(a,b,c):
x = -b+(((b**2)-(4*a*c))**(1/2))/(2*a)
return x
print quadratic(1,5,4)
Your parentheses are in the wrong places, you're only calculating and returning one root, and (most importantly), you're using **(1/2) to calculate the square root. In Python 2, this will evaluate to 0 (integer arithmetic). To get 0.5, use (1./2) (or 0.5 directly).
This is (slightly) better:
def quadratic(a,b,c):
x1 = (-b+(b**2 - 4*a*c)**(1./2))/(2*a)
x2 = (-b-(b**2 - 4*a*c)**(1./2))/(2*a)
return x1, x2
print quadratic(1,5,4)
and returns (-1.0, -4.0).
To get your parentheses, put the negative of the roots in an appropriate string:
def quadratic(a,b,c):
x1 = (-b+(b**2 - 4*a*c)**(1./2))/(2*a)
x2 = (-b-(b**2 - 4*a*c)**(1./2))/(2*a)
return '(x{:+f})(x{:+f})'.format(-x1,-x2)
print quadratic(1,5,4)
Returns:
(x+1.000000)(x+4.000000)
This will help you:
from __future__ import division
def quadratic(a,b,c):
x = (-b+((b**2)-(4*a*c))**(1/2))/(2*a)
y = (-b-((b**2)-(4*a*c))**(1/2))/(2*a)
return x,y
m,n = quadratic(1,5,4)
sign_of_m = '-' if m > 0 else '+'
sign_of_n = '-' if n > 0 else '+'
print '(x'+sign_of_m+str(abs(m))+')(x'+sign_of_n+str(abs(n))+')'
Output
(x+1.0)(x+4.0)
Let me know if it helps.

Solve for the positions of all six roots PYTHON

I'm using Newton's method, so I want to find the positions of all six roots of the sixth-order polynomial, basically the points where the function is zero.
I found the rough values on my graph with this code below but want to output those positions of all six roots. I'm thinking of using x as an array to input the values in to find those positions but not sure. I'm using 1.0 for now to locate the rough values. Any suggestions from here??
def P(x):
return 924*x**6 - 2772*x**5 + 3150*x**4 - 1680*x**3 + 420*x**2 - 42*x + 1
def dPdx(x):
return 5544*x**5 - 13860*x**4 + 12600*x**3 - 5040*x**2 + 840*x - 42
accuracy = 1**-10
x = 1.0
xlast = float("inf")
while np.abs(x - xlast) > accuracy:
xlast = x
x = xlast - P(xlast)/dPdx(xlast)
print(x)
p_points = []
x_points = np.linspace(0, 1, 100)
y_points = np.zeros(len(x_points))
for i in range(len(x_points)):
y_points[i] = P(x_points[i])
p_points.append(P(x_points))
plt.plot(x_points,y_points)
plt.savefig("roots.png")
plt.show()
The traditional way is to use deflation to factor out the already found roots. If you want to avoid manipulations of the coefficient array, then you have to divide the roots out.
Having found z[1],...,z[k] as root approximations, form
g(x)=(x-z[1])*(x-z[2])*...*(x-z[k])
and apply Newtons method to h(x)=f(x)/g(x) with h'(x)=f'/g-fg'/g^2. In the Newton iteration this gives
xnext = x - f(x)/( f'(x) - f(x)*g'(x)/g(x) )
Fortunately the quotient g'/g has a simple form
g'(x)/g(x) = 1/(x-z[1])+1/(x-z[2])+...+1/(x-z[k])
So with a slight modification to the Newton step you can avoid finding the same root over again.
This all still keeps the iteration real. To get at the complex root, use a complex number to start the iteration.
Proof of concept, adding eps=1e-8j to g'(x)/g(x) allows the iteration to go complex without preventing real values. Solves the equivalent problem 0=exp(-eps*x)*f(x)/g(x)
import numpy as np
import matplotlib.pyplot as plt
def P(x):
return 924*x**6 - 2772*x**5 + 3150*x**4 - 1680*x**3 + 420*x**2 - 42*x + 1
def dPdx(x):
return 5544*x**5 - 13860*x**4 + 12600*x**3 - 5040*x**2 + 840*x - 42
accuracy = 1e-10
roots = []
for k in range(6):
x = 1.0
xlast = float("inf")
x_points = np.linspace(0.0, 1.0, 200)
y_points = P(x_points)
for rt in roots:
y_points /= (x_points - rt)
y_points = np.array([ max(-1.0,min(1.0,np.real(y))) for y in y_points ])
plt.plot(x_points,y_points,x_points,0*y_points)
plt.show()
while np.abs(x - xlast) > accuracy:
xlast = x
corr = 1e-8j
for rt in roots:
corr += 1/(xlast-rt)
Px = P(xlast)
dPx = dPdx(xlast)
x = xlast - Px/(dPx - Px*corr)
print(x)
roots.append(x)