Block LMI in CVXPY - python

I want to translate a LMI-constrained optimization problem from Matlab to Python. While reading the CVXPY documentation, I found that I can define an LMI-constrained problem by creating a matrix variable and adding the corresponding constraint. However, instead of constraining the problem by a simple LMI, I need to use the following block LMI:
Where P, L are matrix variables and gamma is a scalar. The other symbols are state space matrices of a dynamic system.
Is it possible to use this kind of LMI as a constraint in CVXPY? If not, is there any other tool that would allow me to solve this problem in Python?

I followed the example posted by Rodrigo de Azevedo and I managed to write the given LMI in cvxpy.
For reference, the code I wrote, It may be helpful for someone:
n = A.shape[0]
L = Variable((B2.shape[1], n))
P = Variable((n, n), PSD=True)
gamma2 = Variable()
LMI1 = bmat([
[P, A*P + B2*L, B1, np.zeros((B1.shape[0], D11.shape[0]))],
[P*A.T + L.T * B2.T, P, np.zeros((P.shape[0], B1.shape[1])), P*C1.T + L.T*D12.T],
[B1.T, np.zeros((B1.shape[1], P.shape[1])), np.eye(B1.shape[1]), D11.T],
[np.zeros((C1.shape[0], B1.shape[0])), C1*P + D12*L, D11, gamma2*np.eye(D11.shape[0])]
])
cons1 = LMI1 >> 0
cons2 = P == P.T
cons3 = gamma2 >= 0
And then, to solve the problem:
optprob = Problem(Minimize(gamma2), constraints=[cons1, cons2, cons3])
optprob.solve()
norm = np.sqrt(gamma2.value)
Pop = P.value
Lop = L.value

Related

How to solve for an ordinary differential equation variable value using Python

I'm new to the SciPy.org maths libraries, so this may be a fairly basic question for those familiar with them.
For this ODE:
y'(t) - 0.05y(t) = d, y(0) = 10
how do I calculate the value of 'd' if y(10) = 100?
I can solve for y(t) this way:
import sympy as sym
y = sym.Function('y')
t, d = sym.symbols('t d')
y1 = sym.Derivative(y(t), t)
eqdiff = y1 - 0.05*y(t) - d
sol = sym.dsolve(eqdiff, y(t), ics={y(0): '10'})
sol
y(t)= −20.0d + (20.0d + 10.0)e^(0.05t)
Whether "sol" is usable to solve for d when y(10) = 100 is unknown to me (SymPy may not be the library of choice for this).
I've looked at numerous web pages such as these for ideas but haven't found a way forward:
https://docs.sympy.org/latest/modules/solvers/ode.html
Converting sympy expression to numpy expression before solving with fsolve( )
https://apmonitor.com/pdc/index.php/Main/SolveDifferentialEquations
I'm aware there are graphical ways to address the problem, but I want a numeric result.
Thanks in advance for helpful advice.
You can substitute the values and use solve:
In [5]: sol.subs(t, 10)
Out[5]: y(10) = 12.9744254140026⋅d + 16.4872127070013
In [6]: sol.subs(t, 10).subs(y(10), 100)
Out[6]: 100 = 12.9744254140026⋅d + 16.4872127070013
In [7]: solve(sol.subs(t, 10).subs(y(10), 100), d)
Out[7]: [6.43672337141557]
https://docs.sympy.org/latest/modules/solvers/solvers.html#sympy.solvers.solvers.solve
You can also solve it with scipy. The whole task is a boundary value problem with a free parameter, one state dimension plus one free parameter equals two boundary slots. So use solve_bvp (even if it is a scalar problem, the solver treats every state space as vector space)
def eqn(t,y,d): return d+0.05*y
def bc(y0,y10,d): return [ y0[0]-10, y10[0]-100 ]
x_init = [0,10]
y_init = [[10, 100]]
d_init = 1
res = solve_bvp(eqn, bc, x_init, y_init, p=[d_init], tol=1e-5)
print(res.message, f"d={res.p[0]:.10f}")
which gives
The algorithm converged to the desired accuracy. d=6.4367242595

CVXPY gives "AttributeError: 'numpy.bool_' object has no attribute 'variables' " error when I use predefined np array in constraints

I am trying to find an optimal solution on predefined np arrays and I need to use these arrays in constraints. I tried converting those arrays to cvxpy variables but it it says that cvxpy variables do not support assignment. Here is code for reference. Can somebody provide some tips?
N, d = xTr.shape
y = yTr.flatten()
## Solution Start
# dummy code: example of establishing objective and constraints, and let the solver solve it.
si = np.random.randn(N)
w = Variable(d)
b = Variable(1)
objective = norm(w) + C * (sum(si))
constraints = []
for i in range(N):
constraints += [
y[i]*(w * xTr[i] + b)+ si[i] >=1,
si[i] >= 0
]
prob = Problem(Minimize(objective), constraints)
prob.solve()>

Solving a System of Ode's using scipy.integrate.ode

I am trying to solve a system of Odes of the form Du/Dt = F(u) in python, and I suspect I may have made a fairly dumb mistake somewhere.
Technically F(u) is actually the second derivative of u with respect to another variable y, but in practice we can consider it to be a system and some function.
#Settings#
minx = -20
h = float(1)
w = float(10)
U0 = float(10)
Nt = 10
Ny = 10
tmax = 10
v=float(1)
#Arrays#
y = np.linspace(0,h,Ny)
t = np.linspace(0,tmax,Nt)
#Variables from arrays#
dt = t[1]-t[0]
p = [0]*(Nt)
delta = y[1] - y[0]
def zo(y):
return math.cos(y/(2*math.pi))
z0 = [zo(i) for i in y]
def df(t,v1):
output = np.zeros(len(y))
it = 1
output[0] = math.cos(w*t)
output[len(y)-1] = math.cos(w*t)
while it < len(y)-1:
output[it] = ( v1[it - 1] + v1[it + 1] - 2 * v1[it] ) * ( v / ( ( delta )**2 ))
it += 1
return output
r = ode(df).set_integrator('zvode', method='bdf',order =15)
r.set_initial_value(z0, 0)
it=0
while r.successful() and r.t < tmax:
p[it] = r.integrate(r.t+dt)
it+=1
print(z0-p[0])
print(p[1])
Now the problem is twofold :
-First of all, the initial "condition" ie p[0] seems to be off.
(That may be just because of the way the ode function works though, so I don't know if that is normal)
-Second, p[1] and all p's after that are just 0.
So for some reason the ode function fails immediately... (you can check that by changing the values to 1 when initializing p)
Except that I know that this method should work.
This is the "equivalent" to ode45 in matlab after all and that definitely works.
Why did you choose a complex solver with an implicit backward differentiation formula of a rather high order if you wanted to use Dormand-Price rk45 resp. dopri5?
Please also correct the loop indentation in df. Why not a for loop over range(1, len(y)-1)?
As it currently stands p[0] contains the solution point after the first step, at t=1*dt. You would have to explicitly assign p[0]=z0 and start it=1 to get the full solution path in p. Check the length of p, it could be that you need Nt+1.

Partial symbolic derivative in Python

I need to partially derivate my equation and form a matrix out of the derivatives. My equation is:
While this conditions must be met:
For doing this I've used the sympy module and its diff() function. My code so far is:
from sympy import*
import numpy as np
init_printing() #delete if you dont have LaTeX installed
logt_r, logt_a, T, T_a, a_0, a_1, a_2, logS, Taa_0, Taa_1, Taa_2 = symbols('logt_r, logt_a, T, T_a, a_0, a_1, a_2, logS, Taa_0, Taa_1, Taa_2')
A = (logt_r - logt_a - (T - T_a) * (a_0 + a_1 * logS + a_2 * logS**2) )**2
parametri = [logt_a, a_0, Taa_0, a_1, Taa_1, a_2, Taa_2]
M = expand(A)
M = M.subs(T_a*a_0, Taa_0)
M = M.subs(T_a*a_1, Taa_1)
M = M.subs(T_a*a_2, Taa_2)
K = zeros(len(parametri), len(parametri))
O = []
def odv(par):
for j in range(len(par)):
for i in range(len(par)):
P = diff(M, par[i])/2
B = P.coeff(par[j])
K[i,j] = B
return K
odv(parametri)
My result:
My problem
The problem that I'm having is in the partial derivatives of products (T_aa_0, T_aa_1 and T_a*a_2), because by using the diff() function, you cannot derivate a function with a product (obviously), else you get an error:
ValueError:
Can't calculate 1-th derivative wrt T_a*a_0.
To solve this I substitued this products with coefficients, like:
M = M.subs(T_a*a_0, Taa_0)
M = M.subs(T_a*a_1, Taa_1)
M = M.subs(T_a*a_2, Taa_2)
But as you can see in the final result, this works only in some cases. I would like to know if there is a better way of doing this where I wouldn't need to substitude the products and that it would work in all cases.
ADDITIONAL INFORMATION
Let me rephrase my question. Is it possible to symbolically derive an equation with a function by using python or in that matter, to use the sympy module?
So I've managed to solve my problem on my own. The main question was how to symbolically derive a function or equation with another function. As I've gone again slowly over the sympy documentation, I saw a little detail, that I've missed before.
In order to derive a function with a function you need to change the settings of the function, that will be used to derive. For example:
x, y, z = symbols('x, y, z')
A = x*y*z
B = x*y
# This is the detail:
type(B)._diff_wrt = True
diff(A, B)
Or in my case, the code looks like:
koef = [logt_a, a_0, T_a*a_0, a_1, T_a*a_1, a_2, T_a*a_2]
M = expand(A)
K = zeros(len(koef), len(koef))
def odvod_mat(par):
for j in range(len(par)):
for i in range(len(par)):
type(par[i])._diff_wrt = True
P = diff(M, par[i])/2
B = P.coeff(par[j])
K[i,j] = B
#Removal of T_a
K[i,j] = K[i,j].subs(T_a, 0)
return K
odvod_mat(koef)
Thanks again to all that were taking their time to read this. I hope this helps to anyone, who will have the same problem as I did.

two dimensional fit with python

I need to fit a function
z(u,v) = C u v^p
That is, I have a two-dimensional data set, and I have to find two parameters, C and p. Is there something in numpy or scipy that can do this in a straightforward manner? I took a look at scipy.optimize.leastsq, but it's not clear to me how I would use it here.
def f(x,u,v,z_data):
C = x[0]
p = x[1]
modelled_z = C*u*v**p
diffs = modelled_z - z_data
return diffs.flatten() # it expects a 1D array out.
# it doesn't matter that it's conceptually 2D, provided flatten it consistently
result = scipy.optimize.leastsq(f,[1.0,1.0], # initial guess at starting point
args = (u,v,z_data) # alternatively you can do this with closure variables in f if you like
)
# result is the best fit point
For your specific function you might be able to do it better - for example, for any given value of p there is one best value of C that can be determined by straightforward linear algebra.
You can transform the problem into a simple linear least squares problem, and then you don't need leastsq() at all.
z[i] == C * u[i] * v[i]**p
becomes
z[i]/u[i] == C * v[i]**p
And then
log(z[i]/u[i]) == log(C) + p * log(v[i])
Change variables and you can solve as a simple linear problem:
Z[i] == L + p * V[i]
Using numpy and assuming you have the data in arrays z, u and v, this is rendered as:
Z = log(z/u)
V = log(v)
p, L = np.polyfit(V, Z, 1)
C = exp(L)
You probably ought to put a try: and except: around it in case some of the u values are zero or there are negative values.

Categories