# 8.1 Separable Convex (SCopt) Interface¶

The Optimizer API for C provides a way to add simple non-linear functions composed from a limited set of non-linear terms. Non-linear terms can be mixed with quadratic terms in objective and constraints. We consider problems which can be formulated as:

$\begin{split}\begin{array} {lcccccc} \mbox{minimize} & & & z_0(x) + c^T x & & & \\ \mbox{subject to} & l^c_i & \leq & z_i(x) + a_i^T x & \leq & u^c_i & i=1\ldots m\\ & l^x & \leq & x & \leq & u^x, & \end{array}\end{split}$

where $$x\in\real^n$$ and each $$z_i : \real^n\rightarrow\real$$ is separable, that is can be written as a sum

$z_i(x) = \sum^{n}_{j=1} z_{i,j}(x_j).$

The interface implements a limited set of functions which can appear as $$z_{i,j}$$. They are:

Table 8.1 Functions supported by the SCopt interface.
Separable function Operator name Name
$$f x \ln (x)$$ ent Entropy function
$$f e^{g x + h}$$ exp Exponential function
$$f \ln (g x + h)$$ log Logarithm
$$f (x+h)^g$$ pow Power function

where $$f,g,h\in\real$$ are constants. This formulation does not guarantee convexity. For MOSEK to be able to solve the problem, the following requirements must be met:

• If the objective is minimized, the sum of non-linear terms must be convex, otherwise it must be concave.
• Any constraint bounded below must be concave, and any constraint bounded above must be convex.
• Each separable term must be twice differentiable within the bounds of the variable it is applied to.

Some simple rules can be followed to ensure that the problem satisfies MOSEK‘s convexity and differentiability requirements. First of all, for any variable $$x_i$$ used in a separable term, the variable bounds must define a range within which the function is twice differentiable. These bounds are defined in Table 8.2.

Table 8.2 Safe bounds for functions in the SCopt interface.
Separable function Operator name Safe $$x$$ bounds
$$f x \ln (x)$$ ent $$0 < x$$.
$$f e^{g x + h}$$ exp $$-\infty <x <\infty$$.
$$f \ln (g x + h)$$ log If $$g > 0$$: $$-h/g < x$$.
If $$g < 0$$: $$x < -h/g$$.
$$f (x+h)^g$$ pow If $$g > 0$$ and integer: $$-\infty <x <\infty$$.
If $$g < 0$$ and integer: either $$-h <x$$ or $$x <-h$$.
Otherwise: $$-h <x$$.

To ensure convexity, we require that each $$z_i(x)$$ is either a sum of convex terms or a sum of concave terms. Table 8.3 lists convexity conditions for the relevant ranges for $$f>0$$ — changing the sign of $$f$$ switches concavity/convexity.

Table 8.3 Convexity conditions for functions in the SCopt interface.
Separable function Operator name Convexity conditions
$$f x \ln (x)$$ ent Convex within safe bounds.
$$f e^{g x + h}$$ exp Convex for all $$x$$.
$$f \ln (g x + h)$$ log Concave within safe bounds.
$$f (x+h)^g$$ pow If $$g$$ is even integer: convex within safe bounds.

If $$g$$ is odd integer:

• concave if $$(-\infty,-h)$$,
• convex if $$(-h,\infty)$$

If $$0<g<1$$: concave within safe bounds.

Otherwise: convex within safe bounds.

A problem involving linear combinations of variables (such as $$\ln(x_1+x_2)$$), can be converted to a separable problem using slack variables and additional equality constraints.

## 8.1.1 Example¶

Consider the following separable convex problem:

(1)$\begin{split}\begin{array}{ll} \mbox{minimize} & x_1 - \ln(x_3) \\ \mbox{subject to} & x_1^2 + x_2^2 \leq 1\\ & x_1 + 2x_2 - x_3 = 0\\ & x_3 \geq 0 \end{array}\end{split}$

Note that all nonlinear functions are well defined for $$x$$ values satisfying the variable bounds strictly. This assures that function evaluation errors will not occur during the optimization process because MOSEK.

The linear part of the problem is specified as usually. The nonlinear part is set using the function MSK_scbegin. See the API reference for a description of the format. After that a standard invocation of MSK_optimize solves the problem. The API reference describes additional functions for reading and writing SCopt terms from/to a file.

Note that the code must include the extension scopt-ext.h and must be linked the implementation contained in scopt-ext.c, both available in examples/c.

Listing 8.1 Implementation of problem (1). Click here to download.
#include "scopt-ext.h"

#define NUMOPRO  1 /* Number of nonlinear expressions in the obj. */
#define NUMOPRC  2 /* Number of nonlinear expressions in the con. */
#define NUMVAR   3 /* Number of variables.     */
#define NUMCON   2 /* Number of constraints.   */
#define NUMANZ   3 /* Number of non-zeros in A. */

static void MSKAPI printstr(void *handle,
const char str[])
{
printf("%s",str);
} /* printstr */

int main()
{
char         buffer[MSK_MAX_STR_LEN];
double       oprfo[NUMOPRO],oprgo[NUMOPRO],oprho[NUMOPRO],
oprfc[NUMOPRC],oprgc[NUMOPRC],oprhc[NUMOPRC],
c[NUMVAR],aval[NUMANZ],
blc[NUMCON],buc[NUMCON],blx[NUMVAR],bux[NUMVAR];
int          numopro,numoprc,
numcon=NUMCON,numvar=NUMVAR,
opro[NUMOPRO],oprjo[NUMOPRO],
oprc[NUMOPRC],opric[NUMOPRC],oprjc[NUMOPRC],
aptrb[NUMVAR],aptre[NUMVAR],asub[NUMANZ];
MSKboundkeye bkc[NUMCON],bkx[NUMVAR];
MSKenv_t     env;
MSKrescodee  r;
schand_t     sch;

/* Specify nonlinear terms in the objective. */
numopro  = NUMOPRO;
opro[0]  = MSK_OPR_LOG; /* Defined in scopt.h */
oprjo[0] = 2;
oprfo[0] = -1.0;
oprgo[0] = 1.0;  /* This value is never used. */
oprho[0] = 0.0;

/* Specify nonlinear terms in the constraints. */
numoprc  = NUMOPRC;

oprc[0]  = MSK_OPR_POW;
opric[0] = 0;
oprjc[0] = 0;
oprfc[0] = 1.0;
oprgc[0] = 2.0;
oprhc[0] = 0.0;

oprc[1]  = MSK_OPR_POW;
opric[1] = 0;
oprjc[1] = 1;
oprfc[1] = 1.0;
oprgc[1] = 2.0;
oprhc[1] = 0.0;

/* Specify c */
c[0] = 1.0; c[1] = 0.0; c[2] = 0.0;

/* Specify a. */
aptrb[0] = 0;   aptrb[1] = 1;   aptrb[2] = 2;
aptre[0] = 1;   aptre[1] = 2;   aptre[2] = 3;
asub[0]  = 1;   asub[1]  = 1;   asub[2]  = 1;
aval[0]  = 1.0; aval[1]  = 2.0; aval[2]  = -1.0;

/* Specify bounds for constraints. */
bkc[0] = MSK_BK_UP;     bkc[1] = MSK_BK_FX;
blc[0] = -MSK_INFINITY; blc[1] = 0.0;
buc[0] = 1.0;           buc[1] = 0.0;

/* Specify bounds for variables. */
bkx[0] = MSK_BK_LO;      bkx[1] = MSK_BK_LO;     bkx[2] = MSK_BK_LO;
blx[0] = 0.0;            blx[1] = 0.1;           blx[2] = 0.0;
bux[0] = MSK_INFINITY;   bux[1] = MSK_INFINITY;  bux[2] = MSK_INFINITY;

/* Create  the mosek environment. */
r = MSK_makeenv(&env,NULL);

if ( r==MSK_RES_OK )
{
/* Make the optimization task. */
if ( r==MSK_RES_OK )

if ( r==MSK_RES_OK )
{
/* Setup the linear part of the problem. */
numcon,numvar,
numcon,numvar,
c,0.0,
aptrb,aptre,
asub,aval,
bkc,blc,buc,
bkx,blx,bux);
}

if ( r== MSK_RES_OK )
{
/* Set-up of nonlinear expressions. */
numopro,opro,oprjo,oprfo,oprgo,oprho,
numoprc,oprc,opric,oprjc,oprfc,oprgc,oprhc,
&sch);

if ( r==MSK_RES_OK )
{
printf("Start optimizing\n");

printf("Done optimizing\n");

}

/* The nonlinear expressions are no longer needed. */
}