Testing your installation with a scheduling problem
Before proceeding with the other tutorials in the Getting Started with CP Optimizer manual, you should test your environment by compiling and running a simple application. The log produced by the application provides useful information about the model and the solution search.
In this lesson, you are provided with a completed example code so that you can test your installation of CP Optimizer. In Using expressions on interval variables: house building with earliness and tardiness costs, you will learn about the classes and member functions used in this program.
The problem is a house building problem in which there are ten tasks of fixed size, each of which needs to be assigned a starting time. Using the C++ API, the code for creating the environment, model and interval variables that represent the tasks is:
#include <ilcp/cp.h>
int main(int argc, const char * argv[]) {
IloEnv env;
try {
IloModel model(env);
/* CREATE THE TIME-INTERVALS. */
IloIntervalVar masonry (env, 35, "masonry ");
IloIntervalVar carpentry(env, 15, "carpentry ");
IloIntervalVar plumbing (env, 40, "plumbing ");
IloIntervalVar ceiling (env, 15, "ceiling ");
IloIntervalVar roofing (env, 5, "roofing ");
IloIntervalVar painting (env, 10, "painting ");
IloIntervalVar windows (env, 5, "windows ");
IloIntervalVar facade (env, 10, "facade ");
IloIntervalVar garden (env, 5, "garden ");
IloIntervalVar moving (env, 5, "moving ");
The constraints in this problem are precedence constraints; some tasks cannot start until other tasks have ended. For example, the ceilings must be completed before painting can begin. The set of precedence constraints for this problem can be added to the model with the code:
model.add(IloEndBeforeStart(env, masonry, carpentry));
model.add(IloEndBeforeStart(env, masonry, plumbing));
model.add(IloEndBeforeStart(env, masonry, ceiling));
model.add(IloEndBeforeStart(env, carpentry, roofing));
model.add(IloEndBeforeStart(env, ceiling, painting));
model.add(IloEndBeforeStart(env, roofing, windows));
model.add(IloEndBeforeStart(env, roofing, facade));
model.add(IloEndBeforeStart(env, plumbing, facade));
model.add(IloEndBeforeStart(env, roofing, garden));
model.add(IloEndBeforeStart(env, plumbing, garden));
model.add(IloEndBeforeStart(env, windows, moving));
model.add(IloEndBeforeStart(env, facade, moving));
model.add(IloEndBeforeStart(env, garden, moving));
model.add(IloEndBeforeStart(env, painting, moving));
Here there is a special constraint, IloEndBeforeStart,
which ensures that one interval variable ends before the other starts.
This constraint is handled specially by the engine. One reason is
to correctly treat the presence of intervals so that if one of the
interval variables is not present, the constraint is automatically
satisfied, and another reason is for stronger inference in constraint
propagation.
The interval variables and precedence constraints completely describe
this simple problem. An optimizer object (an instance of the class IloCP)
is used to find a solution to the model, assigning values to the start
and end of each of the interval variables in the model. The last part
of the code for this example is:
IloCP cp(model);
if (cp.solve()) {
cp.out() << cp.domain(masonry) << std::endl;
cp.out() << cp.domain(carpentry) << std::endl;
cp.out() << cp.domain(plumbing) << std::endl;
cp.out() << cp.domain(ceiling) << std::endl;
cp.out() << cp.domain(roofing) << std::endl;
cp.out() << cp.domain(painting) << std::endl;
cp.out() << cp.domain(windows) << std::endl;
cp.out() << cp.domain(facade) << std::endl;
cp.out() << cp.domain(garden) << std::endl;
cp.out() << cp.domain(moving) << std::endl;
} else {
cp.out() << "No solution found. " << std::endl;
}
cp.printInformation();
} catch (IloException& ex) {
env.out() << "Error: " << ex << std::endl;
}
env.end();
return 0;
}
Open the example file <Install_dir>/cpoptimizer/examples/src/cpp/sched_intro.cpp in
your development environment. To test your installation of CP Optimizer,
build and run the program. When you run the program, you should get
results similar to this search log output:
! ----------------------------------------------------------------------------
! Satisfiability problem - 10 variables, 14 constraints
! Initial process time : 0.00s (0.00s extraction + 0.00s propagation)
! . Log search space : 33.2 (before), 33.2 (after)
! . Memory usage : 304.7 kB (before), 304.7 kB (after)
! Using parallel search with 8 workers.
! ----------------------------------------------------------------------------
! Branches Non-fixed W Branch decision
* 11 0.00s 1 -
! ----------------------------------------------------------------------------
! Search completed, 1 solution found.
! Number of branches : 11
! Number of fails : 0
! Total memory usage : 780.6 kB (735.1 kB CP Optimizer + 45.5 kB Concert)
! Time spent in solve : 0.00s (0.00s engine + 0.00s extraction)
! Search speed (br. / s) : 1100.0
! ----------------------------------------------------------------------------
masonry [1: 0 -- 35 --> 35]
carpentry [1: 35 -- 15 --> 50]
plumbing [1: 35 -- 40 --> 75]
ceiling [1: 35 -- 15 --> 50]
roofing [1: 50 -- 5 --> 55]
painting [1: 50 -- 10 --> 60]
windows [1: 55 -- 5 --> 60]
facade [1: 75 -- 10 --> 85]
garden [1: 75 -- 5 --> 80]
moving [1: 85 -- 5 --> 90]
To understand the solution found by CP Optimizer to this satisfiability scheduling problem, consider the line:
masonry [1: 0 -- 35 --> 35]
The interval variable representing the masonry task, which has size 35, has been assigned the interval [0,35). Masonry starts at time 0 and ends at the time point 35.
Displaying interval variables
After a time
interval has been assigned a start value (say s)
and an end value (say e), the interval is written
as [s,e). The time interval does not include the
endpoint e. If another interval variable is constrained
to be placed after this interval, it can start at the time e.
In subsequent lessons in this manual, the log output is not included in the sections which report the results. You can view the log information when you build and run the completed programs.