5.5. Analysis of constraint conflicts

When you build a model to solve optimization problems in applications, you may encounter infeasible problems. The infeasible problems are caused by conflicts between constraints. It is important to analyze infeasible problems and identify the key conflicting constraints during the application of the solver.

The minimum constraint subset that causes infeasible problems is called irreduciable infeasible system (IIS). MindOpt provides an API for IIS calculation. You can call this API to analyze infeasible problems. Then, you can correct or remove constraints in the IIS to make optimization problems feasible, so as to better analyze actual problems, build models, and obtain the optimal decision.

Note that the IIS may not be unique in a linear programming problem. If multiple IISs exist, you need to adjust the optimization problem multiple times to make it feasible. For example:

\[\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}\]

In this example, we can easily know that \(c_1\) and \(c_2\) form an IIS, and \(c_3\) and \(c_4\) form another IIS. After you remove one constraint from both IISs, the problem becomes feasible.

The following part provides a more practical example to describe how to use conflict analysis to obtain an IIS in MindOpt. In the following infeasible constraint system:

\[\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}\]

The former three constraints form an IIS, and the fourth constraint and the upper and lower bounds of variables form another IIS.

Note

At present, MindOpt uses a filtering algorithm to find IISs. The filtering algorithm can find an IIS within a short time but cannot ensure that this IIS is the smallest among all. In addition, if you adjust the sequence of constraints, MindOpt may generate different IISs.

Note

We recommend that you fix the conflicts in an IIS, input the modified model into the IIS solving API, and fix the next IIS. You need to repeat these steps until all conflicts are fixed.

The following part describes how to use MindOpt in a C/C++/Python environment to obtain an IIS of infeasible problems.

5.5.1. C API: Mdo_computeIIS

First, create an optimization problem and set parameters by referring to Modeling and optimization in C.

 94    /*------------------------------------------------------------------*/
 95    /* Step 1. Create a model and change the parameters.                */
 96    /*------------------------------------------------------------------*/
 97    printf("Step 1. 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));

Then, when the optimization problem is infeasible, use Mdo_computeIIS() to obtain the row and column coordinates of the IIS, and output the corresponding constraint names and variable names.

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;

The linked file MdoLoIIS.c provides complete source code:

  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 listed below!
 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("Step 1. 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.5.2. C++ API:computeIIS

First, create an optimization problem and set parameters by referring to Modeling and optimization in 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");

Then, when the optimization problem is infeasible, use mindopt::MdoModel::computeIIS() to obtain the row and column coordinates of the IIS, and output the corresponding constraint names and variable names.

 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;

The linked file MdoLoIIS.cpp provides complete source code:

  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 listed below!
 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.5.3. Python API: compute_iis

First, create an optimization problem and set parameters by referring to Modeling and optimization in 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"))        

Then, when the optimization problem is infeasible, use mindoptpy.MdoModel.compute_iis() to obtain the row and column coordinates of the IIS, and output the corresponding constraint names and variable names.

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")))

The linked file mdo_lo_iis.py provides complete source code:

 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 <- conflicts with variable bounds listed 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()