What does Sympys' doit() does on derivatives? - python

I'm trying to compute higher derivatives of f(y(x)) w.r.t to x using sympys diff.
from sympy import *
from IPython.display import display
init_printing(use_latex=True)
x = symbols('x')
f, y = symbols('f, y', cls=Function)
d2 = diff(f(y(x)),x,2)
print(d2)
print(d2.doit())
Sympy returns :
Derivative(y(x), x)**2*Derivative(f(y(x)), y(x), y(x)) + Derivative(y(x), x, x)*Subs(Derivative(f(_xi_1), _xi_1), (_xi_1,), (y(x),))
Derivative(f(y(x)), y(x))*Derivative(y(x), x, x) + 2*Derivative(y(x), x)**2*Derivative(f(y(x)), y(x), y(x))
Latex image: Sympy result.
While the first result seems to be correct, I do not understand the factor 2 in the second expression after the doit() operation.

It looks like you stumbled upon a bug, which was just fixed a few weeks ago.
You can test this by substituting f, y, and x with some functions or values respectively (append to your code):
f_ex = Lambda(x, x**2)
y_ex = Lambda(x, sin(x))
x_ex = 2
substitutions = [ (f,f_ex), (y,y_ex), (x,x_ex) ]
print( d2.subs(substitutions).doit().n() ) #-1.30728724172722
print( d2.doit().subs(substitutions).doit().n() ) #-0.960930862590836
The printed values should be the same.
The issue can be further isolated to:
print((Derivative(f(y(x)), x, x)))
print((Derivative(f(y(x)), y(x), y(x))).doit())
Here, a plain doit simply adds a factor of 2, which is obviously wrong.

Related

Cannot integrate function with SymPy

I've been trying to integrate functions with SymPy in Python, but some are not evaluating properly. There've been two problematic scenarios that have been occurring for me:
'expr not of form a*x**b: %s' -- one example of this is with
from sympy import *
x = Symbol('x')
f = 1 / (25 + x**2)**(3/2)
print(integrate(f, x))
Outputs a weird result that is not the answer. One example is
from sympy import *
x, a = symbols('x a')
f = 1 / (a**2 + x**2)
print(integrate(f, x))
In this case, the output is (-I*log(-I*a + x)/2 + I*log(I*a + x)/2)/a which is definitely not the correct answer of atan(x/a)/a that it should return.
How can each of these issues be addressed? Thanks.

How to get the value of a middle variable in a function that need to use 'fsolve'?

My first py file is the function that I want to find the roots, like this:
def myfun(unknowns,a,b):
x = unknowns[0]
y = unknowns[1]
eq1 = a*y+b
eq2 = x**b
z = x*y + y/x
return eq1, eq2
And my second one is to find the value of x and y from a starting point, given the parameter value of a and b:
a = 3
b = 2
x0 = 1
y0 = 1
x, y = scipy.optimize.fsolve(myfun, (x0,y0), args= (a,b))
My question is: I actually need the value of z after plugging in the result of found x and y, and I don't want to repeat again z = x*y + y/x + ..., which in my real case it's a middle step variable without an explicit expression.
However, I cannot replace the last line of fun with return eq1, eq2, z, since fslove only find the roots of eq1 and eq2.
The only solution now is to rewrite this function and let it return z, and plug in x and y to get z.
Is there a good solution to this problem?
I believe that's the wrong approach. Since you have z as a direct function of x and y, then what you need is to retrieve those two values. In the listed case, it's easy enough: given b you can derive x as the inverse of eqn2; also given a, you can invert eqn1 to get y.
For clarity, I'm changing the names of your return variables:
ret1, ret2 = scipy.optimize.fsolve(myfun, (x0,y0), args= (a,b))
Now, invert the two functions:
# eq2 = x**b
x = ret2**(1/b)
# eq1 = a*y+b
y = (ret1 - b) / a
... and finally ...
z = x*y + y/x
Note that you should remove the z computation from your function, as it serves no purpose.

python : intersection geometrical objects in 3D space

Definition of the problem
I am trying to calculate the points of intersection of geometrical objects, such as two planes and a sphere, in python.
Let's consider for example these three objects:
This system gives two solutions:
I would like to know if there is a python library that can help develop a solver to calculate these intersections. I am looking for something working as Wolfram alpha, where we can input three equations and it returns all the possible solutions when there's finite number of solutions for simplicity.
What I tried
I tried with SymPy, but it returns []:
from sympy.solvers import solve
from sympy import Symbol
x = Symbol('x')
y = Symbol('y')
z = Symbol('z')
solve(z, x, x**2 + y**2 + z**2 -1)
I then tried with scipy:
from scipy.optimize import fsolve
def f(x):
y = np.zeros(3)
y[2] = x[2]
y[0] = x[0]
y[1] = x[0] ** 2 + x[1] ** 2+ x[2] ** 2 - 1
return y
x0 = np.array([10, 10, 10])
solution = fsolve(f, x0)
print(solution[0],solution[1],solution[2])
but it only returns one of the two solutions:
6.79746218330325e-28 1.0000000000000002 -2.3528179942097343e-35
I also tried with gekko, and stil it only returns one possible solution (which depends on the initial guess):
from gekko import GEKKO
m = GEKKO()
x = m.Var(value = 1)
y = m.Var(value = 1)
z = m.Var(value = 1)
m.Equation(x == 0)
m.Equation(z == 0)
m.Equation(x**2 + y**2+z**2 ==1)
m.solve()
fsolve from scipy, and all other functions that I personally know of that will accept any form of input function, will return one value.
One workaround if you have an idea where the other solution is would be to give an x0 value that is closer to the second solution with a second call to fsolve (see https://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.fsolve.html).
If you alternatively know what range you want to try and find solutions in, the easiest way is to make an array that you then check to see where the value changes sign (this would be doing it from scratch)
I found the solution with sympy. Apparently it's one of the only (if not only) libraries that allow finding analytical solutions, and returns more than just one solution. Also, we don't need to pass guesses as initial variables. In my question, there was an error in the example I posted with sympy. This is how I solved the system:
from sympy.solvers import solve
import sympy as sp
x = Symbol('x')
y = Symbol('y')
z = Symbol('z')
sp.solve([z , x, (x**2 + y**2 + z**2) - 1], x,y,z)
Result: [0,-1,0], [0,1,0]

Printing expressions of variables in Theano

If I want to print some variable for debugging in theano, it is easy, just write
x2 = printing.Print('x is: ')(x), and then use x2 instead of x in the following computations.
But what if I want to print some expression of x, for example x+y. How can I do it?
If I write z = printing.Print('x+y is: ')(x+y) then I will need to insert z into the computation graph later, what is the recommended way to do it?
The result of a print operation must be reachable (via some path in the computation graph) from an output of the Theano function. If you want to print an expression that is not used then a simple solution is to just include the result of that expression in the outputs of the Theano function.
Suppose you are interested in x*y but would like to print x+y, then
x = theano.tensor.scalar()
y = theano.tensor.scalar()
z = printing.Print('x+y is: ')(x+y)
f1 = theano.function([x, y], [x * y]
f2 = theano.function([x, y], [z]
f3 = theano.function([x, y], [x * y, z]
f1 will fail to print x+y because z is not reachable from an output of the function; f2 will print x+y but will not compute x*y; f3 will do both.
This is a nasty hack, but I've resorted to things like:
x = 1e-11 * Print("mean of x")(x.mean()) + x
If you make it 0 * Print(...) then it gets optimised away.

How to get either side of equation in SymPy?

Suppose I have the code below. I want to get either the right side of the equation (C1 +x...). How do I do that?
My problem is I have some boundary conditions for derivatives of f(x) at specific points, so I want to calculate those and find out the constants. I have also different values for w(x), so the final code will begin defining a variable called wx instead of having the function w(x).
from __future__ import division
from sympy import *
x, y = symbols('x y')
w, f = symbols('w f', cls=Function)
init_printing(use_unicode=True)
diffeq = f(x).diff(x,x,x,x)-w(x)
expr = dsolve(diffeq, f(x))
print diffeq
print expr
results:
-w(x) + Derivative(f(x), x, x, x, x)
f(x) == C1 + x**3*(C4 + Integral(w(x)/6, x)) + x**2*(C3 - Integral(x*w(x)/2, x)) + x*(C2 + Integral(x**2*w(x)/2, x)) - Integral(x**3*w(x)/6, x)
expr.lhs and expr.rhs will give you the left- and right-hand sides of the equation.

Categories

Resources