mzero.qp.xprs

Module to solve convex quadratic programs:
- `solve-qp` solves 0.5 xT.Q.x + cT.x;
- `solve-lcls` solves the linearly constrained least squares problem
(which is a subset of the above)

The solving is done by FICO Xpress software:
https://www.fico.com/fico-xpress-optimization/docs/latest/solver/optimizer/HTML/GUID-3BEAAE64-B07F-302C-B880-A11C2C4AF4F6.html

solve-lcls

(solve-lcls A b C d bounds)(solve-lcls A b C d)
Solve the linearly constrained least squares (LCLS) problem ||`A`x-`b`||² such
that `C`x-`d`<=0.

This is equivalent to minimizing 0.5*xT.AT.A.x - bT.A.x with the
same constraints, so turning it to solve-qp params we have Q=AT.A and c=-AT.b

solve-qp

(solve-qp Q c A b bounds)(solve-qp Q c A b)
Solve a quadratic program, minimizing 0.5*xT.`Q`.x +`c`T.x constrained
by linear inequalities `A`x - `b` <= 0 (xT means x transposed),
where `Q` is a positive semi-definite matrix, `c` is a vector whose
dimension matches Q's number of rows (or cols since Q is square),
`A` is the constraint matrix and `b` is a vector whose dimension
matches A's number of cols.

Optional `bounds` can be specified, e.g. {:lower 0.0 :upper 0.3}, or
{:upper 1e10}. If a bound is not given it is set to its minimal
value (for lower bound) or maximal value (for upper bound).

NOTE: relative to matrix Q, pay attention to the 0.5 coefficient of
the quadratic term above; if the quadratic term of the problem at
hand is in the form xT.K.x, then `Q`=2*K and doubling the matrix
coeff is needed such as done in https://www.fico.com/fico-xpress-optimization/docs/latest/solver/optimizer/HTML/XPRSloadqp.html

Matrices are input as seq of columns (columns are seqs), vectors are
input as seqs.

Since Q should be symmetric, its columns sizes should be decreasing
until reaching 1.

Javadoc about xpress optimizer parameters : https://www.fico.com/fico-xpress-optimization/docs/latest/solver/optimizer/HTML/javadoc/com/dashoptimization/XPRSprob.html?scroll=loadQP-java.lang.String-int-int-byte:A-double:A-double:A-double:A-int:A-int:A-int:A-double:A-double:A-double:A-int-int:A-int:A-double:A-

Example of loadQP call:
https://www.fico.com/fico-xpress-optimization/docs/latest/getting_started/dhtml/chap17_sec_c17s4.html

Return the XPRS problem instance and the solution, assuming it's
unique (which seems to be always true except in edge cases when Q =
0? does Q being not 0 guarantee it? probably)