C/C++ API

 
The simplest optimization problem is a purely linear problem. A linear optimization problem is a problem of the following form:
Minimize or maximize the objective function
 \sum_{j=0}^{n-1} c_{j} x_{j} + c^{f} (1.1)
subject to the linear constraints
 l_{k}^{c} \leq{}\sum_{j=0}^{n-1} a_{kj} x_{j} \leq{} u_{k}^{c},{\ } k=0,\ldots{} ,m-1, (1.2)
and the bounds
 l_{j}^{x} \leq{} x_{j} \leq{} u_{j}^{x}, {\ } j=0,\ldots{} ,n-1, (1.3)
where we have used the problem elements:
m and n
which are the number of constraints and variables respectively,
x
which is the variable vector of length n,
c
which is a coefficient vector of size n
 c = \left[{} \begin{array}{c} \displaystyle{} c_{0} \\[0pt] \displaystyle{} \\[0pt] \displaystyle{} c_{n-1} \\[0pt] \end{array} \right]{},
c^{f}
which is a constant,
A
which is a m{\times}n matrix of coefficients is given by
 A = \left[{} \begin{array}{ccc} \displaystyle{} a_{0,0} &\displaystyle{} \cdots{}&\displaystyle{} a_{0,(n-1)} \\[0pt] \displaystyle{} &\displaystyle{} \cdots{}&\displaystyle{} \\[0pt] \displaystyle{} a_{(m-1),0} &\displaystyle{} \cdots{}&\displaystyle{} a_{(m-1),(n-1)} \\[0pt] \end{array} \right]{},
l^{c} and u^{c}
which specify the lower and upper bounds on constraints respectively, and
l^{x} and u^{x}
which specifies the lower and upper bounds on variables respectively.
Please note the unconventional notation using 0 as the first index rather than 1. Hence, x_{0} is the first element in variable vector x. This convention has been adapted from arrays which are indexed from 0.

Example: Linear optimization

The following is an example of a linear optimization problem:
 \begin{array}{lccccccccc} \displaystyle{} \mbox{maximize}&\displaystyle{} 3 x_{0} &\displaystyle{} + &\displaystyle{} 1 x_{1} &\displaystyle{} + &\displaystyle{} 5 x_{2} &\displaystyle{} + &\displaystyle{} 1 x_{3} &\displaystyle{} &\displaystyle{} \\[0pt] \displaystyle{} \mbox{subject to}&\displaystyle{} 3 x_{0} &\displaystyle{} + &\displaystyle{} 1 x_{1} &\displaystyle{} + &\displaystyle{} 2 x_{2} &\displaystyle{} &\displaystyle{} &\displaystyle{} = &\displaystyle{} 30, \\[0pt] \displaystyle{} &\displaystyle{} 2 x_{0} &\displaystyle{} + &\displaystyle{} 1 x_{1} &\displaystyle{} + &\displaystyle{} 3 x_{2} &\displaystyle{} + &\displaystyle{} 1 x_{3} &\displaystyle{} \geq{}&\displaystyle{} 15, \\[0pt] \displaystyle{} &\displaystyle{} &\displaystyle{} &\displaystyle{} 2 x_{1} &\displaystyle{} &\displaystyle{} &\displaystyle{} + &\displaystyle{} 3 x_{3} &\displaystyle{} \leq{}&\displaystyle{} 25, \\[0pt] \end{array}
having the bounds
 \begin{array}{ccccc} \displaystyle{} 0 &\displaystyle{} \leq{}&\displaystyle{} x_{0} &\displaystyle{} \leq{}&\displaystyle{} \infty{} , \\[0pt] \displaystyle{} 0 &\displaystyle{} \leq{}&\displaystyle{} x_{1} &\displaystyle{} \leq{}&\displaystyle{} 10, \\[0pt] \displaystyle{} 0 &\displaystyle{} \leq{}&\displaystyle{} x_{2} &\displaystyle{} \leq{}&\displaystyle{} \infty{} , \\[0pt] \displaystyle{} 0 &\displaystyle{} \leq{}&\displaystyle{} x_{3} &\displaystyle{} \leq{}&\displaystyle{} \infty{} . \\[0pt] \end{array}

Solving the problem

To solve the problem above we go through the following steps:
Below we explain each of these steps. For the complete source code see section 1.2.
Create an environment.
Before setting up the optimization problem, a MOSEK environment must be created. All tasks in the program should share the same environment.
  1. r = MSK_makeenv(&env,NULL); 
Create an optimization task.
Next, an empty task object is created:
  1. /* Create the optimization task. */ 
  2. r = MSK_maketask(env,numcon,numvar,&task); 
  3.  
  4. /* Directs the log task stream to the 'printstr' function. */ 
  5. if ( r==MSK_RES_OK
  6. r = MSK_linkfunctotaskstream(task,MSK_STREAM_LOG,NULL,printstr); 
We also connect a call-back function to the task log stream. Messages related to the task are passed to the call-back function. In this case the stream call-back function writes its messages to the standard output stream.
Load a problem into the task object.
Before any problem data can be set, variables and constraints must be added to the problem via calls to the functions MSK_appendcons and MSK_appendvars.
  1. /* Append 'numcon' empty constraints. 
  2. The constraints will initially have no bounds. */ 
  3. if ( r == MSK_RES_OK
  4. r = MSK_appendcons(task,numcon); 
  5.  
  6. /* Append 'numvar' variables. 
  7. The variables will initially be fixed at zero (x=0). */ 
  8. if ( r == MSK_RES_OK
  9. r = MSK_appendvars(task,numvar); 
New variables can now be referenced from other functions with indexes in 0, \ldots{}, \mathtt{numvar}-1 and new constraints can be referenced with indexes in 0, \ldots{} , \mathtt{numcon}-1. More variables / constraints can be appended later as needed, these will be assigned indexes from \mathtt{numvar}/\mathtt{numcon} and up.
Next step is to set the problem data. We loop over each variable index j=0, \ldots{}, \mathtt{numvar}-1 calling functions to set problem data. We first set the objective coefficient c_{j} = \mathtt{c[j]} by calling the function MSK_putcj.
  1. /* Set the linear term c_j in the objective.*/  
  2. if(r == MSK_RES_OK
  3. r = MSK_putcj(task,j,c[j]); 
The bounds on variables are stored in the arrays
  1. MSKboundkeye bkx[] = {MSK_BK_LO, MSK_BK_RA, MSK_BK_LO, MSK_BK_LO }; 
  2. double blx[] = {0.0, 0.0, 0.0, 0.0 }; 
  3. double bux[] = {+MSK_INFINITY, 10.0, +MSK_INFINITY, +MSK_INFINITY }; 
and are set with calls to MSK_putvarbound.
  1. /* Set the bounds on variable j. 
  2. blx[j] <= x_j <= bux[j] */ 
  3. if(r == MSK_RES_OK
  4. r = MSK_putvarbound(task
  5. j, /* Index of variable.*/ 
  6. bkx[j], /* Bound key.*/ 
  7. blx[j], /* Numerical value of lower bound.*/ 
  8. bux[j]); /* Numerical value of upper bound.*/ 
The Bound key stored in bkx specify the type of the bound according to Table 1.1.1.1.
Bound key
Type of bound
Lower bound
Upper bound
MSK_BK_FX
\cdots{} = l_{j}
Finite
Identical to the lower bound
MSK_BK_FR
Free
Minus infinity
Plus infinity
MSK_BK_LO
l_{j} \leq{}\cdots{}
Finite
Plus infinity
MSK_BK_RA
l_{j} \leq{}\cdots{}\leq{} u_{j}
Finite
Finite
MSK_BK_UP
\cdots{}\leq{} u_{j}
Minus infinity
Finite
Tab. 1.1.1.1. Interpretation of the bound keys.
For instance bkx[0]=MSK_BK_LO means that x_{0} \geq{} l_{0}^{x}. Finally, the numerical values of the bounds on variables are given by
 l_{j}^{x} = \mathtt{blx[j]}
and
 u_{j}^{x} = \mathtt{bux[j]}.
Recall that in our example the A matrix is given by
 A = \left[{} \begin{array}{cccc} \displaystyle{} 3 &\displaystyle{} 1 &\displaystyle{} 2 &\displaystyle{} 0 \\[0pt] \displaystyle{} 2 &\displaystyle{} 1 &\displaystyle{} 3 &\displaystyle{} 1 \\[0pt] \displaystyle{} 0 &\displaystyle{} 2 &\displaystyle{} 0 &\displaystyle{} 3 \\[0pt] \end{array} \right]{}.
This matrix is stored in sparse format in the arrays:
  1. MSKint32t aptrb[] = {0, 2, 5, 7}, 
  2. aptre[] = {2, 5, 7, 9}, 
  3. asub[] = { 0, 1
  4. 0, 1, 2
  5. 0, 1
  6. 1, 2}; 
  7. double aval[] = { 3.0, 2.0
  8. 1.0, 1.0, 2.0
  9. 2.0, 3.0
  10. 1.0, 3.0}; 
The ptrb, ptre, asub, and aval arguments define the constraint matrix A in the column ordered sparse format.
Using the function MSK_putacol we set column j of A
  1. r = MSK_putacol(task
  2. j, /* Variable (column) index.*/ 
  3. aptre[j]-aptrb[j], /* Number of non-zeros in column j.*/ 
  4. asub+aptrb[j], /* Pointer to row indexes of column j.*/ 
  5. aval+aptrb[j]); /* Pointer to Values of column j.*/ 
Alternatively, the same A matrix can be set one row at a time; please see section 1.3 for an example.
Finally, the bounds on each constraint are set by looping over each constraint index i= 0, \ldots{},\mathtt{numcon}-1
  1. /* Set the bounds on constraints. 
  2. for i=1, ...,numcon : blc[i] <= constraint i <= buc[i] */ 
  3. for(i=0; i<numcon && r==MSK_RES_OK; ++i
  4. r = MSK_putconbound(task
  5. i, /* Index of constraint.*/ 
  6. bkc[i], /* Bound key.*/ 
  7. blc[i], /* Numerical value of lower bound.*/ 
  8. buc[i]); /* Numerical value of upper bound.*/ 
Optimization:
After the problem is set-up the task can be optimized by calling the function MSK_optimizetrm.
  1. r = MSK_optimizetrm(task,&trmcode); 
Extracting the solution.
After optimizing the status of the solution is examined with a call to MSK_getsolsta. If the solution status is reported as MSK_SOL_STA_OPTIMAL or MSK_SOL_STA_NEAR_OPTIMAL the solution is extracted in the lines below:
  1. MSK_getxx(task
  2. MSK_SOL_BAS, /* Request the basic solution. */ 
  3. xx); 
The MSK_getxx function obtains the solution. MOSEK may compute several solutions depending on the optimizer employed. In this example the basic solution is requested by setting the first argument to MSK_SOL_BAS.
The complete source code is listed in lo1.
In the example above, the A matrix is set one column at a time. The same can be done one row at a time, or the two methods can be mixed. Example lo2 shows how to set the A matrix by rows.
For further details on MOSEK and the C API, please see the MOSEK C API Manual.

Compiling and running lo1

This section shows the commands necessary to compile the example lo1 above from a command line and run it.

Microsoft Windows

We assume that MOSEK was installed in the default location
  1. C:\Program Files\mosek 
Open a DOS box with the Visual Studio tool chain enabled: Usually there is under Microsoft Visual Studio 20xx/Visual Studio Tools a menu point ... x64 Tools Command Prompt.
Go to the location of your example file lo1.c, e.g.
  1. c: 
  2. cd \Users\me\src\lo1 
Compile the example:
  1. cl /c /I"C:\Program Files\mosek\7\tools\platform\win64x86\h" /Folo1.obj lo1.c 
  2. link /libpath:"C:\Program Files\mosek\7\tools\platform\win64x86\bin" mosek64_7_0 /out:lo1.exe lo1.obj 
If MOSEK was correctly installed, you can now run the example by entering
  1. lo1 
If you want to make sure that your application can run even when MOSEK is not installed, you need to do two things: First copy the essential MOSEK DLLs into your application directory:
  1. copy "C:\Program Files\mosek\7\tools\platform\win64x86\bin\mosek64_7_0.dll" .  
  2. copy "C:\Program Files\mosek\7\tools\platform\win64x86\bin\libiomp5md.dll" .  
  3. copy "C:\Program Files\mosek\7\tools\platform\win64x86\bin\mosekglb64_7_0.dll" .  
Secondly, make sure that your application knows a valid license file. Usually the license file is started at
  1. %USERPROFILE%\mosek.lic 
or rewrite your application to pass the right path immediately after the environment is created as illustrated in:
  1. int main(int argc, char ** argv) 
  2. char * moseklifile = argv[1]; 
  3. MSKenv_t env; 
  4. MSKrescodee r; 
  5.  
  6. r = MSK_makeenv(&env, NULL); 
  7. if ( r==MSK_RES_OK ) 
  8. r = MSK_putlicensepath(env,moseklicfile); 
  9. ... 
Above we assumed that compilation was done on an x64 machine. If you are compiling on a 32-bit architecture, you must

Linux

We assume that MOSEK was installed in the user's home directory
  1. $HOME/mosek 
Open a terminal and go to the location of your example file lo1.c, e.g.
  1. cd ~/src/lo1 
Compile the example with gcc:
  1. gcc -o lo1 \  
  2. -I$HOME/mosek/7/tools/platform/linux64x86/h \  
  3. -L$HOME/mosek/7/tools/platform/linux64x86/bin \  
  4. -Wl,-rpath-link=$HOME/mosek/7/tools/platform/linux64x86/bin \  
  5. -lmosek64 \  
  6. lo1.c  
If MOSEK was correctly installed, you can now run the example by entering
  1. lo1 
If you want to make sure that your application can run even when MOSEK is not installed, you need to do three things: First, add the parameter
  1. -Wl,-rpath=\$ORIGIN 
to te build line. This will allow the application to look for shared library dependencies in the same directory as the application executable.
Secondly, copy the essential MOSEK libraries into your application directory:
  1. cp $HOME/mosek/7/tools/platform/linux64x86/bin/libmosek64.so.7.0 .  
  2. cp $HOME/mosek/7/tools/platform/linux64x86/bin/libiomp5.so .  
  3. cp $HOME/mosek/7/tools/platform/linux64x86/bin/libmosekglb64.so.7.0 .  
Finally, make sure that your application knows a valid license file. Usually the license file is stored at
  1. $HOME/mosek/mosek.lic 
or rewrite your application to pass the right path immediately after the environment is created, for example:
  1. int main(int argc, char ** argv
  2. char * moseklicfile = argv[1]; 
  3. MSKenv_t env
  4. MSKrescodee r
  5.  
  6. r = MSK_makeenv(&env,NULL); 
  7. if ( r==MSK_RES_OK
  8. r = MSK_putlicensepath(env,moseklicfile); 
  9. ... 
Above we assumed that compilation was done on an x64 machine. If you are compiling on a 32-bit architecture, you must

MacOS X

We assume that MOSEK was installed in the user's home directory
  1. $HOME/mosek 
Open a terminal and go to the location of your example file lo1.c, e.g.
  1. cd ~/src/lo1 
Compile the example with gcc:
  1. gcc -o lo1 \  
  2. -I$HOME/mosek/7/tools/platform/linux64x86/h \  
  3. -L$HOME/mosek/7/tools/platform/linux64x86/bin \  
  4. -Wl,-rpath-link=$HOME/mosek/7/tools/platform/linux64x86/bin \  
  5. -lmosek \  
  6. lo1.c  
If MOSEK was correctly installed, you can now run the example by entering
  1. lo1 
If you want to make sure that your application can run even when MOSEK is not installed, you need to do three things: First, modify the built binary lo1
  1. install_name_tool -change libmosek64.7.0.dylib @executable_path/libmosek64.7.0.dylib  
This will allow the application to look for libmosek64 in the same directory as the application executable.
Secondly, copy the essential MOSEK libraries into your application directory:
  1. cp $HOME/mosek/\mskmajorver/tools/platform/linux64x86/bin/libmosek64.\mskmajorver.\mskminorver.dylib . 
  2. cp $HOME/mosek/\mskmajorver/tools/platform/linux64x86/bin/libiomp5.so . 
  3. cp $HOME/mosek/\mskmajorver/tools/platform/linux64x86/bin/libmosekglb64.\mskmajorver.\mskminorver.dylib . 
Finally, make sure that your application knows a valid license file. Usually the license file is stored at
  1. $HOME/mosek/mosek.lic 
or rewrite your application to pass the right path immediately after the environment is created, for example:
  1. int main(int argc, char ** argv
  2. char * moseklicfile = argv[1]; 
  3. MSKenv_t env
  4. MSKrescodee r
  5. r = MSK_makeenv(&env,NULL); 
  6. if ( r==MSK_RES_OK
  7. r = MSK_putlicensepath(env,moseklicfile); 
  8. ... 
Above we assumed that compilation was done on an x64 machine. If you are compiling on a 32-bit architecture, you must

Further documentation

For further documentation see

Source code for lo1

  1. /* 
  2. Copyright: Copyright (c) MOSEK ApS, Denmark. All rights reserved. 
  3.  
  4. File: lo1.c 
  5.  
  6. Purpose: To demonstrate how to solve a small linear 
  7. optimization problem using the MOSEK C API,  
  8. and handle the solver result and the problem 
  9. solution. 
  10. */ 
  11.  
  12. #include <stdio.h
  13. #include "mosek.h"  
  14.  
  15. /* This function prints log output from MOSEK to the terminal. */ 
  16. static void MSKAPI printstr(void *handle
  17. MSKCONST char str[]) 
  18. printf("%s",str); 
  19. } /* printstr */ 
  20.  
  21. int main(int argc,char *argv[]) 
  22. const MSKint32t numvar = 4
  23. numcon = 3
  24.  
  25. double c[] = {3.0, 1.0, 5.0, 1.0}; 
  26. /* Below is the sparse representation of the A 
  27. matrix stored by column. */ 
  28. MSKint32t aptrb[] = {0, 2, 5, 7}, 
  29. aptre[] = {2, 5, 7, 9}, 
  30. asub[] = { 0, 1
  31. 0, 1, 2
  32. 0, 1
  33. 1, 2}; 
  34. double aval[] = { 3.0, 2.0
  35. 1.0, 1.0, 2.0
  36. 2.0, 3.0
  37. 1.0, 3.0}; 
  38.  
  39. /* Bounds on constraints. */ 
  40. MSKboundkeye bkc[] = {MSK_BK_FX, MSK_BK_LO, MSK_BK_UP }; 
  41. double blc[] = {30.0, 15.0, -MSK_INFINITY}; 
  42. double buc[] = {30.0, +MSK_INFINITY, 25.0 }; 
  43. /* Bounds on variables. */ 
  44. MSKboundkeye bkx[] = {MSK_BK_LO, MSK_BK_RA, MSK_BK_LO, MSK_BK_LO }; 
  45. double blx[] = {0.0, 0.0, 0.0, 0.0 }; 
  46. double bux[] = {+MSK_INFINITY, 10.0, +MSK_INFINITY, +MSK_INFINITY }; 
  47. MSKenv_t env = NULL
  48. MSKtask_t task = NULL
  49. MSKrescodee r
  50. MSKint32t i,j
  51.  
  52. /* Create the mosek environment. */ 
  53. r = MSK_makeenv(&env,NULL); 
  54.  
  55. if ( r==MSK_RES_OK
  56. /* Create the optimization task. */ 
  57. r = MSK_maketask(env,numcon,numvar,&task); 
  58.  
  59. /* Directs the log task stream to the 'printstr' function. */ 
  60. if ( r==MSK_RES_OK
  61. r = MSK_linkfunctotaskstream(task,MSK_STREAM_LOG,NULL,printstr); 
  62.  
  63. /* Append 'numcon' empty constraints. 
  64. The constraints will initially have no bounds. */ 
  65. if ( r == MSK_RES_OK
  66. r = MSK_appendcons(task,numcon); 
  67.  
  68. /* Append 'numvar' variables. 
  69. The variables will initially be fixed at zero (x=0). */ 
  70. if ( r == MSK_RES_OK
  71. r = MSK_appendvars(task,numvar); 
  72.  
  73. for(j=0; j<numvar && r == MSK_RES_OK; ++j
  74. /* Set the linear term c_j in the objective.*/  
  75. if(r == MSK_RES_OK
  76. r = MSK_putcj(task,j,c[j]); 
  77.  
  78. /* Set the bounds on variable j. 
  79. blx[j] <= x_j <= bux[j] */ 
  80. if(r == MSK_RES_OK
  81. r = MSK_putvarbound(task
  82. j, /* Index of variable.*/ 
  83. bkx[j], /* Bound key.*/ 
  84. blx[j], /* Numerical value of lower bound.*/ 
  85. bux[j]); /* Numerical value of upper bound.*/ 
  86.  
  87. /* Input column j of A */  
  88. if(r == MSK_RES_OK
  89. r = MSK_putacol(task
  90. j, /* Variable (column) index.*/ 
  91. aptre[j]-aptrb[j], /* Number of non-zeros in column j.*/ 
  92. asub+aptrb[j], /* Pointer to row indexes of column j.*/ 
  93. aval+aptrb[j]); /* Pointer to Values of column j.*/ 
  94.  
  95. /* Set the bounds on constraints. 
  96. for i=1, ...,numcon : blc[i] <= constraint i <= buc[i] */ 
  97. for(i=0; i<numcon && r==MSK_RES_OK; ++i
  98. r = MSK_putconbound(task
  99. i, /* Index of constraint.*/ 
  100. bkc[i], /* Bound key.*/ 
  101. blc[i], /* Numerical value of lower bound.*/ 
  102. buc[i]); /* Numerical value of upper bound.*/ 
  103.  
  104. /* Maximize objective function. */ 
  105. if (r == MSK_RES_OK
  106. r = MSK_putobjsense(task, MSK_OBJECTIVE_SENSE_MAXIMIZE); 
  107.  
  108. if ( r==MSK_RES_OK
  109. MSKrescodee trmcode
  110.  
  111. /* Run optimizer */ 
  112. r = MSK_optimizetrm(task,&trmcode); 
  113.  
  114. /* Print a summary containing information 
  115. about the solution for debugging purposes. */ 
  116. MSK_solutionsummary (task,MSK_STREAM_LOG); 
  117.  
  118. if ( r==MSK_RES_OK
  119. MSKsolstae solsta
  120.  
  121. if ( r==MSK_RES_OK
  122. r = MSK_getsolsta (task
  123. MSK_SOL_BAS
  124. &solsta); 
  125. switch(solsta
  126. case MSK_SOL_STA_OPTIMAL:  
  127. case MSK_SOL_STA_NEAR_OPTIMAL
  128. double *xx = (double*) calloc(numvar,sizeof(double)); 
  129. if ( xx
  130. MSK_getxx(task
  131. MSK_SOL_BAS, /* Request the basic solution. */ 
  132. xx); 
  133.  
  134. printf("Optimal primal solution\n"); 
  135. for(j=0; j<numvar; ++j
  136. printf("x[%d]: %e\n",j,xx[j]); 
  137.  
  138. free(xx); 
  139. else  
  140. r = MSK_RES_ERR_SPACE
  141.  
  142. break
  143. case MSK_SOL_STA_DUAL_INFEAS_CER
  144. case MSK_SOL_STA_PRIM_INFEAS_CER
  145. case MSK_SOL_STA_NEAR_DUAL_INFEAS_CER
  146. case MSK_SOL_STA_NEAR_PRIM_INFEAS_CER:  
  147. printf("Primal or dual infeasibility certificate found.\n"); 
  148. break
  149. case MSK_SOL_STA_UNKNOWN
  150. char symname[MSK_MAX_STR_LEN]; 
  151. char desc[MSK_MAX_STR_LEN]; 
  152.  
  153. /* If the solutions status is unknown, print the termination code 
  154. indicating why the optimizer terminated prematurely. */ 
  155.  
  156. MSK_getcodedesc(trmcode
  157. symname
  158. desc); 
  159.  
  160. printf("The solution status is unknown.\n"); 
  161. printf("The optimizer terminitated with code: %s\n",symname); 
  162. break
  163. default
  164. printf("Other solution status.\n"); 
  165. break
  166.  
  167. if (r != MSK_RES_OK
  168. /* In case of an error print error code and description. */  
  169. char symname[MSK_MAX_STR_LEN]; 
  170. char desc[MSK_MAX_STR_LEN]; 
  171.  
  172. printf("An error occurred while optimizing.\n");  
  173. MSK_getcodedesc (r
  174. symname
  175. desc); 
  176. printf("Error %s - '%s'\n",symname,desc); 
  177.  
  178. /* Delete the task and the associated data. */ 
  179. MSK_deletetask(&task); 
  180.  
  181. /* Delete the environment and the associated data. */ 
  182. MSK_deleteenv(&env); 
  183.  
  184. return r
  185. } 

Row-wise input

  1. /* 
  2. Copyright: Copyright (c) MOSEK ApS, Denmark. All rights reserved. 
  3.  
  4. File: lo2.c 
  5.  
  6. Purpose: To demonstrate how to solve a small linear 
  7. optimization problem using the MOSEK C API,  
  8. and handle the solver result and the problem 
  9. solution. 
  10. */ 
  11.  
  12. #include <stdio.h
  13. #include "mosek.h"  
  14.  
  15. /* This function prints log output from MOSEK to the terminal. */ 
  16. static void MSKAPI printstr(void *handle
  17. MSKCONST char str[]) 
  18. printf("%s",str); 
  19. } /* printstr */ 
  20.  
  21. int main(int argc,char *argv[]) 
  22. const int numvar = 4
  23. numcon = 3
  24.  
  25. double c[] = {3.0, 1.0, 5.0, 1.0}; 
  26. /* Below is the sparse representation of the A 
  27. matrix stored by row. */ 
  28. MSKlidxt aptrb[] = {0, 3, 7}; 
  29. MSKlidxt aptre[] = {3, 7, 9}; 
  30. MSKidxt asub[] = { 0,1,2
  31. 0,1,2,3
  32. 1,3};  
  33. double aval[] = { 3.0, 1.0, 2.0
  34. 2.0, 1.0, 3.0, 1.0
  35. 2.0, 3.0};  
  36.  
  37. /* Bounds on constraints. */ 
  38. MSKboundkeye bkc[] = {MSK_BK_FX, MSK_BK_LO, MSK_BK_UP }; 
  39. double blc[] = {30.0, 15.0, -MSK_INFINITY}; 
  40. double buc[] = {30.0, +MSK_INFINITY, 25.0 }; 
  41. /* Bounds on variables. */ 
  42. MSKboundkeye bkx[] = {MSK_BK_LO, MSK_BK_RA, MSK_BK_LO, MSK_BK_LO }; 
  43. double blx[] = {0.0, 0.0, 0.0, 0.0 }; 
  44. double bux[] = {+MSK_INFINITY, 10.0, +MSK_INFINITY, +MSK_INFINITY }; 
  45. MSKenv_t env = NULL
  46. MSKtask_t task = NULL
  47. MSKrescodee r
  48. MSKidxt i,j
  49.  
  50. /* Create the mosek environment. */ 
  51. r = MSK_makeenv(&env,NULL); 
  52.  
  53. if ( r==MSK_RES_OK
  54. /* Create the optimization task. */ 
  55. r = MSK_maketask(env,numcon,numvar,&task); 
  56.  
  57. /* Directs the log task stream to the 'printstr' function. */ 
  58. if ( r==MSK_RES_OK
  59. r = MSK_linkfunctotaskstream(task,MSK_STREAM_LOG,NULL,printstr); 
  60.  
  61. /* Append 'numcon' empty constraints. 
  62. The constraints will initially have no bounds. */ 
  63. if ( r == MSK_RES_OK
  64. r = MSK_appendcons(task,numcon); 
  65.  
  66. /* Append 'numvar' variables. 
  67. The variables will initially be fixed at zero (x=0). */ 
  68. if ( r == MSK_RES_OK
  69. r = MSK_appendvars(task,numvar); 
  70.  
  71. for(j=0; j<numvar && r == MSK_RES_OK; ++j
  72. /* Set the linear term c_j in the objective.*/  
  73. if(r == MSK_RES_OK
  74. r = MSK_putcj(task,j,c[j]); 
  75.  
  76. /* Set the bounds on variable j. 
  77. blx[j] <= x_j <= bux[j] */ 
  78. if(r == MSK_RES_OK
  79. r = MSK_putvarbound(task
  80. j, /* Index of variable.*/ 
  81. bkx[j], /* Bound key.*/ 
  82. blx[j], /* Numerical value of lower bound.*/ 
  83. bux[j]); /* Numerical value of upper bound.*/ 
  84.  
  85. /* Set the bounds on constraints. 
  86. for i=1, ...,numcon : blc[i] <= constraint i <= buc[i] */ 
  87. for(i=0; i<numcon && r==MSK_RES_OK; ++i
  88. r = MSK_putconbound(task
  89. i, /* Index of constraint.*/ 
  90. bkc[i], /* Bound key.*/ 
  91. blc[i], /* Numerical value of lower bound.*/ 
  92. buc[i]); /* Numerical value of upper bound.*/ 
  93.  
  94. /* Input row i of A */  
  95. if(r == MSK_RES_OK
  96. r = MSK_putarow(task
  97. i, /* Row index.*/ 
  98. aptre[i]-aptrb[i], /* Number of non-zeros in row i.*/ 
  99. asub+aptrb[i], /* Pointer to column indexes of row i.*/ 
  100. aval+aptrb[i]); /* Pointer to values of row i.*/ 
  101.  
  102. /* Maximize objective function. */ 
  103. if (r == MSK_RES_OK
  104. r = MSK_putobjsense(task, MSK_OBJECTIVE_SENSE_MAXIMIZE); 
  105.  
  106. if ( r==MSK_RES_OK
  107. MSKrescodee trmcode
  108.  
  109. /* Run optimizer */ 
  110. r = MSK_optimizetrm(task,&trmcode); 
  111.  
  112. /* Print a summary containing information 
  113. about the solution for debugging purposes. */ 
  114. MSK_solutionsummary (task,MSK_STREAM_LOG); 
  115.  
  116. if ( r==MSK_RES_OK
  117. MSKsolstae solsta
  118.  
  119. if (r == MSK_RES_OK
  120. r = MSK_getsolsta (task,MSK_SOL_BAS,&solsta); 
  121. switch(solsta
  122. case MSK_SOL_STA_OPTIMAL:  
  123. case MSK_SOL_STA_NEAR_OPTIMAL
  124. double *xx = (double*) calloc(numvar,sizeof(double)); 
  125. if ( xx
  126. MSK_getxx(task
  127. MSK_SOL_BAS, /* Request the basic solution. */ 
  128. xx); 
  129.  
  130. printf("Optimal primal solution\n"); 
  131. for(j=0; j<numvar; ++j
  132. printf("x[%d]: %e\n",j,xx[j]); 
  133. else 
  134. r = MSK_RES_ERR_SPACE
  135.  
  136. free(xx); 
  137. break
  138. case MSK_SOL_STA_DUAL_INFEAS_CER
  139. case MSK_SOL_STA_PRIM_INFEAS_CER
  140. case MSK_SOL_STA_NEAR_DUAL_INFEAS_CER
  141. case MSK_SOL_STA_NEAR_PRIM_INFEAS_CER:  
  142. printf("Primal or dual infeasibility certificate found.\n"); 
  143. break
  144. case MSK_SOL_STA_UNKNOWN
  145. char symname[MSK_MAX_STR_LEN]; 
  146. char desc[MSK_MAX_STR_LEN]; 
  147.  
  148. /* If the solutions status is unknown, print the termination code 
  149. indicating why the optimizer terminated prematurely. */ 
  150.  
  151. MSK_getcodedesc(trmcode
  152. symname
  153. desc); 
  154.  
  155. printf("The solutuion status is unknown.\n"); 
  156. printf("The optimizer terminitated with code: %s\n",symname); 
  157. break
  158. default
  159. printf("Other solution status.\n"); 
  160. break
  161.  
  162. if (r != MSK_RES_OK
  163. /* In case of an error print error code and description. */  
  164. char symname[MSK_MAX_STR_LEN]; 
  165. char desc[MSK_MAX_STR_LEN]; 
  166.  
  167. printf("An error occurred while optimizing.\n");  
  168. MSK_getcodedesc (r
  169. symname
  170. desc); 
  171. printf("Error %s - '%s'\n",symname,desc); 
  172.  
  173. /* Delete the task and the associated data. */ 
  174. MSK_deletetask(&task); 
  175.  
  176. /* Delete the environment and the associated data. */ 
  177. MSK_deleteenv(&env); 
  178.  
  179. return r
  180. }