In this notebook, we are going to use projected gradient to solve the following optimization problem.
$$\begin{align} \min \quad 2(x_1 - 1)^2 &+ (x_2 - 2)^2 \\ \mathrm{s.t.} \quad x_1 + 4x_2 - 2 &\le 0 \\ \quad -x_1 + x_2 &\le 0 \\ \quad x_1, x_2 &\ge 0 \end{align} $$import numpy as np
from numpy.linalg import inv
from scipy.optimize import minimize_scalar
x1 = 0
x2 = 0
g1 = 4*(x1 - 1)
g2 = 2*(x2 - 2)
gradF = np.array([g1,g2])
Note that we have constraints -x1 + x2 <= 0, x1 >= 0, x2 >= 0.
We only use -x1 + x2 <= 0 and x2 >= 0 as it automatically implies x1 >= 0. If we use all three, then we cannot invert the matrix.
E = np.array([[-1,1],[0,-1]])
I = np.identity(2)
ET = np.transpose(E)
P = I - np.dot(np.dot(ET,inv(np.dot(E,ET))),E)
print(P)
d = -np.dot(P, gradF)
print(d)
Since d=0, we calculate Q.
Q = -np.dot(np.dot(inv(np.dot(E,ET)),E),gradF)
print(Q)
Since the second row is the most negative, we delete the second row of the matrix E.
E = np.array([[-1,1]])
I = np.identity(2)
ET = np.transpose(E)
P = I - np.dot(np.dot(ET,inv(np.dot(E,ET))),E)
print(P)
d = -np.dot(P, gradF)
print(d)
x1 = 0 + lam*4
x2 = 0 + lam*4
lam <= 2/20
def fun(l):
return 2*(0 + 4*l - 1)**2 + (0 + 4*l - 2)**2
lam = minimize_scalar(fun, bounds=(0, 0.1), method='bounded')
print(lam.x)
x1 = 0 + 4*lam.x
x2 = 0 + 4*lam.x
print("x1= ", x1)
print("x2= ", x2)
x1 = 0.4
x2 = 0.4
g1 = 4*(x1 - 1)
g2 = 2*(x2 - 2)
gradF = np.array([g1,g2])
E = np.array([[1,4],[-1,1]])
I = np.identity(2)
ET = np.transpose(E)
P = I - np.dot(np.dot(ET,inv(np.dot(E,ET))),E)
print(P)
d = -np.dot(P, gradF)
print(d)
Q = -np.dot(np.dot(inv(np.dot(E,ET)),E),gradF)
print(Q)
Since the second row has negative values, delete the second row from the E matrix.
E = np.array([[1,4]])
I = np.identity(2)
ET = np.transpose(E)
P = I - np.dot(np.dot(ET,inv(np.dot(E,ET))),E)
print(P)
d = -np.dot(P, gradF)
print(d)
def fun(l):
return 2*(0.4 + 1.505*l - 1)**2 + (0.4 - 0.3764*l - 2)**2
lam = minimize_scalar(fun, bounds=(0, 1.0627), method='bounded')
print(lam.x)
x1 = 0.4 + 1.505*lam.x
x2 = 0.4 - 0.3764*lam.x
print("x1= ", x1)
print("x2= ", x2)