IBM ILOG Solver User's Manual > Developing Solver Applications > Debugging and Tracing > Tracing variable processing

As Solver propagates constraints, it maintains them in a queue. Tracing the propagation queue shows the order in which variables are processed by the Solver propagation algorithm. In the following example, we create a trace to trace the constraint propagation queue using the ILOCPTRACEWRAPPER0 macro, like this:

ILOCPTRACEWRAPPER0(PrintAllVars, solver) {

Then we turn on the trace mode, like this:

  solver.setTraceMode(IlcTrue);

Next, use IlcTraceVars as a flag to the constructor IlcPrintTrace. It causes a message to be printed each time a demon or constraint is executed by the propagation algorithm:

  IlcPrintTrace trace(solver, IlcTraceVars);

Then we set that hook as the global trace hook by using the member function IloSolver::setTrace, like this:

  solver.setTrace(trace);

Here are those steps in the context of a complete program.

ILOCPTRACEWRAPPER0(PrintAllVars, solver) {
  solver.setTraceMode(IlcTrue);
  IlcPrintTrace trace(solver, IlcTraceVars);
  solver.setTrace(trace);
}

int TraceAll2(){
  IloEnv env;
  try {
    IloModel mdl(env);
    IloNumVar S(env, 0, 9, ILOINT, "S"),
      E(env, 0, 9, ILOINT, "E"),
      N(env, 0, 9, ILOINT, "N"),
      D(env, 0, 9, ILOINT, "D"),
      M(env, 0, 9, ILOINT, "M"),
      O(env, 0, 9, ILOINT, "O"),
      R(env, 0, 9, ILOINT, "R"),
      Y(env, 0, 9, ILOINT, "Y");
    IloNumVarArray vars (env, 8, S, E, N, D, M, O, R, Y);

    mdl.add(S != 0);
    mdl.add(M != 0);

    IloConstraint alldiff=IloAllDiff(env,vars);
    mdl.add(alldiff);
    mdl.add(  1000*S + 100*E + 10*N + D
      + 1000*M + 100*O + 10*R + E
      == 10000*M + 1000*O + 100*N + 10*E + Y);

    IloSolver solver(mdl);
    solver.addTrace(PrintAllVars(env));
    solver.solve(IloGenerate(env, vars));
  }
  catch (IloException ex) {
    cerr << "Error: " << ex << endl;
  }
  env.end();
  return 0;
}


That program output is:

 
>> begin-set-min: S[0..9] 1
>> end-set-min: S[1..9] 1
>> begin-set-min: M[0..9] 1
>> end-set-min: M[1..9] 1
>> begin-set-min: S[1..9] 9
>> end-set-min: S[9] 9
>> begin-set-max: M[1..9] 1
>> end-set-max: M[1] 1
>> begin-set-max: O[0..9] 1
>> end-set-max: O[0..1] 1
>> begin-set-max: E[0..9] 8
>> end-set-max: E[0..8] 8
>> begin-set-max: N[0..9] 8
>> end-set-max: N[0..8] 8
>> begin-set-max: D[0..9] 8
>> end-set-max: D[0..8] 8
>> begin-set-max: R[0..9] 8
>> end-set-max: R[0..8] 8
>> begin-set-max: Y[0..9] 8
>> end-set-max: Y[0..8] 8
>> begin-set-max: O[0..1] 0
>> end-set-max: O[0] 0
>> begin-remove-value: E[0..8] 1
>> end-remove-value: E[0 2..8] 1
>> begin-remove-value: N[0..8] 1
>> end-remove-value: N[0 2..8] 1
>> begin-remove-value: D[0..8] 1
>> end-remove-value: D[0 2..8] 1
>> begin-remove-value: R[0..8] 1
>> end-remove-value: R[0 2..8] 1
>> begin-remove-value: Y[0..8] 1
>> end-remove-value: Y[0 2..8] 1
>> begin-set-min: N[0 2..8] 2
>> end-set-min: N[2..8] 2
>> begin-set-min: D[0 2..8] 2
>> end-set-min: D[2..8] 2
>> begin-set-min: E[0 2..8] 2
>> end-set-min: E[2..8] 2
>> begin-set-min: R[0 2..8] 2
>> end-set-min: R[2..8] 2
>> begin-set-min: Y[0 2..8] 2
>> end-set-min: Y[2..8] 2
>> begin-set-min: N[2..8] 3
>> end-set-min: N[3..8] 3
>> begin-set-max: E[2..8] 7
>> end-set-max: E[2..7] 7
>> begin-set-min: E[2..7] 3
>> end-set-min: E[3..7] 3
>> begin-set-min: N[3..8] 4
>> end-set-min: N[4..8] 4
>> begin-set-min: E[3..7] 4
>> end-set-min: E[4..7] 4
>> begin-set-min: N[4..8] 5
>> end-set-min: N[5..8] 5
IlcOr   : 1
>> begin-set-value: E[4..7] 4
>> end-set-value: E[4] 4
>> begin-remove-value: D[2..8] 4
>> end-remove-value: D[2..3 5..8] 4
>> begin-remove-value: R[2..8] 4
>> end-remove-value: R[2..3 5..8] 4
>> begin-remove-value: Y[2..8] 4
>> end-remove-value: Y[2..3 5..8] 4
>> begin-set-min: D[2..3 5..8] 8
>> end-set-min: D[8] 8
>> begin-set-min: R[2..3 5..8] 8
>> end-set-min: R[8] 8
>> begin-set-max: N[5..8] 5
>> end-set-max: N[5] 5
>> begin-set-max: Y[2..3 5..8] 2
>> end-set-max: Y[2] 2
>> begin-set-min: E[4..7] 5
>> end-set-min: E[5..7] 5
>> begin-set-min: N[5..8] 6
>> end-set-min: N[6..8] 6
IlcOr   : 2
>> begin-set-value: E[5..7] 5
>> end-set-value: E[5] 5
>> begin-remove-value: D[2..8] 5
>> end-remove-value: D[2..4 6..8] 5
>> begin-remove-value: R[2..8] 5
>> end-remove-value: R[2..4 6..8] 5
>> begin-remove-value: Y[2..8] 5
>> end-remove-value: Y[2..4 6..8] 5
>> begin-set-min: D[2..4 6..8] 7
>> end-set-min: D[7..8] 7
>> begin-set-min: R[2..4 6..8] 8
>> end-set-min: R[8] 8
>> begin-set-max: N[6..8] 6
>> end-set-max: N[6] 6
>> begin-set-max: Y[2..4 6..8] 3
>> end-set-max: Y[2..3] 3
>> begin-set-max: D[7..8] 7
>> end-set-max: D[7] 7
>> begin-set-max: Y[2..3] 2
>> end-set-max: Y[2] 2
 

The choice points and the failures are now visible.

In the following example, we associate the trace only with a single variable, E.


ILOCPTRACEWRAPPER1(TraceVarArray, solver, IloIntVarArray, vars) {
  IlcIntVarArray svars=solver.getIntVarArray(vars);
  solver.setTraceMode(IlcTrue);
  IlcPrintTrace trace(solver, IlcTraceVars);
  trace.trace(svars[1]);
}


int TraceAll3(){
  IloEnv env;
  try {
    IloModel mdl(env);
    IloIntVar S(env, 0, 9, "S"),
      E(env, 0, 9, "E"),
      N(env, 0, 9, "N"),
      D(env, 0, 9, "D"),
      M(env, 0, 9, "M"),
      O(env, 0, 9, "O"),
      R(env, 0, 9, "R"),
      Y(env, 0, 9, "Y");
    IloIntVarArray vars (env, 8, S, E, N, D, M, O, R, Y);

    mdl.add(S != 0);
    mdl.add(M != 0);

    IloConstraint alldiff=IloAllDiff(env,vars);
    mdl.add(alldiff);
    mdl.add(  1000*S + 100*E + 10*N + D
      + 1000*M + 100*O + 10*R + E
      == 10000*M + 1000*O + 100*N + 10*E + Y);

    IloSolver solver(mdl);
    solver.addTrace(TraceVarArray(env, vars));
    solver.solve(IloGenerate(env, vars));
  }
  catch (IloException ex) {
    cerr << "Error: " << ex << endl;
  }
  env.end();
  return 0;
}



The output becomes:

>> begin-set-max: E[0..9] 8
>> end-set-max: E[0..8] 8
>> begin-remove-value: E[0..8] 1
>> end-remove-value: E[0 2..8] 1
>> begin-set-min: E[0 2..8] 2
>> end-set-min: E[2..8] 2
>> begin-set-max: E[2..8] 7
>> end-set-max: E[2..7] 7
>> begin-set-min: E[2..7] 3
>> end-set-min: E[3..7] 3
>> begin-set-min: E[3..7] 4
>> end-set-min: E[4..7] 4
IlcOr   : 1
>> begin-set-value: E[4..7] 4
>> end-set-value: E[4] 4
IlcFail : 1
>> begin-set-min: E[4..7] 5
>> end-set-min: E[5..7] 5
IlcOr   : 2
>> begin-set-value: E[5..7] 5
>> end-set-value: E[5] 5
 

The following program traces all modifications of all variables. To get that effect, we turn on the trace mode and use the flag IlcTraceAll when we construct the trace.

ILOCPTRACEWRAPPER0(PrintAllTrace, solver) {
  solver.setTraceMode(IlcTrue);
  IlcPrintTrace trace(solver, IlcTraceAll);
  solver.setTrace(trace);
}
 
int TraceAll4(){
  IloEnv env;
  try {
    IloModel mdl(env);
    IloIntVar S(env, 0, 9, "S"),
      E(env, 0, 9, "E"),
      N(env, 0, 9, "N"),
      D(env, 0, 9, "D"),
      M(env, 0, 9, "M"),
      O(env, 0, 9, "O"),
      R(env, 0, 9, "R"),
      Y(env, 0, 9, "Y");
    IloIntVarArray vars (env, 8, S, E, N, D, M, O, R, Y);
 
    mdl.add(S != 0);
    mdl.add(M != 0);
 
    IloConstraint alldiff=IloAllDiff(env,vars);
    mdl.add(alldiff);
    mdl.add(  1000*S + 100*E + 10*N + D
      + 1000*M + 100*O + 10*R + E
      == 10000*M + 1000*O + 100*N + 10*E + Y);
 
    IloSolver solver(mdl);
    solver.addTrace(PrintAllTrace(env));
    solver.solve(IloGenerate(env, vars));
  }
  catch (IloException ex) {
    cerr << "Error: " << ex << endl;
  }
  env.end();
  return 0;
}
 
 

The output is too lengthy to show entirely, but it starts like this:

>> begin-constraint-propagate ((S[0..9] != 0))
>> begin-set-min: S[0..9] 1
>> end-set-min: S[1..9] 1
>> end-constraint-propagate ((S[1..9] != 0))
>> begin-constraint-propagate ((M[0..9] != 0))
>> begin-set-min: M[0..9] 1
>> end-set-min: M[1..9] 1
>> end-constraint-propagate ((M[1..9] != 0))
>> begin-constraint-post (IlcAllDiff(00ACED48) {S[1..9], E[0..9], N[0..9],
D[0..
9], M[1..9], O[0..9], R[0..9], Y[0..9], })
>> end-constraint-post (IlcAllDiff(00ACED48) {S[1..9], E[0..9], N[0..9],
D[0..9]
, M[1..9], O[0..9], R[0..9], Y[0..9], })
>> begin-constraint-propagate (IlcAllDiff(00ACED48) {S[1..9], E[0..9],
N[0..9],
D[0..9], M[1..9], O[0..9], R[0..9], Y[0..9], })
>> end-constraint-propagate (IlcAllDiff(00ACED48) {S[1..9], E[0..9],
N[0..9], D[
0..9], M[1..9], O[0..9], R[0..9], Y[0..9], })
>> begin-constraint-post ((IlcArraySumI(00ACF070)[1000..9099] ==
(IlcArraySumI(0
0ACEF38)[9000..89919] - 91 * E[0..9])))
>> end-constraint-post ((IlcArraySumI(00ACF070)[1000..9099] ==
(IlcArraySumI(00A
CEF38)[9000..89919] - 91 * E[0..9])))
>> begin-constraint-propagate ((IlcArraySumI(00ACF070)[1000..9099] ==
(IlcArrayS
umI(00ACEF38)[9000..89919] - 91 * E[0..9])))
>> begin-set-min: S[1..9] 9
>> end-set-min: S[9] 9
>> begin-set-max: M[1..9] 1
>> end-set-max: M[1] 1
>> begin-set-max: O[0..9] 1
>> end-set-max: O[0..1] 1
>> end-constraint-propagate ((IlcArraySumI(00ACF070)[9000..9099] ==
(IlcArraySum
I(00ACEF38)[9000..10719] - 91 * E[0..9])))
>> begin-var-process: S[9]
>> begin-demon-process (IlcAllDiffDemon)
>> begin-set-max: E[0..9] 8
>> end-set-max: E[0..8] 8
>> begin-set-max: N[0..9] 8
>> end-set-max: N[0..8] 8
>> begin-set-max: D[0..9] 8
>> end-set-max: D[0..8] 8
>> begin-set-max: R[0..9] 8
>> end-set-max: R[0..8] 8
>> begin-set-max: Y[0..9] 8
>> end-set-max: Y[0..8] 8
>> end-demon-process (IlcAllDiffDemon)
>> begin-demon-process ((IlcArraySumI(00ACF070)[9000..9088] ==
(IlcArraySumI(00
ACEF38)[9000..10628] - 91 * E[0..8])))
>> begin-set-max: O[0..1] 0
>> end-set-max: O[0] 0
>> end-demon-process ((IlcArraySumI(00ACF070)[9000..9088] ==
...
 

The examples in this chapter show you some possibilities of the tracing mode in Solver. You should choose the level of detail most useful for your application: the more detail, the longer the output, and the longer its analysis, of course.