7.1 The conic interface tutorial¶
In this tutorial we demonstrate how to set up and solve a linear or conic problem with mosekmodel
, the main interface of the API for MATLAB.
A problem solved with mosekmodel
has the form
where
\(n\) is the number of decision variables.
\(x \in \real^n\) is a vector of decision variables.
\(c \in \real^n\) is the linear part of the objective function.
\(c^f\in \real\) is a constant term in the objective
\(F \in \real^{k \times n}\) is the affine conic constraint matrix.,
\(g \in \real^{k}\) is the affine conic constraint constant term vector.,
\(\D\) is a domain of dimension \(k\), constructed from the Sec. 13.8 (Supported domains).
Let us indicate a few syntactic features of the API for MATLAB, which allow specifying such poblems with greater flexibility:
Compact input with one call. The problem data has only three major elements,
F,g,c
, so if these matrices are constructed in advance, the problem can be set up with a single call tomosekmodel
.Setting up constraint blocks separately. Alternatively, as it is in most practical applications, the constraint section may consist of blocks, each corresponding to some logical part of the problem specification. We refer to them as affine conic constraints (ACCs). In this case it may be more natural to enter individual ACCs
\[F_ix +g_i\in \D_i\]separately, using the method
mosekmodel.appendcons
. The API for MATLAB will then internally combine these blocks into the \(F,g\) data by vertical stacking and let \(\D = \D_1 \times \cdots \times \D_p\), where \(p\) is the number of ACCs.Linear problems. The general formulation in (7.1) includes standard linear problems by using linear domains. For example \(Ax+b\leq 0\) is expressed as \(Ax+b\in\real_{\leq 0}\) and \(Ax+b=0\) as \(Ax+b\in\{0\}\), see Sec. 13.8 (Supported domains).
Shifted domains. To simplify some constructions a domain may be shifted by a vector \(b\), so that effectively one can write
\[Fx+g\in \D + b.\]This is a syntactic feature as one could achieve the same effect replacing \(g\) with \(g-b\), but it is sometimes more natural; especially for linear problems it may be more intuitive to write \(Ax\geq b\) as \(Ax\in\real_{\geq 0} + b\) rather than \(Ax-b\in \real_{\geq 0}\). For obvious reasons this argument is called
rhs
(right-hand side) when creating a domain withmosekdomain
.
After this introduction we proceed to demonstrate examples of linear and conic problems, set up either at once or in chunks. We then finish the tutorial demonstrating how to invoke the optimizer and retrieve the solutions.
7.1.1 Linear example (LO1)¶
We set up a linear problem in one go. Consider the problem
We create a model by providing all data at once:
the number of variables is 4 and is set as
numvar
,the objective vector is \(c=[3,1,5,1]\) and is passed as
objective
,the objective sense is maximization, and is passed as
objsense
,the problem name
name
(optional) islo1
.
model = mosekmodel(...
name = "lo1", ...
objsense = "maximize", ...
objective = [ 3 1 5 1 ]', ...
numvar = 4, ...
F = [ 3 1 2 0 ; ...
2 1 3 1 ; ...
0 2 0 3 ; ...
1 0 0 0 ; ...
0 1 0 0 ; ...
0 0 1 0 ; ...
0 0 0 1 ; ...
0 1 0 0 ;], ...
domain = [ mosekdomain("equal", rhs=30), ...
mosekdomain("greater than", rhs=15), ...
mosekdomain("less than", rhs=25), ...
mosekdomain("nonnegative", n=4), ...
mosekdomain("less than", rhs=10) ]);
The remaining data is the matrix \(F\), each row of \(F\) corresponding to one linear bound in the problem. For each of those bounds there is a corresponding domain in the list of domains domain
which indicates the type of (in)equality (lower-bounded, upper-bounded, equals). We exploit the rhs
vector mentioned in the introduction to pass the bounds inside domains, rather than having to add a g
vector, although both options would be just as good. Note that the bounds
are covered by one domain \(\R_{\geq 0}^4\), that is of dimension n=4
to indicate the number of rows of \(F\) it covers. All other bounds are (by default) 1-dimensional, i.e. correspond to a single row of F
. The total dimension of all domains (\(1+1+1+4+1=8\)) equals the number of rows in \(F\).
In large, practical applications the matrix \(F\) can, and should, be specified as a sparse matrix.
See the API reference for mosekmodel
for a specification of all possible arguments.
7.1.2 Linear example with multiple calls (LO2)¶
We can set up the model of (7.2) adding linear constraints one by one with multiple calls to mosekmodel.appendcons
. In the example below we first initialize the model object with the name, objective and number of variables, and then we add the linear constraints separately
model = mosekmodel(name = "lo2", ...
objsense = "maximize", ...
objective = [ 3 1 5 1 ]', ...
numvar = 4);
model.appendcons(name="con-eq30", F = [ 3 1 2 0 ], domain = mosekdomain("equal", rhs=30));
model.appendcons(name="con-gt14", F = [ 2 1 3 1 ], domain = mosekdomain("greater than", rhs=15));
model.appendcons(name="con-lt25", F = [ 0 2 0 3 ], domain = mosekdomain("less than", rhs=25));
model.appendcons(name="con-nneg", F = speye(4), domain = mosekdomain("nonnegative", n=4));
model.appendcons(name="con-lt10", F = [ 0 1 0 0 ], domain = mosekdomain("less than", rhs="10"));
Each call to mosekmodel.appendcons
contains the constraint’s name (optional) and it’s \(F\) matrix and domain as before. In each call to mosekmodel.appendcons
the number of rows in \(F\) equals the dimension of the domain.
7.1.3 Conic quadratic example (ACC1)¶
We now go through an example with non-linear conic constraints, in this case quadratic. All other cones would be added in a similar way. Consider the problem
where \(x\in \real^n\) is the optimization variable and \(G\in\real^{k\times n}\), \(h\in\real^k\), \(c\in\real^n\) and \(\gamma\in\real\).
The norm constraint has a conic representation:
and we can write it explicitly in matrix format \(Fx+g\in\D\) as follows:
We formulate the problem by including the linear constraint and the conic constraint in two separate calls.
% Initialize the model
model = mosekmodel(name = "acc1",...
numvar = n);
% Set objective vector
model.objective("maximize", c);
% The constraint sum(x) = 1
model.appendcons(F = ones(1,n), domain = mosekdomain("equal", rhs=1));
% The conic quadratic constraint Fx+g \in \Quad with k+1 rows
model.appendcons(F = sparse([zeros(1,n); G]), ...
g = [gamma; h], ...
domain = mosekdomain("quadratic cone", dim=k+1));
7.1.4 Solving and retrieving the solution¶
We wrap up with a short demonstration of what to do after the model has been defined, that is how to solve the model and retrieve solutions.
% Solve the problem
model.solve();
% Check if solution is available
[hassol, prosta, solsta] = model.hassolution("interior");
if hassol && solsta == "OPTIMAL"
% Get primal solution
xx = model.getsolution("interior", "x");
% Get dual solution
y = model.getsolution("interior", "y");
disp("Primal solution");
disp(xx);
end
We note that
The optimizer is invoked with
mosekmodel.solve
.We check if the interior point solution is available with
mosekmodel.hassolution
, which returns also problem and solution status.The primal and dual solution are obtained by requesting the
"x"
or"y"
component inmosekmodel.getsolution
.See Sec. 6.1 (Accessing the solution) for more details about retrieving solutions and handling more solution statuses, and Sec. 6.2 (Errors and exceptions) for information about error handling, which we omitted for readability.