Let’s go through Stackoverflow_RelatedJobs_13_and_21_inSameRoute_13_immediatelyAfter_21:
What do we want to achieve here?
We want services 13 and 21 are in the same route and service 13 is immediately after service 21.
Ok let’s use a constraint to achieve it.
Hard constraint vs. soft constraint?
A question we need to ask ourselves here is what we would like to do if what we want to achieve contradicts other existing hard constraints? For example, what if time windows of the jobs determine that service 13 cannot be after service 21, or what if skills of routes and jobs determine that services 13 and 21 cannot be in the same route? If we are fine that service 13 is not immediately after service 21 or they are not in the same route in such cases, then we’d use a soft constraint; if we would rather one of the two jobs gets unassigned than to compromise in such cases, then we’d use a hard constraint.
Route constraint vs. activity constraint?
We are trying to manipulate the position of activities in a route (service 13 is immediately after service 21), so we’d use an activity constraint.
Thus let’s go ahead with a soft activity constraint.
Note that what the soft constraint does is that it guides the insertion of individual activity, penalizing or rewarding certain insertions, in the hope of generating “good” solutions. In the meantime, we need a custom objective function which is in line with the soft constraint. What the objective function does is that it selects the solution we want from the generated solutions. If the soft constraint and the objective function are not coordinated, then we might end up with a sub-optimal solution.
Now let’s look at the soft activity constraint in the example, and what it does is that:
- if the activity we are trying to insert (newAct) is service 13, then we reward the insertion if the previous activity is service 21, or we penalize the insertion otherwise;
- if the next activity is service 13, then we reward the insertion if the new activity is service 21, or we penalize the insertion otherwise.
And what about the objective function? It goes like this: besides the usual cost calculations,
- it rewards a route if services 13 and 21 are both in it and if service 21 is immediately after service 13;
- it penalizes a route if services 13 and 21 are both in it but the activity before service 21 is not service 13;
- it penalizes a route if only one of service 13 and 21 is in it.
We can see that the soft activity constraint and the objective function are not coordinated - in fact, they are opposite to each other! Then why do we still get a solution doing what we want? It probably is that the soft constraint is good enough that all the generated solutions achieve what we want. But in general, we would like that the soft constraint and the objective function are coordinated.
Hopefully this helps.