-
Notifications
You must be signed in to change notification settings - Fork 7
Expand file tree
/
Copy pathmodel_objective_distance.go
More file actions
93 lines (77 loc) · 2.69 KB
/
Copy pathmodel_objective_distance.go
File metadata and controls
93 lines (77 loc) · 2.69 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
// © 2019-present nextmv.io inc
package nextroute
// DistanceObjective minimizes total traveled distance.
type DistanceObjective interface {
ModelObjective
}
// NewDistanceObjective returns a new DistanceObjective.
func NewDistanceObjective() DistanceObjective {
return &distanceObjectiveImpl{}
}
type distanceObjectiveImpl struct{}
// distanceObjectiveVehicleData keeps track of the cumulative distance traveled
// by a vehicle.
type distanceObjectiveVehicleData struct {
cumulativeDistance float64
}
func (d *distanceObjectiveImpl) UpdateObjectiveVehicleData(s SolutionVehicle) (Copier, error) {
distance := 0.0
vehicleType := s.ModelVehicle().(*modelVehicleImpl).vehicleType
distanceExpr := vehicleType.(*vehicleTypeImpl).distance
var previousStop ModelStop
s.iterateStops(func(stop SolutionStop) bool {
modelStop := stop.ModelStop()
if previousStop != nil {
distance += distanceExpr.Value(vehicleType, previousStop, modelStop)
}
previousStop = modelStop
return true
})
return &distanceObjectiveVehicleData{
cumulativeDistance: distance,
}, nil
}
func (d *distanceObjectiveVehicleData) Copy() Copier {
return &distanceObjectiveVehicleData{
cumulativeDistance: d.cumulativeDistance,
}
}
func (d *distanceObjectiveImpl) EstimateDeltaValue(move SolutionMoveStops) float64 {
impl := move.(*solutionMoveStopsImpl)
vehicle := impl.vehicle()
vehicleType := vehicle.ModelVehicle().VehicleType()
distanceExpr := vehicleType.DistanceExpression()
delta := 0.0
for _, pos := range impl.stopPositions {
modelStop := pos.Stop().ModelStop()
previous := pos.Previous()
// We always add the distance from the previous stop to this one
// (independent of whether the previous stop is planned or not).
delta += distanceExpr.Value(vehicleType, previous.ModelStop(), modelStop)
// If the previous stop is planned, remove the distance from it to its
// original successor. The connection has been replaced by going through
// the new stop instead.
if previous.IsPlanned() {
delta -= distanceExpr.Value(vehicleType, previous.ModelStop(), previous.Next().ModelStop())
}
// If the next stop is planned we need to add the distance from the new
// stop to it too to complete the triangle of the new connection.
successor := pos.Next()
if successor.IsPlanned() {
delta += distanceExpr.Value(vehicleType, modelStop, successor.ModelStop())
}
}
return delta
}
func (d *distanceObjectiveImpl) Value(solution Solution) float64 {
s := solution.(*solutionImpl)
total := 0.0
for _, v := range s.vehicles {
data := v.ObjectiveData(d).(*distanceObjectiveVehicleData)
total += data.cumulativeDistance
}
return total
}
func (d *distanceObjectiveImpl) String() string {
return "distance"
}