IBM ILOG Dispatcher User's Manual > Field Service Solutions > Dispatching Technicians II > Model |
Model |
INDEX
![]() |
Once you have written a description of your problem, you can use Dispatcher classes to model it.
Step 2 - | Open the example file |
Open the example file YourDispatcherHome/examples/src/tutorial/technic1_partial.cpp
in your development environment.
This program starts with a class that models both skill requirements for jobs and skills provided by technicians.
Step 3 - | Declare the SkillProfile class |
Add the following code after the comment //Declare the SkillProfile class.
The SkillProfile
class maps a level
for each technician skill. The function SkillProfile::isGreaterThanOrEqual
follows, and is used to ensure that the skill level meets the constraint of the job profile.
Step 4 - | Declare the RoutingModel class |
Add the following code after the comment //Declare the RoutingModel class
.
The only dimension defined in createDimensions
is time
, and createIloNodes
is similar to previous lessons. createTechnicians
is similar to the same function in Chapter 13, Dispatching Technicians. The other functions in RoutingModel
are new, and these are associated with the technician skills, levels, and visit requirements.
The following is the first section of RoutingModel
and is provided for you:
Step 5 - | Create the getSkillProfile function |
Add the following code after the comment //Create the getSkillProfile function
.
Skill profiles, both for jobs and technicians, are stored in an array and identified by a unique ID. Retrieving the profile from its ID is performed by a lazy accessor technique. Missing array slots are filled with zeros; then, if a returned profile is null, a new profile is created, stored, and returned.
The final section of RoutingModel
follows:
public: RoutingModel(IloEnv env); ~RoutingModel() {} void parse(int argc, char** argv); void createModel(); IloEnv getEnv() const { return _env; } IloModel getModel() const { return _mdl; } }; |
Step 6 - | Create the parse function |
//Create the parse function.
_visitPath
accesses the data for the visit: the time window during which the visit can occur, and the service time. The technicians are identified through _technicianPath
. _visitProfilePath
accesses the map of visits to the visit skill profile IDs. _techProfilePath
accesses the map of technicians to the technician skill profile IDs, and _profilePath
accesses the technician skill ability levels and the skill ability levels required at the customer visits.
Step 7 - | Add the vehicle/technician |
Add the following code after the comment //Add the vehicle/technician
.
IloVehicle technician(first, last, name); technician.setCost(time, 1.0); technician.setKey(name); _mdl.add(technician); |
This code is a section of createTechnicians
, and adds the vehicle/technician with the sole cost factor of time
. The first section of the function follows.
Step 8 - | Add the PenaltyCost |
Add the following code after the comment //Add the PenaltyCost
.
_mdl.add( visit.getDelayVar(time) == serviceTime ); _mdl.add( minTime <= visit.getCumulVar(time) <= maxTime); visit.setPenaltyCost(10000); visit.setKey(visitName); _mdl.add(visit); |
minTime
and maxTime
are the time windows for a paticular visit. The member function IloVisit::setPenaltyCost
is used to set the cost of not performing a visit. By default, the penalty cost is IloInfinity
, which means that visits must be performed in a solution if a value is not set with this member function.
The following code is the first section of createVisits
.
Step 9 - | Define the createSkillProfiles function |
Add the following code after the comment //Define the createSkillProfiles function
.
This function reads the csv file and creates the skill profiles of the technicians and visits; the levels of each skill that are available from the technician or required at the customer visit.
Step 10 - | Define the setTechnicianSkillProfiles function |
Add the following code after the comment //Define the setTechnicianSkillProfiles function
.
This function implements the mapping between the technician and the skill profile. The profile itself is stored in the object field of the IloVehicle
(for technicians) or IloVisit
(for visits), as an IloAny void*
pointer. Attaching profiles to a vehicle/visit is crucial to the implementation of the compatibility constraint, which takes one vehicle and one visit.
Step 11 - | Define the setVisitSkillProfiles function |
Add the following code after the comment //Define the setVisitSkillProfiles function
.
This function identifies the visitProfileId
required at each customer visit.
Step 12 - | Define the AreSkillsCompatible predicate |
Add the following code after the comment //Define the AreSkillsCompatible predicate
.
This predicate checks the compatibility relation between a visit and a technician. A visit is compatible with a technician if the visit profile is subsumed by the technician profile. A special case is also considered for a visit with no profile where all technicians are compatible.
Step 13 - | Define the postCompatibility function |
Add the following code after the comment //Define the postCompatibility function
.
void RoutingModel::postCompatibility() { IloVisitVehicleCompat compat(_env, AreSkillsCompatible); _mdl.add( IloCompatible(compat, "skill compatibility")); } |
IBM ILOG Dispatcher provides a way for you to define compatibility relations between visits and vehicles. These relations can then be used to build compatibility constraints. In this example the constructor IloVisitVehicleCompat
uses the predicate AreSkillsCompatible
to build the compatibility relation. The function IloCompatible
is then used to create the compatibility constraint to ensure that only compatible vehicles are used on a visit.
The compatibility constraint is used to check that only compatible visit/vehicle assignments are built, by removing incompatible vehicles. A predicate is used for convenience; you can also subclass a predefined class for more complex cases.
© Copyright IBM Corp. 1987, 2009. Legal terms. | PREVIOUS NEXT |