Taking inverse of a matrix of function - python

I'd like to take the inverse of the A martix
import sympy as sp
import numpy as np
b = np.array([[0.1], [0.1], [-0.1]])
x, y, z = sp.symbols("x y z")
eq1 = 3*x - sp.cos(y*z) - 1/2
eq2 = x**2 -81*(y+0.1)**2 + sp.sin(z) + 1.06
eq3 = sp.exp(-x*y) + 20*z + (10*np.pi - 3)/3
A = np.array([[0,0,x],[0,0,0],[0,0,0]])
f = np.array([[eq1],[eq2],[eq3]])
A[0,0] = sp.diff(eq1,x)
A[1,0] = sp.diff(eq1,y)
A[2,0] = sp.diff(eq1,z)
A[0,1] = sp.diff(eq2,x)
A[1,1] = sp.diff(eq2,y)
A[2,1] = sp.diff(eq2,z)
A[0,2] = sp.diff(eq3,x)
A[1,2] = sp.diff(eq3,y)
A[2,2] = sp.diff(eq3,z)
print(A)
J = np.linalg.inv(A)
print(A)
However, the built-in function doesn't work. So how can I take the inverse of it?

You should use sympy matrix instead:
J = sp.Matrix(A).inv()

If you initialize matrix A using sympy rather than numpy array it will work.
import sympy as sp
import numpy as np
from sympy import Matrix
b = np.array([[0.1], [0.1], [-0.1]])
x, y, z = sp.symbols("x y z")
eq1 = 3*x - sp.cos(y*z) - 1/2
eq2 = x**2 -81*(y+0.1)**2 + sp.sin(z) + 1.06
eq3 = sp.exp(-x*y) + 20*z + (10*np.pi - 3)/3
f = np.array([[eq1],[eq2],[eq3]])
a1 = sp.diff(eq1,x)
b1 = sp.diff(eq1,y)
c1 = sp.diff(eq1,z)
a2 = sp.diff(eq2,x)
b2 = sp.diff(eq2,y)
c2 = sp.diff(eq2,z)
a3 = sp.diff(eq3,x)
b3 = sp.diff(eq3,y)
c3 = sp.diff(eq3,z)
print(A)
A = Matrix( [[a1,a2,a3],[b1,b2,b3],[c1,c2,c3]]) # Initialize using sympy Matrix
A_inverse = A.inv()
print(A_inverse)

I don’t think you can do numpy operations like inv on SymPy expressions. However, I don’t use SymPy.
Also, not all matrices are invertable.

A is a numpy array, object dtype, containing sympy objects:
In [5]: A
Out[5]:
array([[3, 2*x, -y*exp(-x*y)],
[z*sin(y*z), -162*y - 16.2, -x*exp(-x*y)],
[y*sin(y*z), cos(z), 20]], dtype=object)
In [6]: np.linalg.inv(A)
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-6-ae645f97e1f8> in <module>
----> 1 np.linalg.inv(A)
<__array_function__ internals> in inv(*args, **kwargs)
/usr/local/lib/python3.6/dist-packages/numpy/linalg/linalg.py in inv(a)
545 signature = 'D->D' if isComplexType(t) else 'd->d'
546 extobj = get_linalg_error_extobj(_raise_linalgerror_singular)
--> 547 ainv = _umath_linalg.inv(a, signature=signature, extobj=extobj)
548 return wrap(ainv.astype(result_t, copy=False))
549
TypeError: No loop matching the specified signature and casting was found for ufunc inv
np.linalg works for numeric arrays, not general Python objects.
Math on object dtype arrays is hit-or-miss. Somethings work, but many don't. Mixing sympy and numpy is generally not recommended.
A row sum does work - because the sympy objects can 'add' themselves:
In [7]: A.sum(axis=1)
Out[7]:
array([2*x - y*exp(-x*y) + 3,
-x*exp(-x*y) - 162*y + z*sin(y*z) - 16.2,
y*sin(y*z) + cos(z) + 20
], dtype=object)
That numpy array can be made into a sparse matrix, as other show:
In [10]: As = Matrix(A.tolist() )
In [11]: As
Out[11]:
⎡ -x⋅y⎤
⎢ 3 2⋅x -y⋅ℯ ⎥
⎢ ⎥
⎢ -x⋅y⎥
⎢z⋅sin(y⋅z) -162⋅y - 16.2 -x⋅ℯ ⎥
⎢ ⎥
⎣y⋅sin(y⋅z) cos(z) 20 ⎦
and the inverse exists - but it is (3,3), but the elements are large expressions:
In [12]: As.inv()
...
In [14]: _12.shape
Out[14]: (3, 3)
In [15]: As.det()
Out[15]:
2 -x⋅y -x⋅y 2 -x⋅y
- 2⋅x ⋅y⋅ℯ ⋅sin(y⋅z) - 40⋅x⋅z⋅sin(y⋅z) + 3⋅x⋅ℯ ⋅cos(z) + y ⋅(-162⋅y - 16.2)⋅ℯ ⋅sin(y
-x⋅y
⋅z) - y⋅z⋅ℯ ⋅sin(y⋅z)⋅cos(z) - 9720⋅y - 972.0

Related

Why won't SymPy directly solve for the normalization of this wavefunction?

Here is some minimal code demonstrating the problem.
from sympy import *
x = Symbol('x', real=True)
t = Symbol('t', real=True)
A = Symbol('A', real=True, positive=True)
λ = Symbol('λ', real=True, positive=True)
ω = Symbol('ω', real=True, positive=True)
# Define wavefunction
psi_x_t = A * exp(-λ * Abs(x)) * exp(-I*ω*t)
# Normalize
print(solve(integrate(psi_x_t**2, (x, -oo, oo)) - 1))
print(solve(integrate(psi_x_t**2, (x, -oo, oo)) - 1, A))
Where I simply call solve it returns [{t: 0, λ: A**2}]. What I am looking for is actually A=sqrt(λ). But when I include A as the symbol I am solving for I don't get a plus/minus sqrt(λ) but rather an empty collection [].
Why is solve giving me an empty list of solutions, and is there a way to make it directly return the solution for A?
You are not getting a solution because you have declared assumptions on your variables and those assumptions are inconsistent with the solution. Let's try without those assumptions:
In [20]: from sympy import *
...:
...: x = Symbol('x')
...: t = Symbol('t')
...: A = Symbol('A')
...: λ = Symbol('λ')
...: ω = Symbol('ω')
...:
...: # Define wavefunction
...: psi_x_t = A * exp(-λ * Abs(x)) * exp(-I*ω*t)
In [21]: psi_x_t
Out[21]:
-λ⋅│x│ -ⅈ⋅t⋅ω
A⋅ℯ ⋅ℯ
In [22]: eq = integrate(psi_x_t**2, (x, -oo, oo)) - 1
In [23]: eq
Out[23]:
⎛⎧ 2 -2⋅ⅈ⋅t⋅ω ⎞
⎜⎪ A ⋅ℯ π⎟
⎜⎪ ──────────── for │arg(λ)│ < ─⎟
⎜⎪ λ 2⎟
⎜⎪ ⎟
⎜⎨∞ ⎟ - 1
⎜⎪⌠ ⎟
⎜⎪⎮ 2 -2⋅λ⋅│x│ -2⋅ⅈ⋅t⋅ω ⎟
⎜⎪⎮ A ⋅ℯ ⋅ℯ dx otherwise ⎟
⎜⎪⌡ ⎟
⎝⎩-∞ ⎠
I'm guessing that this Piecewise is the reason that you set those assumptions. Let's just manually select the first case of the Piecewise and work from there:
In [26]: eq1 = piecewise_fold(eq).args[0][0]
In [27]: eq1
Out[27]:
2 -2⋅ⅈ⋅t⋅ω
A ⋅ℯ
──────────── - 1
λ
Now we solve this:
In [28]: solve([eq1], [A])
Out[28]:
⎡⎛ ⅈ⋅t⋅ω ⎞ ⎛ ⅈ⋅t⋅ω ⎞⎤
⎣⎝-√λ⋅ℯ ,⎠, ⎝√λ⋅ℯ ,⎠⎦
Now for almost all possible values of omega this is not going to be real which is a violation of the assumptions you stated that A should be positive.
Presumably the equation you actually wanted comes from integrating abs(psi)^2:
In [34]: from sympy import *
...:
...: x = Symbol('x', real=True)
...: t = Symbol('t', real=True)
...: A = Symbol('A', real=True, positive=True)
...: λ = Symbol('λ', real=True, positive=True)
...: ω = Symbol('ω', real=True, positive=True)
...:
...: # Define wavefunction
...: psi_x_t = A * exp(-λ * Abs(x)) * exp(-I*ω*t)
In [35]: eq = integrate(abs(psi_x_t)**2, (x, -oo, oo)) - 1
In [36]: eq
Out[36]:
2
A
── - 1
λ
In [37]: solve([eq], [A])
Out[37]: [(√λ,)]
Here only the positive root is returned because we assumed A to be positive.
Why is solve giving me an empty list of solutions, and is there a way to make it directly return the solution for A?
I can't answer this question. However, when solve fails I usually give a try to solveset:
print(solveset(integrate(psi_x_t**2, (x, -oo, oo)) - 1, A))
# {-sqrt(λ)*exp(I*t*ω), sqrt(λ)*exp(I*t*ω)}
It did not solve for A as expected because it doesn't choose some time in which to solve for it. If we first set time, such as t=0, then it will find a suitable solution.
from sympy import *
x = Symbol('x', real=True)
t = Symbol('t', real=True)
A = Symbol('A', real=True, positive=True)
λ = Symbol('λ', real=True, positive=True)
ω = Symbol('ω', real=True, positive=True)
# Define wavefunction
psi_x_t = A * exp(-λ *Abs(x)) * exp(-I*ω*t)
# Intergrate
result = integrate(psi_x_t**2, (x, -oo, oo)) - 1
result = result.subs(t, 0)
# Normalize
print(solve(result))
print(solve(result, A))

SymPy not simplifying "enough" while differentiating an implicit function

I am trying to find the 1st and 2nd derivatives of the implicit function y = f(x)
which is defined by the equation: exp(sin(x)) - x * exp(sin(y)) = 0
SymPy calculates the 1st derivative and gives this answer:
But this expression can be written much simpler as:
(x * cos(x) - 1) / (x * cos(y))
using the fact that x = exp(sin(x)-sin(y))
The answer given for the 2nd derivative is also quite complicated.
Of course the second derivative can also be simplified
quite a lot using the same fact x = exp(sin(x)-sin(y)) .
How can I make/force SymPy apply these additional simplifications?
Is that possible even?
Here is my script.
#!/usr/bin/env python
# coding: utf-8
# ### Differentiating an implicit function using SymPy
# In[1]:
import sympy as sp
# In[2]:
sp.__version__
# In[3]:
sp.init_printing(use_latex='mathjax') # use pretty mathjax output
# In[4]:
sp.var('x y z')
F = sp.exp(sp.sin(x)) - x * sp.exp(sp.sin(y))
# In[5]:
f1 = sp.idiff( F, y, x ) # First derivative of y w.r.t. x
f1
# In[6]:
sp.simplify(f1)
# In[7]:
f2 = sp.idiff( F, y, x, 2) # Second derivative of y w.r.t. x
f2
sp.simplify(f2)
# In[ ]:
And also, here is an even simpler example which shows this undesired behavior.
#!/usr/bin/env python
# coding: utf-8
# ### Differentiating an implicit function using SymPy
# In[1]:
import sympy as sp
# In[2]:
sp.__version__
# In[3]:
sp.init_printing(use_latex='mathjax') # use pretty mathjax output
# In[4]:
sp.var('x y')
F = sp.ln(sp.sqrt(x**2 + y**2)) - sp.atan(y / x)
# In[5]:
f1 = sp.idiff( F, y, x ) # First derivative of y w.r.t. x
f1
# In[6]:
sp.simplify(f1)
# In[7]:
f2 = sp.idiff( F, y, x, 2) # Second derivative of y w.r.t. x
f2
sp.simplify(f2)
# In[ ]:
The second derivative here is given as:
This expression obviously can be simplified further even without using any special facts.
You can simplify the expressions yourself. In the first example you can just choose a term to eliminate and solve F for that:
In [42]: F
Out[42]:
sin(y) sin(x)
- x⋅ℯ + ℯ
In [43]: solve(F, exp(sin(y)))
Out[43]:
⎡ sin(x)⎤
⎢ℯ ⎥
⎢───────⎥
⎣ x ⎦
In [44]: [esy] = solve(F, exp(sin(y)))
In [45]: f2.subs(exp(sin(y)), esy)
Out[45]:
2
x⋅sin(y)⋅cos (x) 2⋅sin(y)⋅cos(x) sin(y) 1
-x⋅sin(x) + ──────────────── - ─────────────── + ───────── + ─
2 2 2 x
cos (y) cos (y) x⋅cos (y)
──────────────────────────────────────────────────────────────
x⋅cos(y)
You can apply further simplification operations from there.
In the second example you can just call factor:
In [47]: f2
Out[47]:
⎛ 2 2⎞
2⋅⎝x + y ⎠
─────────────────────────
3 2 2 3
x - 3⋅x ⋅y + 3⋅x⋅y - y
In [48]: factor(f2)
Out[48]:
⎛ 2 2⎞
2⋅⎝x + y ⎠
───────────
3
(x - y)

how to solve a system of differential ecuations and a linear equation in Python

I tried to solve this equation system that are two ordinary differential equations and a linear equation
dx(t)/dt = (-x(t) + u(t)) / 2.0,
dy(t)/dt = (-y(t) + x(t)) / 5.0
u(t) = x(t) + 3*y(t)
With this initial conditions x(0) = 0, y(0) = 0 and u(0)=1. I have been trying to solve the system using odeint but I don't know hoy to define the linear function, this is, the function u. I don't know if it is another way to solve this system.
import numpy as np
from scipy.integrate import odeint
import matplotlib.pyplot as plt
def f(z,t,u):
dzdt = np.zeros(2,)
x = z[0]
y = z[1]
dzdt[0] = (-x + u) / 2.0
dzdt[1] = (-y + x) / 5.0
return dzdt
z0 = [0,0]
n = 150
t = np.linspace(0,15, n)
u = np.zeros(n)
u[0] = 1
x = np.zeros(n)
y = np.zeros(n)
for i in range (1,n):
tspan = [t[i-1],t[i]]
z = odeint(f,z0,t,args=(u[i],))
u[i] = x[i] + 3*y[i]
z0 = z[1]
x[i] = z0[0]
y[i] = z0[1]
plt.plot(t,u)
plt.plot(t,x)
plt.plot(t,y)
plt.show()
You can just substitute u into the other equations. Also these particular ODEs can be solved symbolically using SymPy:
In [34]: x, y, u = symbols('x, y, u', cls=Function)
In [35]: t = symbols('t')
In [36]: eqs = [Eq(x(t).diff(t), (-x(t) + u(t)) / 2.0),
...: Eq(y(t).diff(t), (-y(t) + x(t)) / 5.0),
...: Eq(u(t), x(t) + 3*y(t))]
In [37]: eqs[2]
Out[37]: u(t) = x(t) + 3⋅y(t)
In [38]: eqs_new = [eq.subs(eqs[2].lhs, eqs[2].rhs) for eq in eqs[:2]]
In [39]: eqs_new
Out[39]:
⎡d d ⎤
⎢──(x(t)) = 1.5⋅y(t), ──(y(t)) = 0.2⋅x(t) - 0.2⋅y(t)⎥
⎣dt dt ⎦
In [41]: dsolve(eqs_new)[0]
Out[41]:
-0.656776436283002⋅t 0.456776436283002⋅t
x(t) = - 2.28388218141501⋅C₁⋅ℯ + 3.28388218141501⋅C₂⋅ℯ
In [42]: dsolve(eqs_new)[1]
Out[42]:
-0.656776436283002⋅t 0.456776436283002⋅t
y(t) = 1.0⋅C₁⋅ℯ + 1.0⋅C₂⋅ℯ

Sympy differentiation, equation is in numpy array?

I have a function that is updated -- I'm optimizing using the method of newton and steepest.
I'm new to sympy, and hoping to get some quick clarification.
x1,x2 = sym.symbols('x1 x2')
y = 2*x1 + 3*x2**2 + sym.exp(2*x1**2 + x2**2)
gy1 = sym.diff(y,x1)
gy2 = sym.diff(y,x2)
grad1 = sym.lambdify([x1,x2],gy1)(x[0],x[1])
grad2 = sym.lambdify([x1,x2],gy2)(x[0],x[1])
d = np.array([-1*grad1,-1*grad2])
l = sym.symbols('l')
theta = 2*(x[0]+l*d[0]) + 3*(x[1]+l*d[1])**2 + sym.exp(2*(x[0]+l*d[0])**2 + (x[1]+l*d[1])**2)
theta_p = sym.diff(theta,l)
my function, y is updated as follow: f(x_n) --> f(x_n + lambda*d_n) -- call this theta(lambda)
I've updated as above ('theta' function), and when printed to screen, it gives a numpy array:
array([-63.1124487914452*l + 2 + exp([1991.5905962264*(0.0316894691665188 - l)**2])],
dtype=object)
That is the equation I need, but now I want to differentiate it with respect to l, my lambda. But sympy doesn't work like this.
When I run
sym.diff(theta,l)
I get this output:
AttributeError: 'ImmutableDenseNDimArray' object has no attribute 'as_coeff_Mul'
Any ideas?
Try sym.diff(theta[0], l) and sym.diff(theta[1], l)
For some reason you end up with a ndarray containing objects that are sympy expressions. Print the type of each element to confirm.
Oh, there are nested ndarray expressions. You need to review what you are passing to theta.
You should end up with:
-63.1124487914452*l + 2 + exp(1991.5905962264*(0.0316894691665188 - l)**2)
instead of
array([-63.1124487914452*l + 2 + exp([1991.5905962264*(0.0316894691665188 - l)**2])],
dtype=object)
Replace x[0] and x[1] with symbols in theta, then diff, lambdify and evaluate with x[0] and x[1]
If xx (your unspecified x) is (2,1) array:
In [153]: xx = np.array([[1],[1]])
In [154]: grad1 = sym.lambdify([x1,x2],gy1)(xx[0],xx[1])
...: grad2 = sym.lambdify([x1,x2],gy2)(xx[0],xx[1])
...: d = np.array([-1*grad1,-1*grad2])
In [155]: d
Out[155]:
array([[-82.34214769],
[-46.17107385]])
In [156]: theta = 2*(xx[0]+l*d[0]) + 3*(xx[1]+l*d[1])**2 + sym.exp(2*(xx[0]+l*d[0])**2 + (xx[1]+l*d[1])
...: **2)
In [157]: theta
Out[157]:
array([-164.684295385501*l + 6395.30418038233*(0.0216585822397654 - l)**2 + 2 + exp([13560.4585733095*(0.0121444488396316 - l)**2 + 2131.76806012744*(0.0216585822397654 - l)**2])],
dtype=object)
If instead it is (2,) or a simple list
In [158]: xx = np.array([1,1]) # [1,1]
...
In [160]: d
Out[160]: array([-82.34214769, -46.17107385])
and theta is then a simple sympy expression, not an object array containing an expression. Then theta_p evaluates fine.
We can evaluate gy1 at specific x1,x2 with evalf instead of lambdify:
In [174]: xsub = {x1:1, x2:1}
In [175]: d = [-1*gy1.evalf(subs=xsub), -1*gy2.evalf(subs=xsub)]
In [176]: d
Out[176]: [-82.3421476927507, -46.1710738463753]

Harder equations (with Derivatives and Integrals) and ConditionSet in SymPy

I am planning to calculate b (Its also x on Xo axis) for which curve (function) length from 0 to x is equal 1.
By knowing: https://www.mathsisfun.com/calculus/arc-length.html
(integral from 0 to b) ∫ (1 + ((f’(x))^2)^(1/2) dx = 1
and that:
(integral from a to b) ∫ f(x)dx = F(b) - F(a)
We can calculate it by
1 - F(0) + F(b) = 0 , where this is now an Equation in terms of x, beacuse b as I said is x on Xo axis.
So now I tried it for f(x) = x**3 (full code will be below)
F(b) is equal to this monster: https://www.wolframalpha.com/input/?i=integral&assumption=%7B%22C%22%2C+%22integral%22%7D+-%3E+%7B%22Calculator%22%7D&assumption=%7B%22F%22%2C+%22Integral%22%2C+%22integrand%22%7D+-%3E%22%281+%2B+9x%5E4%29%5E%281%2F2%29%22
All I get from SymPy is ConditionSet but not number. Of course ConditionSet cannot be evauluated by evalf()
So here are my questions:
Did I make a mistake in math?
Is my code wrong and how to improve it?
Is SymPy enough to calculate this?
Did I misunderstand documentation?
Code:
from __future__ import division
import matplotlib.pyplot as plt
from sympy import *
x, y, z = symbols('x y z', real=True)
function1 = x**3
Antiderivative1 = integrate((1+(diff(function1))**2)**(1/2), x)
b = solveset(Eq(1 + Antiderivative1.subs(x, 0).evalf() - Antiderivative1, 0), x)
print(b)
Thats the output:
ConditionSet(x, Eq(x*hyper((-0.5, 1/4), (5/4,), 9*x**4*exp_polar(I*pi)) - 4.0*gamma(5/4)/gamma(1/4), 0), Complexes)
Thanks in advance and sorry for mistakes in grammar.
Note that you should use S(1)/2 or Rational(1, 2) (or sqrt) rather than 1/2 which will give you a float in Python. With that we have
In [16]: integrand = sqrt(1 + ((x**3).diff(x))**2)
In [17]: integrand
Out[17]:
__________
╱ 4
╲╱ 9⋅x + 1
In [18]: antiderivative = integrand.integrate(x)
In [19]: antiderivative
Out[19]:
┌─ ⎛-1/2, 1/4 │ 4 ⅈ⋅π⎞
x⋅Γ(1/4)⋅ ├─ ⎜ │ 9⋅x ⋅ℯ ⎟
2╵ 1 ⎝ 5/4 │ ⎠
─────────────────────────────────────
4⋅Γ(5/4)
While that isn't the same form as the result from Wolfram Alpha it could easily be the same function (up to an additive constant). From this result or the one on Wolfram Alpha I very much doubt that you will find an analytic solution (using SymPy or anything else).
You can however find a numerical solution. Unfortunately there is a bug in SymPy's lambdify function that means nsolve doesn't work with this function:
In [22]: nsolve(equation, x, 1)
...
NameError: name 'exp_polar' is not defined
We can do it ourselves with Newton steps though:
In [76]: f = equation.lhs
In [77]: fd = f.diff(x)
In [78]: newton = lambda xi: (xi - f.subs(x, xi)/fd.subs(x, xi)).evalf()
In [79]: xj = 1.0
In [80]: xj = newton(xj); print(xj)
0.826749667942050
In [81]: xj = newton(xj); print(xj)
0.791950624620750
In [82]: xj = newton(xj); print(xj)
0.790708415511451
In [83]: xj = newton(xj); print(xj)
0.790706893629886
In [84]: xj = newton(xj); print(xj)
0.790706893627605
In [85]: xj = newton(xj); print(xj)
0.790706893627605

Categories

Resources