Why is this derivative not being calculated automatically? - sympy

I am trying to use differentiation on a function on sympy.
This is the code that i am using.
from sympy import *
x, y = symbols('x y')
expr = 5*x**9 - 4*x**3 + 21 - 1/x
print("Expression : {}".format(expr))
expr_diff = Derivative(expr, x)
print("Derivative of expression with respect to x : {}".format(expr_diff))
print("Value of the derivative : {}".format(expr_diff.doit()))
when it outputs
Expression : 5*x**9 - 4*x**3 + 21 - 1/x
Derivative of expression with respect to x : Derivative(5*x**9 - 4*x**3 + 21 - 1/x, x)
Value of the derivative : 45*x**8 - 12*x**2 + x**(-2)
Is there a way to get the derivative directly without using doit?

Using Derivative creates an unevaluated expression which, as you see, is evaluated with doit. If you don't want the evaluated form, use expr.diff() (which also accepts variable of differentiation and order to be specified:
>>> expr.diff()
45*x**8 - 12*x**2 + x**(-2)
>>> expr.diff(x,x)==expr.diff(x,2), expr.diff(x,x)
(True, 2*(180*x**7 - 12*x - 1/x**3))

Related

How to make sympy simplify a radical expression equaling zero

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.

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

Sympy diffgeom: Metric dependent on function

I'm having problems defining a metric using sympy's diffgeom package, where the metric depends on a function f(x,y).
I get the error ValueError: Can't calculate 1st derivative wrt x.
import sympy as sym
from sympy.diffgeom import Manifold, Patch, CoordSystem
m = Manifold("M",2)
patch = Patch("P",m)
cartesian = CoordSystem("cartesian", patch, ["x", "y"])
x, y = cartesian.coord_functions()
f = sym.Function('f')
xi = sym.Symbol('xi')
g = sym.Matrix([
[ xi + sym.diff(f,x)**2 , sym.diff(f,x) * sym.diff(f,y) ],
[ sym.diff(f,x) * sym.diff(f,y) , xi + sym.diff(f,y)**2 ]
])
I have a feeling it's because of how x and y are defined, but I haven't been able to figure it out.
Indeed, differentiation with respect to these x and y (objects of class sympy.diffgeom.diffgeom.BaseScalarField) is not supported. You can see this by accessing the internal property _diff_wrt which indicates if something can be a thing with respect to which to differentiate.
>>> x._diff_wrt
False
Do those derivative (with respect to a scalar field) make mathematical sense here? I'm not sure.
An additional issue is that SymPy does not differentiate functions, so
f = Function('f')
diff(f, x)
is always an error. SymPy can differentiate expressions, e.g., diff(f(x, y), x).
Aside: diff can be used as a method of an expression, which in your case would result in shorter code, like f(x, y).diff(x).

symbolic derivation of a larger function

I want to take the derivative of the following function
y=(np.log(x))/(1+x),
if I am using sympy, it gives me the following error
from sympy import *
y1=Derivative((np.log(x))/(1+x), x)
print y1
sequence too large; cannot be greater than 32
Do it like this:
>>> from sympy import *
>>> var('x')
x
>>> y1 = diff(log(x)/(1+x))
>>> y1
-log(x)/(x + 1)**2 + 1/(x*(x + 1))
As Sanjeev mentioned in a comment you need to define variables in one way or another.
np.log in your code would be a function that accepts a numerical value and returns a numerical value; sympy needs to see a function names that it knows in formal terms, such as log
In this context, you need to use sympy's diff function, rather than Derivative.

rotating coordinate systems sympy

I'm a complete beginner with sympy, so it may be I'm overlooking something basic. I would like to rotate my coordinate system so I can build a hyperbola in standard position and then transform it to the arbitrary case. First I set up my equation:
> x, y, a, b, theta = symbols('x y a b theta')
> f = Eq(x ** 2/a ** 2 - y ** 2/b ** 2, 1)
> f1 = f.subs({a: 5, b: 10})
> f1
> x**2/25 - y**2/100 == 1
Next I want to rotate it, which I try to do by using a sub:
> f1.subs({x: x*cos(theta) - y*sin(theta), y: x*sin(theta) + y*cos(theta)})
> -(x*sin(theta) + y*cos(theta))**2/100 + (x*cos(theta) - (x*sin(theta) + y*cos(theta))*sin(theta))**2/25 == 1
But that doesn't work because apparently the substitution for x is made before the one for y, and the value of x substituted in is already updated. There must be some way to do this substitution, right?
Or is there a better tool than sympy to do this in? Once I get my hyperbolas I will want to find points of intersection between different ones.
Thanks for any suggestions.
One simple solution is to use temporary symbols :
x_temp, y_temp = symbols('x_temp y_temp')
f1.subs({x: x_temp*cos(theta) - y_temp*sin(theta), y: x_temp*sin(theta) + y_temp*cos(theta)}).subs({x_temp: x, y_temp: y})
> -(x*sin(theta) + y*cos(theta))**2/100 + (x*cos(theta) - y*sin(theta))**2/25 == 1
I think sympy can do what you want. There is a polysys modules in sympy.solvers :
"""
Solve a system of polynomial equations.
Examples
========
>>> from sympy import solve_poly_system
>>> from sympy.abc import x, y
>>> solve_poly_system([x*y - 2*y, 2*y**2 - x**2], x, y)
[(0, 0), (2, -sqrt(2)), (2, sqrt(2))]
"""
You can set simultaneous=True in the .subs( ) method to force SymPy to replace all variables at once (practically, SymPy internally creates temporary variables, proceeds with the substitution, then restores the old variables).
In [13]: f1.subs({x: x*cos(theta) - y*sin(theta),
y: x*sin(theta) + y*cos(theta)}, simultaneous=True)
Out[13]:
2 2
(x⋅sin(θ) + y⋅cos(θ)) (x⋅cos(θ) - y⋅sin(θ))
- ────────────────────── + ────────────────────── = 1
100 25
Otherwise use .xreplace( ... ) instead of .subs( ... )
In [11]: f1.xreplace({x: x*cos(theta) - y*sin(theta),
y: x*sin(theta) + y*cos(theta)})
Out[11]:
2 2
(x⋅sin(θ) + y⋅cos(θ)) (x⋅cos(θ) - y⋅sin(θ))
- ────────────────────── + ────────────────────── = 1
100 25