Solving normal equations in sympy - python

I'm trying to learn SymPy, and I'd like to figure out how to do a cool task, deriving the normal equations for a least-squares problem symbolically.
from sympy import *
init_session()
x, y, b = Matrix(), Matrix(), Matrix()
sqNorm = (y - x*b).dot(y- x*b)
solve(diff(sqNorm, b), b)
When I run that, I get
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "/usr/local/lib/python2.7/dist-packages/sympy/core/function.py", line 1638, in diff
return Derivative(f, *symbols, **kwargs)
File "/usr/local/lib/python2.7/dist-packages/sympy/core/function.py", line 1005, in __new__
if v._diff_wrt:
File "/usr/local/lib/python2.7/dist-packages/sympy/matrices/matrices.py", line 3084, in __getattr__
"%s has no attribute %s." % (self.__class__.__name__, attr))
AttributeError: ImmutableMatrix has no attribute _diff_wrt.
I am hoping for a result like (x'x)^{-1}x'y or something. Is that possible in SymPy?

No, SymPy doesn't come with this level of abstract matrix calculus built-in. To be able to differentiate matrices, they have to have specific size and be filled with things you can differentiate in: I give an example below. That said, you may be interested in this project, which implements elements of abstract matrix calculus in SymPy by axiomatizing certain rules.
Here is a sample of you can actually do in terms of symbolic least squares with SymPy. Filling matrices with symbolic variables can be done with symarray (which uses a_0_0 notation). Then compute the residuals, differentiate, and solve.
from sympy import *
m = 3
n = 2
x = Matrix(symarray('x', (m, n)))
y = Matrix(symarray('y', (m, 1)))
b = Matrix(symarray('b', (n, 1)))
z = (y-x*b).dot(y-x*b)
vars = [b[i,0] for i in range(n)]
eqs = [z.diff(b) for b in vars]
print solve(eqs, vars)
The output, though correct, is not enlightening:
{b_0_0: ((x_0_1**2 + x_1_1**2 + x_2_1**2)*(x_0_0*y_0_0 + x_1_0*y_1_0 + x_2_0*y_2_0) - (x_0_0*x_0_1 + x_1_0*x_1_1 + x_2_0*x_2_1)*(x_0_1*y_0_0 + x_1_1*y_1_0 + x_2_1*y_2_0))/((x_0_0**2 + x_1_0**2 + x_2_0**2)*(x_0_1**2 + x_1_1**2 + x_2_1**2) - (x_0_0*x_0_1 + x_1_0*x_1_1 + x_2_0*x_2_1)**2), b_1_0: ((x_0_0**2 + x_1_0**2 + x_2_0**2)*(x_0_1*y_0_0 + x_1_1*y_1_0 + x_2_1*y_2_0) - (x_0_0*x_0_1 + x_1_0*x_1_1 + x_2_0*x_2_1)*(x_0_0*y_0_0 + x_1_0*y_1_0 + x_2_0*y_2_0))/((x_0_0**2 + x_1_0**2 + x_2_0**2)*(x_0_1**2 + x_1_1**2 + x_2_1**2) - (x_0_0*x_0_1 + x_1_0*x_1_1 + x_2_0*x_2_1)**2)}

Related

Getting a: "TypeError: 'numpy.float64' object is not callable" error in program related to Bessel functions

The aim of the program is to:
"Write a python function J(m,x) that calculates the value of Jm(x) using the trapezium rule, with N = 10000. Use your function in a program to make a plot of the Bessel functions J0(x), J1(x) and J2(x) as a function of x from x = 0 to x = 20."
Jm(x) = (1/pi) . integrate[cos(m.theta - x.sin(theta))] from 0 --> pi
and is part of an intro to python module for a 1st year physics degree.
The line the type error originates from is from my function to integrate a function using the trapezium rule:
def integrate(f, a, b, N:int):
h = (b-a) / N
s = 0
for i in range(1,N):
c = f(a + i*h)
s = s + c
Area = h*(0.5*f(a) + 0.5*f(b) + s)
return Area
The error refers to the line " c = f(a + i*h) ": "TypeError: 'numpy.float64' object is not callable".
Given this function works in other programs I've made, I'm not sure what the origin of this error is. I am aware that scipy.integrate.quad could do the integration better, however we've been asked not to use it to demonstrate learning different techniques.
One possibility is that the problem is caused by other parts of the larger program. As someone very new to programming in general it seems likely that other problems exist which I haven't run into yet as the program doesn't reach them before turning up an error. The rest of the code is as follows:
import numpy as np
#Defining how to integrate a function using the trapezium rule
def integrate(f, a, b, N:int):
h = (b-a) / N
s = 0
for i in range(1,N):
c = f(a + i*h)
s = s + c
Area = h*(0.5*f(a) + 0.5*f(b) + s)
return Area
def func(o, m, x):
return np.cos(m*o - x*np.sin(o)) #1st attempt at defining the bessel function
def J(m,x):
return (1 / np.pi) * integrate(func(0, m, x), 0, np.pi, 10000)
#Produce range of x-values from 0 to 20.
xvals = np.linspace(0,20,200)
#Calculating the value of the bessel function for each value of x and m
for i in range(200):
for j in range(3):
bessel = J(j, xvals[i])
print("x: {}, m: {}, Val: {}".format(xvals[i], j, bessel)) #Print statement to check the program is functioning correctly before moving on to the next stage
return (1 / np.pi) * integrate(func(0, m, x), 0, np.pi, 10000)
In your function J, you are giving a function call as a parameter, i.e. its return value. Change func(0, m, x) to func and it should work.
Edit:
The correct answer was to pass a lambda expression: lambda i: func(i, m, x). Credit goes to Barmar.

Sympy ValueError: First variable cannot be a number

So I am coding a Kinematics problem for physics. I have a formula for the displacement. The code correctly gives me the derivative (velocity) and second derivative (acceleration). But when I try to solve for a variable out of any of the derivatives I get weird errors. It will give me the value of the displacement though!
import numpy as np
import sympy
import matplotlib.pyplot as plt
from sympy import *
x, y, z, t = symbols('x y z t')
i, j, k = symbols('i j k')
init_printing(use_unicode=True)
# **********************************************************************************
#Question 1 - The position of an electron is given by r = 3.0t(i) − 4.0t^2(j) + 2.0(k) (where t is in
#seconds and the coefficients have the proper units for r to be in meters).
#(a) What is v(t) for the electron?
#(b) In unit–vector notation, what is v at t = 2.0 s?
#(c) What are the magnitude and direction of v just then?
def r(t):
return (3*t)*i-(4*t*t)*j+2*k
def v(t):
return diff(r(t), t)
def a(t):
return diff(v(t), t)
print("Questions 1 -")
print("a)")
print("r(t) = ", r(t))
print("v(t) = ", v(t))
print("a(t) = ", a(t))
print("")
print('b)')
print("R(2) = ", r(2))
print("v(2) = ", v(2))
When I hit run, this is the output:
Questions 1 -
a)
r(t) = 3*i*t - 4*j*t**2 + 2*k
v(t) = 3*i - 8*j*t
a(t) = -8*j
b)
R(2) = 6*i - 16*j + 2*k
Traceback (most recent call last):
File "/tmp/sessions/b12e4bdebdf741f3/main.py", line 48, in <module>
print("v(2) = ", v(2))
File "/tmp/sessions/b12e4bdebdf741f3/main.py", line 35, in v
return diff(r(t), t)
File "/usr/local/lib/python3.6/dist-packages/sympy/core/function.py", line 1979, in diff
return Derivative(f, *symbols, **kwargs)
File "/usr/local/lib/python3.6/dist-packages/sympy/core/function.py", line 1156, in __new__
raise ValueError("First variable cannot be a number: %i" % v)
ValueError: First variable cannot be a number: 2
Short answer:
v(2) means differentiate r(2) with respect to 2.
2 is not a symbol so you get the error. You need an additional argument in your function v().
def v(t,at_point):
return diff(r(t), t, at_point)
v(t,2)
#-8⋅j
Long answer:
The problem is the following is that when you do:
v(2)
you are asking for:
diff(r(2), 2)
The last means to Differentiate r(2) with respect to 2. 2 is not a symbol so you get the error. You need an additional argument.
def v(t,at_point):
return diff(r(t), t, at_point)
You should define your function as follows:
def v(t,t0):
return diff(r(t), t, t0)
and then call it using v(t,2)

Simplify Quadratic Vertex Form Equation to Standard Form

I wanted to make a function to get a quadratic equation given the vertex and a point. I got all of this right until, I was using sympy to simplify the expression because that's how it gets to standard form, but it gave me an error. Here is my code:
from math import sort
from sympy import *
x = Symbol('x')
def point_cd_vertex_hk(c,d,h,k):
a = (d - k) / (c - h) ** 2
equation = a * (x + h) ** 2 + k
print(f"Your equation is y = {equation}")
point_cd_vertex_hk(2,4,6,8)
And with this I got the error:
Traceback (most recent call last):
File "/Users/michaeldavid/Desktop/Coding/Python/Standard/quadratic_for_project.py",
line 11, in
quad_point_cd_vertex_hk(2,4,6,8)
File "/Users/michaeldavid/Desktop/Coding/Python/Standard/quadratic_for_project.py",
line 8, in quad_point_cd_vertex_hk
equation = a (x + h) ** 2 + k
TypeError: 'float' object is not callable
I have an idea that it might be something with the fact that the "a" value is a floating point number, but I don't know what is really causing the problem.
What does it mean and how do I fix this?
It seems you are typo in this line equation = a (x + h) ** 2 + k. 'a' is not a function. May be a * (x+h) is what you are looking for

python complex_ode pass matrix-valued parameters

I'm having some trouble with python's complex_ode solver.
I'm trying to solve the following equation:
dy/dt = -iAy - icos(Omegat)By
where A and B are NxN arrays and the unknown y is an Nx1 array, i is the imaginary unit and Omega is a parameter.
Here's my code:
import numpy as np
from scipy.integrate import ode,complex_ode
N = 3 #linear matrix dim
Omega = 1.0 #parameter
# define symmetric matrices A and B
A = np.random.ranf((N,N))
A = (A + A.T)/2.0
B = np.random.ranf((N,N))
B = (B + B.T)/2.0
# define RHS of ODE
def f(t,y,Omega,A,B):
return -1j*A.dot(y)-1j*np.cos(Omega*t)*B.dot(y)
# define list of parameter
params=[Omega,A,B]
# choose solver: need complex_ode for this ODE
#solver = ode(f)
solver = complex_ode(f)
solver.set_f_params(*params)
solver.set_integrator("dop853")
# set initial value
v0 = np.zeros((N,),dtype=np.float64)
v0[0] = 1.0
# check that the function f works properly
print f(0,v0,Omega,A,B)
# solve-check the ODE
solver.set_initial_value(v0)
solver.integrate(10.0)
print solver.successful()
Running this script produces the error
capi_return is NULL
Call-back cb_fcn_in___user__routines failed.
Traceback (most recent call last):
File "ode_test.py", line 37, in <module>
solver.integrate(10.0)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/scipy/integrate/_ode.py", line 515, in integrate
y = ode.integrate(self, t, step, relax)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/scipy/integrate/_ode.py", line 388, in integrate
self.f_params, self.jac_params)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/scipy/integrate/_ode.py", line 946, in run
tuple(self.call_args) + (f_params,)))
File "/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/scipy/integrate/_ode.py", line 472, in _wrap
f = self.cf(*((t, y[::2] + 1j * y[1::2]) + f_args))
TypeError: f() takes exactly 5 arguments (2 given)
If instead I use solver = ode(f), ie. the real-valued solver, it runs fine. Except that it doesn't solve the ODE I want which is complex-valued :(
I then tried to reduce the number of parameters by making the matrices A and B global variables. This way the only parameter the function f accepts is Omega. The error changes to
capi_return is NULL
Call-back cb_fcn_in___user__routines failed.
Traceback (most recent call last):
File "ode_test.py", line 37, in <module>
solver.integrate(10.0)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/scipy/integrate/_ode.py", line 515, in integrate
y = ode.integrate(self, t, step, relax)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/scipy/integrate/_ode.py", line 388, in integrate
self.f_params, self.jac_params)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/scipy/integrate/_ode.py", line 946, in run
tuple(self.call_args) + (f_params,)))
File "/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/scipy/integrate/_ode.py", line 472, in _wrap
f = self.cf(*((t, y[::2] + 1j * y[1::2]) + f_args))
TypeError: 'float' object has no attribute '__getitem__'
where I figured out that float refers to the parameter Omega [by trying an integer]. Again, "ode" alone works in this case as well.
Last, I tried the same complex valued equation, but now A and B are just numbers. I tried to pass them both as parameters, i.e. params = [Omega,A,B], as well as making them global variables in which case params=[Omega]. The error is the
TypeError: 'float' object has no attribute '__getitem__'
error - the full error is the same as above. And once again this problem does not occur for the real-valued "ode".
I know zvode is an alternative, but it appears to become quite slow for large N. In the real problem I have, A is a diagonal matrix but B is a non-sparse full matrix.
Any insights are much appreciated! I'm interested both in (i) alternative ways to solve this complex-valued ODE with array-valued parameters, and (ii) how to get complex_ode to run :)
Thanks!
It seems like the link that Reti43 posted contains the answer, so let me put it here for the benefit of future users:
from scipy.integrate import complex_ode
import numpy as np
N = 3
Omega = 1.0;
class myfuncs(object):
def __init__(self, f, fargs=[]):
self._f = f
self.fargs=fargs
def f(self, t, y):
return self._f(t, y, *self.fargs)
def f(t, y, Omega,A,B):
return -1j*(A+np.cos(Omega*t)*B).dot(y)
A = np.random.ranf((N,N))
A = (A + A.T)/2.0
B = np.random.ranf((N,N))
B = (B + B.T)/2.0
v0 = np.zeros((N,),dtype=np.float64)
v0[0] = 1.0
t0 = 0
case = myfuncs(f, fargs=[Omega, A, B] )
solver = complex_ode(case.f)
solver.set_initial_value(v0, t0)
solver.integrate([10.0])
print solver.successful()
"""
t1 = 10
dt = 1
while solver.successful() and solver.t < t1:
solver.integrate(solver.t+dt)
print(solver.t, solver.y)
"""
Could maybe someone comment on why this trick does the job?

Error in sympy.solve on Freudenstein equation

I'm trying to obtain one of the angles of Freudenstein equation (psi):
k1 * cos(psi) - k2 * cos(fi) + k3 - cos(psi - fi) = 0
I have k1, k2, k3 and fi values. I tried the following:
from sympy import Symbol, solve, cos
x = Symbol('x')
realPsi = solve(k1 * cos(x) - k2 * cos(fi) + k3 - cos(x - fi), x)
I receive this error:
File "/usr/lib/python2.7/dist-packages/sympy/solvers/solvers.py", line 484, in solve solution = _solve(f, *symbols, **flags)
File "/usr/lib/python2.7/dist-packages/sympy/solvers/solvers.py", line 700, in _solve soln = tsolve(f_num, symbol)
File "/usr/lib/python2.7/dist-packages/sympy/solvers/solvers.py", line 1143, in tsolve "(tsolve: at least one Function expected at this point")
NotImplementedError: Unable to solve the equation(tsolve: at least one Function expected at this point
I don't use this kind of tools before, maybe I'm doing something really wrong...
Any idea?
Thanks,
Héctor.
EDIT:
Thanks for the fast response.
I tried the following (simple equation with cos):
eq = 3.2 * cos(x + 0.2).rewrite(exp) + 1.7
eq
Out[1]: 1.6*exp(I*(-x - 0.2)) + 1.6*exp(I*(x + 0.2)) + 1.7
solve(1.6*exp(I*(-x - 0.2)) + 1.6*exp(I*(x + 0.2)) + 1.7, x)
NotImplementedError: Unable to solve the equation(tsolve: at least one Function expected at this point
Am I using correctly .rewrite??
Of course it should "just work" but here is a case where, with a little help for the "simpler equation with cos" given above you can get an answer:
>>> eq=3.2*cos(x+.2)+1.7
>>> [w.n(3,chop=True) for w in solve(expand(eq.rewrite(exp)))]
[-2.33, 1.93]
NotImplementedError means what it says, namely that a solver for this type of equations is "not implemented".
You can help SymPy a bit to find the solution:
>>> k * cos(x) - m * cos(y) + n - cos(x - y)
k*cos(x) - m*cos(y) + n - cos(x - y)
>>> _.rewrite(exp)
k*(exp(I*x)/2 + exp(-I*x)/2) - .....
>>> solve(_, x)
..... long solution
You can use rewrite to transform expressions written with trigonometric functions into expressions containing complex exponentials.

Categories