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_idx
和 row2_idx
分别表示第一和第二个约束中非零元素的位置(索引),而 row1_val
和 row2_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}