3

[ Update: question solved, answer is at the end of the post]


I need to solve this problem

$$ \min \| x \|_{\infty} \; \text{s.t.} \; Ax = b $$

where $Ax = b$ is an underdetermined system, e.g., $A \in \mathbb{R}^{n \times m}$, with $n < m$. Unfortunately this problem seems to be not so treated in the research literature. After some googling, I found this thesis by Earle AC to be a clear reference. Many approaches are provided, unfortunately with no code at all, and the most pragmatic way to solve such a problem would be to cast this problem as a linear programming one, i.e.,

$$\min c^T [x |s] \\ A x = b \; , \; x_i \leq s , \; -x_i \leq s\\ $$ where $s$ is meant to be $\| x \|_{\infty}$, $c = [\textbf{0}|1]$, $\textbf{0} \in \mathbb{R}^m$ being the zero vector.

Such an approach is well described in page 36 of thesis by Earle AC

Unfortunately when I try to code this in Python, I obtain not feasible solutions: in particular when using the simplex method of Scipy, at some point in the tableau reduction the algorithm is no more able to find a pivot in the column.

An example is provided at the end of the post.

The questions hence are:

  1. Are there any errors in the code below? Or the problem is effectively ill posed?

  2. Are there any out of the box implemented solvers that deal with the same problem?

Thanks!

# divergence of linear programming for minimization of l_inf norm
# for overdetermined linear solution
import numpy as np

# p.36 of Infinity Norm Minimization EarleAC
n, m = 2,5
np.random.seed(10)
b = np.random.rand(n)
A = np.random.rand(n*m).reshape((n,m))
m = A.shape[1]

# check that system has solution
if (np.linalg.matrix_rank(np.column_stack((A,b))) - np.linalg.matrix_rank(A)):
    raise ValueError("matrix rank problem")

# matrix costraints for equality Ax = b
A_eq = np.column_stack((A, np.zeros(n)))
b_eq = b

# matrix constraint for |x|<s
M_3 = np.column_stack((np.diag(np.ones(m)),  np.ones(m)))
b_3 = np.zeros(m)

M_4 = np.column_stack(( - np.diag(np.ones(m)),  np.ones(m)))
b_4 = np.zeros(m)
# contraint s > 0
M_5 = np.zeros(M_4.shape[1])
M_5[-1] = 1
b_5 = [0.]

A_ub = np.row_stack((M_3, M_4, M_5))
b_ub = np.concatenate((b_3, b_4, b_5))

# define target
from scipy.optimize import linprog
c = np.append(np.zeros(m), [1.])

sol_scipy = linprog(c = c,
        A_ub = -A_ub, # minus is to consider <= instead of >=
        b_ub = -b_ub, # minus is to consider <= instead of >=
        A_eq = A_eq,
        b_eq = b_eq,
        method =  'simplex'
        )
print sol_scipy["message"]
# >> Optimization failed. Unable to find a feasible starting point.

# however a feasible solution exists, given by

x_fea, residuals, rank, __ = np.linalg.lstsq(A, b)
inf_norm_fea = np.max(np.abs(x_fea))
tmp_sol = np.concatenate((x_fea, [inf_norm_fea]))

np.testing.assert_allclose(A_eq.dot(tmp_sol), b_eq)
assert np.all(A_ub.dot(tmp_sol) >= b_ub)

[UPDATE]

Thanks to the suggestion by Michael Grant, solving the problem with cvxpy (readily available out of the box through conda install -c omnia cvxpy) solved the problem in a straightforward manner. Thanks a lot to him (and its amazing job with cvx) and at jjjjjj for suggesting other options. Here is the code that solves the above problem.

import cvxpy as cvx
# Construct the problem.
x = cvx.Variable(c.shape[0])
objective = cvx.Minimize(c * x)
constraints = [A_eq*x == b_eq, A_ub*x >= b_ub ]
prob = cvx.Problem(objective, constraints)

# The optimal objective is returned by prob.solve().
result = prob.solve()
# The optimal value for x is stored in x.value.
print x.value
  • 2
    My recommendation is that you consider a tool like cvxpy (disclaimer: developed by colleagues of mine). This will let you specify the problem in its native form, and let it create the LP reformulation and call the underlying solver for you. – Michael Grant Feb 20 '18 at 19:42
  • Thanks Micheal, cvxpy solved my problem. Thanks for your amazing job with cvx and the work of your friends that made the utilisation of the package astonishingly easy ! – Mattia Casotto Feb 22 '18 at 08:38

1 Answers1

1

As @MichaelGrant said, you might first try using CVX on test problems to guage the feasibility concern you're seeing. Then increase the scale for your problem of interest.

If scale becomes an issue, I'd maybe consider using IPOPT, or if you want to build your own KKT solver, using Pardiso to solve the KKT system. Disclaimer: I'm not too familiar with either and have been using the numerically focused JuMP which has led me to learn about IPOPT etc...

jjjjjj
  • 2,779