#!/usr/bin/env python
# coding: utf-8
# ***
# # Problem Sheet 6 Part B - Solutions
# ***
# $\newcommand{\vct}[1]{\mathbf{#1}}$
# $\newcommand{\mtx}[1]{\mathbf{#1}}$
# $\newcommand{\e}{\varepsilon}$
# $\newcommand{\norm}[1]{\|#1\|}$
# $\newcommand{\minimize}{\text{minimize}\quad}$
# $\newcommand{\maximize}{\text{maximize}\quad}$
# $\newcommand{\subjto}{\quad\text{subject to}\quad}$
# $\newcommand{\R}{\mathbb{R}}$
# $\newcommand{\trans}{T}$
# $\newcommand{\ip}[2]{\langle {#1}, {#2} \rangle}$
# $\newcommand{\zerovct}{\vct{0}}$
# $\newcommand{\diff}[1]{\mathrm{d}{#1}}$
# ### Solution to Problem 6.4
# (a) We first write down the matrix $\mtx{A}$:
#
# \begin{equation*}
# \mtx{A} = \begin{pmatrix}
# 0 & 0.2 & 0.4 & 0.6 & 0.8 & 1 & 1.2 & 1.4&1.6&1.8&2 \\
# 1 & 1 & 1 & 1 & 1 & 1 & 1 & 1 & 1 & 1 & 1
# \end{pmatrix}
# \end{equation*}
#
# and the vectors $\vct{b}$ and $\vct{c}$:
#
# \begin{equation*}
# \vct{b} = \begin{pmatrix}
# 1\\1
# \end{pmatrix}, \
# \vct{c} = \begin{pmatrix}
# 1 & 1.01 & 1.04 & 1.09 & 1.16 & 1.25 & 1.36 & 1.49 & 1.64 & 1.81 & 2
# \end{pmatrix}^{\trans}
# \end{equation*}
#
# The primal version of the problem is given by
#
# \begin{align*}
# \minimize & x_1+1.01x_2+1.04x_3+1.09x_4+1.16x_5+1.25x_6+1.36x_7\\
# &+1.49x_8+1.64x_9+1.81x_{10}+2x_{11}\\
# \subjto &0.2x_2+0.4x_3+0.6x_4+0.8x_5+x_6+1.2x_7+1.4x_8+1.6x_9\\
# &+1.8x_{10}+2x_{11}=1\\
# &x_1+x_2+x_3+x_4+x_5+x_6+x_7+x_8+x_9+x_{10}+x_{11}=1\\
# & x_i\geq 0.
# \end{align*}
# We define the matrix $\mtx{A}$ and the vectors $\vct{b}$ and $\vct{c}$ for this problem in Python as follows.
# In[1]:
import numpy as np
import numpy.linalg as la
# In[2]:
v = np.linspace(0,1,11)
n = len(v)
A = np.concatenate((2*v.reshape((1,n)), np.ones((1,n))), axis=0)
c = 1+v**2
b = np.array([1,1])
# (b) The problem has $m=2$ dual variables $y_1$ and $y_2$, so the projection of the trajectory on the $\vct{y}$-plane can easily be visualised. The Python code implementinng the long-step primal-dual method with parameters $\sigma=0.1, 0.5, 0.9$ is given below.
# In[3]:
# Define the function F and the Jacobian matrix M
def F(x, y, s):
C1 = np.dot(A.T,y)+s-c
C2 = np.dot(A,x)-b
C3 = x*s
return np.concatenate((C1, C2, C3))
def M(x, y, s):
return np.asarray(np.bmat([[np.zeros((n,n)), A.T, np.eye(n)],
[A, np.zeros((2,2)), np.zeros((2,n))],
[np.diag(s), np.zeros((n,2)), np.diag(x)]]))
# In[4]:
x = np.ones(n)/11.
y = np.array([0,0])
s = c-np.dot(A.T, y)
# In[5]:
def longstep(x, y, s, sigma, gamma=1e-3, tol=1e-4):
mu = 1
i = 1
yy = np.zeros((2,50))
while mu>tol and i<50:
a = 1
mu = np.dot(x,s)/11.
rhs = F(x,y,s)-np.concatenate((np.zeros(n+2), sigma*mu*np.ones(11)))
delta = -la.solve(M(x,y,s), rhs)
xs = np.concatenate((x,s))
deltaxs = np.concatenate((delta[:11], delta[13:]))
I = np.argmin(xs+deltaxs)
m = xs[I]+deltaxs[I]
if mtol and i<50:
a = 1
mu = np.dot(x,s)/11.
rhs = F(x,y,s)-np.concatenate((np.zeros(n+2), sigma*mu*np.ones(11)))
delta = -la.solve(M(x,y,s), rhs)
xs = np.concatenate((x,s))
deltaxs = np.concatenate((delta[:11], delta[13:]))
I = np.argmin(xs+deltaxs)
m = xs[I]+deltaxs[I]
if m