Skip to content

Commit

Permalink
Improve multi stop plan unit generation
Browse files Browse the repository at this point in the history
  • Loading branch information
dirkschumacher committed May 10, 2024
1 parent 018a994 commit eb7497f
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 9 deletions.
46 changes: 41 additions & 5 deletions solution_sequence_generator.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ package nextroute
import (
"math/rand"
"slices"
"sync/atomic"
)

// SequenceGeneratorChannel generates all possible sequences of solution stops
Expand All @@ -31,10 +30,10 @@ func SequenceGeneratorChannel(
) chan SolutionStops {
planUnit := pu.(*solutionPlanStopsUnitImpl)
solution := planUnit.solution()
maxSequences := int64(solution.Model().SequenceSampleSize())
solutionStops := planUnit.SolutionStops()
ch := make(chan SolutionStops)
go func() {
maxSequences := int64(solution.Model().SequenceSampleSize())
defer close(ch)
switch planUnit.ModelPlanStopsUnit().NumberOfStops() {
case 1:
Expand Down Expand Up @@ -64,7 +63,7 @@ func SequenceGeneratorChannel(
select {
case <-quit:
return
case ch <- solutionStops:
case ch <- slices.Clone(solutionStops):
}
},
-1,
Expand All @@ -85,9 +84,13 @@ func sequenceGenerator(
yield func(SolutionStops),
directSuccessor int,
) {
if *maxSequences == 0 {
return
}
if len(sequence) == len(stops) {
if atomic.AddInt64(maxSequences, -1) >= 0 {
yield(slices.Clone(sequence))
*maxSequences = *maxSequences - 1

Check failure on line 91 in solution_sequence_generator.go

View workflow job for this annotation

GitHub Actions / go-lint

assignOp: replace `*maxSequences = *maxSequences - 1` with `*maxSequences--` (gocritic)
if *maxSequences >= 0 {
yield(sequence)
}
return
}
Expand Down Expand Up @@ -143,3 +146,36 @@ func sequenceGenerator(
}
}
}

func sequenceGeneratorSync(
pu SolutionPlanUnit,
yield func(SolutionStops),
) {
planUnit := pu.(*solutionPlanStopsUnitImpl)
solutionStops := planUnit.SolutionStops()
if planUnit.ModelPlanStopsUnit().NumberOfStops() == 1 {
yield(solutionStops)
return
}
solution := planUnit.solution()
maxSequences := int64(solution.Model().SequenceSampleSize())
used := make([]bool, len(solutionStops))
inDegree := make(map[int]int, len(solutionStops))
modelPlanUnit := planUnit.ModelPlanUnit().(*planMultipleStopsImpl)
dag := modelPlanUnit.dag.(*directedAcyclicGraphImpl)
for _, arc := range dag.arcs {
inDegree[arc.Destination().Index()]++
}

sequenceGenerator(
solutionStops,
make([]SolutionStop, 0, len(solutionStops)),
used,
inDegree,
dag,
solution.Random(),
&maxSequences,
yield,
-1,
)
}
6 changes: 2 additions & 4 deletions solution_vehicle.go
Original file line number Diff line number Diff line change
Expand Up @@ -385,12 +385,10 @@ func (v solutionVehicleImpl) bestMovePlanMultipleStops(
preAllocatedMoveContainer *PreAllocatedMoveContainer,
) SolutionMove {
var bestMove SolutionMove = newNotExecutableSolutionMoveStops(planUnit)
quitSequenceGenerator := make(chan struct{})
defer close(quitSequenceGenerator)
for sequence := range SequenceGeneratorChannel(planUnit, quitSequenceGenerator) {
sequenceGeneratorSync(planUnit, func(sequence SolutionStops) {
newMove := v.bestMoveSequence(ctx, planUnit, sequence, preAllocatedMoveContainer)
bestMove = takeBestInPlace(bestMove, newMove)
}
})
return bestMove
}

Expand Down

0 comments on commit eb7497f

Please sign in to comment.