5.2.2. C 语言的MILP建模和优化

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

5.2.2.1. 按行输入:MdoMiloEx1

首先,引入头文件:

25#include "Mindopt.h"

并创建优化模型:

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

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

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

Note

在函数 Mdo_addCol() 中,最后一个参数位是 is_integer ,设置为 MDO_YES 代表这个变量是整形变量。

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

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

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

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

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

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

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

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

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