Proposal:
Jsprit now contains only three priorities which is now an integer. My proposal is
(1) change priority to enum (cleaner, java-like): LOW, NORMAL, HIGH
(2) add two additional types of priorities: IMPORTANT, MANDATORY.
Leaving out jobs with IMPORTANT and MANDATORY priorities from the solution should have an enourmous cost impact: HIGH now has a cost 4 times the higher travel cost, the new ones should have 1000 times or more.
What jobs with these new priorities should be unique is that the initial solution builder should try hard to add these to the initial solution. The difference could be that IMPORTANT may be left out when it can’t be (easily) added to the initial solution, while MANDATORY could throw exception.
Therefore, MANDATORY is best if these jobs has non-overlapping time windows, while the IMPORTANT is more flexible.
Why are these new priorities needed?
In real life, there could be jobs, which simply can’t be left out. At first, the cost impact looks enough to solve the problem, but I experienced in real life projects, that with high number of overlapping Jobs, it is not guaranteed that these tasks will ever be choosen into the solution – not even when I’ve increased the iteration number to an insane 100.000.
As an example, I had 3 vehicles, about 1000 jobs, 6 of them with HIGH priority (mandatory). I changed the multiplier for HIGH from 4 to 1000000 (yes, one million). I had several runs (with different random seeds). There was one solution with all jobs assigned and a total cost of 30k, proving that the problem had a solution. But all the other runs provided solutions with one or two of these HIGH jobs left out, regardless of the cost being above hundred millions. Later I realized the reason: these mandatory Jobs had a relatively short timewindow with a long activity time (10-20 times more) compared to the regular jobs. Therefore, if the initial solution didn’t contain the job, it was impossible to mutate to have them (too many other jobs would have to be thrown out “under the HIGH job” – an extremely low probability).
Compatibility impact
(1) Switching to enum may cause some incompability. The builders could be modified by duplicating the setter method to support both inputs. The getter is the problematic. If you want to keep backward compability above all: there have to be two getters (@Deprecated int getPriority()
and Priority getPriorityValue()
),
(2) It is an extension, so it has no impact.