-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathmodel_constraint_successors.go
101 lines (88 loc) · 2.83 KB
/
model_constraint_successors.go
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
94
95
96
97
98
99
100
101
// © 2019-present nextmv.io inc
package nextroute
import "fmt"
// SuccessorConstraint is a constraint that disallows certain stops to be
// planned after other stops.
type SuccessorConstraint interface {
ModelConstraint
DisallowSuccessors(ModelStop, ModelStops) error
}
// NewSuccessorConstraint returns a new SuccessorConstraint.
func NewSuccessorConstraint() (SuccessorConstraint, error) {
return &successorConstraintImpl{
modelConstraintImpl: newModelConstraintImpl(
"successor",
ModelExpressions{},
),
disallowedSuccessors: make(map[ModelStop]ModelStops),
}, nil
}
type successorConstraintImpl struct {
modelConstraintImpl
disallowedSuccessors map[ModelStop]ModelStops
}
func (l *successorConstraintImpl) Lock(model Model) error {
modelImpl := model.(*modelImpl)
// initialize disallowedSuccessors
modelImpl.disallowedSuccessors = make([][]bool, modelImpl.NumberOfStops())
for i := range modelImpl.disallowedSuccessors {
modelImpl.disallowedSuccessors[i] = make([]bool, modelImpl.NumberOfStops())
}
// copy the information from disallowedSuccessors to the model
for stop, successors := range l.disallowedSuccessors {
for _, successor := range successors {
modelImpl.disallowedSuccessors[stop.Index()][successor.Index()] = true
}
}
return nil
}
func (l *successorConstraintImpl) DisallowSuccessors(
stop ModelStop,
successors ModelStops,
) error {
if stop == nil {
return fmt.Errorf("stop cannot be nil")
}
if stop.Model().IsLocked() {
return fmt.Errorf(lockErrorMessage, "disallow successors")
}
if successors == nil {
return fmt.Errorf("successors cannot be nil")
}
if _, ok := l.disallowedSuccessors[stop]; !ok {
l.disallowedSuccessors[stop] = ModelStops{}
}
l.disallowedSuccessors[stop] = append(l.disallowedSuccessors[stop], successors...)
return nil
}
func (l *successorConstraintImpl) String() string {
return l.name
}
func (l *successorConstraintImpl) EstimationCost() Cost {
return LinearStop
}
func (l *successorConstraintImpl) EstimateIsViolated(
move SolutionMoveStops,
) (isViolated bool, stopPositionsHint StopPositionsHint) {
modelImpl := move.PlanStopsUnit().Solution().Model().(*modelImpl)
stopPositions := move.StopPositions()
for _, stopPosition := range stopPositions {
stop := stopPosition.Stop().ModelStop()
nextModelStop := stopPosition.Next().ModelStop()
if disallowed := modelImpl.disallowedSuccessors[stop.Index()][nextModelStop.Index()]; disallowed {
return true, noPositionsHint()
}
}
return false, noPositionsHint()
}
func (l *successorConstraintImpl) DoesStopHaveViolations(
stop SolutionStop,
) bool {
modelImpl := stop.Solution().Model().(*modelImpl)
stopImpl := stop
previousModelStop := stopImpl.Previous().modelStop()
if disallowed := modelImpl.disallowedSuccessors[previousModelStop.Index()][stop.ModelStop().Index()]; disallowed {
return true
}
return false
}