5.1.2. C 语言的建模和优化

在本节中,我们将使用 MindOpt C 语言的 API 来建模以及求解 线性规划问题示例 中的问题。

5.1.2.1. 按行输入:MdoLoEx1

首先,引入头文件:

23#include "Mindopt.h"

并创建优化模型:

52    /*------------------------------------------------------------------*/
53    /* Step 1. Create a model and change the parameters.                */
54    /*------------------------------------------------------------------*/
55    /* Create an empty model. */
56    MDO_CHECK_CALL(Mdo_createMdl(&model));

接下来,我们通过 Mdo_setIntAttr() 将目标函数设置为 最小化 ,并调用 Mdo_addCol() 来添加四个优化变量,定义其下界、上界、名称和类型(关于 Mdo_setIntAttr()Mdo_addCol() 的详细使用方式,请参考 C 接口函数):

58    /*------------------------------------------------------------------*/
59    /* Step 2. Input model.                                             */
60    /*------------------------------------------------------------------*/
61    /* Change to minimization problem. */
62    MDO_CHECK_CALL(Mdo_setIntAttr(model, MDO_INT_ATTR_MIN_SENSE, MDO_YES));
63
64    /* Add variables. */
65    MDO_CHECK_CALL(Mdo_addCol(model, 0.0, 10.0,         1.0, 0, NULL, NULL, "x0", MDO_NO));
66    MDO_CHECK_CALL(Mdo_addCol(model, 0.0, MDO_INFINITY, 1.0, 0, NULL, NULL, "x1", MDO_NO));
67    MDO_CHECK_CALL(Mdo_addCol(model, 0.0, MDO_INFINITY, 1.0, 0, NULL, NULL, "x2", MDO_NO));
68    MDO_CHECK_CALL(Mdo_addCol(model, 0.0, MDO_INFINITY, 1.0, 0, NULL, NULL, "x3", MDO_NO));

Note

矩阵的非零元将在后面按 输入;因此,Mdo_addCol() 中,按 输入非零元的相关参数 sizeindicesvalue 分别用 0NULLNULL 代替(换句话说,此时问题无约束)。

以下我们将开始添加线性约束中的的非零元及其上下界,我们使用以下四列数组来定义线性约束;其中, row1_idxrow2_idx 分别表示第一和第二个约束中非零元素的位置(索引),而 row1_valrow2_val 则是与之相对应的非零数值。

47    const int    row1_idx[] = { 0,   1,   2,   3   };
48    const double row1_val[] = { 1.0, 1.0, 2.0, 3.0 };
49    const int    row2_idx[] = { 0,    2,   3   };
50    const double row2_val[] = { 1.0, -1.0, 6.0 };

我们调用 Mdo_addRow() 将输入约束:

70    /* Add constraints.
71     * Note that the nonzero elements are inputted in a row-wise order here.
72     */
73    MDO_CHECK_CALL(Mdo_addRow(model, 1.0, MDO_INFINITY, 4, row1_idx, row1_val, "c0"));
74    MDO_CHECK_CALL(Mdo_addRow(model, 1.0, 1.0,          3, row2_idx, row2_val, "c1"));

问题输入完成后,再调用 Mdo_solveProb() 求解优化问题,并通过 Mdo_displayResults() 查看优化结果:

76    /*------------------------------------------------------------------*/
77    /* Step 3. Solve the problem and populate the result.               */
78    /*------------------------------------------------------------------*/
79    /* Solve the problem. */
80    MDO_CHECK_CALL(Mdo_solveProb(model));
81    Mdo_displayResults(model);

最后,调用 Mdo_freeMdl() 来释放内存:

84    /*------------------------------------------------------------------*/
85    /* Step 4. Free the model.                                          */
86    /*------------------------------------------------------------------*/
87    /* Free the model. */
88    Mdo_freeMdl(&model);

文件链接 MdoLoEx1.c 提供了完整源代码:

 1/**
 2 *  Description
 3 *  -----------
 4 *
 5 *  Linear optimization (row-wise input).
 6 *
 7 *  Formulation
 8 *  -----------
 9 *
10 *  Minimize
11 *    obj: 1 x0 + 1 x1 + 1 x2 + 1 x3
12 *  Subject To
13 *   c0 : 1 x0 + 1 x1 + 2 x2 + 3 x3 >= 1
14 *   c1 : 1 x0 - 1 x2 + 6 x3 = 1
15 *  Bounds
16 *    0 <= x0 <= 10
17 *    0 <= x1
18 *    0 <= x2
19 *    0 <= x3
20 *  End
21 */
22#include <stdio.h>
23#include "Mindopt.h"
24
25/* Macro to check the return code */
26#define MDO_CHECK_CALL(MDO_CALL)                                    \
27    code = MDO_CALL;                                                \
28    if (code != MDO_OKAY)                                           \
29    {                                                               \
30        Mdo_explainResult(model, code, str);                        \
31        Mdo_freeMdl(&model);                                        \
32        fprintf(stderr, "===================================\n");   \
33        fprintf(stderr, "Error   : code <%d>\n", code);             \
34        fprintf(stderr, "Reason  : %s\n", str);                     \
35        fprintf(stderr, "===================================\n");   \
36        return (int)code;                                           \
37    }
38
39int main(void)
40{
41    /* Variables. */
42    char str[1024] = { "\0" };
43    MdoMdl * model = NULL;
44    MdoResult code = MDO_OKAY;
45    MdoStatus status = MDO_UNKNOWN;
46
47    const int    row1_idx[] = { 0,   1,   2,   3   };
48    const double row1_val[] = { 1.0, 1.0, 2.0, 3.0 };
49    const int    row2_idx[] = { 0,    2,   3   };
50    const double row2_val[] = { 1.0, -1.0, 6.0 };
51
52    /*------------------------------------------------------------------*/
53    /* Step 1. Create a model and change the parameters.                */
54    /*------------------------------------------------------------------*/
55    /* Create an empty model. */
56    MDO_CHECK_CALL(Mdo_createMdl(&model));
57
58    /*------------------------------------------------------------------*/
59    /* Step 2. Input model.                                             */
60    /*------------------------------------------------------------------*/
61    /* Change to minimization problem. */
62    MDO_CHECK_CALL(Mdo_setIntAttr(model, MDO_INT_ATTR_MIN_SENSE, MDO_YES));
63
64    /* Add variables. */
65    MDO_CHECK_CALL(Mdo_addCol(model, 0.0, 10.0,         1.0, 0, NULL, NULL, "x0", MDO_NO));
66    MDO_CHECK_CALL(Mdo_addCol(model, 0.0, MDO_INFINITY, 1.0, 0, NULL, NULL, "x1", MDO_NO));
67    MDO_CHECK_CALL(Mdo_addCol(model, 0.0, MDO_INFINITY, 1.0, 0, NULL, NULL, "x2", MDO_NO));
68    MDO_CHECK_CALL(Mdo_addCol(model, 0.0, MDO_INFINITY, 1.0, 0, NULL, NULL, "x3", MDO_NO));
69
70    /* Add constraints.
71     * Note that the nonzero elements are inputted in a row-wise order here.
72     */
73    MDO_CHECK_CALL(Mdo_addRow(model, 1.0, MDO_INFINITY, 4, row1_idx, row1_val, "c0"));
74    MDO_CHECK_CALL(Mdo_addRow(model, 1.0, 1.0,          3, row2_idx, row2_val, "c1"));
75
76    /*------------------------------------------------------------------*/
77    /* Step 3. Solve the problem and populate the result.               */
78    /*------------------------------------------------------------------*/
79    /* Solve the problem. */
80    MDO_CHECK_CALL(Mdo_solveProb(model));
81    Mdo_displayResults(model);
82 
83    /*------------------------------------------------------------------*/
84    /* Step 4. Free the model.                                          */
85    /*------------------------------------------------------------------*/
86    /* Free the model. */
87    Mdo_freeMdl(&model);
88       
89    return (int)code;
90}

5.1.2.2. 按列输入:MdoLoEx2

在下面的代码中,我们依然对上述问题进行建模,但改以 按列排列 的方式输入矩阵的非零元。换句话说,在增加一个新变量的同时,亦输入各约束在此列中相对应的非零元;一旦输入所有变量及非零元后,再修改线性约束的下界(left-hand-side;LHS)和上界(right-hand-side;RHS)。

此外,我们还调用 Mdo_getStatus() 来检查求解器的优化状态,并通过 Mdo_getRealAttr()Mdo_getRealAttrArray() 来获取目标值和最优解( Mdo_getRealAttr()Mdo_getRealAttrArray() 的详细使用方式,请参考 C 接口函数 )。

文件链接 MdoLoEx2.c 提供了完整源代码:

  1/**
  2 *  Description
  3 *  -----------
  4 *
  5 *  Linear optimization (column-wise input).
  6 *
  7 *  Formulation
  8 *  -----------
  9 *
 10 *  Minimize
 11 *    obj: 1 x0 + 1 x1 + 1 x2 + 1 x3
 12 *  Subject To
 13 *   c0 : 1 x0 + 1 x1 + 2 x2 + 3 x3 >= 1
 14 *   c1 : 1 x0 - 1 x2 + 6 x3 = 1
 15 *  Bounds
 16 *    0 <= x0 <= 10
 17 *    0 <= x1
 18 *    0 <= x2
 19 *    0 <= x3
 20 *  End
 21 */
 22#include <stdio.h>
 23#include "Mindopt.h"
 24
 25/* Macro to check the return code */
 26#define MDO_CHECK_CALL(MDO_CALL)                                    \
 27    code = MDO_CALL;                                                \
 28    if (code != MDO_OKAY)                                           \
 29    {                                                               \
 30        Mdo_explainResult(model, code, str);                        \
 31        Mdo_freeMdl(&model);                                        \
 32        fprintf(stderr, "===================================\n");   \
 33        fprintf(stderr, "Error   : code <%d>\n", code);             \
 34        fprintf(stderr, "Reason  : %s\n", str);                     \
 35        fprintf(stderr, "===================================\n");   \
 36        return (int)code;                                           \
 37    }
 38
 39int main(void)
 40{
 41    /* Variables. */
 42    char str[1024] = { "\0" };
 43    MdoMdl * model = NULL;
 44    MdoResult code = MDO_OKAY;
 45    MdoStatus status = MDO_UNKNOWN;
 46    double val, soln[4];
 47    int j;
 48    const int     col1_idx[] = { 0,    1   };
 49    const double  col1_val[] = { 1.0,  1.0 };
 50    const int     col2_idx[] = { 0         };
 51    const double  col2_val[] = { 1.0       };
 52    const int     col3_idx[] = { 0,    1   };
 53    const double  col3_val[] = { 2.0, -1.0 };
 54    const int     col4_idx[] = { 0,    1   };
 55    const double  col4_val[] = { 3.0,  6.0 };
 56
 57    /*------------------------------------------------------------------*/
 58    /* Step 1. Create a model and change the parameters.                */
 59    /*------------------------------------------------------------------*/
 60    /* Create an empty model. */
 61    MDO_CHECK_CALL(Mdo_createMdl(&model));
 62    
 63    /*------------------------------------------------------------------*/
 64    /* Step 2. Input model.                                             */
 65    /*------------------------------------------------------------------*/
 66    /* Change to minimization problem. */
 67    MDO_CHECK_CALL(Mdo_setIntAttr(model, MDO_INT_ATTR_MIN_SENSE, MDO_YES));
 68
 69    /* Add variables. 
 70     * Note that the nonzero elements are inputted in a column-wise order here.
 71     */
 72    MDO_CHECK_CALL(Mdo_addCol(model, 0.0,         10.0, 1.0, 2, col1_idx, col1_val, "x0", MDO_NO));
 73    MDO_CHECK_CALL(Mdo_addCol(model, 0.0, MDO_INFINITY, 1.0, 1, col2_idx, col2_val, "x1", MDO_NO));
 74    MDO_CHECK_CALL(Mdo_addCol(model, 0.0, MDO_INFINITY, 1.0, 2, col3_idx, col3_val, "x2", MDO_NO));
 75    MDO_CHECK_CALL(Mdo_addCol(model, 0.0, MDO_INFINITY, 1.0, 2, col4_idx, col4_val, "x3", MDO_NO));
 76
 77    /* Change the LHS value and RHS value of the constraints. */
 78    MDO_CHECK_CALL(Mdo_setRealAttrIndex(model, MDO_REAL_ATTR_LHS, 0,          1.0));
 79    MDO_CHECK_CALL(Mdo_setRealAttrIndex(model, MDO_REAL_ATTR_RHS, 0, MDO_INFINITY));
 80    MDO_CHECK_CALL(Mdo_setRealAttrIndex(model, MDO_REAL_ATTR_LHS, 1,          1.0));
 81    MDO_CHECK_CALL(Mdo_setRealAttrIndex(model, MDO_REAL_ATTR_RHS, 1,          1.0));
 82    
 83    /*------------------------------------------------------------------*/
 84    /* Step 3. Solve the problem and populate the result.               */
 85    /*------------------------------------------------------------------*/
 86    /* Solve the problem. */
 87    MDO_CHECK_CALL(Mdo_solveProb(model));
 88    Mdo_displayResults(model);
 89
 90    switch (Mdo_getStatus(model))
 91    {
 92    case MDO_UNKNOWN:
 93        printf("Optimizer terminated with an UNKNOWN status.\n");
 94        break;
 95    case MDO_OPTIMAL:
 96        MDO_CHECK_CALL(Mdo_getRealAttr(model, MDO_REAL_ATTR_PRIMAL_OBJ_VAL, &val));
 97        printf("Optimizer terminated with an OPTIMAL status.\n");
 98        printf(" - Primal objective : %e.\n", val);
 99        MDO_CHECK_CALL(Mdo_getRealAttrArray(model, MDO_REAL_ATTR_PRIMAL_SOLN, 0, 4, soln));
100        for (j = 0; j < 4; ++j)
101        {
102            printf("x[%d] = %e\n", j, soln[j]);
103        }
104        break;
105    case MDO_INFEASIBLE:
106        printf("Optimizer terminated with an INFEASIBLE status.\n");
107        break;
108    case MDO_UNBOUNDED:
109        printf("Optimizer terminated with an UNBOUNDED status.\n");
110        break;
111    case MDO_INF_OR_UBD:
112        printf("Optimizer terminated with an INFEASIBLE or UNBOUNDED status.\n");
113        break;
114    }
115
116    /*------------------------------------------------------------------*/
117    /* Step 4. Free the model.                                          */
118    /*------------------------------------------------------------------*/
119    /* Free the model. */
120    Mdo_freeMdl(&model);
121       
122    return (int)code;
123}

5.1.2.3. 进阶使用示例:MdoLoEx3

在下面的代码中,我们展示了其他进阶 API 的使用方式,如:输入模型、修改模型、获取基解、热启动的例子;关于 API 的完整使用方法,请参考 完整的API说明

文件链接 MdoLoEx3.c 提供了完整源代码:

  1/**
  2 *  Description
  3 *  -----------
  4 *
  5 *  Linear optimization.
  6 *   - Row input.
  7 *   - Column input.
  8 *   - Query.
  9 */
 10#include <stdio.h>
 11#include <stdlib.h>
 12#include "Mindopt.h"
 13
 14#define WRITE_LP    
 15#define MY_FOLDER "./"
 16
 17/* Macro to check the return code */
 18#define MDO_CHECK_CALL(MDO_CALL)                                    \
 19    code = MDO_CALL;                                                \
 20    if (code != MDO_OKAY)                                           \
 21    {                                                               \
 22        Mdo_explainResult(model, code, str);                        \
 23        Mdo_freeMdl(&model);                                        \
 24        fprintf(stderr, "===================================\n");   \
 25        fprintf(stderr, "Error   : code <%d>\n", code);             \
 26        fprintf(stderr, "Reason  : %s\n", str);                     \
 27        fprintf(stderr, "===================================\n");   \
 28        return (int)code;                                           \
 29    }
 30
 31int main(void)
 32{
 33    /* Variables. */
 34    char str[1024] = { "\0" };
 35    MdoMdl * model = NULL;
 36    MdoResult code = MDO_OKAY;
 37    MdoStatus status = MDO_UNKNOWN;
 38    int i, j, c, r, e;
 39
 40    const int csr_bgn[] = {0, 4, 7};
 41    const int csr_indices[] = 
 42    {
 43        0,   1,   2,   3,
 44        0,        2,   3  
 45    };
 46    const double csr_values[] = 
 47    {
 48        1.0, 1.0,  2.0, 3.0,
 49        1.0,      -1.0, 6.0
 50    };
 51
 52    const int csc_bgn[] = {0, 2, 3, 5, 7};
 53    const int csc_indices[] = 
 54    {
 55        0,  1,
 56        0,
 57        0,  1,
 58        0,  1
 59    };
 60    const double csc_values[] = 
 61    {
 62        1.0,   1.0,
 63        1.0, 
 64        2.0,  -1.0, 
 65        3.0,   6.0
 66    };
 67
 68    const double lhss[] = { 1, 1            };
 69    const double rhss[] = { MDO_INFINITY, 1 };
 70    const char* row_names[] = { "c0", "c1" };
 71
 72    const double lbs[] =  {  0.0,          0.0,          0.0,          0.0 };
 73    const double ubs[] =  { 10.0, MDO_INFINITY, MDO_INFINITY, MDO_INFINITY };
 74    const double objs[] = {  1.0,          1.0,          1.0,          1.0 };
 75    const char* col_names[] = { "x0", "x1", "x2", "x3" };
 76      
 77    /*------------------------------------------------------------------*/
 78    /* Step 1. Create a model and change the parameters.                */
 79    /*------------------------------------------------------------------*/
 80    printf(" Create a model and change the parameters.\n\n");
 81    /* Create an empty model. */
 82    MDO_CHECK_CALL(Mdo_createMdl(&model));
 83
 84    /*------------------------------------------------------------------*/
 85    /* Step 2. Input model.                                             */
 86    /*------------------------------------------------------------------*/
 87    printf("\nStep 2. Input model.\n\n");    
 88    /* The following three input methods will all result in the same model. */
 89#if 0
 90    /* Method 1. */
 91    /* Change to minimization problem. */
 92    MDO_CHECK_CALL(Mdo_setIntAttr(model, MDO_INT_ATTR_MIN_SENSE, MDO_YES));
 93    
 94    /* Add variables. */
 95    for (i = 0; i < 4; ++i)
 96    {
 97        MDO_CHECK_CALL(Mdo_addCol(model, lbs[i], ubs[i], objs[i], 0, NULL, NULL, col_names[i], MDO_NO));    
 98    }    
 99    /* Add two constraints. 
100     * The coefficients of the constraint matrix are inputted in a row-wise order.
101     */
102    MDO_CHECK_CALL(Mdo_addRows(model, 2, lhss, rhss, csr_bgn, csr_indices, csr_values, row_names));
103#endif
104#if 0
105    /* Method 2. */
106    /* Change to minimization problem. */
107    MDO_CHECK_CALL(Mdo_setIntAttr(model, MDO_INT_ATTR_MIN_SENSE, MDO_YES));
108    
109    /* Add variables and constraints. 
110     * The coefficients of the constraint matrix are inputted in a column-wise order.
111     */ 
112    MDO_CHECK_CALL(Mdo_addCols(model, 4, lbs, ubs, objs, csc_bgn, csc_indices, csc_values, col_names, NULL));    
113    
114    /* Change LHS values and RHS values. */
115    MDO_CHECK_CALL(Mdo_setRealAttrArray(model, MDO_REAL_ATTR_LHS, 0, 2, lhss));
116    MDO_CHECK_CALL(Mdo_setRealAttrArray(model, MDO_REAL_ATTR_RHS, 0, 2, rhss));
117#endif    
118#if 1
119    /* Method 3. */
120    /* Add four variables and two constraints in one shot.
121     * The coefficients of the constraint matrix are inputted in a column-wise order.
122     */
123    MDO_CHECK_CALL(Mdo_loadModel(model, 4, 2, csc_bgn, csc_indices, csc_values, 
124        lbs, ubs, objs, NULL, 0.0, MDO_YES, lhss, rhss, col_names, row_names));
125#endif
126    MdoI32 idx[2] = { 0, 1 };
127    MdoReal tmp[2];
128    Mdo_getLhss(model, 2, idx, tmp);
129    for (int i = 0; i < 2; ++i)
130    {
131        printf("%d has LHS = %e\n", i, tmp[i]);
132    }
133    Mdo_getRhss(model, 2, idx, tmp);
134    for (int i = 0; i < 2; ++i)
135    {
136        printf("%d has RHS = %e\n", i, tmp[i]);
137    }
138
139    /*------------------------------------------------------------------*/
140    /* Step 3. Solve the problem and populate the result.               */
141    /*------------------------------------------------------------------*/
142    printf("\nStep 3. Solve the problem and populate the result.\n\n");
143    Mdo_setIntParam(model, MDO_INT_PARAM_METHOD, 2);
144    Mdo_setIntParam(model, MDO_INT_PARAM_NUM_THREADS, 1);
145
146    /* Solve the problem. */
147    MDO_CHECK_CALL(Mdo_solveProb(model));
148    Mdo_displayResults(model);
149#ifdef WRITE_LP    
150    MDO_CHECK_CALL(Mdo_writeProb(model, MY_FOLDER"Step3.lp"));   
151#endif
152
153
154    Mdo_setIntParam(model, MDO_INT_PARAM_PRESOLVE, 0);
155    double newobj[4];
156    int indices[] = { 0, 1, 2, 3 };
157    MDO_CHECK_CALL(Mdo_getObjs(model, 4, indices, newobj));
158    for (int j = 0; j < 4; ++j)
159    {
160        newobj[j] = -newobj[j];
161    }
162#if 0
163    Mdo_setMaxObjSense(model);
164    MDO_CHECK_CALL(Mdo_setObjs(model, 4, indices, newobj));
165#else
166    MDO_CHECK_CALL(Mdo_loadModel(model, 4, 2, csc_bgn, csc_indices, csc_values,
167        lbs, ubs, newobj, NULL, 0.0, MDO_YES, lhss, rhss, col_names, row_names));
168#endif
169
170    MDO_CHECK_CALL(Mdo_solveProb(model));
171    Mdo_displayResults(model);
172#ifdef WRITE_LP    
173    MDO_CHECK_CALL(Mdo_writeProb(model, MY_FOLDER"Step3-1.lp"));
174#endif
175
176
177    /*------------------------------------------------------------------*/
178    /* Step 4. Add another two variables and then resolve the problem.  */
179    /*------------------------------------------------------------------*/
180    printf("\nStep 4. Add another two variables and then resolve the problem.\n\n");
181    /* Add another two variables. */    
182    double lbs2[] =  { 0,            -2           };
183    double ubs2[] =  { MDO_INFINITY, MDO_INFINITY };
184    double objs2[] = { 1,            -1           };
185
186    int col_bgn[] = {0, 2, 4 };
187    int col_indices[] =   
188    {
189        0, 1, 
190        0, 1
191    };
192    double col_values[] = 
193    {
194        1, 2, 
195        3, 4
196    };
197    const char * col_names2[] = { "y1", "y2" };
198    
199    MDO_CHECK_CALL(Mdo_addCols(model, 2, lbs2, ubs2, objs2, col_bgn, col_indices, col_values, col_names2, NULL));
200        
201    /* Solve the problem. */
202    MDO_CHECK_CALL(Mdo_solveProb(model));
203    Mdo_displayResults(model);
204#ifdef WRITE_LP
205    MDO_CHECK_CALL(Mdo_writeProb(model, MY_FOLDER"Step4.lp"));   
206#endif
207      
208    /*------------------------------------------------------------------*/
209    /* Step 5. Add another two constraints and then resolve the problem.*/
210    /*------------------------------------------------------------------*/
211    printf("\nStep 5. Add another two constraints and then resolve the problem.\n\n");
212    int bgn2[] = {0, 3, 6};
213    int indices2[] = 
214    {
215        0,   1,        3,
216        0,        2,   3  
217    };
218    double values2[] = 
219    {
220        1.0, 1.0,      -2.0,
221        1.0,      -2.0, 6.0
222    };    
223    
224    const double lhss2[] = { 0, 1            };
225    const double rhss2[] = { 2, MDO_INFINITY };
226
227    const char* row_names2[] = { "C2", "C3" };
228    
229    /* Add two constraints. */
230    MDO_CHECK_CALL(Mdo_addRows(model, 2, lhss2, rhss2, bgn2, indices2, values2, row_names2));
231 
232    /* Solve the problem. */
233    MDO_CHECK_CALL(Mdo_solveProb(model));
234    Mdo_displayResults(model);
235#ifdef WRITE_LP    
236    MDO_CHECK_CALL(Mdo_writeProb(model, MY_FOLDER"Step5.lp"));   
237#endif
238
239    /*------------------------------------------------------------------*/
240    /* Step 6. Obtain optimal basis.                                    */
241    /*------------------------------------------------------------------*/       
242    printf("\nStep 6. Obtain optimal basis.\n\n");
243    int * row_basis = (int *)calloc(4, sizeof(int));
244    int * col_basis = (int *)calloc(6, sizeof(int));    
245    MDO_CHECK_CALL(Mdo_getIntAttrArray(model, MDO_INT_ATTR_ROW_BASIS, 0, 4, row_basis));
246    MDO_CHECK_CALL(Mdo_getIntAttrArray(model, MDO_INT_ATTR_COL_BASIS, 0, 6, col_basis));
247    /*
248     * isFree = 0,
249     * basic = 1,
250     * atUpperBound = 2,
251     * atLowerBound = 3,
252     * superBasic = 4,
253     * isFixed = 5,
254     */
255    for (i = 0; i < 4; ++i)
256    {
257        printf("Row [%d] status: %d\n", i, row_basis[i]);
258    }
259    for (j = 0; j < 6; ++j)
260    {
261        printf("Col [%d] status: %d\n", j, col_basis[j]);
262    }
263#ifdef WRITE_LP   
264    MDO_CHECK_CALL(Mdo_writeSoln(model, MY_FOLDER "Step6.bas"));   
265    MDO_CHECK_CALL(Mdo_writeProb(model, MY_FOLDER "Step6.lp"));   
266#endif
267
268    /*------------------------------------------------------------------*/
269    /* Step 7. Warm-start Simplex.                                      */
270    /*------------------------------------------------------------------*/       
271    printf("\nStep 7. Warm-start Simplex.\n\n");
272
273    /* Change the objective coefficients. */
274    int obj_indices[] =   { 1, 2 };
275    double obj_values[] = { 3, -3 };
276    MDO_CHECK_CALL(Mdo_setObjs(model, 2, obj_indices, obj_values));
277
278    /* Load the basis. */
279    MDO_CHECK_CALL(Mdo_setIntAttrArray(model, MDO_INT_ATTR_ROW_BASIS, 0, 4, row_basis));
280    MDO_CHECK_CALL(Mdo_setIntAttrArray(model, MDO_INT_ATTR_COL_BASIS, 0, 6, col_basis));
281
282    /* Solve the problem. */
283    printf("Resolve with warm-start basis.\n");
284    Mdo_setIntParam(model, MDO_INT_PARAM_PRESOLVE, 0);
285    Mdo_setIntParam(model, MDO_INT_PARAM_METHOD, 0);
286    MDO_CHECK_CALL(Mdo_solveProb(model));
287    Mdo_displayResults(model);
288
289    free(row_basis);
290    free(col_basis);
291
292    /*------------------------------------------------------------------*/
293    /* Step 8. Model query.                                             */
294    /*------------------------------------------------------------------*/    
295    printf("\nStep 8. Model query.\n\n");
296    /* Query 1: Retrieve first two rows. */
297    printf("Query 1: Retrieve first two rows.\n");
298    int row_indices[2] = {0, 1};
299    int real_size;
300    /* Step 8.1. Get the total number of NNZs first. */
301    MDO_CHECK_CALL(Mdo_getRows(model, 2, row_indices, NULL, NULL, NULL, 0, &real_size)); 
302    int bgn3[2 + 1]; 
303    int * indices3 = (int *)calloc(real_size, sizeof(int));
304    double * values3 = (double *)calloc(real_size, sizeof(double));  
305    printf("Number of nonzeros = %d.\n", real_size);
306    
307    /* Step 8.2. Retrieve the rows. */
308    MDO_CHECK_CALL(Mdo_getRows(model, 2, row_indices, bgn3, indices3, values3, real_size, &real_size)); 
309    for (r = 0; r < 2; ++r)
310    {
311        for (e = bgn3[r]; e < bgn3[r + 1]; ++e)
312        {
313            printf("Element[%d, %d] = %e\n", row_indices[r], indices3[e], values3[e]);
314        }
315    }
316    free(indices3);
317    free(values3); 
318    
319    /* Query 2: Retrieve column 3 and column 5. */
320    printf("Query 2: Retrieve column 3 and column 5.\n");
321    int col_indices2[2] = {3, 5};
322    /* Step 8.3. Get the total number of NNZs first. */
323    MDO_CHECK_CALL(Mdo_getCols(model, 2, col_indices2, NULL, NULL, NULL, 0, &real_size)); 
324    int bgn4[2 + 1]; 
325    int * indices4 = (int *)calloc(real_size, sizeof(int));
326    double * values4 = (double *)calloc(real_size, sizeof(double));  
327    printf("Number of nonzeros = %d.\n", real_size);    
328    
329    /* Step 8.4. Retrieve the columns. */
330    MDO_CHECK_CALL(Mdo_getCols(model, 2, col_indices2, bgn4, indices4, values4, real_size, &real_size)); 
331    for (c = 0; c < 2; ++c)
332    {
333        for (e = bgn4[c]; e < bgn4[c + 1]; ++e)
334        {
335            printf("Element[%d, %d] = %e\n", indices4[e], col_indices2[c], values4[e]);
336        }
337    }
338    free(indices4);
339    free(values4); 
340
341    /*------------------------------------------------------------------*/
342    /* Step 9. Change row/col name and then delete rows and columns.    */
343    /*------------------------------------------------------------------*/
344    char buf[256];
345    int itmp;
346    MDO_CHECK_CALL(Mdo_getRowName(model, 1, buf, 256, &itmp));
347    printf("Row 1 has name = %s\n", buf);
348    snprintf(buf, 256, "row_%d", 999);
349    itmp = 1;
350    char * pbuf[] = { buf };
351    MDO_CHECK_CALL(Mdo_setRowNames(model, 1, &itmp, pbuf));
352    MDO_CHECK_CALL(Mdo_getRowName(model, 1, buf, 256, &itmp));
353    printf("Updated Row 1 has name = %s (idx: %d)\n", buf, Mdo_getRowIndex(model, buf));
354    printf("Unknown index = %d\n", Mdo_getRowIndex(model, ""));
355
356    MDO_CHECK_CALL(Mdo_getColName(model, 1, buf, 256, &itmp));
357    printf("Col 1 has name = %s\n", buf);
358    snprintf(buf, 256, "col_%d", 999);
359    itmp = 1;
360    MDO_CHECK_CALL(Mdo_setColNames(model, 1, &itmp, pbuf));
361    MDO_CHECK_CALL(Mdo_getColName(model, 1, buf, 256, &itmp));
362    printf("Updated Col has name = %s (idx: %d)\n", buf, Mdo_getColIndex(model, buf));
363    printf("Unknown index = %d\n", Mdo_getColIndex(model, ""));
364
365
366#ifdef WRITE_LP    
367    MDO_CHECK_CALL(Mdo_writeProb(model, MY_FOLDER"Step9.lp"));
368#endif
369
370    int delrow[2] = { 3, 1 };
371    MDO_CHECK_CALL(Mdo_deleteRows(model, 2, delrow));
372#ifdef WRITE_LP    
373    MDO_CHECK_CALL(Mdo_writeProb(model, MY_FOLDER"Step9_delrow1.lp"));
374#endif
375    int delcol[2] = { 1, 3 };
376    MDO_CHECK_CALL(Mdo_deleteCols(model, 2, delcol));
377#ifdef WRITE_LP    
378    MDO_CHECK_CALL(Mdo_writeProb(model, MY_FOLDER"Step9_delcol1.lp"));
379#endif
380
381    /*------------------------------------------------------------------*/
382    /* Step 10. Free the model.                                         */
383    /*------------------------------------------------------------------*/
384    printf("\nStep 10. Free the model.n\n");
385    /* Free the model. */
386    Mdo_freeMdl(&model);
387
388    return (int)code;
389}