This chapter provides information about additional problem classes and functionality provided in the .NET API.
A linear optimization problem always has an optimal solution which is also a basic solution. In an optimal basic solution there are exactly m basic variables where m is the number of rows in the constraint matrix A. Define
as a matrix consisting of the columns of A corresponding to the basic variables.
The basis matrix B is always non-singular, i.e.
or equivalently that
exists. This implies that the linear systems
 |
(6.1.1) |
and
 |
(6.1.2) |
each has a unique solution for all w.
MOSEK provides functions for solving the linear systems (6.1.1) and (6.1.2) for an arbitrary w.
To use the solutions to (6.1.1) and (6.1.2) it is important to know how the basis matrix B is constructed.
Internally MOSEK employs the linear optimization problem
 |
(6.1.3) |
where
The basis matrix is constructed of m columns taken from
If variable
is a basis variable, then the j'th column of A denoted
will appear in B. Similarly, if
is a basis variable, then the i'th column of -I will appear in the basis. The ordering of the basis variables and therefore the ordering of the columns of B is arbitrary. The ordering of the basis variables may be retrieved by calling the function:
mosek.Task.initbasissolve(int[] basis);
This function initializes data structures for later use and returns the indexes of the basic variables in the array basis. The interpretation of the basis is as follows. If
then the i'th basis variable is
. Moreover, the i'th column in B will be the i'th column of -I. On the other hand if
then the i'th basis variable is variable
and the i'th column of B is the column
For instance if
and
, then since
, the first basis variable is
. Therefore, the first column of B is the fourth column of -I. Similarly, if
, then the second variable in the basis is
. Hence, the second column of B is identical to
.
Consider the linear optimization problem:
 |
(6.1.4) |
Suppose a call to mosek.Task.initbasissolve returns an array basis so that
basis[0] = 1,
basis[1] = 2.
Then the basis variables are
and
and the corresponding basis matrix B is
![\begin{math}\nonumber{}\left[\begin{array}{cc}\nonumber{}0 & 1\\\nonumber{}-1 & 1\end{array}\right].\end{math}](math/math145.png) |
(6.1.5) |
Please note the ordering of the columns in B.
The following program demonstrates the use of mosek.Task.solvewithbasis.
using System;
class msgclass : mosek.Stream
{
string prefix;
public msgclass (string prfx)
{
prefix = prfx;
}
public override void streamCB (string msg)
{
Console.Write ("{0}{1}", prefix,msg);
}
}
public class lo1
{
public static void Main ()
{
const int NUMCON = 2;
const int NUMVAR = 2;
double
infinity = 0;
double[] c = {1.0, 1.0};
int[] ptrb = {0, 2};
int[] ptre = {2, 3};
int[] asub = {0, 1,
0, 1};
double[] aval = {1.0, 1.0,
2.0, 1.0};
mosek.boundkey[] bkc = {mosek.boundkey.up,
mosek.boundkey.up};
double[] blc = {-infinity,
-infinity};
double[] buc = {2.0,
6.0};
mosek.boundkey[] bkx = {mosek.boundkey.lo,
mosek.boundkey.lo};
double[] blx = {0.0,
0.0};
double[] bux = {+infinity,
+infinity};
mosek.Task
task = null;
mosek.Env
env = null;
double[] w1 = {2.0, 6.0};
double[] w2 = {1.0, 0.0};
try
{
env = new mosek.Env ();
env.set_streamCB (mosek.streamtype.log, new msgclass ("[env]"));
env.init ();
task = new mosek.Task (env, NUMCON,NUMVAR);
task.set_streamCB (mosek.streamtype.log, new msgclass ("[task]"));
task.inputdata(NUMCON,NUMVAR,
c,
0.0,
ptrb,
ptre,
asub,
aval,
bkc,
blc,
buc,
bkx,
blx,
bux);
task.putobjsense(mosek.objsense.maximize);
try
{
task.optimize();
}
catch (mosek.Warning w)
{
Console.WriteLine("Mosek warning:");
Console.WriteLine (w.Code);
Console.WriteLine (w);
}
int[] basis = new int[NUMCON];
task.initbasissolve(basis);
int[] varsub = {0,1};
for (int i = 0; i < NUMCON; i++) {
if (basis[varsub[i]] < NUMCON)
Console.WriteLine ("Basis variable no {0} is xc{1}",
i,
basis[i]);
else
Console.WriteLine ("Basis variable no {0} is x{1}",
i,
basis[i] - NUMCON);
}
int nz = 2;
task.solvewithbasis(0, ref nz, varsub, w1);
Console.WriteLine ("nz = {0}", nz);
Console.WriteLine ("Solution to Bx = w1:\n");
for (int i = 0; i < nz; i++) {
if (basis[varsub[i]] < NUMCON)
Console.WriteLine ("xc {0} = {1}",
basis[varsub[i]],
w1[varsub[i]] );
else
Console.WriteLine ("x{0} = {1}",
basis[varsub[i]] - NUMCON,
w1[varsub[i]]);
}
nz = 1;
varsub[0] = 0;
task.solvewithbasis(1, ref nz, varsub, w2);
Console.WriteLine ("\nSolution to B^Tx = w2:\n");
for (int i = 0; i < nz; i++) {
if (basis[varsub[i]] < NUMCON)
Console.WriteLine ("xc {0} = {1}",
basis[varsub[i]],
w2[varsub[i]]);
else
Console.WriteLine ("x {0} = {1}",
basis[varsub[i]] - NUMCON,
w2[varsub[i]]);
}
}
catch (mosek.Exception e)
{
Console.WriteLine (e.Code);
Console.WriteLine (e);
}
if (task != null) task.Dispose ();
if (env != null) env.Dispose ();
}
}
In the example above the linear system is solved using the optimal basis for (6.1.4) and the original right-hand side of the problem. Thus the solution to the linear system is the optimal solution to the problem. When running the example program the following output is produced.
basis[0] = 1
Basis variable no 0 is xc1.
basis[1] = 2
Basis variable no 1 is x0.
Solution to Bx = b:
x0 = 2.000000e+00
xc1 = -4.000000e+00
Solution to B^Tx = c:
x1 = -1.000000e+00
x0 = 1.000000e+00
Please note that the ordering of the basis variables is
and thus the basis is given by:
![\begin{math}\nonumber{}B=\left[\begin{array}{cc}\nonumber{}0 & 1\\\nonumber{}-1 & 1\end{array}\right]\end{math}](math/math147.png) |
(6.1.6) |
It can be verified that
is a solution to
MOSEK can be used to solve an arbitrary (rectangular) linear system
using the mosek.Task.solvewithbasis function without optimizing the problem as in the previous example. This is done by setting up an A matrix in the task, setting all variables to basic and calling the mosek.Task.solvewithbasis function with the b vector as input. The solution is returned by the function.
Below we demonstrate how to solve the linear system
![\begin{math}\nonumber{}\left[\begin{array}{cc}\nonumber{}0 & 1\\\nonumber{}-1 & 1\end{array}\right]\left[\begin{array}{c}\nonumber{}x_{0}\\\nonumber{}x_{1}\end{array}\right]=\left[\begin{array}{c}\nonumber{}b_{1}\\\nonumber{}b_{2}\end{array}\right]\end{math}](math/math151.png) |
(6.1.7) |
with b=(1,-2) and b=(7,0).
using System;
class msgclass : mosek.Stream
{
string prefix;
public msgclass (string prfx)
{
prefix = prfx;
}
public override void streamCB (string msg)
{
Console.Write ("{0}{1}", prefix,msg);
}
}
public class solvelinear
{
static public void put_a(mosek.Task task,
double[][] aval,
int[][] asub,
int[] ptrb,
int[] ptre,
int numvar,
int[] basis
)
{
double
infinity = 0;
mosek.stakey[] skx = new mosek.stakey [numvar];
mosek.stakey[] skc = new mosek.stakey [numvar];
for (int i=0;i<numvar ;++i)
{
skx[i] = mosek.stakey.bas;
skc[i] = mosek.stakey.fix;
}
task.append(mosek.accmode.var,numvar);
task.append(mosek.accmode.con,numvar);
for (int i=0;i<numvar ;++i)
task.putavec(mosek.accmode.var,
i,
asub[i],
aval[i]);
for (int i=0 ; i<numvar ;++i)
task.putbound(mosek.accmode.con,
i,
mosek.boundkey.fx,
0.0,
0.0);
for (int i=0 ; i<numvar ;++i)
task.putbound(mosek.accmode.var,
i,
mosek.boundkey.fr,
-infinity,
infinity);
task.makesolutionstatusunknown(mosek.soltype.bas);
for (int i=0 ; i<numvar ;++i)
task.putsolutioni (
mosek.accmode.var,
i,
mosek.soltype.bas,
skx[i],
0.0,
0.0,
0.0,
0.0);
for (int i=0 ; i<numvar ;++i)
task.putsolutioni (
mosek.accmode.con,
i,
mosek.soltype.bas,
skc[i],
0.0,
0.0,
0.0,
0.0);
task.initbasissolve(basis);
}
public static void Main ()
{
const int NUMCON = 2;
const int NUMVAR = 2;
int numvar = 2;
int numcon = 2;
double[][]
aval = new double[NUMVAR][];
aval[0] = new double[] {-1.0 };
aval[1] = new double[] {1.0, 1.0};
int[][]
asub = new int[NUMVAR][];
asub[0] = new int[] {1};
asub[1] = new int[] {0,1};
int [] ptrb = {0,1};
int [] ptre = {1,3};
int[] bsub = new int[numvar];
double[] b = new double[numvar];
int[] basis = new int[numvar];
mosek.Task
task = null;
mosek.Env
env = null;
try
{
env = new mosek.Env ();
env.set_streamCB (mosek.streamtype.log, new msgclass ("[env]"));
env.init ();
task = new mosek.Task (env, NUMCON,NUMVAR);
task.set_streamCB (mosek.streamtype.log, new msgclass ("[task]"));
put_a(
task,
aval,
asub,
ptrb,
ptre,
numvar,
basis
);
b[0] = 1;
b[1] = -2;
bsub[0] = 0;
bsub[1] = 1;
int nz = 2;
task.solvewithbasis(0,ref nz,bsub,b);
Console.WriteLine ("\nSolution to Bx = b:\n\n");
for (int i=0;i<nz;++i)
{
if (basis[bsub[i]] < numcon)
Console.WriteLine ("This should never happen\n");
else
Console.WriteLine ("x{0} = {1}\n",basis[bsub[i]] - numcon , b[bsub[i]] );
}
b[0] = 7;
bsub[0] = 0;
nz = 1;
task.solvewithbasis(0,ref nz,bsub,b);
Console.WriteLine ("\nSolution to Bx = b:\n\n");
for (int i=0;i<nz;++i)
{
if (basis[bsub[i]] < numcon)
Console.WriteLine ("This should never happen\n");
else
Console.WriteLine ("x{0} = {1}\n",basis[bsub[i]] - numcon , b[bsub[i]] );
}
}
catch (mosek.Exception e)
{
Console.WriteLine (e.Code);
Console.WriteLine (e);
}
if (task != null) task.Dispose ();
if (env != null) env.Dispose ();
}
}
The most important step in the above example is the definition of the basic solution using the mosek.Task.putsolutioni function, where we define the status key for each variable. The actual values of the variables are not important and can be selected arbitrarily, so we set them to zero. All variables corresponding to columns in the linear system we want to solve are set to basic and the slack variables for the constraints, which are all non-basic, are set to their bound.
The program produces the output:
Solution to Bx = b:
x1 = 1
x0 = 3
Solution to Bx = b:
x1 = 7
x0 = 7
and we can verify that
is indeed a solution to (6.1.7).