5.6.8. MISOCP Modeling and Optimization in C++¶
In this chapter, we will use MindOpt C++ API to model and solve the problem in MIQCP Example II.
Include the header file:
26#include <iostream>
Create an optimization model model:
32int main(void)
33{
34 /*------------------------------------------------------------------*/
35 /* Step 1. Create environment and model. */
36 /*------------------------------------------------------------------*/
37 MDOEnv env = MDOEnv();
Note
To mark a variable as integer, set the value of vtype as MDO_INTEGER in MDOModel::addVar().
Next, we set the optimization sense to minimization via MDOModel::set(). Then, we call MDOModel::addVar() to add five variables, specifying their lower bounds, upper bounds, objective coefficients, types, and names.
43 /* Step 2. Input model. */
44 /*------------------------------------------------------------------*/
45 /* Change to minimization problem. */
46 model.set(MDO_IntAttr_ModelSense, MDO_MINIMIZE);
47
48 /* Add variables. */
49 std::vector<MDOVar> x;
50 x.push_back(model.addVar(0.0, 10.0, 1.0, MDO_INTEGER, "x0"));
51 x.push_back(model.addVar(0.0, MDO_INFINITY, 2.0, MDO_INTEGER, "x1"));
52 x.push_back(model.addVar(0.0, MDO_INFINITY, 1.0, MDO_INTEGER, "x2"));
53 x.push_back(model.addVar(0.0, MDO_INFINITY, 1.0, MDO_CONTINUOUS, "x3"));
Note
The linear objective coefficients (1, 2, 1, 1, 0.5) are passed directly during variable creation via the third argument of addVar(). Therefore, there is no separate call to setObjective(), and the objective is purely linear.
We now add the linear constraints.
Constraint c0: \(x_0 + x_1 + 2x_2 + 3x_3 \geq 1\)
Constraint c1: \(x_0 - x_2 + 6x_3 = 1\)
These are added using overloaded arithmetic operators to build linear expressions:
61 model.addConstr(1.0 * x[0] - 1.0 * x[2] + 6.0 * x[3], MDO_EQUAL, 1.0, "c1");
62
63 /* second order cone constraint */
64 int qc2_nnz = 3;
65 MDOVar qc2_col1[] = { x[1], x[2], x[4]};
Finally, we add the quadratic (second-order cone) constraint:
c2: \(x_1^2 + x_2^2 - x_4^2 \leq 0\)
This is modeled as a quadratic constraint using MDOQuadExpr. We define the quadratic terms by specifying variable pairs and coefficients:
67 double qc2_values[] = { 1.0, 1.0, -1.0};
68
69 /* Add the second order cone constraint. c2*/
70 MDOQuadExpr c2 = MDOQuadExpr(0.0);
71 c2.addTerms(qc2_values, qc2_col1, qc2_col2, qc2_nnz);
Then, the quadratic expression is added to the model as a constraint:
74 /*------------------------------------------------------------------*/
75 /* Step 3. Solve the problem. */
76 /*------------------------------------------------------------------*/
77 /* Solve the problem. */
Once the model is fully constructed, we solve it by calling:
81 /* Step 4. Retrive model status and objective. */
82 /* For MIP(MILP,MIQP, MIQCP) problems, if the solving process */
After solving, we check the solution status and retrieve the optimal objective value and variable values:
92 cout << "Decision variables:" << endl;
93 int i = 0;
94 for (auto v : x)
95 {
96 cout << "x[" << i++ << "] = " << v.get(MDO_DoubleAttr_X) << endl;
97 }
98 }
99 else
100 {
101 cout<< "No feasible solution." << endl;
102 }
103
104 }
105 catch (MDOException& e)
106 {
The complete example code is shown in MdoMISOCPEx1.cpp :
1/**
2 * Description
3 * -----------
4 *
5 * Formulation
6 * -----------
7 *
8 Minimize
9 * obj: 1 x0 + 2 x1 + 1 x2 + 1 x3 + 0.5 x_4
10 *
11 *
12 * Subject To
13 * c0 : 1 x0 + 1 x1 + 2 x2 + 3 x3 >= 1
14 * c1 : 1 x0 - 1 x2 + 6 x3 = 1
15 * c2 : x_1^2 + x_2^2 - x_4^2 <= 0
16 * Bounds
17 * 0 <= x0 <= 10
18 * 0 <= x1
19 * 0 <= x2
20 * 0 <= x3
21 * 0 <= x4
22 * Integer
23 * x0, x1, x2
24 * End
25 */
26#include <iostream>
27#include "MindoptCpp.h"
28#include <vector>
29
30using namespace std;
31
32int main(void)
33{
34 /*------------------------------------------------------------------*/
35 /* Step 1. Create environment and model. */
36 /*------------------------------------------------------------------*/
37 MDOEnv env = MDOEnv();
38 MDOModel model = MDOModel(env);
39
40 try
41 {
42 /*------------------------------------------------------------------*/
43 /* Step 2. Input model. */
44 /*------------------------------------------------------------------*/
45 /* Change to minimization problem. */
46 model.set(MDO_IntAttr_ModelSense, MDO_MINIMIZE);
47
48 /* Add variables. */
49 std::vector<MDOVar> x;
50 x.push_back(model.addVar(0.0, 10.0, 1.0, MDO_INTEGER, "x0"));
51 x.push_back(model.addVar(0.0, MDO_INFINITY, 2.0, MDO_INTEGER, "x1"));
52 x.push_back(model.addVar(0.0, MDO_INFINITY, 1.0, MDO_INTEGER, "x2"));
53 x.push_back(model.addVar(0.0, MDO_INFINITY, 1.0, MDO_CONTINUOUS, "x3"));
54 x.push_back(model.addVar(0.0, MDO_INFINITY, 0.5, MDO_CONTINUOUS, "x4"));
55
56 /* Prepare model data. */
57 /* add c0 */
58 model.addConstr(1.0 * x[0] + 1.0 * x[1] + 2.0 * x[2] + 3.0 * x[3], MDO_GREATER_EQUAL, 1.0, "c0");
59
60 /* add c1 */
61 model.addConstr(1.0 * x[0] - 1.0 * x[2] + 6.0 * x[3], MDO_EQUAL, 1.0, "c1");
62
63 /* second order cone constraint */
64 int qc2_nnz = 3;
65 MDOVar qc2_col1[] = { x[1], x[2], x[4]};
66 MDOVar qc2_col2[] = { x[1], x[2], x[4]};
67 double qc2_values[] = { 1.0, 1.0, -1.0};
68
69 /* Add the second order cone constraint. c2*/
70 MDOQuadExpr c2 = MDOQuadExpr(0.0);
71 c2.addTerms(qc2_values, qc2_col1, qc2_col2, qc2_nnz);
72 model.addQConstr(c2, MDO_LESS_EQUAL, 0.0, "c2");
73
74 /*------------------------------------------------------------------*/
75 /* Step 3. Solve the problem. */
76 /*------------------------------------------------------------------*/
77 /* Solve the problem. */
78 model.optimize();
79
80 /*------------------------------------------------------------------*/
81 /* Step 4. Retrive model status and objective. */
82 /* For MIP(MILP,MIQP, MIQCP) problems, if the solving process */
83 /* terminates early due to reasons such as timeout or interruption, */
84 /* the model status will indicate termination by timeout (or */
85 /* interruption, etc.). However, suboptimal solutions may still */
86 /* exist, making it necessary to check the SolCount property. */
87 /*------------------------------------------------------------------*/
88 if (model.get(MDO_IntAttr_Status) == MDO_OPTIMAL || model.get(MDO_IntAttr_Status) == MDO_SUB_OPTIMAL ||
89 model.get(MDO_IntAttr_SolCount) != 0)
90 {
91 cout << "Optimal objective value is: " << model.get(MDO_DoubleAttr_ObjVal) << endl;
92 cout << "Decision variables:" << endl;
93 int i = 0;
94 for (auto v : x)
95 {
96 cout << "x[" << i++ << "] = " << v.get(MDO_DoubleAttr_X) << endl;
97 }
98 }
99 else
100 {
101 cout<< "No feasible solution." << endl;
102 }
103
104 }
105 catch (MDOException& e)
106 {
107 std::cout << "Error code = " << e.getErrorCode() << std::endl;
108 std::cout << e.getMessage() << std::endl;
109 }
110 catch (...)
111 {
112 std::cout << "Error during optimization." << std::endl;
113 }
114
115 return static_cast<int>(MDO_OKAY);
116}