2 Interfaces

In this section we give a quick tour of the kinds of interfaces available for MOSEK:

The image below presents a schematic view of the MOSEK ecosystem including the official MOSEK interfaces and major third-party interfaces.

2.1 Object oriented

An object oriented interface deals directly with variable, expression and constraint objects which can be put together using familiar linear algebra operations. The implemented model can be made similar to the mathematical model one would write directly on paper and the translation from the mathematical model to the implementation is very efficient.

2.1.1 The Fusion API

The MOSEK Fusion API is an object orientated API for expressing conic optimization problems which can include

  • linear objective,

  • linear constraints of the form \(Ax=b\), \(Ax\geq b\), \(Ax\leq b\), \(b_1\leq Ax\leq b_2\) and similar,

  • conic constraints of the form \(Ax+b\in K\) where \(K\) is a convex cone,

  • integer variables,

  • disjunctive constraints (a constraint which is an alternative of a number of conditions).

Perhaps surprisingly most convex optimization problems occurring in practice can be expressed in conic form. The advantages of the conic form are

  • the problem is convex by construction.

  • the problem description is explicit.

  • it is not necessary for the user to provide derivative information e.g. gradients.

  • almost all the concepts known from linear optimization, like duality, generalize to conic problems.

  • a powerful solution algorithm exists.

A typical model in Fusion is a direct reflection of the mathematical formulation of the problem. For example, here is a code sample in Python:

def BasicMarkowitz(n,mu,GT,x0,w,gamma):
    
    with  Model("Basic Markowitz") as M:

        # Redirect log output from the solver to stdout for debugging. 
        # if uncommented.
        # M.setLogHandler(sys.stdout) 
        
        # Defines the variables (holdings). Shortselling is not allowed.
        x = M.variable("x", n, Domain.greaterThan(0.0))
        
        #  Maximize expected return
        M.objective('obj', ObjectiveSense.Maximize, x.T @ mu)
        
        # The amount invested  must be identical to initial wealth
        M.constraint('budget', Expr.sum(x) == w+sum(x0))
        
        # Imposes a bound on the risk
        M.constraint('risk', Expr.vstack(gamma, GT @ x) == Domain.inQCone())
        #M.constraint('risk', Expr.vstack(gamma, 0.5, Expr.mul(GT, x)), Domain.inRotatedQCone())

        # Solves the model.
        M.solve()

        # Check if the solution is an optimal point
        solsta = M.getPrimalSolutionStatus()
        if (solsta != SolutionStatus.Optimal):
            # See https://docs.mosek.com/latest/pythonfusion/accessing-solution.html about handling solution statuses.
            raise Exception(f"Unexpected solution status: {solsta}")

        return np.dot(mu, x.level()), x.level()

It is a very compact and straightforward mapping of the mathematical model to code, which looks similar in all other languages supporting Fusion.

Fusion is a thin layer on top of the Optimizer API and it uses objects to represent

  • multi-dimensional variables,

  • linear operators and

  • domains (typical bounds or cones).

Fusion has been designed with the following principles in mind:

  • Expressive: Fusion yields readable code.

  • Seamlessly multi-language: A Fusion model can easily be ported from one supported language and to another supported language.

  • Predictability: Fusion does very little transformations to the problem before sending the problem to MOSEK. The advantage is that the problem solved is predictable for Fusion user.

  • Efficiency: Fusion should only add moderate computational overhead compared to using the optimizer APIs.

Currently, Fusion is available for

  • Python,

  • Java,

  • .NET,

  • C++ (except Windows 32bit).

Fusion is ideal for fast prototyping of models and in most cases fast enough for production use.

2.2 Matrix oriented

An interface is said to be matrix oriented if it allows inputting optimization problems of the form

\[\begin{split}\begin{array}{lccl} \minimize & c^T x & \\ \st & A x & \left [ \begin{array}{c} \leq \\ = \\ \geq \end{array} \right ] & b \\ \end{array}\end{split}\]

where the vectors \(c\) and \(b\) and matrix \(A\) are parts of input. This form is close to the form employed by the optimization algorithm and hence this type of interface has low computational overhead. The disadvantage of a matrix oriented interface is that the problem description is quite different from the formulation the modeler thinks about. Therefore, a lot of work goes into casting the problem into the matrix form. This recasting is typically time consuming and error prone.

For instance consider the problem

\[\begin{split}\begin{array}{lccl} \minimize & c^T y + t & & \\ \mbox{subject to} & F y & = & b, \\ & G y - z & = & 0, \\ & t \geq \left \Vert z \right \Vert, & \\ & y \geq 0. & \end{array}\end{split}\]

Observe the problem has three variables i.e. \(y\), \(z\) and \(t\). In order to solve the problem with a matrix oriented interface these variables must be mapped to a single variable \(x\), the matrix \(A\) has to be formed out of \(F\), \(G\), and so on. This can be cumbersome.

The different matrix oriented interfaces available in the MOSEK Optimization Suite are discussed subsequently.

2.2.1 The Optimizer API

The C Optimizer Application Programming Interface (API) is the core of the MOSEK Optimization Suite because it contains optimization algorithms and a matrix orientated interface that can be used from any C compatible programming language. The C Optimizer API is the most comprehensive API and all other APIs are built on top of that. Hence, it is also the interface with lowest computational overhead. Almost all of its functionality is available from

  • Java,

  • Python,

  • .NET,

  • Julia,

  • Rust.

The Optimizer API accepts problems with:

  • linear objective,

  • linear constraints of the form \(Ax=b\), \(Ax\geq b\), \(Ax\leq b\), \(b_1\leq Ax\leq b_2\) and similar,

  • integer variables,

and nonlinearities can be inputted either in conic form as:

  • conic constraints of the form \(Ax+b\in K\) where \(K\) is a convex cone,

  • disjunctive constraints (a constraint which is an alternative of a number of conditions),

or for the pure QP users as:

  • quadratic objective and quadratic constraints.

The code sample

    for (j = 0; j < numvar && r == MSK_RES_OK; ++j)
    {
      /* Set the linear term c_j in the objective.*/
      if (r == MSK_RES_OK)
        r = MSK_putcj(task, j, c[j]);


      /* Set the bounds on variable j.
       blx[j] <= x_j <= bux[j] */
      if (r == MSK_RES_OK)
        r = MSK_putvarbound(task,
                            j,           /* Index of variable.*/
                            bkx[j],      /* Bound key.*/
                            blx[j],      /* Numerical value of lower bound.*/
                            bux[j]);     /* Numerical value of upper bound.*/

      /* Input column j of A */
      if (r == MSK_RES_OK)
        r = MSK_putacol(task,
                        j,                 /* Variable (column) index.*/
                        aptre[j] - aptrb[j], /* Number of non-zeros in column j.*/
                        asub + aptrb[j],   /* Pointer to row indexes of column j.*/
                        aval + aptrb[j]);  /* Pointer to Values of column j.*/
    }

illustrates how to input the vector \(c\) and matrix \(A\). This should provide the flavor of the interface.

A common feature of all the optimizer APIs is a low performance overhead.

2.2.2 The Optimization Toolbox for MATLAB

MOSEK provides its own Optimization Toolbox for MATLAB that gives access to most of the Optimizer API functionalities, plus some specialized drivers. It solves problems with:

  • linear objective,

  • linear constraints of the form \(Ax=b\), \(Ax\geq b\), \(Ax\leq b\), \(b_1\leq Ax\leq b_2\) and similar,

  • integer variables,

and nonlinearities can be inputted either:

  • in conic form as conic constraints \(Ax+b\in K\) where \(K\) is a convex cone,

  • or for the pure QP users as quadratic objective and quadratic constraints.

The following code

c     = [3 1 5 1]';
a     = [[3 1 2 0];[2 1 3 1];[0 2 0 3]];
blc   = [30 15  -inf]';
buc   = [30 inf 25 ]';
blx   = zeros(4,1);
bux   = [inf 10 inf inf]';

[res] = msklpopt(c,a,blc,buc,blx,bux,[],'maximize');
sol   = res.sol;

illustrates how to solve a linear optimization problem using the toolbox. Some of the main advantages of using MATLAB compared to say C are: no memory management required and direct operations with sparse vectors and matrices.

There is a MATLAB Optimization Toolbox available from the company MathWorks. For convenience the MOSEK Optimization Toolbox for MATLAB provides functions compatible with those in the MATLAB Optimization Toolbox, e.g.

  • linprog: Solves linear optimization problems.

  • intlinprog: Solves a linear optimization problem with integer variables.

  • quadprog: Solves quadratic optimization problems.

  • lsqlin: Minimizes a least-squares objective with linear constraints.

  • lsqnonneg: Minimizes a least-squares objective with nonnegativity constraints.

In general the MOSEK Optimization Toolbox for MATLAB is not capable of handling all the problem types that the MATLAB Optimization Toolbox can deal with and vice versa. For instance only MOSEK can deal with conic optimization problems.

2.2.3 Rmosek

Rmosek is a simple R interface to the MOSEK solver. It has features that mimic those of the Optimizer API. It solves problems with:

  • linear objective,

  • linear constraints of the form \(Ax=b\), \(Ax\geq b\), \(Ax\leq b\), \(b_1\leq Ax\leq b_2\) and similar,

  • integer variables,

and nonlinearities can be inputted either:

  • in conic form as conic constraints \(Ax+b\in K\) where \(K\) is a convex cone,

  • or for the pure QP users as quadratic objective and quadratic constraints.

    # Objective coefficients
    prob$c <- c(3, 1, 5, 1)

    # Specify matrix 'A' in sparse format.
    asubi  <- c(1, 1, 1, 2, 2, 2, 2, 3, 3)
    asubj  <- c(1, 2, 3, 1, 2, 3, 4, 2, 4)
    aval   <- c(3, 1, 2, 2, 1, 3, 1, 2, 3)

    prob$A <- sparseMatrix(asubi,asubj,x=aval)

    # Bound values for constraints
    prob$bc <- rbind(blc=c(30,  15, -Inf), 
                     buc=c(30, Inf,   25))

    # Bound values for variables
    prob$bx <- rbind(blx=rep(0,4), 
                     bux=c(Inf, 10, Inf, Inf))

    # Solve the problem
    r <- mosek(prob)

2.2.4 The Command Line Tool

The MOSEK Optimization Suite includes a command line tool that allows to use MOSEK directly. This is quite convenient in many situations:

  • testing the license setup,

  • performing tests bypassing any API,

  • benchmarking the solver without involving API calling.

  • solving an optimization problem stored in a file,

  • performing infeasibility analysis on a problem dumped to disk from an API.

2.3 Modeling languages

MOSEK is available from several external modeling languages such as

  • AMPL

  • JuMP

  • GAMS

  • CVXPY

  • Pyomo

  • YALMIP

  • CVX

(see full list on https://www.mosek.com/resources/third-party/) that make it easy to build optimization models that look almost like the one the modeler has in mind. Hence, the big advantage of modeling languages is convenience and prototyping optimization models is typically extremely fast. However, it is important to remember that such tools:

  • add an extra layer between the user and the optimizer,

  • can make debugging much more cumbersome,

  • do not provide access to full capabilities of MOSEK.

2.3.1 AMPL

MOSEK can be used with the modeling language AMPL via the AMPL/MP Library available at https://github.com/ampl/mp

2.3.2 GAMS

MOSEK can be used with the modeling language GAMS. However, a special link must be purchased from GAMS in order to do that. GAMS also provides documentation for how to use MOSEK from GAMS.