We've introduced the SWAP* local search operator back in #507, an efficient extension of our previous Exchange more naive operator.
I've been doing some low-level profiling recently and found out that the time spent on SWAP* is unexpectedly high in many situations. After giving this more thoughts, I think we could move a lot of the computing to store additional stuff in SolutionState and enjoy much more data re-use upon operator evaluation.
To be a bit more specific, whenever we evaluate SWAP* for routes source and target, there is a (quadratic) pre-processing step applied to find top 3 insertions of all jobs from source into target and vice-versa top 3 insertions of all jobs from targert into source. Now if a different operator only touches target, then for sure the first part has to be re-computed, but the "jobs from target into source" part is still valid. The flaw is that we later recompute that across all source routes after modifying target, while we should only update the "other jobs into target" part.
We've introduced the SWAP* local search operator back in #507, an efficient extension of our previous
Exchangemore naive operator.I've been doing some low-level profiling recently and found out that the time spent on SWAP* is unexpectedly high in many situations. After giving this more thoughts, I think we could move a lot of the computing to store additional stuff in
SolutionStateand enjoy much more data re-use upon operator evaluation.To be a bit more specific, whenever we evaluate SWAP* for routes
sourceandtarget, there is a (quadratic) pre-processing step applied to find top 3 insertions of all jobs fromsourceintotargetand vice-versa top 3 insertions of all jobs fromtargertintosource. Now if a different operator only touchestarget, then for sure the first part has to be re-computed, but the "jobs fromtargetintosource" part is still valid. The flaw is that we later recompute that across all source routes after modifyingtarget, while we should only update the "other jobs intotarget" part.