5.8. 约束不可行性分析

在对实际应用中的优化问题进行建模求解的过程中,往往会遇到问题不可行的情况。而不可行问题必然是由某些约束互相之间冲突导致的,如何分析问题的不可行性并识别出导致冲突的关键约束成为求解器应用的重要一环。

这类导致问题不可行的最小约束子集被称为不可约不可行系统 (IIS, irreduciable infeasible system)。MindOpt 设计了用来计算 IIS 的 API,用户可以通过利用该 API 来对不可行问题进行分析。再依据此对 IIS 中的约束进行修正或移除,可以使得优化问题变得可行,以便于更好地对实际问题进行分析建模和获得最优决策。

需要注意的是,在线性规划问题中,IIS 可能并不是唯一的。若存在多个 IIS,则需要对优化问题进行多次调整,才能使其变得可行。例如:

\[\begin{split}\text{c}_1: ~~ x_1 \leq 1 \\ \text{c}_2: ~~ x_1 \geq 2 \\ \text{c}_3: ~~ x_2 \leq 3 \\ \text{c}_4: ~~ x_2 \geq 4 \\\end{split}\]

在这个例子中,我们很容易知道 \(c_1\)\(c_2\) 为一组 IIS,\(c_3\)\(c_4\) 为一组 IIS。在同时移除 \(c_1\)\(c_2\) 中的任意一条约束以及 \(c_3\)\(c_4\) 中的任意一条约束后,该问题将变得可行。

我们将通过一个更加实际的例子,来展示如何在 MindOpt 中使用约束不可行性分析来获取 IIS。考虑如下的不可行约束系统:

\[\begin{split}\text{Constraints:} & & \\ & -0.5 x_0 + x_1 &>= 0.5 \\ & 2 x_0 - x_1 &>= 3 \\ & 3 x_0 + x_1 &<= 6 \\ & 3 x_3 - x_4 &<= 2 \\ & x_0 + x_4 &<= 10 \\ & x_0 + 2 x_1 + x_3 &<= 14 \\ & x_1 + x_3 &>= 1 \\ \text{Bounds:} & & \\ & 5 <= x_3 & \\ & 0 <= x_4 <= 2 &\end{split}\]

其中,前面三组约束构成一组IIS,而第四个约束和变量上下界则构成另外一组IIS。

Note

MindOpt 目前采用过滤算法来寻找IIS。过滤算法虽然能在短时间找出一组IIS,但无法保证IIS的规模是所有IIS组合中最小的。此外,若使用者对约束顺序做调整,则 MindOpt 也可能会产生不同的IIS。

Note

实际操作上,我们建议使用者修复IIS中的冲突后,再将修改后的模型输入至求解IIS的API,并修复下一个IIS;依此直至所有的冲突都得以修复。

接下来,我们将分别说明如何在 C/C++/Python 环境中应用 MindOpt 来获取不可行问题的 IIS。

5.8.1. C API: Mdo_computeIIS

首先,参考 C 语言的建模和优化 中的方法创建优化问题并设置参数:

 94    /*------------------------------------------------------------------*/
 95    /* Step 1. Create a model and change the parameters.                */
 96    /*------------------------------------------------------------------*/
 97    printf(" Create a model and change the parameters.\n\n");
 98    /* Create an empty model. */
 99    MDO_CHECK_CALL(Mdo_createMdl(&model));
100    /* Turn-off the presolver so that solver won't terminate with an MDO_INF_OR_UBD status. */
101    MDO_CHECK_CALL(Mdo_setIntParam(model, MDO_INT_PARAM_PRESOLVE, 0));
102    /* Use dual-Simplex method. */
103    MDO_CHECK_CALL(Mdo_setIntParam(model, MDO_INT_PARAM_METHOD, 1));
104
105    /*------------------------------------------------------------------*/
106    /* Step 2. Input model.                                             */
107    /*------------------------------------------------------------------*/
108    printf("\nStep 2. Input model.\n\n");    
109    /* The following three input methods will all result in the same model. */
110    /* Change to minimization problem. */
111    MDO_CHECK_CALL(Mdo_setIntAttr(model, MDO_INT_ATTR_MIN_SENSE, MDO_YES));
112    
113    /* Add variables. */
114    for (i = 0; i < 5; ++i)
115    {
116        MDO_CHECK_CALL(Mdo_addCol(model, lbs[i], ubs[i], objs[i], 0, NULL, NULL, col_names[i], MDO_NO));    
117    }    
118    /* Add two constraints. 
119     * The coefficients of the constraint matrix are inputted in a row-wise order.
120     */
121    MDO_CHECK_CALL(Mdo_addRows(model, 7, lhss, rhss, csr_bgn, csr_indices, csr_values, row_names));

接下来,当优化问题不可行时,使用 Mdo_computeIIS() 获取不可约不可行子系统的行列坐标,并打印对应的约束名与变量名:

140    case MDO_INFEASIBLE:
141        printf("Optimizer terminated with an INFEASIBLE status.\n");
142        printf("Compute IIS.\n");
143        MDO_CHECK_CALL(Mdo_computeIIS(model, &num_iis_rows, idx_iis_rows, &num_iis_cols, idx_iis_cols));
144        printf("Computed IIS has %d rows and %d columns.\n", num_iis_rows, num_iis_cols);
145        printf("Populating IIS.\n");
146        for (i = 0; i < num_iis_rows; ++i)
147        {
148            char row_name_iis[1024] = { "\0" };
149            Mdo_getRowName(model, idx_iis_rows[i], row_name_iis, 1024, NULL);
150            printf(" Constraint: %s\n", row_name_iis);
151        }
152        for (j = 0; j < num_iis_cols; ++j)
153        {
154            char col_name_iis[1024] = { "\0" };
155            Mdo_getColName(model, idx_iis_cols[j], col_name_iis, 1024, NULL);
156            printf(" Variable: %10d\n", col_name_iis);
157        }
158        break;

MdoLoIIS.c 提供了完整源代码:

  1/**
  2 *  Description
  3 *  -----------
  4 *
  5 *  Linear optimization.
  6 *   - Compute IIS of an infeasible problem.
  7 * 
  8 *  Formulation
  9 *  -----------
 10 *
 11 *  Minimize
 12 *  Obj:
 13 *  Subject To
 14 *  c0:  -0.500000000 x0 + x1 >= 0.500000000
 15 *  c1:  2 x0 - x1 >= 3
 16 *  c2:  3 x0 + x1 <= 6
 17 *  c3:  3 x3 - x4 <= 2 <- conflicts with variable bounds!
 18 *  c4:  x0 + x4 <= 10
 19 *  c5:  x0 + 2 x1 + x3 <= 14
 20 *  c6:  x1 + x3 >= 1
 21 *  Bounds
 22 *   5 <= x3
 23 *   0 <= x4 <= 2
 24 *  End
 25 */
 26#include <stdio.h>
 27#include <stdlib.h>
 28#include "Mindopt.h"
 29
 30
 31/* Macro to check the return code */
 32#define MDO_CHECK_CALL(MDO_CALL)                                    \
 33    code = MDO_CALL;                                                \
 34    if (code != MDO_OKAY)                                           \
 35    {                                                               \
 36        Mdo_explainResult(model, code, str);                        \
 37        Mdo_freeMdl(&model);                                        \
 38        fprintf(stderr, "===================================\n");   \
 39        fprintf(stderr, "Error   : code <%d>\n", code);             \
 40        fprintf(stderr, "Reason  : %s\n", str);                     \
 41        fprintf(stderr, "===================================\n");   \
 42        return (int)code;                                           \
 43    }
 44
 45int main(void)
 46{
 47    /* Variables. */
 48    char str[1024] = { "\0" };
 49    MdoMdl * model = NULL;
 50    MdoResult code = MDO_OKAY;
 51    MdoStatus status = MDO_UNKNOWN;
 52    double val;
 53    int num_iis_rows, num_iis_cols;
 54    int idx_iis_rows[7], idx_iis_cols[5];
 55    int i, j;
 56
 57    const int csr_bgn[] = {0, 2, 4, 6, 8, 10, 13, 15};
 58    const int csr_indices[] = 
 59    {
 60        0,   1, 
 61        0,   1,
 62        0,   1,
 63        3,   4,
 64        0,   4,
 65        0,   1,   3,
 66        1,   3  
 67    };
 68    const double csr_values[] = 
 69    {
 70       -0.5, 1,
 71        2,  -1,
 72        3,   1,
 73        3,  -1,
 74        1,   1,
 75        1,   2,   1,
 76        1,   1
 77    };
 78
 79    const double lhss[] = 
 80    {          
 81        0.5, 3.0, -MDO_INFINITY, -MDO_INFINITY, -MDO_INFINITY, -MDO_INFINITY, 1.0 
 82    };
 83    const double rhss[] = 
 84    {
 85        MDO_INFINITY, MDO_INFINITY, 6.0, 2.0, 10.0, 14.0, MDO_INFINITY
 86    };
 87    const char* row_names[] = { "c0", "c1" , "c2" , "c3" , "c4" , "c5" , "c6" };
 88
 89    const double lbs[] =  {          0.0,          0.0,          0.0,          5.0, 0.0 };
 90    const double ubs[] =  { MDO_INFINITY, MDO_INFINITY, MDO_INFINITY, MDO_INFINITY, 2.0 };
 91    const double objs[] = {          0.0,          0.0,          0.0,          0.0, 0.0 };
 92    const char* col_names[] = { "x0", "x1", "x2", "x3", "x4" };
 93      
 94    /*------------------------------------------------------------------*/
 95    /* Step 1. Create a model and change the parameters.                */
 96    /*------------------------------------------------------------------*/
 97    printf(" Create a model and change the parameters.\n\n");
 98    /* Create an empty model. */
 99    MDO_CHECK_CALL(Mdo_createMdl(&model));
100    /* Turn-off the presolver so that solver won't terminate with an MDO_INF_OR_UBD status. */
101    MDO_CHECK_CALL(Mdo_setIntParam(model, MDO_INT_PARAM_PRESOLVE, 0));
102    /* Use dual-Simplex method. */
103    MDO_CHECK_CALL(Mdo_setIntParam(model, MDO_INT_PARAM_METHOD, 1));
104
105    /*------------------------------------------------------------------*/
106    /* Step 2. Input model.                                             */
107    /*------------------------------------------------------------------*/
108    printf("\nStep 2. Input model.\n\n");    
109    /* The following three input methods will all result in the same model. */
110    /* Change to minimization problem. */
111    MDO_CHECK_CALL(Mdo_setIntAttr(model, MDO_INT_ATTR_MIN_SENSE, MDO_YES));
112    
113    /* Add variables. */
114    for (i = 0; i < 5; ++i)
115    {
116        MDO_CHECK_CALL(Mdo_addCol(model, lbs[i], ubs[i], objs[i], 0, NULL, NULL, col_names[i], MDO_NO));    
117    }    
118    /* Add two constraints. 
119     * The coefficients of the constraint matrix are inputted in a row-wise order.
120     */
121    MDO_CHECK_CALL(Mdo_addRows(model, 7, lhss, rhss, csr_bgn, csr_indices, csr_values, row_names));
122
123    /*------------------------------------------------------------------*/
124    /* Step 3. Solve the problem and populate the result.               */
125    /*------------------------------------------------------------------*/
126    printf("\nStep 3. Solve the problem and populate the result.\n\n");
127    /* Solve the problem. */
128    MDO_CHECK_CALL(Mdo_solveProb(model));
129    Mdo_displayResults(model);
130
131    switch (Mdo_getStatus(model))
132    {
133    case MDO_UNKNOWN:
134        printf("Optimizer terminated with an UNKNOWN status.\n");
135        break;
136    case MDO_OPTIMAL:
137        MDO_CHECK_CALL(Mdo_getRealAttr(model, MDO_REAL_ATTR_PRIMAL_OBJ_VAL, &val));
138        printf("Optimizer terminated with an OPTIMAL status.\n");
139        printf(" - Primal objective : %e.\n", val);
140        break;
141    case MDO_INFEASIBLE:
142        printf("Optimizer terminated with an INFEASIBLE status.\n");
143        printf("Compute IIS.\n");
144        MDO_CHECK_CALL(Mdo_computeIIS(model, &num_iis_rows, idx_iis_rows, &num_iis_cols, idx_iis_cols));
145        printf("Computed IIS has %d rows and %d columns.\n", num_iis_rows, num_iis_cols);
146        printf("Populating IIS.\n");
147        for (i = 0; i < num_iis_rows; ++i)
148        {
149            char row_name_iis[1024] = { "\0" };
150            Mdo_getRowName(model, idx_iis_rows[i], row_name_iis, 1024, NULL);
151            printf(" Constraint: %s\n", row_name_iis);
152        }
153        for (j = 0; j < num_iis_cols; ++j)
154        {
155            char col_name_iis[1024] = { "\0" };
156            Mdo_getColName(model, idx_iis_cols[j], col_name_iis, 1024, NULL);
157            printf(" Variable: %10d\n", col_name_iis);
158        }
159        break;
160    case MDO_UNBOUNDED:
161        printf("Optimizer terminated with an UNBOUNDED status.\n");
162        break;
163    case MDO_INF_OR_UBD:
164        printf("Optimizer terminated with an INFEASIBLE or UNBOUNDED status.\n");
165        break;
166    }
167
168    /*------------------------------------------------------------------*/
169    /* Step 4. Free the model.                                          */
170    /*------------------------------------------------------------------*/
171    printf("\nStep 4. Free the model.\n");
172    /* Free the model. */
173    Mdo_freeMdl(&model);
174       
175    return (int)code;
176}

5.8.2. C++ API:computeIIS

首先,参考 C++ 的建模和优化 中的方法创建优化问题并设置参数:

52        model.setIntAttr(MDO_INT_ATTR::MIN_SENSE, MDO_YES);
53
54        /* Add variables. */
55        std::vector<MdoVar> x;
56        x.push_back(model.addVar(0.0, MDO_INFINITY, 0.0, "x0", MDO_NO));
57        x.push_back(model.addVar(0.0, MDO_INFINITY, 0.0, "x1", MDO_NO));
58        x.push_back(model.addVar(0.0, MDO_INFINITY, 0.0, "x2", MDO_NO));
59        x.push_back(model.addVar(5.0, MDO_INFINITY, 0.0, "x3", MDO_NO));
60        x.push_back(model.addVar(0.0, 2.0,          0.0, "x4", MDO_NO));
61
62        /* Add constraints. */
63        model.addCons(-0.5 * x[0]       + x[1]                     >= 0.5,  "c0");
64        model.addCons( 2.0 * x[0]       - x[1]                     >= 3.0,  "c1");
65        model.addCons( 3.0 * x[0]       + x[1]                     <= 6.0,  "c2");
66        model.addCons(                          3.0 * x[3] - x[4]  <= 2.0,  "c3");
67        model.addCons(       x[0]                          + x[4]  <= 10.0, "c4");
68        model.addCons(       x[0] + 2.0 * x[1]      + x[3]         <= 14.0, "c5");
69        model.addCons(       x[1] +                   x[3]         >= 1.0,  "c6");

接下来,当优化问题不可行时,使用 mindopt::MdoModel::computeIIS() 获取不可约不可行子系统的行列坐标,并打印对应的约束名与变量名:

 86        case MDO_INFEASIBLE:
 87            std::cout << "Optimizer terminated with an INFEASIBLE status." << std::endl;
 88            std::cout << "Compute IIS." << std::endl;
 89            model.computeIIS(idx_rows, idx_cols);
 90
 91            std::cout << "Computed IIS has " << idx_rows.size() << " rows and " << idx_cols.size() << " columns." << std::endl;
 92            std::cout << "Populating IIS." << std::endl;
 93            for (int i : idx_rows)
 94            {
 95                std::cout << "Constraint: " << model.getStrAttrIndex("RowName", i) << std::endl;
 96            }
 97            for (int j : idx_cols)
 98            {
 99                std::cout << "Variable: " << model.getStrAttrIndex("ColName", j) << std::endl;
100            }
101            break;

MdoLoIIS.cpp 提供了完整源代码:

  1/**
  2 *  Description
  3 *  -----------
  4 *
  5 *  Linear optimization.
  6 *   - Compute IIS of an infeasible problem.
  7 * 
  8 *  Formulation
  9 *  -----------
 10 *
 11 *  Minimize
 12 *  Obj:
 13 *  Subject To
 14 *  c0:  -0.500000000 x0 + x1 >= 0.500000000
 15 *  c1:  2 x0 - x1 >= 3
 16 *  c2:  3 x0 + x1 <= 6
 17 *  c3:  3 x3 - x4 <= 2 <- conflicts with variable bounds!
 18 *  c4:  x0 + x4 <= 10
 19 *  c5:  x0 + 2 x1 + x3 <= 14
 20 *  c6:  x1 + x3 >= 1
 21 *  Bounds
 22 *   5 <= x3
 23 *   0 <= x4 <= 2
 24 *  End
 25 */
 26#include <iostream>
 27#include <vector>
 28#include "MindoptCpp.h"
 29
 30using namespace mindopt;
 31
 32int main(void)
 33{
 34    std::vector<int> idx_rows, idx_cols;
 35
 36    /*------------------------------------------------------------------*/
 37    /* Step 1. Create a model and change the parameters.                */
 38    /*------------------------------------------------------------------*/
 39    /* Create an empty model. */
 40    MdoModel model;
 41    /* Turn-off the presolver so that solver won't terminate with an MDO_INF_OR_UBD status. */
 42    model.setIntParam(MDO_INT_PARAM::PRESOLVE, 0);
 43    /* Use dual-Simplex method. */
 44    model.setIntParam(MDO_INT_PARAM::METHOD, 1);
 45
 46    try 
 47    {
 48        /*------------------------------------------------------------------*/
 49        /* Step 2. Input model.                                             */
 50        /*------------------------------------------------------------------*/
 51        /* Change to minimization problem. */
 52        model.setIntAttr(MDO_INT_ATTR::MIN_SENSE, MDO_YES);
 53
 54        /* Add variables. */
 55        std::vector<MdoVar> x;
 56        x.push_back(model.addVar(0.0, MDO_INFINITY, 0.0, "x0", MDO_NO));
 57        x.push_back(model.addVar(0.0, MDO_INFINITY, 0.0, "x1", MDO_NO));
 58        x.push_back(model.addVar(0.0, MDO_INFINITY, 0.0, "x2", MDO_NO));
 59        x.push_back(model.addVar(5.0, MDO_INFINITY, 0.0, "x3", MDO_NO));
 60        x.push_back(model.addVar(0.0, 2.0,          0.0, "x4", MDO_NO));
 61
 62        /* Add constraints. */
 63        model.addCons(-0.5 * x[0]       + x[1]                     >= 0.5,  "c0");
 64        model.addCons( 2.0 * x[0]       - x[1]                     >= 3.0,  "c1");
 65        model.addCons( 3.0 * x[0]       + x[1]                     <= 6.0,  "c2");
 66        model.addCons(                          3.0 * x[3] - x[4]  <= 2.0,  "c3");
 67        model.addCons(       x[0]                          + x[4]  <= 10.0, "c4");
 68        model.addCons(       x[0] + 2.0 * x[1]      + x[3]         <= 14.0, "c5");
 69        model.addCons(       x[1] +                   x[3]         >= 1.0,  "c6");
 70
 71        /*------------------------------------------------------------------*/
 72        /* Step 3. Solve the problem and populate the result.               */
 73        /*------------------------------------------------------------------*/
 74        /* Solve the problem. */
 75        model.solveProb();
 76        model.displayResults();
 77
 78        switch (model.getStatus())
 79        {
 80        case MDO_UNKNOWN:
 81            std::cout << "Optimizer terminated with an UNKNOWN status." << std::endl;
 82            break;
 83        case MDO_OPTIMAL:
 84            std::cout << "Optimizer terminated with an OPTIMAL status." << std::endl;
 85            break;
 86        case MDO_INFEASIBLE:
 87            std::cout << "Optimizer terminated with an INFEASIBLE status." << std::endl;
 88            std::cout << "Compute IIS." << std::endl;
 89            model.computeIIS(idx_rows, idx_cols);
 90
 91            std::cout << "Computed IIS has " << idx_rows.size() << " rows and " << idx_cols.size() << " columns." << std::endl;
 92            std::cout << "Populating IIS." << std::endl;
 93            for (int i : idx_rows)
 94            {
 95                std::cout << "Constraint: " << model.getStrAttrIndex("RowName", i) << std::endl;
 96            }
 97            for (int j : idx_cols)
 98            {
 99                std::cout << "Variable: " << model.getStrAttrIndex("ColName", j) << std::endl;
100            }
101            break;
102        case MDO_UNBOUNDED:
103            std::cout << "Optimizer terminated with an UNBOUNDED status." << std::endl;
104            break;
105        case MDO_INF_OR_UBD:
106            std::cout << "Optimizer terminated with an INFEASIBLE or UNBOUNDED status." << std::endl;
107            break;
108        }
109    }
110    catch (MdoException & e)
111    {
112        std::cerr << "===================================" << std::endl;
113        std::cerr << "Error   : code <" << e.getResult() << ">" << std::endl;
114        std::cerr << "Reason  : " << model.explainResult(e.getResult()) << std::endl;
115        std::cerr << "===================================" << std::endl;
116
117        return static_cast<int>(e.getResult());
118    }
119
120    return static_cast<int>(MDO_OKAY);
121}

5.8.3. Python API: compute_iis

首先,参考 Python 的建模与优化 中的方法创建优化问题并设置参数:

42        # Step 2. Input model.
43        # Change to minimization problem.
44        model.set_int_attr(MDO_INT_ATTR.MIN_SENSE, 1)
45
46        # Add variables.
47        # Note that the nonzero elements are inputted in a column-wise order here.
48        x = []
49        x.append(model.add_var(0.0, MDO_INFINITY, 0.0, None, "x0", False))
50        x.append(model.add_var(0.0, MDO_INFINITY, 0.0, None, "x1", False))
51        x.append(model.add_var(0.0, MDO_INFINITY, 0.0, None, "x2", False))
52        x.append(model.add_var(5.0, MDO_INFINITY, 0.0, None, "x3", False))
53        x.append(model.add_var(0.0,          2.0, 0.0, None, "x4", False))
54
55        # Add constraints.
56        # Note that the nonzero elements are inputted in a row-wise order here.
57        conss = []
58        conss.append(model.add_cons(-0.5 * x[0]       + x[1]                     >= 0.5,  "c0"))
59        conss.append(model.add_cons( 2.0 * x[0]       - x[1]                     >= 3.0,  "c1"))
60        conss.append(model.add_cons( 3.0 * x[0]       + x[1]                     <= 6.0,  "c2"))
61        conss.append(model.add_cons(                          3.0 * x[3] - x[4]  <= 2.0,  "c3"))
62        conss.append(model.add_cons(       x[0]                          + x[4]  <= 10.0, "c4"))
63        conss.append(model.add_cons(       x[0] + 2.0 * x[1]      + x[3]         <= 14.0, "c5"))
64        conss.append(model.add_cons(       x[1] +                   x[3]         >= 1.0,  "c6"))        

接下来,当优化问题不可行时,使用 mindoptpy.MdoModel.compute_iis() 获取不可约不可行子系统的行列坐标,并打印对应的约束名与变量名:

70        status_code, status_msg = model.get_status()
71        if status_msg == "INFEASIBLE":
72            print("Optimizer terminated with an MDO_INFEASIBLE status (code {0}).".format(status_code))
73            print("Compute IIS.")
74            idx_rows, idx_cols = model.compute_iis()
75
76            print("Computed IIS has {0} rows and {1} columns.".format(len(idx_rows), len(idx_cols)))
77            print("Populating IIS.")
78            for i in idx_rows:
79                print("Constraint: {0}".format(conss[i].get_str_attr("RowName")))
80            for j in idx_cols:
81                print("Variable: {0}".format(x[j].get_str_attr("ColName")))

mdo_lo_iis.py 提供了完整源代码:

 1"""
 2/**
 3 *  Description
 4 *  -----------
 5 *
 6 *  Linear optimization.
 7 *   - Compute IIS of an infeasible problem.
 8 * 
 9 *  Formulation
10 *  -----------
11 *
12 *  Minimize
13 *  Obj:
14 *  Subject To
15 *  c0:  -0.500000000 x0 + x1 >= 0.500000000
16 *  c1:  2 x0 - x1 >= 3
17 *  c2:  3 x0 + x1 <= 6
18 *  c3:  3 x3 - x4 <= 2 <- conflit with variable bounds below!
19 *  c4:  x0 + x4 <= 10
20 *  c5:  x0 + 2 x1 + x3 <= 14
21 *  c6:  x1 + x3 >= 1
22 *  Bounds
23 *   5 <= x3
24 *   0 <= x4 <= 2
25 *  End
26 */
27"""
28from mindoptpy import *
29
30
31if __name__ == "__main__":
32
33    MDO_INFINITY = MdoModel.get_infinity()
34
35    # Step 1. Create a model and change the parameters.
36    model = MdoModel()
37    # Turn-off the presolver so that solver won't terminate with an MDO_INF_OR_UBD status.
38    model.set_int_param(MDO_INT_PARAM.PRESOLVE, 0)
39    model.set_int_param(MDO_INT_PARAM.METHOD, 1)
40
41    try:
42        # Step 2. Input model.
43        # Change to minimization problem.
44        model.set_int_attr(MDO_INT_ATTR.MIN_SENSE, 1)
45
46        # Add variables.
47        # Note that the nonzero elements are inputted in a column-wise order here.
48        x = []
49        x.append(model.add_var(0.0, MDO_INFINITY, 0.0, None, "x0", False))
50        x.append(model.add_var(0.0, MDO_INFINITY, 0.0, None, "x1", False))
51        x.append(model.add_var(0.0, MDO_INFINITY, 0.0, None, "x2", False))
52        x.append(model.add_var(5.0, MDO_INFINITY, 0.0, None, "x3", False))
53        x.append(model.add_var(0.0,          2.0, 0.0, None, "x4", False))
54
55        # Add constraints.
56        # Note that the nonzero elements are inputted in a row-wise order here.
57        conss = []
58        conss.append(model.add_cons(-0.5 * x[0]       + x[1]                     >= 0.5,  "c0"))
59        conss.append(model.add_cons( 2.0 * x[0]       - x[1]                     >= 3.0,  "c1"))
60        conss.append(model.add_cons( 3.0 * x[0]       + x[1]                     <= 6.0,  "c2"))
61        conss.append(model.add_cons(                          3.0 * x[3] - x[4]  <= 2.0,  "c3"))
62        conss.append(model.add_cons(       x[0]                          + x[4]  <= 10.0, "c4"))
63        conss.append(model.add_cons(       x[0] + 2.0 * x[1]      + x[3]         <= 14.0, "c5"))
64        conss.append(model.add_cons(       x[1] +                   x[3]         >= 1.0,  "c6"))        
65
66        # Step 3. Solve the problem and populate the result.
67        model.solve_prob()
68        model.display_results()
69
70        status_code, status_msg = model.get_status()
71        if status_msg == "INFEASIBLE":
72            print("Optimizer terminated with an MDO_INFEASIBLE status (code {0}).".format(status_code))
73            print("Compute IIS.")
74            idx_rows, idx_cols = model.compute_iis()
75
76            print("Computed IIS has {0} rows and {1} columns.".format(len(idx_rows), len(idx_cols)))
77            print("Populating IIS.")
78            for i in idx_rows:
79                print("Constraint: {0}".format(conss[i].get_str_attr("RowName")))
80            for j in idx_cols:
81                print("Variable: {0}".format(x[j].get_str_attr("ColName")))
82        else:
83            print("Optimizer terminated with a(n) {0} status (code {1}).".format(status_msg, status_code))
84
85    except MdoError as e:
86        print("Received Mindopt exception.")
87        print(" - Code          : {}".format(e.code))
88        print(" - Reason        : {}".format(e.message))
89    except Exception as e:
90        print("Received exception.")
91        print(" - Explanation   : {}".format(e))
92    finally:
93        # Step 4. Free the model.
94        model.free_mdl()