5.6.2. MIQCP Modeling and Optimization in CΒΆ
In this chapter, we will use MindOpt C API to model and solve the problem in Example of Mixed Integer Quadratically Constrained Programming.
Include the header file:
27#include <stdio.h>
Create an optimization model model:
78 /* Step 1. Create environment and model. */
79 /*------------------------------------------------------------------*/
80 CHECK_RESULT(MDOemptyenv(&env));
Next, we set the optimization sense to minimization via MDOsetIntAttr() and four variables are added by calling MDOaddvar(). Their lower bounds, upper bounds, names, types and linear objective coefficients are defined as follows (for more details on how to use MDOsetIntAttr() and MDOaddvar(), please refer to Attributes):
86 /* Step 2. Input model. */
87 /*------------------------------------------------------------------*/
88 /* Change to minimization problem. */
89 CHECK_RESULT(MDOsetintattr(model, MODEL_SENSE, MDO_MINIMIZE));
90
91 /* Add variables. */
92 CHECK_RESULT(MDOaddvar(model, 0, NULL, NULL, 1.0, 0, 10.0, MDO_INTEGER, "x0"));
93 CHECK_RESULT(MDOaddvar(model, 0, NULL, NULL, 1.0, 0, MDO_INFINITY, MDO_CONTINUOUS, "x1"));
Note
The non-zero elements of the matrix \(A\) will be inputted later. After adding the four aforementioned variables, certain parameters of the constraint matrix, specifically size, indices, and value, are set to 0, NULL, and NULL, respectively. This means that, as of now, model has no constraints.
Next, we will introduce the quadratic terms in the objective. Three arrays are utilized for this purpose. Specifically, qo_col1, qo_col2, and qo_values record the row indices, column indices, and values of all the non-zero quadratic terms.
49 /* Prepare model data. */
50 /* Quadratic part in objective: 1/2 [ x0^2 + x1^2 + x2^2 + x3^2 + x0 x1] */
51 int qo_nnz = 5;
52 int qo_col1[] = { 0, 1, 2, 3, 0 };
We call MDOaddqpterms() to set the quadratic terms of the objective.
95 CHECK_RESULT(MDOaddvar(model, 0, NULL, NULL, 1.0, 0, MDO_INFINITY, MDO_CONTINUOUS, "x3"));
Now we start to add quadratic constraints to the model. The linear part is constructed in the same way as in the objective.
55 double qo_values[] = { 0.5, 0.5, 0.5, 0.5, 0.5 };
56
57 /* Linear part in the first constraint: 1 x0 + 1 x1 + 2 x2 + 3 x3 */
58 int row1_nnz = 4;
65 double qc1_values[] = { -0.5, -0.5, -0.5, -0.5, -0.5 };
66
67 /* Linear part in the second constraint: 1 x0 - 1 x2 + 6 x3 */
68 int row2_nnz = 3;
The quadratic part is constructed in the same way as it is in the objective as well.
59 int row1_idx[] = { 0, 1, 2, 3 };
60 double row1_val[] = { 1.0, 1.0, 2.0, 3.0 };
61 /* Quadratic part in the first constraint: - 1/2 [ x0^2 + x1^2 + x2^2 + x3^2 + x0 x1] */
62 int qc1_nnz = 5;
63 int qc1_col1[] = { 0, 1, 2, 3, 0 };
69 int row2_idx[] = { 0, 2, 3 };
70 double row2_val[] = { 1.0, -1.0, 6.0 };
71 /* Quadratic part in the second constraint: 1/2 [x1^2] */
72 int qc2_nnz = 1;
73 int qc2_col1[] = { 1 };
We call MDOaddqconstr() to input the linear constraints into model:
98 CHECK_RESULT(MDOaddqpterms(model, qo_nnz, qo_col1, qo_col2, qo_values));
99
100 /* Add quadratic constraints. */
Once the model is constructed, we call MDOoptimize() to solve the problem:
105 /* Step 3. Solve the problem and populate optimization result. */
106 /*------------------------------------------------------------------*/
We can retrieive the optimal objective value and solutions via getting attributes:
108 CHECK_RESULT(MDOoptimize(model));
109
110 CHECK_RESULT(MDOgetintattr(model, STATUS, &status));
111 if (status == MDO_OPTIMAL)
112 {
113 CHECK_RESULT(MDOgetdblattr(model, OBJ_VAL, &obj));
114 printf("The optimal objective value is: %f\n", obj);
115 for (int i = 0; i < 4; ++i)
116 {
117 CHECK_RESULT(MDOgetdblattrelement(model, X, i, &x));
118 printf("x[%d] = %f\n", i, x);
119 }
120 }
121 else
122 {
Finally, we call MDOfreemodel() and MDOfreeenv() to free the model:
30/* Macro to check the return code */
31#define RELEASE_MEMORY \
127 /* Step 4. Free the model. */
The complete example code is provided in MdoMIQCPEx1.c:
1/**
2 * Description
3 * -----------
4 *
5 * Mixed Integer Quadratically constrained quadratic optimization (row-wise input).
6 *
7 * Formulation
8 * -----------
9 *
10 * Minimize
11 * obj: 1 x0 + 1 x1 + 1 x2 + 1 x3
12 * + 1/2 [ x0^2 + x1^2 + x2^2 + x3^2 + x0 x1]
13 *
14 * Subject To
15 * c0 : 1 x0 + 1 x1 + 2 x2 + 3 x3 - 1/2 [ x0^2 + x1^2 + x2^2 + x3^2 + x0 x1] >= 1
16 * c1 : 1 x0 - 1 x2 + 6 x3 + 1/2 [x1^2] <= 1
17 * Bounds
18 * 0 <= x0 <= 10
19 * 0 <= x1
20 * 0 <= x2
21 * 0 <= x3
22 * Integer
23 * x0
24 * End
25 */
26
27#include <stdio.h>
28#include <stdlib.h>
29#include "Mindopt.h"
30
31/* Macro to check the return code */
32#define RELEASE_MEMORY \
33 MDOfreemodel(model); \
34 MDOfreeenv(env);
35#define CHECK_RESULT(code) { int res = code; if (res != 0) { fprintf(stderr, "Bad code: %d\n", res); RELEASE_MEMORY; return (res); } }
36#define MODEL_NAME "QCP_01"
37#define MODEL_SENSE "ModelSense"
38#define STATUS "Status"
39#define OBJ_VAL "ObjVal"
40#define X "X"
41
42int main(void)
43{
44 /* Variables. */
45 MDOenv *env;
46 MDOmodel *model;
47 double obj, x;
48 int status, i;
49
50 /* Prepare model data. */
51 /* Quadratic part in objective: 1/2 [ x0^2 + x1^2 + x2^2 + x3^2 + x0 x1] */
52 int qo_nnz = 5;
53 int qo_col1[] = { 0, 1, 2, 3, 0 };
54 int qo_col2[] = { 0, 1, 2, 3, 1 };
55 double qo_values[] = { 0.5, 0.5, 0.5, 0.5, 0.5 };
56
57 /* Linear part in the first constraint: 1 x0 + 1 x1 + 2 x2 + 3 x3 */
58 int row1_nnz = 4;
59 int row1_idx[] = { 0, 1, 2, 3 };
60 double row1_val[] = { 1.0, 1.0, 2.0, 3.0 };
61 /* Quadratic part in the first constraint: - 1/2 [ x0^2 + x1^2 + x2^2 + x3^2 + x0 x1] */
62 int qc1_nnz = 5;
63 int qc1_col1[] = { 0, 1, 2, 3, 0 };
64 int qc1_col2[] = { 0, 1, 2, 3, 1 };
65 double qc1_values[] = { -0.5, -0.5, -0.5, -0.5, -0.5 };
66
67 /* Linear part in the second constraint: 1 x0 - 1 x2 + 6 x3 */
68 int row2_nnz = 3;
69 int row2_idx[] = { 0, 2, 3 };
70 double row2_val[] = { 1.0, -1.0, 6.0 };
71 /* Quadratic part in the second constraint: 1/2 [x1^2] */
72 int qc2_nnz = 1;
73 int qc2_col1[] = { 1 };
74 int qc2_col2[] = { 1 };
75 double qc2_values[] = { 0.5 };
76
77 /*------------------------------------------------------------------*/
78 /* Step 1. Create environment and model. */
79 /*------------------------------------------------------------------*/
80 CHECK_RESULT(MDOemptyenv(&env));
81 CHECK_RESULT(MDOstartenv(env));
82 CHECK_RESULT(MDOnewmodel(env, &model, MODEL_NAME, 0, NULL, NULL, NULL, NULL, NULL));
83
84
85 /*------------------------------------------------------------------*/
86 /* Step 2. Input model. */
87 /*------------------------------------------------------------------*/
88 /* Change to minimization problem. */
89 CHECK_RESULT(MDOsetintattr(model, MODEL_SENSE, MDO_MINIMIZE));
90
91 /* Add variables. */
92 CHECK_RESULT(MDOaddvar(model, 0, NULL, NULL, 1.0, 0, 10.0, MDO_INTEGER, "x0"));
93 CHECK_RESULT(MDOaddvar(model, 0, NULL, NULL, 1.0, 0, MDO_INFINITY, MDO_CONTINUOUS, "x1"));
94 CHECK_RESULT(MDOaddvar(model, 0, NULL, NULL, 1.0, 0, MDO_INFINITY, MDO_CONTINUOUS, "x2"));
95 CHECK_RESULT(MDOaddvar(model, 0, NULL, NULL, 1.0, 0, MDO_INFINITY, MDO_CONTINUOUS, "x3"));
96
97 /* Add quadratic objective term. */
98 CHECK_RESULT(MDOaddqpterms(model, qo_nnz, qo_col1, qo_col2, qo_values));
99
100 /* Add quadratic constraints. */
101 CHECK_RESULT(MDOaddqconstr(model, row1_nnz, row1_idx, row1_val, qc1_nnz, qc1_col1, qc1_col2, qc1_values, MDO_GREATER_EQUAL, 1.0, "c0"));
102 CHECK_RESULT(MDOaddqconstr(model, row2_nnz, row2_idx, row2_val, qc2_nnz, qc2_col1, qc2_col2, qc2_values, MDO_LESS_EQUAL, 1.0, "c1"));
103
104 /*------------------------------------------------------------------*/
105 /* Step 3. Solve the problem and populate optimization result. */
106 /*------------------------------------------------------------------*/
107 /* Solve the problem. */
108 CHECK_RESULT(MDOoptimize(model));
109
110 CHECK_RESULT(MDOgetintattr(model, STATUS, &status));
111 if (status == MDO_OPTIMAL)
112 {
113 CHECK_RESULT(MDOgetdblattr(model, OBJ_VAL, &obj));
114 printf("The optimal objective value is: %f\n", obj);
115 for (int i = 0; i < 4; ++i)
116 {
117 CHECK_RESULT(MDOgetdblattrelement(model, X, i, &x));
118 printf("x[%d] = %f\n", i, x);
119 }
120 }
121 else
122 {
123 printf("No feasible solution.\n");
124 }
125
126 /*------------------------------------------------------------------*/
127 /* Step 4. Free the model. */
128 /*------------------------------------------------------------------*/
129 RELEASE_MEMORY;
130
131 return 0;
132}