Model Matrix Least Squares (Frobenius Norm) Problem with pyomo? - pyomo

How to model the following problem with pyomo and Gurobi solver?
This is a non-convex problem, and can not model as a QCQP problem. So I want to solve it with pyomo and Gurobi solver. The most difficult part is matrix algebra (pyomo do not support yet).
Many thanks!

Here is my own answer. Please let me know if there are any mistakes. Thanks!
import pyomo.environ as pyo
## get your param
L, Delta =
K, P =
O, l =
ones3 = np.ones((3, 1))
model = pyo.ConcreteModel()
model.r = pyo.RangeSet(0,2) # 3
model.s = pyo.RangeSet(0,0) # 1
model.n = pyo.RangeSet(0,len(L)-1) # n
model.m = pyo.RangeSet(0,len(K)-1) # m
model.q = pyo.RangeSet(0,len(O)-1) # q
def param_rule(I, J, mat):
return dict(((i,j), mat[i,j]) for i in I for j in J)
model.L = pyo.Param(model.n, model.n, initialize=param_rule(model.n, model.n, L)) # L
model.Delta = pyo.Param(model.n, model.r, initialize=param_rule(model.n, model.r, Delta)) # Delta
model.K = pyo.Param(model.m, model.n, initialize=param_rule(model.m, model.n, K)) # K
model.P = pyo.Param(model.m, model.r, initialize=param_rule(model.m, model.r, P)) # P
model.O = pyo.Param(model.q, model.n, initialize=param_rule(model.q, model.n, O)) # O
model.ones3 = pyo.Param(model.r, model.s, initialize=param_rule(model.r, model.s, ones3)) # ones3
model.l = pyo.Param(model.q, initialize=dict(((i),l[i,0]) for i in model.q)) # l
model.V = pyo.Var(model.n, model.r, initialize=param_rule(model.n, model.r, Delta)) # V
def ObjRule(model):
return 0.5*sum((sum(model.L[i,k]*model.V[k,j] for k in model.n) - model.Delta[i,j])**2 for i in model.n for j in model.r)
model.obj = pyo.Objective(rule=ObjRule, sense=pyo.minimize)
model.constraints = pyo.ConstraintList()
# constraints 1
[model.constraints.add(sum(model.K[i,k] * model.V[k,j] for k in model.n) == model.P[i,j]) for i in model.m for j in model.r]
# constraint 2
for i in model.q:
model.constraints.add(sum(sum(model.O[i,k] * model.V[k,j] for k in model.n)**2 for j in model.r) == model.l[i])
opt = pyo.SolverFactory('gurobi')
opt.options['nonconvex'] = 2
solution = opt.solve(model)
V_opt = np.array([pyo.value(model.V[i,j]) for i in model.n for j in model.r]).reshape(len(model.n),len(model.r))
obj_values = pyo.value(model.obj)
print("optimum point: \n {} ".format(V_opt))
print("optimal objective: {}".format(obj_values))

Related

Is there a way in Sympy to simplify Matrix algebra? Say with woodbury identity

I want to specifya N x M matrix where N >> M and use the woodbury,
and for Sympy to simplify the matrix algebra.
Is this possible or something similar?
Is there a way in Sympy to simplify Matrix algebra? Say with woodbury identity
Yes, it's possible to apply Woodbury's identity. In the code below, the identity is applied on (I + Phi^T * Phi)**(-1).
The particular case used was (I+UV)^-1 = I - U*(I+VU)^-1*V
from sympy.simplify.simplify import nc_simplify
from sympy import *
N,M,sigma = symbols("N M \sigma")
Phi = MatrixSymbol("Phi", N, M)
In,Im = Identity(N), Identity(M)
f = (Im + Phi.transpose()#Phi).inverse()
f = f # Phi.transpose()
f = Phi # f
f = In - sigma**(-2)*f
f = sigma**(-2)*Phi.transpose()#f
f = f# Phi
def apply_woodburry_1(e,U,V):
# The Woodbury identity
#
# (I+UV)^-1 = I - U * (I+VU)^-1 * V
#
# Below, P will be LHS and Q will be RHS
#
UV_dim = (U * V).shape
I1 = Identity(UV_dim[0])
VU_dim = (V * U).shape
I2 = Identity(VU_dim[0])
P = (I1+U*V)**(-1)
Q = I1 - U * ( (I2+V*U)**(-1) ) * V
return e.replace(P,Q)
display(f)
f = apply_woodburry_1(f,Phi.transpose(),Phi)
display(f)
f = nc_simplify(f.expand())
display(f)
Output:

Odeint function from scipy.integrate gives wrong result

I use odeint function to solve a coupled differential equations system and plot one of the variables (theta_i) after the system is solved. My variable (theta_i) comes from the equation:
theta_i = np.arctan2(g1,g2)
where g1 ang g2 are variables calculated in the same function. The results have to be between -pi and pi and they are supposed to look like this (plot from matlab simulation):
However, when I try to plot theta_i after odeint has finished I get this(plot from my python code):
which is really weird. When I print the values of theta_i right after its calcumation (still inside the function) they look correct (between -0.2 and 0.5), so it has to be something with the result's storing and my implementation of odeint. All the other variables that come from the odeint solution are correct. I searched similar posts but nobody had the same problem with me. What might be the problem here? I am new to python and I use python 2.7.12. Thank you in advance.
import numpy as np
from scipy.integrate import odeint
import matplotlib.pyplot as plt
added_mass_x = 0.03 # kg
added_mass_y = 0.04
mb = 0.3 # kg
m1 = mb-added_mass_x
m2 = mb-added_mass_y
l1 = 0.07 # m
l2 = 0.05 # m
J = 0.00050797 # kgm^2
Sa = 0.0110 # m^2
Cd = 2.44
Cl = 3.41
Kd = 0.000655 # kgm^2
r = 1000 # kg/m^3
c1 = 0.5*r*Sa*Cd
c2 = 0.5*r*Sa*Cl
c3 = 0.5*mb*(l1**2)
c4 = Kd/J
c5 = (1/(2*J))*(l1**2)*mb*l2
c6 = (1/(3*J))*(l1**3)*mb
theta_0 = 10*(np.pi/180) # rad
theta_A = 20*(np.pi/180) # rad
f = 2 # Hz
t = np.linspace(0,100,8000) # s
def direct(u,t):
vcx = u[0]
vcy = u[1]
wz = u[2]
psi = u[3]
x = u[4]
y = u[5]
vcx_i = u[6]
vcy_i = u[7]
psi_i = u[8]
wz_i = u[9]
theta_i = u[10]
theta_deg_i = u[11]
# Subsystem 1
omega = 2*np.pi*f # rad/s
theta = theta_0 + theta_A*np.sin(omega*t) # rad
theta_deg = (theta*180)/np.pi # deg
thetadotdot = -(omega**2)*theta_A*np.sin(omega*t) # rad/s^2
# Subsystem 2
vcxdot = (m2/m1)*vcy*wz-(c1/m1)*vcx*np.sqrt((vcx**2)+(vcy**2))+(c2/m1)*vcy*np.sqrt((vcx**2)+(vcy**2))*np.arctan2(vcy,vcx)-(c3/m1)*thetadotdot*np.sin(theta)
vcydot = -(m1/m2)*vcx*wz-(c1/m2)*vcy*np.sqrt((vcx**2)+(vcy**2))-(c2/m2)*vcx*np.sqrt((vcx**2)+(vcy**2))*np.arctan2(vcy,vcx)+(c3/m2)*thetadotdot*np.cos(theta)
wzdot = ((m1-m2)/J)*vcx*vcy-c4*wz*wz*np.sign(wz)-c5*thetadotdot*np.cos(theta)-c6*thetadotdot
psidot = wz
# Subsystem 3
xdotdot = vcxdot*np.cos(psi)-vcx*np.sin(psi)*wz+vcydot*np.sin(psi)+vcy*np.cos(psi)*wz # m/s^2
ydotdot = -vcxdot*np.sin(psi)-vcx*np.cos(psi)*wz+vcydot*np.cos(psi)-vcy*np.sin(psi)*wz # m/s^2
xdot = vcx*np.cos(psi)+vcy*np.sin(psi) # m/s
ydot = -vcx*np.sin(psi)+vcy*np.cos(psi) # m/s
# Subsystem 4
vcx_i = xdot*np.cos(psi_i)-ydot*np.sin(psi_i)
vcy_i = ydot*np.cos(psi_i)+xdot*np.sin(psi_i)
psidot_i = wz_i
vcxdot_i = xdotdot*np.cos(psi_i)-xdot*np.sin(psi_i)*psidot_i-ydotdot*np.sin(psi_i)-ydot*np.cos(psi_i)*psidot_i
vcydot_i = ydotdot*np.cos(psi_i)-ydot*np.sin(psi_i)*psidot_i+xdotdot*np.sin(psi_i)+xdot*np.cos(psi_i)*psidot_i
g1 = -(m1/c3)*vcxdot_i+(m2/c3)*vcy_i*wz_i-(c1/c3)*vcx_i*np.sqrt((vcx_i**2)+(vcy_i**2))+(c2/c3)*vcy_i*np.sqrt((vcx_i**2)+(vcy_i**2))*np.arctan2(vcy_i,vcx_i)
g2 = (m2/c3)*vcydot_i+(m1/c3)*vcx_i*wz_i+(c1/c3)*vcy_i*np.sqrt((vcx_i**2)+(vcy_i**2))+(c2/c3)*vcx_i*np.sqrt((vcx_i**2)+(vcy_i**2))*np.arctan2(vcy_i,vcx_i)
A = 12*np.sin(2*np.pi*f*t+np.pi) # eksiswsi tail_frequency apo simulink
if A>=0.1:
wzdot_i = ((m1-m2)/J)*vcx_i*vcy_i-c4*wz_i**2*np.sign(wz_i)-c5*g2-c6*np.sqrt((g1**2)+(g2**2))
elif A<-0.1:
wzdot_i = ((m1-m2)/J)*vcx_i*vcy_i-c4*wz_i**2*np.sign(wz_i)-c5*g2+c6*np.sqrt((g1**2)+(g2**2))
else:
wzdot_i = ((m1-m2)/J)*vcx_i*vcy_i-c4*wz_i**2*np.sign(wz)-c5*g2
if g2>0:
theta_i = np.arctan2(g1,g2)
elif g2<0 and g1>=0:
theta_i = np.arctan2(g1,g2)-np.pi
elif g2<0 and g1<0:
theta_i = np.arctan2(g1,g2)+np.pi
elif g2==0 and g1>0:
theta_i = -np.pi/2
elif g2==0 and g1<0:
theta_i = np.pi/2
elif g1==0 and g2==0:
theta_i = 0
theta_deg_i = (theta_i*180)/np.pi
#print theta_deg_i
return [vcxdot, vcydot, wzdot, psidot, xdot, ydot, vcxdot_i, vcydot_i, psidot_i, wzdot_i, theta_i, theta_deg_i]
# arxikes synthikes
vcx_0 = 0.1257
vcy_0 = 0
wz_0 = 0
psi_0 = 0
x_0 = 0
y_0 = 0
vcx_i_0 = 0.1257
vcy_i_0 = 0
psi_i_0 = 0
wz_i_0 = 0
theta_i_0 = 0.1745
theta_deg_i_0 = 9.866
u0 = [vcx_0, vcy_0, wz_0, psi_0, x_0, y_0, vcx_i_0, vcy_i_0, psi_i_0, wz_i_0, theta_i_0, theta_deg_i_0]
u = odeint(direct, u0, t, tfirst=False)
vcx = u[:,0]
vcy = u[:,1]
wz = u[:,2]
psi = u[:,3]
x = u[:,4]
y = u[:,5]
vcx_i = u[:,6]
vcy_i = u[:,7]
psi_i = u[:,8]
wz_i = u[:,9]
theta_i = u[:,10]
theta_deg_i = u[:,11]
print theta_i
plt.figure(17)
plt.plot(t,theta_i,'r-',linewidth=1,label='theta_i')
plt.xlabel('t [s]')
plt.title('theta_i [rad] (Main body CF)')
plt.legend()
plt.show()
The problem as you stated is that theta_i is not part of the gradient. When you formulate your direct, it should be of the form:
def direct(vector, t):
return vector_dot
The quickest and dirtiest solution (without cleaning the code) is to use the function you already defined:
theta_i = [direct(u_i, t_i)[10] for t_i, u_i in zip(t, u)]
I used a a shorter interval: t = np.linspace(0,10,8000). It yielded this:
EDIT: How to remove your theta from the integrator:
def direct(u, t):
# your original function as it is
def direct2(u,t):
return direct(u,t)[:9]
#now integrate the second function
u = odeint(direct2, u0, t)

SymPy simplify cannot 2*3**n/3 ---> 2*3**(n-1)

Thank you in advance and sorry for the bad english!
FullScript.py
from sympy import *
var('n')
f= 3**n/3
print(simplify(f))
#---------------------
f= 2*3**n/3
print(simplify(f))
# 3**(n - 1) # OK
# 2*3**n/3 # I want 2*3**(n-1)
2018-11-27------------------------------
Please tell me how to use the if statement
How to extract numerator and denominator from polynomial without evaluating?
FullScript.py
from sympy import *
var('n')
def MySimplify(h):
Mypoly = poly(h)
aa = Mypoly.all_coeffs()[1]
bb = h - aa
n, d = fraction(bb)
nn0 = n.as_base_exp()[0]
nn1 = poly(nn0)
import re
rese1 = re.search('^Poly\((.+?),(.+?),', str(nn1)).group(1)
rese2 = re.search('^Poly\((.+?),(.+?),', str(nn1)).group(2)
two=sympify(rese1)/sympify(rese2)
ans = powsimp(bb/two)*two+aa
return ans
f= 3**n/3
print("f1=",f)
print("f2=",simplify(f))
g= 4+2*3**n/3
print("g1=",g)
print("g2=",simplify(g))
print("g3=",MySimplify(g))
# f1= 3**n/3
# f2= 3**(n - 1)
# g1= 2*3**n/3 + 4
# g2= 2*3**n/3 + 4
# g3= 2*3**(n - 1) + 4
2018-11-28------------------------------
FullScript.py
from sympy import *
var('m n p q r s t u v x')
def ps(e, *args):
x = Dummy(integer=True)
t=list(Add.make_args(e))
for i, ti in enumerate(t):
c, r = ti.as_coeff_Mul()
if c.is_Rational and not c.is_Integer:
t[i] = Mul(c.p, r, Pow(c.q, x), evaluate=False)
# t[i] = powersimp(t[i], *args).xreplace({x: -1})
t[i] = powsimp(t[i], *args).xreplace({x: -1})
else:
t[i] = powsimp(t[i], *args)
return Add(*t)
f= 4+2*3**n/3
print("f1=",f)
print("f1=",ps(f))
f= 4+2*3**n/3+5*2.4**(m-1)/2.4+6*5.6*(p-7)/8.9
print("f2=",f)
print("f2=",ps(f))
g= x+p**n/p
print("g1=",g)
print("g1=",ps(g))
g= x+p**n/p+q*s**(m-1)/s+r*t**(u-2)/v
print("g2=",g)
print("g2=",ps(g))
# f1= 2*3**n/3 + 4
# f1= 2*3**(n - 1) + 4
# f2= 2.08333333333333*2.4**(m - 1) + 2*3**n/3 + 3.7752808988764*p - 22.4269662921348
# f2= 2.08333333333333*2.4**(m - 1) + 2*3**(n - 1) + 3.7752808988764*p - 22.4269662921348
# g1= x + p**n/p
# g1= p**(n - 1) + x
# g2= q*s**(m - 1)/s + r*t**(u - 2)/v + x + p**n/p
# g2= p**(n - 1) + q*s**(m - 2) + r*t**(u - 2)/v + x
powsimp(f/2)*2 will do what you want. The following is a more general workaround that incorporates this idea:
def ps(e, *args):
x = Dummy(integer=True)
t=list(Add.make_args(e))
for i, ti in enumerate(t):
c, r = ti.as_coeff_Mul()
if c.is_Rational and not c.is_Integer:
t[i] = Mul(c.p, r, Pow(c.q, x), evaluate=False)
t[i] = powersimp(t[i], *args).xreplace({x: -1})
else:
t[i] = powsimp(t[i], *args)
return Add(*t)

Reformulating the AMPL car example

I am trying migrating the ampl car problem that comes in the Ipopt source code tarball as example. I am having got problems with the end condition (reach a place with zero speed at final iteration) and with the cost function (minimize final time).
Can someone help me revise the following model?
# min tf
# dx/dt = 0
# dv/dt = a - R*v^2
# x(0) = 0; x(tf) = 100
# v(0) = 0; v(tf) = 0
# -3 <= a <= 1 (a is the control variable)
#!Python3.5
from pyomo.environ import *
from pyomo.dae import *
N = 20;
T = 10;
L = 100;
m = ConcreteModel()
# Parameters
m.R = Param(initialize=0.001)
# Variables
def x_init(m, i):
return i*L/N
m.t = ContinuousSet(bounds=(0,1000))
m.x = Var(m.t, bounds=(0,None), initialize=x_init)
m.v = Var(m.t, bounds=(0,None), initialize=L/T)
m.a = Var(m.t, bounds=(-3.0,1.0), initialize=0)
# Derivatives
m.dxdt = DerivativeVar(m.x, wrt=m.t)
m.dvdt = DerivativeVar(m.v, wrt=m.t)
# Objetives
m.obj = Objective(expr=m.t[N])
# DAE
def _ode1(m, i):
if i==0:
return Constraint.Skip
return m.dxdt[i] == m.v[i]
m.ode1 = Constraint(m.t, rule=_ode1)
def _ode2(m, i):
if i==0:
return Constraint.Skip
return m.dvdt[i] == m.a[i] - m.R*m.v[i]**2
m.ode2 = Constraint(m.t, rule=_ode2)
# Constraints
def _init(m):
yield m.x[0] == 0
yield m.v[0] == 0
yield ConstraintList.End
m.init = ConstraintList(rule=_init)
'''
def _end(m, i):
if i==N:
return m.x[i] == L amd m.v[i] == 0
return Constraint.Skip
m.end = ConstraintList(rule=_end)
'''
# Discretize
discretizer = TransformationFactory('dae.finite_difference')
discretizer.apply_to(m, nfe=N, wrt=m.t, scheme='BACKWARD')
# Solve
solver = SolverFactory('ipopt', executable='C:\\EXTERNOS\\COIN-OR\\win32-msvc12\\bin\\ipopt')
results = solver.solve(m, tee=True)
Currently, a ContinuousSet in Pyomo has to be bounded. This means that in order to solve a minimum time optimal control problem using this tool, the problem must be reformulated to remove the time scaling from the ContinuousSet. In addition, you have to introduce an extra variable to represent the final time. I've added an example to the Pyomo github repository showing how this can be done for your problem.

AssertionError when running K means Main Function

When Running the below code, I receive an AssertionError in the Main Function, assert len(args) > 1. Any idea where in the code the issue occurs?
K-Means clustering implementation
import numpy as np
from math import sqrt
import csv
import sys
====
Define a function that computes the distance between two data points
GAP = 2
MIN_VAL = 1000000
def get_distance(point1, point2):
dis = sqrt(pow(point1[0] - point2[0],2) + pow(point1[1] - point2[1],2))
return dis
====
Define a function that reads data in from the csv
def csvreader(data_file):
sampleData = []
global Countries
with open(data_file, 'r') as csvfile:
read_data = csv.reader(csvfile, delimiter=' ', quotechar='|')
for row in read_data:
print ', '.join(row)
if read_data <> None:
for f in read_data:
values = f.split(",")
if values[0] <> 'Countries':
sampleData.append([values[1],values[2]])
return sampleData
====
Write the initialisation procedure
def cluster_dis(centroid, cluster):
dis = 0.0
for point in cluster:
dis += get_distance(centroid, point)
return dis
def update_centroids(centroids, cluster_id, cluster):
x, y = 0.0, 0.0
length = len(cluster)
if length == 0:
return
for item in cluster:
x += item[0]
y += item[1]
centroids[cluster_id] = (x / length, y / length)
====
Implement the k-means algorithm, using appropriate looping
def kmeans(data, k):
assert k <= len(data)
seed_ids = np.random.randint(0, len(data), k)
centroids = [data[idx] for idx in seed_ids]
clusters = [[] for _ in xrange(k)]
cluster_idx = [-1] * len(data)
pre_dis = 0
while True:
for point_id, point in enumerate(data):
min_distance, tmp_id = MIN_VAL, -1
for seed_id, seed in enumerate(centroids):
distance = get_distance(seed, point)
if distance < min_distance:
min_distance = distance
tmp_id = seed_id
if cluster_idx[point_id] != -1:
dex = clusters[cluster_idx[point_id]].index(point)
del clusters[cluster_idx[point_id]][dex]
clusters[tmp_id].append(point)
cluster_idx[point_id] = tmp_id
now_dis = 0.0
for cluster_id, cluster in enumerate(clusters):
now_dis += cluster_dis(centroids[cluster_id], cluster)
update_centroids(centroids, cluster_id, cluster)
delta_dis = now_dis - pre_dis
pre_dis = now_dis
if delta_dis < GAP:
break
print(centroids)
print(clusters)
return centroids, clusters
def main():
args = sys.argv[1:]
assert len(args) > 1
data_file, k = args[0], int(args[1])
data = csvreader(data_file)
kmeans(data, k)
if __name__ == '__main__':
main()