ILOG CPLEX 10.1 User's Manual > Infeasibility and Unboundedness > Diagnosing Infeasibility by Refining Conflicts > Using the Conflict Refiner in an Application

Here is an example using the conflict refiner in the C++ API of Concert Technology. You will modify one of the standard examples ilomipex2.cpp distributed with the product. Starting from that example, locate this statement in it:

cplex.solve();

Immediately after that statement, insert the following lines to prepare for and invoke the conflict refiner:

 if ( ( cplex.getStatus() == IloAlgorithm::Infeasible ) ||
           ( cplex.getStatus() == IloAlgorithm::InfeasibleOrUnbounded  ) ) {
         cout << endl << "No solution - starting Conflict refinement" << endl;

         IloConstraintArray infeas(env);
         IloNumArray preferences(env);

         infeas.add(rng); 
         infeas.add(sos1); infeas.add(sos2);
         if ( lazy.getSize() || cuts.getSize() ) {
           cout << "Lazy Constraints and User Cuts ignored" << endl;
         }
         for (IloInt i = 0; i<var.getSize(); i++) {
            if ( var[i].getType() != IloNumVar::Bool ) {
              infeas.add(IloBound(var[i], IloBound::Lower));
              infeas.add(IloBound(var[i], IloBound::Upper));
            }
         }

         for (IloInt i = 0; i<infeas.getSize(); i++) {
           preferences.add(1.0);  // user may wish to assign unique preferences
         }

         if ( cplex.refineConflict(infeas, preferences) ) {
            IloCplex::ConflictStatusArray conflict = cplex.getConflict(infeas);
            env.getImpl()->useDetailedDisplay(IloTrue);
            cout << "Conflict :" << endl;
            for (IloInt i = 0; i<infeas.getSize(); i++) {
              if ( conflict[i] == IloCplex::ConflictMember)
                   cout << "Proved  : " << infeas[i] << endl;
              if ( conflict[i] == IloCplex::ConflictPossibleMember)
                   cout << "Possible: " << infeas[i] << endl;
            }
         }
         else
            cout << "Conflict could not be refined" << endl;
         cout << endl;
      }
Now run this modified version with the model you have seen in
A Model for the Conflict Refiner. You will see results like these:
No solution - starting Conflict refinement

Refine conflict on 14 members...

 Iteration  Max Members  Min Members
         1           11            0
         2            9            0
         3            5            0
         4            3            0
         5            2            0
         6            2            1
         7            2            2
Conflict :
Proved  : c2( 2.1 <= ( x1 + x2 + 0.8 * x3 + 0.6 * x4 + 0.4 * x5 ) )
Proved  : c8( ( x2 + x3 + x4 + x5 )  <= 0)

What Belongs in an Application to Refine Conflict

There are a few remarks to make about that modification:

Conflict Application vs Interactive Optimizer

This modified example also demonstrates a few features that are available only in the Callable Library and Concert Technology, not in the Interactive Optimizer:

Preferences in the Conflict Refiner

You can assign preference to members of a conflict. In most cases there is no advantage to assigning unique preferences, but if you know something about your model that suggests assigning an ordering to certain members, you can do so.

Groups in the Conflict Refiner

You can organize constraints and bounds into one or more groups in a conflict. A group is a set of constraints or bounds that must be considered together; that is, if one member of a group is determined by the conflict refiner to be a necessary in a minimal conflict, then the entire group will be part of the conflict.

For example, in the resource allocation problem from A Model for the Conflict Refiner, management might consider the three skill requirements (c2, c3, c4) as inseparable. Adjusting the data in any one of them should require a careful re-evaluation of all three. To achieve that effect in the modified version of ilomipex2.cpp, replace this line:

 infeas.add(rng);

by the following lines to declare a group of the constraints expressing skill requirements:

         infeas.add(rng[0]);
         IloAnd skills(env);
         skills.add(rng[1]);
         skills.add(rng[2]);
         skills.add(rng[3]);
         infeas.add(skills);
         for (IloInt i = 4; i<rng.getSize(); i++) {
           infeas.add(rng[i]);
         }

(This particular modification is specific to this simplified resource allocation model and thus would not make sense in some other infeasible model you might run with the modified ilomipex2.cpp application.)

After that modification, the cost constraint and the constraints indexed 4 through 10 are treated individually (that is, normally) as before. The three constraints indexed 1 through three are combined into a skills constraint through the IloAnd operator, and added to the infeasible set.

Individual preferences are not assigned to any of these members in this example, but you could assign preferences if they express your knowledge of the problem.

After this modification to group the skill constraints, a minimal conflict is reported like this, with the skill constraints grouped inseparably:

Conflict :
Proved  : IloAnd and36 = {
c2( 2.1 <= ( x1 + x2 + 0.8 * x3 + 0.6 * x4 + 0.4 * x5 ) ) 
c3( 1.2 <= ( x6 + 0.9 * x7 + 0.5 * x8 ) ) 
c4( 0.8 <= ( x9 + 0.9 * x10 ) ) }

Proved  : c8( ( x2 + x3 + x4 + x5 )  <= 0)