IBM ILOG Scheduler User's Manual > Getting Started with Scheduler > Using the Trace Facilities > Define the Problem, Design a Model > Using filters

The modification of a traced object results in two trace events: one just before the modification and one just after the modification. The class IlcSchedulerPrintTrace is a trace object that, by default, prints information about all trace events. Printing all trace events, especially in a large application, may produce too much data to be easily analyzed. To help you cope with this, Scheduler Engine provides trace filters, functions with the following signature:

typedef IlcBool (*IlcSchedulerTraceFilter)(IlcBool isBeginEvent,
    IlcSchedulerChange schedChange, IlcSolverChange solverChange);

Writing a function of type IlcSchedulerTraceFilter allows you to customize the trace information that is printed. After you attach the function to the print trace object (using setFilter), the function will be called for each trace event.

The following list describes the parameters of an IlcSchedulerTraceFilter function.

  1. isBeginEvent: This argument will have the value IlcTrue if the function is called just before the modification of an object. When called just after the modification of an object, the value is IlcFalse.
  2. schedChange: This argument specifies the type of Scheduler Engine object that is about to be (or just was) changed. For example, the values of the IlcSchedulerChange enum IlcActivityStart, IlcPrecedenceConstraintDelay, and IlcResourceConstraintCapacity correspond to events which modify, respectively, the start variable of an activity, the delay variable of a precedence constraint, and the capacity variable of a resource constraint.
  3. solverChange: This argument, when it is applicable, specifies the type of Solver variable that is modifed and what the modification is. For example, the values of the IlcSolverChange enum IlcIntExpSetMin and IlcIntSetVarRemovePossible, correspond to events which, respectively, increase the minimum value of an integer variable and remove an element from a set variable.

Each time a trace event occurs (that is, just before and just after the modification of a traced object), this function will be called with the information corresponding to the event as argument. The event will be displayed if and only if the function returns IlcTrue.

The member functions IlcSchedulerPrintTrace::setFilter and IlcSchedulerPrintTrace::resetFilter allow you to define or reset such a filter function. If there is no filter definition (the default), all the events will be displayed.

For our example, with traceLevel equal to 1 or 2, we only want to print before the modification. If this event concerns an activity, we only want to print modifications that increase the minimum of the start variable or assign that variable. Here is the code of the filter function that does this.

IlcBool MyPrintTraceFilter(IlcBool isBeginEvent,
                           IlcSchedulerChange change, 
                           IlcSolverChange solverChange) {
  // We are only interested in events that occur just
  // before a modification
  if (!isBeginEvent) {
    return IlcFalse;
  }
  switch (change) {
    // If the start variable of an activity is modified,
    // we only care if it becomes bound, or its min is
    // modified. 
    //I.e. we do not care about the Latest Start Time
    case IlcActivityStart:
      return ((solverChange == IlcIntExpSetMin) ||
              (solverChange == IlcIntExpSetValue));
    // All other modifications of activities are skipped
    case IlcActivityEnd:
    case IlcActivityProcessingTime:
    case IlcActivityDuration:
    case IlcActivityDurationOfBreaks:
    case IlcActivityStartOverlap:
    case IlcActivityEndOverlap:
      return IlcFalse;
    // Other events are traced
    default:
      return IlcTrue;
  }
}
 

Having defined this function, we simply have to call IlcSchedulerPrintTrace::setFilter with the address of the function as parameter.

    // Setting a filter to get only some specified events
    trace.setFilter(MyPrintTraceFilter);

The following code then defines the goal to set the trace.

ILCGOAL1(SetTraceIlc, IlcInt, traceLevel) {
  IloSolver solver = getSolver();
  IlcScheduler scheduler(solver);
  IlcSchedulerPrintTrace trace(scheduler);
  solver.setTraceMode(IlcTrue);
  if (traceLevel == 0) {
    // Trace only some specific activities
    for (IlcActivityIterator it(scheduler); it.ok(); ++it) {
      IlcActivity act = *it;
      if (act.getObject() == (IloAny)1) {
        trace.trace(act);
      }
    }
  } else if (traceLevel == 1) {
    // We trace only the activities that require a specific resource
    for (IlcResourceIterator it(scheduler); it.ok(); ++it) {
      IlcResource res = *it;
      if (res.getObject() == (IloAny)1) {
        trace.trace(res);
      }
    }
  } else {
    // Tracing all activities in the problem
    trace.traceAllActivities();
  }
  if (traceLevel > 0) {
    // Setting a filter to get only some specified events
    trace.setFilter(MyPrintTraceFilter);
  }
  return 0;
}
 
ILOCPGOALWRAPPER1(SetTrace, solver, IloInt, traceLevel) {
  return SetTraceIlc(solver, traceLevel);
}