I want to convert the following SDP — which just verifies the feasibility of the constraints — from CVX (MATLAB) to CVXPY (Python):
Ah = [1.0058, -0.0058; 1, 0];
Bh = [-1; 0];
Ch = [1.0058, -0.0058; -0.9829, 0.0056];
Dh = [-1; 1];
M = [0, 1;1, 0];
ni = size(M,1)/2;
n = size(Ah,1);
rho = 0.5;
cvx_begin sdp quiet
variable P(n,n) semidefinite
variable lambda(ni) nonnegative
Mblk = M*kron(diag(lambda),eye(2));
lambda(ni) == 1 % break homogeneity (many ways to do this...)
[Ah Bh]'*P*[Ah Bh] - rho^2*blkdiag(P,0) + [Ch Dh]'*Mblk*[Ch Dh] <= 0
cvx_end
switch cvx_status
case 'Solved'
feas = 1;
otherwise
feas = 0;
end
Below is my Python code,
import cvxpy as cvx
import numpy as np
import scipy as sp
Ah = np.array([[1.0058, -0.0058], [1, 0]])
Bh = np.array([[-1], [0]])
Ch = np.array([[1.0058, -0.0058], [-0.9829, 0.0056]])
Dh = np.array([[-1], [1]])
M = np.array([[0, 1], [1, 0]])
ni, n = M.shape[0] / 2, Ah.shape[0]
rho = 0.5
P = cvx.Semidef(n)
lamda = cvx.Variable()
Mblk = np.dot(M, np.kron(cvx.diag(lamda), np.eye(2)))
ABh = np.concatenate((Ah, Bh), axis=1)
CDh = np.concatenate((Ch, Dh), axis=1)
constraints = [lamda[-1] == 1,
np.dot(ABh.T, np.dot(P, ABh)) - rho**2*np.linalg.block_diag(P, 0) +
np.dot(CDh.T, np.dot(Mblk, CDh)) << 0]
prob = cvx.Problem(cvx.Minimize(1), constraints)
feas = prob.status is cvx.OPTIMAL
There are several errors when I run the program.
1. When I print Mblk, it shows
Traceback (most recent call last):
File
"/usr/lib/python2.7/dist-packages/IPython/core/interactiveshell.py",
line 2820, in run_code
Out[1]: exec code_obj in self.user_global_ns, self.user_ns
File "", line 1, in
Mblk
File "/usr/lib/python2.7/dist-packages/IPython/core/displayhook.py",
line 247, in call
format_dict, md_dict = self.compute_format_data(result)
File "/usr/lib/python2.7/dist-packages/IPython/core/displayhook.py",
line 157, in compute_format_data
return self.shell.display_formatter.format(result)
File "/usr/lib/python2.7/dist-packages/IPython/core/formatters.py",
line 152, in format
data = formatter(obj)
File "/usr/lib/python2.7/dist-packages/IPython/core/formatters.py",
line 481, in call
printer.pretty(obj)
File "/usr/lib/python2.7/dist-packages/IPython/lib/pretty.py", line
362, in pretty
return _default_pprint(obj, self, cycle)
File "/usr/lib/python2.7/dist-packages/IPython/lib/pretty.py", line
482, in _default_pprint
p.text(repr(obj))
File "/usr/lib/python2.7/dist-packages/numpy/core/numeric.py", line
1553, in array_repr
', ', "array(")
File "/usr/lib/python2.7/dist-packages/numpy/core/arrayprint.py", line
454, in array2string
separator, prefix, formatter=formatter)
File "/usr/lib/python2.7/dist-packages/numpy/core/arrayprint.py", line
256, in _array2string
'int' : IntegerFormat(data),
File "/usr/lib/python2.7/dist-packages/numpy/core/arrayprint.py", line
641, in init
max_str_len = max(len(str(maximum.reduce(data))),
File
"/usr/local/lib/python2.7/dist-packages/cvxpy/constraints/leq_constraint.py",
line 67, in nonzero
Raise Exception("Cannot evaluate the truth value of a constraint.")
Exception: Cannot evaluate the truth value of a constraint.
When I step to this line,
constraints = [lamda[-1] == 1,
np.dot(ABh.T, np.dot(P, ABh)) - rho**2*np.linalg.block_diag(P, 0) +
np.dot(CDh.T, np.dot(Mblk, CDh)) << 0]
it shows
Traceback (most recent call last): File
".../sdp.py", line 22, in
np.dot(ABh.T, np.dot(P, ABh)) - rho**2*np.linalg.block_diag(P, 0) +
ValueError: setting an array element with a sequence.
How to fix these problems?
The big issue with your code is that you can't use NumPy functions on CVXPY objects. You need to use the equivalent CVXPY functions. Here's a working version of your code:
import cvxpy as cvx
import numpy as np
import scipy as sp
Ah = np.array([[1.0058, -0.0058], [1, 0]])
Bh = np.array([[-1], [0]])
Ch = np.array([[1.0058, -0.0058], [-0.9829, 0.0056]])
Dh = np.array([[-1], [1]])
M = np.array([[0, 1], [1, 0]])
ni, n = M.shape[0] / 2, Ah.shape[0]
rho = 0.5
P = cvx.Semidef(n)
lamda = cvx.Variable()
Mblk = M*lamda*np.eye(2)
ABh = cvx.hstack(Ah, Bh)
CDh = cvx.hstack(Ch, Dh)
zeros = np.zeros((n,1))
constraints = [lamda[-1] == 1,
ABh.T*P*ABh - rho**2*cvx.bmat([[P,zeros],[zeros.T, 0]]) +
CDh.T*Mblk*CDh << 0]
prob = cvx.Problem(cvx.Minimize(1), constraints)
prob.solve()
feas = prob.status is cvx.OPTIMAL
I removed the kron function because it wasn't doing anything here and CVXPY doesn't currently support Kronecker products with a variable left-hand side. I can add it if you need it.
Related
In my python code, I keep getting the following error:
TypeError: No loop matching the specified signature and casting was found for ufunc svd_n
the code is as follows:
import numpy as np
from numpy.linalg import norm
def sdm_3eqs():
def f_bold(x):
return [15*x[0] + x[1]**2 - 4*x[2] - 15, x[0]**2 + 10*x[1] - x[2] - 10, x[1]**3 - 25*x[2] + 24]
def f(x):
f_n = []
for i in range(len(x)):
f_i = f_bold[i]**2
f_n.append(f_i)
return np.sum(f_n)
def M(x):
m = np.array([[15, 2*x[0], 0], [2*x[1], 10, 3*x[1]**2], [-4, -1, -25]])
return m
def grad_f(x):
return 2*M(x)*f_bold(x)
def d(x):
return -grad_f(x)/norm(grad_f(x), ord=2)
def s_prime(x, alpha, d):
return grad_f(x + alpha*d)*d
x = [0.5, 0.5, 0.5]
iter = 0
err = 100
while err > 0.005:
x_k = x
d_k = d(x_k)
m = 0
sprime = 300
alpha_l = 0
alpha_u = 1.5
alpha = (alpha_l+alpha_u)/2
while abs(sprime) > 0.0005:
alpha = (alpha_l+alpha_u)/2
sprime = s_prime(x_k, alpha, d_k)[0][0]
if abs(sprime) < 0.001:
break
elif sprime > 0:
alpha_u = alpha
else:
alpha_l = alpha
m += 1
iter += 1
x = x_k + alpha*d_k
err = norm(grad_f(x), ord=2)/max(1, norm(f_bold(x), ord=2))
print(f'f_bold: {f_bold(x)}')
sdm_3eqs()
I am unsure why but it says the type error come from line 57 in the code:
err = norm(grad_f(x), ord=2)/max(1, norm(f_bold(x), ord=2))
If anyone can help, that would be great!
EDIT:
Traceback (most recent call last):
File "/Users/aidanpayne/Desktop/Scripts/Python/University of Greenwich/MATH1157/Scripts/Steepest Descent Method.py", line 61, in <module>
sdm_3eqs()
File "/Users/aidanpayne/Desktop/Scripts/Python/University of Greenwich/MATH1157/Scripts/Steepest Descent Method.py", line 57, in sdm_3eqs
err = norm(grad_f(x), ord=2)/max(1, norm(f_bold(x), ord=2))
File "<__array_function__ internals>", line 5, in norm
File "/Users/aidanpayne/opt/anaconda3/lib/python3.8/site-packages/numpy/linalg/linalg.py", line 2579, in norm
ret = _multi_svd_norm(x, row_axis, col_axis, amax)
File "/Users/aidanpayne/opt/anaconda3/lib/python3.8/site-packages/numpy/linalg/linalg.py", line 2355, in _multi_svd_norm
result = op(svd(y, compute_uv=False), axis=-1)
File "<__array_function__ internals>", line 5, in svd
File "/Users/aidanpayne/opt/anaconda3/lib/python3.8/site-packages/numpy/linalg/linalg.py", line 1673, in svd
s = gufunc(a, signature=signature, extobj=extobj)
TypeError: No loop matching the specified signature and casting was found for ufunc svd_n
It looks like the M(x) function is returning a 3-dimensional array, of structure
[
[ a [b c d] e ]
[[f g h] i [k l m]]
[ n o p ]
]
and then you're attempting to matrix-multiply that with the result of f_bold(x) and calculate the norm.
I believe the error is related to trying to calculate the norm of this irregular matrix. In particular, check your function definition for M(x) to verify the shape/regularity of its returned array.
line 17: m = np.array([[15, 2*x[0], 0], [2*x[1], 10, 3*x[1]**2], [-4, -1, -25]])
^^^^ ^^^^ ^^^^
I added a couple of prints to your code, and got this run:
In [63]: sdm_3eqs()
<ipython-input-62-2b082fcea817>:14: VisibleDeprecationWarning: Creating an ndarray from ragged nested sequences (which is a list-or-tuple of lists-or-tuples-or ndarrays with different lengths or shapes) is deprecated. If you meant to do this, you must specify 'dtype=object' when creating the ndarray.
m = np.array([[15, 2*x[0], 0], [2*x[1], 10, 3*x[1]**2], [-4, -1, -25]])
f_bold
[array([ 6.64610017e-05, -8.57391288e+00, -1.40877199e+01]), array([-3.81306816, -3.03705309, -6.81097338]), array([ 15.47764768, 12.41073581, -18.41883603])]
grad_f
array([[0.0019938300511945783,
array([-36.8081748 , -17.89173085, -17.14782575]), -0.0],
[array([ -8.20903822, -10.93449844, -7.0767119 ]),
-60.74106175194817,
array([-11.83793275, -21.00337307, -8.79740011])],
[-123.82118142652486, -24.821471626766595, 920.9418016830625]],
dtype=object)
Traceback (most recent call last):
File "<ipython-input-63-8732d4079184>", line 1, in <module>
sdm_3eqs()
File "<ipython-input-62-2b082fcea817>", line 57, in sdm_3eqs
err = np.linalg.norm(grad_f(x), ord=2)/max(1, np.linalg.norm(f_bold(x), ord=2))
File "<__array_function__ internals>", line 5, in norm
File "/usr/local/lib/python3.8/dist-packages/numpy/linalg/linalg.py", line 2579, in norm
ret = _multi_svd_norm(x, row_axis, col_axis, amax)
File "/usr/local/lib/python3.8/dist-packages/numpy/linalg/linalg.py", line 2355, in _multi_svd_norm
result = op(svd(y, compute_uv=False), axis=-1)
File "<__array_function__ internals>", line 5, in svd
File "/usr/local/lib/python3.8/dist-packages/numpy/linalg/linalg.py", line 1672, in svd
s = gufunc(a, signature=signature, extobj=extobj)
UFuncTypeError: Cannot cast ufunc 'svd_n' input from dtype('O') to dtype('float64') with casting rule 'same_kind'
In new enough numpy versions, the creation of a "ragged array" gets this warning, and tells us that we are not creating a simple numeric array. Instead M is an object dtype array, containing a mix of numbers and arrays.
f_bold is a list of arrays. grad_f is a (3,3) object dtype array with a mix of floats and arrays.
And in the latest numpy version this kind of error specifies the problem dtype - which as I suspected is 'O', object.
norm cannot handle that kind of array. That's why I asked for the dtype of the 2 norm arguments.
I have solved it.
In some of the functions, it was supposed to be the dot product of two matrices.
e.g.:
def grad_f(x):
return 2*np.dot(M(x), f_bold(x))
Here's the updated code:
import numpy as np
from numpy.core.fromnumeric import shape
from numpy.linalg import norm
from numpy import transpose
from numpy import array
from numpy import sum
from matplotlib import pyplot as plt
def sdm_3eqs():
def f_bold(x):
x_1 = x[0]
x_2 = x[1]
x_3 = x[2]
return array([15*x_1 + x_2**2 - 4*x_3 - 15, x_1**2 + 10*x_2 - x_3 - 10, x_2**3 - 25*x_3 + 24], dtype='float32')
def f(x):
f_n = []
for i in range(len(x)):
f_i = f_bold[i]**2
f_n.append(f_i)
return sum(f_n)
def M(x):
x_1 = x[0]
x_2 = x[1]
d1 = 2*x_1
d2 = 2*x_2
d3 = 3*x_2**2
return array([[15, d1, 0], [d2, 10, d3], [-4, -1, -25]], dtype='float32')
def grad_f(x):
return 2*np.dot(M(x), f_bold(x))
def d(x):
return -1*grad_f(x)/norm(grad_f(x), ord=2)
def s_prime(x, alpha, d):
return np.dot(transpose(grad_f(x + alpha*d)), d)
x = array([[0.5], [0.5], [0.5]], dtype='float32')
iter = 0
err = 100
while err > 0.005:
x_k = x
d_k = d(x_k)
m = 0
sprime = 300
alpha_l = 0
alpha_u = 1.5
alpha = (alpha_l+alpha_u)/2
while abs(sprime) > 0.0005:
alpha = (alpha_l+alpha_u)/2
sprime = s_prime(x_k, alpha, d_k)
if abs(sprime) < 0.001:
break
elif sprime > 0:
alpha_u = alpha
else:
alpha_l = alpha
m += 1
iter += 1
x = x_k + alpha*d_k
err = norm(grad_f(x), ord=2)/max(1, norm(f_bold(x), ord=2))
print(f'\nf_bold:\nEquation 1 = {f_bold(x)[0][0]}\nEquation 2 = {f_bold(x)[1][0]}\nEquation 3 = {f_bold(x)[2][0]}\n')
sdm_3eqs()
This is my standalone code to reproduce the problem:
import numpy as np
from scipy.optimize import curve_fit
def find_vector_of_minor_axis_from_chunk(data):
n = 20 # number of points
time = np.linspace(0, 2 * np.pi, n)
guess_center_point = data.mean(1)
guess_center_point = guess_center_point[np.newaxis, :].transpose()
guess_a_phase = 0
guess_b_phase = 0
guess_a = 1
guess_b = 1
guess_a_axis_vector = np.array([[1], [0], [0]])
guess_b_axis_vector = np.array([[0], [1], [0]])
p0 = np.array([guess_center_point,
guess_a, guess_a_axis_vector, guess_a_phase,
guess_b, guess_b_axis_vector, guess_b_phase])
def ellipse_func(t, center_point, a, a_axis_vector, a_phase, b, b_axis_vector, b_phase):
return center_point + a * a_axis_vector * np.sin(t * a_phase) + b * b_axis_vector * np.sin(t + b_phase)
popt, pcov = curve_fit(ellipse_func, time, data, p0=p0)
center_point, a, a_axis_vector, a_phase, b, b_axis_vector, b_phase = popt
print(str(a_axis_vector, b_axis_vector))
shorter_vector = a_axis_vector
if np.abs(a_axis_vector) > np.aps(b_axis_vector):
shorter_vector = b_axis_vector
return shorter_vector
def main():
data = np.array([[-4.62767933, -4.6275775, -4.62735346, -4.62719652, -4.62711625, -4.62717975,
-4.62723845, -4.62722407, -4.62713901, -4.62708749, -4.62703238, -4.62689101,
-4.62687185, -4.62694013, -4.62701082, -4.62700483, -4.62697488, -4.62686825,
-4.62675683, -4.62675204],
[-1.58625998, -1.58625039, -1.58619648, -1.58617611, -1.58620606, -1.5861833,
-1.5861821, -1.58619169, -1.58615814, -1.58616893, -1.58613179, -1.58615934,
-1.58611262, -1.58610782, -1.58613179, -1.58614017, -1.58613059, -1.58612699,
-1.58607428, -1.58610183],
[-0.96714786, -0.96713827, -0.96715984, -0.96715145, -0.96716703, -0.96712869,
-0.96716104, -0.96713228, -0.96719698, -0.9671838, -0.96717062, -0.96717062,
-0.96715744, -0.96707717, -0.96709275, -0.96706519, -0.96715026, -0.96711791,
-0.96713588, -0.96714786]])
print(str(find_vector_of_minor_axis_from_chunk(data)))
if __name__ == '__main__':
main()
That gives me this traceback:
Traceback (most recent call last):
File "C:/Users/X/PycharmProjects/lissajous-achse/ellipse_fit.py", line 52, in <module>
main()
File "C:/Users/X/PycharmProjects/lissajous-achse/ellipse_fit.py", line 49, in main
print(str(find_vector_of_minor_axis_from_chunk(data)))
File "C:/Users/X/PycharmProjects/lissajous-achse/ellipse_fit.py", line 25, in find_vector_of_minor_axis_from_chunk
popt, pcov = curve_fit(ellipse_func, time, data, p0=p0)
File "C:\Users\X\PycharmProjects\lissajous-achse\venv\lib\site-packages\scipy\optimize\minpack.py", line 763, in curve_fit
res = leastsq(func, p0, Dfun=jac, full_output=1, **kwargs)
File "C:\Users\X\PycharmProjects\lissajous-achse\venv\lib\site-packages\scipy\optimize\minpack.py", line 392, in leastsq
raise TypeError('Improper input: N=%s must not exceed M=%s' % (n, m))
TypeError: Improper input: N=7 must not exceed M=3
Process finished with exit code 1
My code is an adaption of the second answer here. The problem causing the error message is solved by simple packing of variables here.
Why does the problem not surface in the mentioned second answer? And how can I pack my variables, which consist of several 3d vectors and individual scalars, to solve this problem? How do i pass in my t, which is a constant and should not be optimized?
Apparently python is quite smart regarding the length of the fields of the arguments, depending on the the initial guesses. So i could just pass in ONE variable, and split it up inside the function like so:
import numpy as np
from scipy.optimize import minimize
def find_vector_of_minor_axis_from_chunk(data):
n = 20 # number of points
guess_center_point = data.mean(1)
guess_center_point = guess_center_point[np.newaxis, :].transpose()
guess_a_phase = 0.0
guess_b_phase = 0.0
guess_a = 1.0
guess_b = 1.0
guess_a_axis_vector = np.array([[1.0], [0.0], [0.0]])
guess_b_axis_vector = np.array([[0.0], [1.0], [0.0]])
p0 = np.array([guess_center_point,
guess_a, guess_a_axis_vector, guess_a_phase,
guess_b, guess_b_axis_vector, guess_b_phase])
def ellipse_func(x, data):
center_point = x[0]
a = x[1]
a_axis_vector = x[2]
a_phase = x[3]
b = x[4]
b_axis_vector = x[5]
b_phase = x[6]
t = np.linspace(0, 2 * np.pi, n)
error = center_point + a * a_axis_vector * np.sin(t * a_phase) + b * b_axis_vector * np.sin(t + b_phase) - data
error_sum = np.sum(error**2)
print(str(error_sum))
return error_sum
popt, pcov = minimize(ellipse_func, p0, args=(data))
center_point, a, a_axis_vector, a_phase, b, b_axis_vector, b_phase = popt
print(str(a_axis_vector, b_axis_vector))
shorter_vector = a_axis_vector
if np.abs(a_axis_vector) > np.aps(b_axis_vector):
shorter_vector = b_axis_vector
return shorter_vector
def main():
data = np.array([[-4.62767933, -4.6275775, -4.62735346, -4.62719652, -4.62711625, -4.62717975,
-4.62723845, -4.62722407, -4.62713901, -4.62708749, -4.62703238, -4.62689101,
-4.62687185, -4.62694013, -4.62701082, -4.62700483, -4.62697488, -4.62686825,
-4.62675683, -4.62675204],
[-1.58625998, -1.58625039, -1.58619648, -1.58617611, -1.58620606, -1.5861833,
-1.5861821, -1.58619169, -1.58615814, -1.58616893, -1.58613179, -1.58615934,
-1.58611262, -1.58610782, -1.58613179, -1.58614017, -1.58613059, -1.58612699,
-1.58607428, -1.58610183],
[-0.96714786, -0.96713827, -0.96715984, -0.96715145, -0.96716703, -0.96712869,
-0.96716104, -0.96713228, -0.96719698, -0.9671838, -0.96717062, -0.96717062,
-0.96715744, -0.96707717, -0.96709275, -0.96706519, -0.96715026, -0.96711791,
-0.96713588, -0.96714786]])
print(str(find_vector_of_minor_axis_from_chunk(data)))
if __name__ == '__main__':
main()
Also i fixed some floating point vs integer errors in the vector for the initial values.
However now I get a different error:
Traceback (most recent call last):
File "C:/Users/X/PycharmProjects/lissajous-achse/ellipse_fit.py", line 61, in <module>
main()
File "C:/Users/X/PycharmProjects/lissajous-achse/ellipse_fit.py", line 58, in main
print(str(find_vector_of_minor_axis_from_chunk(data)))
File "C:/Users/X/PycharmProjects/lissajous-achse/ellipse_fit.py", line 34, in find_vector_of_minor_axis_from_chunk
popt, pcov = minimize(ellipse_func, p0, args=(data))
File "C:\Users\X\PycharmProjects\lissajous-achse\venv\lib\site-packages\scipy\optimize\_minimize.py", line 604, in minimize
return _minimize_bfgs(fun, x0, args, jac, callback, **options)
File "C:\Users\X\PycharmProjects\lissajous-achse\venv\lib\site-packages\scipy\optimize\optimize.py", line 1063, in _minimize_bfgs
if isinf(rhok): # this is patch for numpy
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
I guess that
The truth value of an array with more than one element is ambiguous.
Use a.any() or a.all()
is some internal error, stemming from the internal decision matrix how to proceed. I don't know how I caused it and how to fix it. When i figure out how it is done properly, I will come back and edit this answer.
I am trying to complete this, where I have to solve five ordinary
differential equations using odeint and reproduce figures given in that task.
Here is my code:
import scipy as sp
import scipy.interpolate as ip
import numpy as np
import matplotlib.pyplot as pl
d = 8.64
Mu1 = 4.95*10**2
Mu2 = 4.95*10**(-2)
vs = 0.12
vd = 1.23
w = 10**(-3)
k1 = 2.19*10**(-4)
k2 = 6.12*10**(-5)
k3 = 0.997148
k4 = 6.79*10**(-2)
p0 = 1.00
sigmas0 = 2.01
sigmad0 = 2.23
alphas0 = 2.20
alphad0 = 2.26
hs = (sigmas0-(sigmas0**(2)-k3*alphas0*(2*sigmas0-alphas0))**(1/2))/k3
cs = (alphas0-hs)/2
ps = k4*(hs**2)/cs
t_points = [ 1000, 1850, 1950, 1980, 2000, 2050, 2080, 2100, 2120, 2150, 2225, 2300, 2500, 5000 ]
y_points = [ 0.0, 0.0, 1.0, 4.0, 5.0, 8.0, 10.0, 10.5, 10.0, 8.0, 3.5, 2.0, 0.0, 0.0 ]
t1 = np.array(t_points)
y1 = np.array(y_points)
new_length = 1000
new_t = np.linspace(t1.min(), t1.max(), new_length)
new_y2 = ip.pchip_interpolate(t1, y1, new_t)
pl.plot(t_points,y_points,'o', new_t,new_y2)
pl.show()
ft = sp.interpolate.interp1d(new_t, new_y2)
def equations(x, t1):
p = x[0]
alphad = x[1]
alphas = x[2]
sigmad = x[3]
sigmas = x[4]
dpdt = (ps-p)/d + ft/Mu1
dalphaddt = (1/vd)*(k2-w*(alphad-alphas))
dalphasdt = (1/vs)*(w*(alphad-alphas)-k2)
dsigmaddt = (1/vd)*(k1-w*(sigmad-sigmas))
dsigmasdt = (1/vs)*(w*(sigmad-sigmas)-k1-(ps-p)/d*Mu2)
return [dpdt, dalphaddt, dalphasdt, dsigmaddt, dsigmasdt]
solve = sp.integrate.odeint(equations, [p0, alphad0, alphas0, sigmad0, sigmas0], t1)
It seems like this part:
dpdt = (ps-p)/d + ft/Mi1
is wrong and I have no idea how to solve it.
The error says:
TypeError: unsupported operand type(s) for /: 'interp1d' and 'float'.
Any ideas and advices are much appreciated.
EDIT: When I apply changes suggested by meowgoesthedog, I get error:
Traceback (most recent call last):
File "<ipython-input-5-324757833872>", line 1, in <module>
runfile('E:/Data/Project 2/project2.py', wdir='E:/Data/Project 2')
File "D:\Programs\Anaconda3\lib\site-packages\spyder_kernels\customize\spydercustomize.py", line 668, in runfile
execfile(filename, namespace)
File "D:\Programs\Anaconda3\lib\site-packages\spyder_kernels\customize\spydercustomize.py", line 108, in execfile
exec(compile(f.read(), filename, 'exec'), namespace)
File "E:/Data/Project 2/project2.py", line 59, in <module>
solve = odeint(equations, [p0, alphad0, alphas0, sigmad0, sigmas0], t1)
File "D:\Programs\Anaconda3\lib\site-packages\scipy\integrate\odepack.py", line 233, in odeint
int(bool(tfirst)))
File "E:/Data/Project 2/project2.py", line 51, in equations
dpdt = (ps-p)/d + ft(t1)/Mu1
File "D:\Programs\Anaconda3\lib\site-packages\scipy\interpolate\polyint.py", line 79, in __call__
y = self._evaluate(x)
File "D:\Programs\Anaconda3\lib\site-packages\scipy\interpolate\interpolate.py", line 664, in _evaluate
below_bounds, above_bounds = self._check_bounds(x_new)
File "D:\Programs\Anaconda3\lib\site-packages\scipy\interpolate\interpolate.py", line 696, in _check_bounds
raise ValueError("A value in x_new is above the interpolation "
ValueError: A value in x_new is above the interpolation range.
`
According to interp1d's documentation:
ynew = f(xnew) # use interpolation function returned by interp1d
It returns a function / callable object which takes a value x and returns the interpolated value of f(x). In your case "x" = t:
dpdt = (ps-p)/d + ft(t1)/Mu1 # pass t1 to ft to obtain interpolated value
UPDATE
This new error is due to odeint sampling the function f(t) at values of t beyond the last value of t_points. This is necessary for error correction and there is no option to prevent odeint from doing so. However, we can instead extrapolate f(t) beyond the supplied samples, using InterpolatedUnivariateSpline:
from scipy.interpolate import InterpolatedUnivariateSpline
...
ft = InterpolatedUnivariateSpline(t1, y1, k=1)
As with interp1d, this returns a function with the same signature. However, after applying this fix the result becomes:
Which is of course incorrect.
You have declared hs, cs, ps outside of the function as constants. In-fact they are functions of the alpha* and sigma* variables, so have to be evaluated during each call to equation:
def equations(x, t):
p = x[0]
alphad = x[1]
alphas = x[2]
sigmad = x[3]
sigmas = x[4]
hs = (sigmas-(sigmas**(2)-k3*alphas*(2*sigmas-alphas))**(1/2))/k3
cs = (alphas-hs)/2
ps = k4*(hs**2)/cs
dpdt = (ps-p)/d + ft(t)/Mu1
dalphaddt = (1/vd)*(k2-w*(alphad-alphas))
dalphasdt = (1/vs)*(w*(alphad-alphas)-k2)
dsigmaddt = (1/vd)*(k1-w*(sigmad-sigmas))
dsigmasdt = (1/vs)*(w*(sigmad-sigmas)-k1-(ps-p)/d*Mu2)
return [dpdt, dalphaddt, dalphasdt, dsigmaddt, dsigmasdt]
The result now matches the graph in the exercise... almost.
You passed t1 as the horizontal axis variable to odeint. It only has 14 elements which is too few for a smooth output. Pass new_t instead:
solve = ig.odeint(equations, [p0, alphad0, alphas0, sigmad0, sigmas0], new_t)
The result now exactly matches the expected one!
I want to model a multivariate (bivariate in the example) normal with separate means and a covariance matrix, somehow I just can't get the dimensions to match. The model is relatively straight forward, here is the data generating process:
import numpy as np
import pymc3 as pm
import theano.tensor as tt
np.random.seed(123)
N = 200
# x1 and x2 are independent variables
x1 = np.random.randn(N)
x2 = np.random.randn(N)
α1, β1, α2, β2 = np.random.randn(4)
# the means of the joint distribution
μ1 = α1 + β1 * x1
μ2 = α2 + β2 * x2
# the covariance of the joint distribution
σ = 1, 2
Ω = np.array([[1, 0.5], [0.5, 1]])
Σ = np.diag(σ) # Ω # np.diag(σ)
# the error term
ϵ = np.random.multivariate_normal(mean=(0, 0), cov=Σ, size=N)
# the dependent variable as bivariate normal
y = np.stack((μ1, μ2)).T + ϵ
Here is my model:
with pm.Model() as joint_model:
a1 = pm.Normal('a1', 0, 1)
b1 = pm.Normal('b1', 0, 1)
a2 = pm.Normal('a2', 0, 1)
b2 = pm.Normal('b2', 0, 1)
mu1 = a1 + b1 * x1
mu2 = a2 + b2 * x2
sigma = pm.HalfCauchy('sigma', 1, shape=2)
# build the covariance matrix
C_triu = pm.LKJCorr('omega', n=2, p=2)
C = tt.fill_diagonal(C_triu[np.zeros((2, 2), dtype=np.int64)], 1)
sigma_diag = tt.nlinalg.diag(sigma)
cov = tt.nlinalg.matrix_dot(sigma_diag, C, sigma_diag)
joint_obs = pm.MvNormal('joint', mu=(mu1, mu2), cov=cov, observed=y)
The error message is ValueError: Input dimension mis-match. (input[0].shape[0] = 200, input[1].shape[0] = 2).
It's clear I've made a mistake specifying the Multivariate normal distribution, there is a (maybe more than one) dimension mismatch between mu, cov, and the observed data, I just can't figure out where and how to fix it. Here is the (very long) error message, and the code above should be able to replicate the error:
Traceback (most recent call last):
File "<ipython-input-4-b3658e712eaf>", line 18, in <module>
joint_obs = pm.MvNormal('joint', mu=(mu1, mu2), cov=cov, observed=y)
File "/Users/oma/anaconda/lib/python3.6/site-packages/pymc3/distributions/distribution.py", line 39, in __new__
return model.Var(name, dist, data, total_size)
File "/Users/oma/anaconda/lib/python3.6/site-packages/pymc3/model.py", line 545, in Var
total_size=total_size, model=self)
File "/Users/oma/anaconda/lib/python3.6/site-packages/pymc3/model.py", line 970, in __init__
self.logp_elemwiset = distribution.logp(data)
File "/Users/oma/anaconda/lib/python3.6/site-packages/pymc3/distributions/multivariate.py", line 200, in logp
delta = value - mu
File "/Users/oma/anaconda/lib/python3.6/site-packages/theano/tensor/var.py", line 147, in __sub__
return theano.tensor.basic.sub(self, other)
File "/Users/oma/anaconda/lib/python3.6/site-packages/theano/gof/op.py", line 674, in __call__
required = thunk()
File "/Users/oma/anaconda/lib/python3.6/site-packages/theano/gof/op.py", line 843, in rval
fill_storage()
File "/Users/oma/anaconda/lib/python3.6/site-packages/theano/gof/cc.py", line 1698, in __call__
reraise(exc_type, exc_value, exc_trace)
File "/Users/oma/anaconda/lib/python3.6/site-packages/six.py", line 686, in reraise
raise value
ValueError: Input dimension mis-match. (input[0].shape[0] = 200, input[1].shape[0] = 2)
The question has been answered on discourse.pymc.io.
The specification for mu in pm.MvNormal should be mu = tt.stack([mu1, mu2]).T.
I have constructed two matrices. For one I calculate matrix exponential, but for the other one I can not. They are similarly constructed and have the same structure and dimension. I really don't know why one can work but the other can not. I put my code below.
import numpy as np
import math as math
from scipy.sparse import csc_matrix
from scipy.sparse.linalg import *
sigmax = [[0, 1], [1, 0]]
sigmay = [[0, -1j], [1j, 0]]
sigmaz = [[1, 0], [0, -1]]
sigmaxx = np.kron(sigmax,sigmax)
sigmayy = np.kron(sigmay,sigmay)
sigmazz = np.kron(sigmaz,sigmaz)
sigmaxxyy = np.mat(sigmaxx) + np.mat(sigmayy)
N = 6
Hxxyy = 0
for i in range (0,N-2+1):
Hxxyy = np.mat(Hxxyy) + np.mat(np.kron(np.kron(np.identity(2**i),2*np.mat(sigmaxxyy)),np.identity(2**(N-i-2)) ))
Hxxyy = np.mat(Hxxyy) + np.mat(np.kron(np.kron(2*np.mat(sigmax),np.identity(2**(N-2))),sigmax))+np.mat(np.kron(np.kron(2*np.mat(sigmay),np.identity(2**(N-2))),sigmay))
print(expm(Hxxyy))
Hhi = 0
for j in range (0,N-1+1):
Hhi = np.mat(Hhi) + np.mat(np.kron( np.kron(np.identity(2**j),3*np.mat(sigmaz)),np.identity(2**(N-1-j))) )
print(expm(Hhi))
The error message is:
Traceback (most recent call last):
File "new test.py", line 20, in <module>
print(expm(Hhi))
File "/Users/sherlock/Library/Enthought/Canopy_64bit/User/lib/python2.7/site-packages/scipy/sparse/linalg/matfuncs.py", line 582, in expm
return _expm(A, use_exact_onenorm='auto')
File "/Users/sherlock/Library/Enthought/Canopy_64bit/User/lib/python2.7/site-packages/scipy/sparse/linalg/matfuncs.py", line 637, in _expm
X = _fragment_2_1(X, h.A, s)
File "/Users/sherlock/Library/Enthought/Canopy_64bit/User/lib/python2.7/site-packages/scipy/sparse/linalg/matfuncs.py", line 755, in _fragment_2_1
X[k, k] = exp_diag[k]
ValueError: setting an array element with a sequence.
Your code works in Python3 (Python 3.4.5) but fails in Python2 (Python 2.7.12).
There were a few changes in scipy/sparse/linalg/matfuncs.py between these two versions that cleaned all code paths to support both dense and sparse matrices.
Since the dimensions are not very big, a quick fix would be to
replace
expm(Hhi)
with
expm(np.array(Hhi))