diff --git a/model_cluster.go b/model_cluster.go index 7f393bc..a5ceaa2 100644 --- a/model_cluster.go +++ b/model_cluster.go @@ -226,7 +226,7 @@ func (l *clusterImpl) estimateDeltaScore( return deltaScore, constNoPositionsHint } - candidate := stopPosition.stop() + candidate := stopPosition.Stop() var c *centroidData if asConstraint { diff --git a/model_constraint_maximum_stops.go b/model_constraint_maximum_stops.go index 6839058..17b3091 100644 --- a/model_constraint_maximum_stops.go +++ b/model_constraint_maximum_stops.go @@ -57,7 +57,7 @@ func (l *maximumStopsConstraintImpl) EstimateIsViolated( stopPositions := moveImpl.stopPositions nrStopsToBeAddedToSolution := len(stopPositions) - beforeStop := stopPositions[len(stopPositions)-1].next() + beforeStop := stopPositions[len(stopPositions)-1].Next() vehicle := beforeStop.vehicle() vehicleType := vehicle.ModelVehicle().VehicleType().Index() diff --git a/model_constraint_no_mix.go b/model_constraint_no_mix.go index bcf6b1f..a508cb8 100644 --- a/model_constraint_no_mix.go +++ b/model_constraint_no_mix.go @@ -349,19 +349,19 @@ func (l *noMixConstraintImpl) EstimateIsViolated( move SolutionMoveStops, ) (isViolated bool, stopPositionsHint StopPositionsHint) { moveImpl := move.(*solutionMoveStopsImpl) - _, hasRemoveMixItem := l.remove[moveImpl.stopPositions[0].stop().ModelStop()] + _, hasRemoveMixItem := l.remove[moveImpl.stopPositions[0].Stop().ModelStop()] if hasRemoveMixItem { return true, constNoPositionsHint } - previousStopImp := moveImpl.stopPositions[0].previous() + previousStopImp := moveImpl.stopPositions[0].Previous() previousNoMixData := previousStopImp.ConstraintData(l).(*noMixSolutionStopData) contentName := previousNoMixData.content.Name contentQuantity := previousNoMixData.content.Quantity deltaQuantity := 0 - insertMixItem, hasInsertMixItem := l.insert[moveImpl.stopPositions[0].stop().ModelStop()] + insertMixItem, hasInsertMixItem := l.insert[moveImpl.stopPositions[0].Stop().ModelStop()] if hasInsertMixItem { if contentName != insertMixItem.Name && previousNoMixData.content.Quantity != 0 { return true, constNoPositionsHint @@ -377,14 +377,14 @@ func (l *noMixConstraintImpl) EstimateIsViolated( } for idx := 1; idx < len(moveImpl.stopPositions); idx++ { - previousStopImp = moveImpl.stopPositions[idx].previous() + previousStopImp = moveImpl.stopPositions[idx].Previous() if previousStopImp.IsPlanned() { previousNoMixData = previousStopImp.ConstraintData(l).(*noMixSolutionStopData) if previousNoMixData.tour != tour || previousNoMixData.content.Name != contentName { return true, constNoPositionsHint } } - insertMixItem, hasInsertMixItem = l.insert[moveImpl.stopPositions[idx].stop().ModelStop()] + insertMixItem, hasInsertMixItem = l.insert[moveImpl.stopPositions[idx].Stop().ModelStop()] if hasInsertMixItem { if contentName != insertMixItem.Name { return true, constNoPositionsHint @@ -392,7 +392,7 @@ func (l *noMixConstraintImpl) EstimateIsViolated( deltaQuantity += insertMixItem.Quantity continue } - removeMixItem, hasRemoveMixItem := l.remove[moveImpl.stopPositions[idx].stop().ModelStop()] + removeMixItem, hasRemoveMixItem := l.remove[moveImpl.stopPositions[idx].Stop().ModelStop()] if hasRemoveMixItem { if contentName != removeMixItem.Name || contentQuantity+deltaQuantity < removeMixItem.Quantity { return true, constNoPositionsHint diff --git a/solution.go b/solution.go index 0856ae8..2e67eb0 100644 --- a/solution.go +++ b/solution.go @@ -510,7 +510,7 @@ func (s *solutionImpl) addInitialSolution(m Model) error { ) } for _, position := range move.(*solutionMoveStopsImpl).stopPositions { - position.stop().detach() + position.Stop().detach() } infeasiblePlanUnits[solutionPlanUnit] = true continue diff --git a/solution_move_stops.go b/solution_move_stops.go index e2f63ca..4e761ef 100644 --- a/solution_move_stops.go +++ b/solution_move_stops.go @@ -132,11 +132,11 @@ func (m *solutionMoveStopsImpl) Vehicle() SolutionVehicle { if len(m.stopPositions) == 0 { return SolutionVehicle{} } - return m.stopPositions[len(m.stopPositions)-1].next().Vehicle() + return m.stopPositions[len(m.stopPositions)-1].Next().Vehicle() } func (m *solutionMoveStopsImpl) vehicle() SolutionVehicle { - return m.stopPositions[len(m.stopPositions)-1].next().vehicle() + return m.stopPositions[len(m.stopPositions)-1].Next().vehicle() } func (m *solutionMoveStopsImpl) Next() SolutionStop { @@ -150,7 +150,7 @@ func (m *solutionMoveStopsImpl) next() (SolutionStop, bool) { if len(m.stopPositions) == 0 { return SolutionStop{}, false } - return m.stopPositions[len(m.stopPositions)-1].next(), true + return m.stopPositions[len(m.stopPositions)-1].Next(), true } func (m *solutionMoveStopsImpl) Previous() SolutionStop { @@ -165,7 +165,7 @@ func (m *solutionMoveStopsImpl) previous() (SolutionStop, bool) { if len(m.stopPositions) == 0 { return SolutionStop{}, false } - return m.stopPositions[0].previous(), true + return m.stopPositions[0].Previous(), true } func (m *solutionMoveStopsImpl) Execute(_ context.Context) (bool, error) { @@ -198,7 +198,7 @@ func (m *solutionMoveStopsImpl) Execute(_ context.Context) (bool, error) { } for _, position := range m.stopPositions { - position.stop().detach() + position.Stop().detach() } constraint, _, err := m.planUnit.solution().isFeasible(startPropagate, true) @@ -224,9 +224,9 @@ func (m *solutionMoveStopsImpl) attach() (int, error) { startPropagate := -1 for i := len(m.stopPositions) - 1; i >= 0; i-- { stopPosition := m.stopPositions[i] - m.planUnit.solutionStops[i] = stopPosition.stop() - beforeStop := stopPosition.next() - if stopPosition.stop().IsPlanned() { + m.planUnit.solutionStops[i] = stopPosition.Stop() + beforeStop := stopPosition.Next() + if stopPosition.Stop().IsPlanned() { return -1, fmt.Errorf( "stop %v is already planned", stopPosition.Stop(), @@ -238,7 +238,7 @@ func (m *solutionMoveStopsImpl) attach() (int, error) { beforeStop, ) } - startPropagate = stopPosition.stop().attach( + startPropagate = stopPosition.Stop().attach( beforeStop.PreviousIndex(), ) } @@ -321,7 +321,7 @@ func (m *solutionMoveStopsImpl) TakeBest(that SolutionMove) SolutionMove { func (m *solutionMoveStopsImpl) deltaStopTravelDurationValue( vehicleType ModelVehicleType, ) float64 { - if len(m.stopPositions) == 0 || m.stopPositions[0].stop().IsPlanned() { + if len(m.stopPositions) == 0 || m.stopPositions[0].Stop().IsPlanned() { return 0 } deltaStopDurationValue := 0.0 @@ -329,12 +329,12 @@ func (m *solutionMoveStopsImpl) deltaStopTravelDurationValue( vehicleTravelDuration := vehicleType.TravelDurationExpression() vehicleDuration := vehicleType.DurationExpression() for _, stopPosition := range m.stopPositions { - modelStop := stopPosition.stop().ModelStop() - nextStop := stopPosition.next().ModelStop() - previousStop := stopPosition.previous().ModelStop() - if stopPosition.next().IsPlanned() { - deltaStopDurationValue -= stopPosition.next().DurationValue() - travelDuration -= stopPosition.next().TravelDurationValue() + modelStop := stopPosition.Stop().ModelStop() + nextStop := stopPosition.Next().ModelStop() + previousStop := stopPosition.Previous().ModelStop() + if stopPosition.Next().IsPlanned() { + deltaStopDurationValue -= stopPosition.Next().DurationValue() + travelDuration -= stopPosition.Next().TravelDurationValue() travelDuration += vehicleTravelDuration.Value( vehicleType, modelStop, @@ -361,7 +361,7 @@ func (m *solutionMoveStopsImpl) deltaStopTravelDurationValue( } func (m *solutionMoveStopsImpl) deltaTravelDurationValue() float64 { - if len(m.stopPositions) == 0 || m.stopPositions[0].stop().IsPlanned() { + if len(m.stopPositions) == 0 || m.stopPositions[0].Stop().IsPlanned() { return 0 } @@ -373,7 +373,7 @@ func (m *solutionMoveStopsImpl) deltaTravelDurationValue() float64 { if isDependentOnTime { if len(m.stopPositions) == 1 { - solutionStop := m.stopPositions[0].stop() + solutionStop := m.stopPositions[0].Stop() previousStop, _ := m.previous() departure := previousStop.EndValue() fromDuration, _, _, _ := vehicleType.TemporalValues( @@ -422,18 +422,18 @@ func (m *solutionMoveStopsImpl) deltaTravelDurationValue() float64 { travelDuration := 0.0 for _, stopPosition := range m.stopPositions { - modelStop := stopPosition.stop().ModelStop() - if stopPosition.next().IsPlanned() { - travelDuration -= stopPosition.next().TravelDurationValue() + modelStop := stopPosition.Stop().ModelStop() + if stopPosition.Next().IsPlanned() { + travelDuration -= stopPosition.Next().TravelDurationValue() travelDuration += vehicleType.TravelDurationExpression().Value( vehicleType, modelStop, - stopPosition.next().ModelStop(), + stopPosition.Next().ModelStop(), ) } travelDuration += vehicleType.TravelDurationExpression().Value( vehicleType, - stopPosition.previous().ModelStop(), + stopPosition.Previous().ModelStop(), modelStop, ) } @@ -493,7 +493,7 @@ func newMoveStops( ) } - vehicle := stopPositions[0].previous().vehicle() + vehicle := stopPositions[0].Previous().vehicle() lastPlannedPreviousStop := stopPositions[0].Previous() @@ -518,65 +518,65 @@ func newMoveStops( ) } - if stopPosition.previous().IsPlanned() { - if stopPosition.previous().Position() < position { + if stopPosition.Previous().IsPlanned() { + if stopPosition.Previous().Position() < position { return nil, fmt.Errorf("previous stop %s of stop position %v is planned at position %v,"+ " which is before or at the last planned previous stop %s at position %v", - stopPosition.previous().ModelStop().ID(), + stopPosition.Previous().ModelStop().ID(), index, - stopPosition.previous().Position(), + stopPosition.Previous().Position(), lastPlannedPreviousStop.ModelStop().ID(), lastPlannedPreviousStop.Position(), ) } - position = stopPosition.previous().Position() + position = stopPosition.Previous().Position() - lastPlannedPreviousStop = stopPosition.previous() + lastPlannedPreviousStop = stopPosition.Previous() } - if stopPosition.next().IsPlanned() { - if stopPosition.next().Position() < position { + if stopPosition.Next().IsPlanned() { + if stopPosition.Next().Position() < position { return nil, fmt.Errorf("next stop %s of stop position %v is planned at position %v,"+ " which is before or at the last planned previous stop %s at position %v", - stopPosition.next().ModelStop().ID(), + stopPosition.Next().ModelStop().ID(), index, - stopPosition.next().Position(), + stopPosition.Next().Position(), lastPlannedPreviousStop.ModelStop().ID(), lastPlannedPreviousStop.Position(), ) } - position = stopPosition.next().Position() + position = stopPosition.Next().Position() } - if stopPosition.next().IsPlanned() && !stopPosition.previous().IsPlanned() { - if lastPlannedPreviousStop.Position() != stopPosition.next().Position()-1 { + if stopPosition.Next().IsPlanned() && !stopPosition.Previous().IsPlanned() { + if lastPlannedPreviousStop.Position() != stopPosition.Next().Position()-1 { return nil, fmt.Errorf("stop positions are not allowed, planned previous stop %v is not adjacent"+ " to the planned next stop %v of the next stop position", lastPlannedPreviousStop.ModelStop().ID(), - stopPosition.next().ModelStop().ID(), + stopPosition.Next().ModelStop().ID(), ) } } - if stopPosition.next().IsPlanned() && stopPosition.previous().IsPlanned() { - if stopPosition.next().Position() != stopPosition.previous().Position()+1 { + if stopPosition.Next().IsPlanned() && stopPosition.Previous().IsPlanned() { + if stopPosition.Next().Position() != stopPosition.Previous().Position()+1 { return nil, fmt.Errorf("stop positions are not allowed, planned previous stop %v is not adjacent"+ " to the planned next stop %v of stop position %v", - stopPosition.previous().ModelStop().ID(), - stopPosition.next().ModelStop().ID(), + stopPosition.Previous().ModelStop().ID(), + stopPosition.Next().ModelStop().ID(), index, ) } } - if !stopPosition.previous().IsPlanned() { - if stopPositions[index-1].Stop() != stopPosition.previous() { + if !stopPosition.Previous().IsPlanned() { + if stopPositions[index-1].Stop() != stopPosition.Previous() { return nil, fmt.Errorf("the previous stop %s of stop position %v"+ " must be the stop %s of the previous stop position %v if it is unplanned", - stopPosition.previous().ModelStop().ID(), + stopPosition.Previous().ModelStop().ID(), index, stopPositions[index-1].Stop().ModelStop().ID(), index-1, @@ -584,12 +584,12 @@ func newMoveStops( } } - if !stopPosition.next().IsPlanned() { - if stopPositions[index+1].Stop() != stopPosition.next() { + if !stopPosition.Next().IsPlanned() { + if stopPositions[index+1].Stop() != stopPosition.Next() { return nil, fmt.Errorf("the next stop %s of stop position %v"+ " must be the stop %s of the next stop position %v if it is unplanned", - stopPosition.next().ModelStop().ID(), + stopPosition.Next().ModelStop().ID(), index, stopPositions[index+1].Stop().ModelStop().ID(), index+1, @@ -597,23 +597,23 @@ func newMoveStops( } } - if stopPosition.previous().IsPlanned() && stopPosition.previous().vehicle().index != vehicle.index { + if stopPosition.Previous().IsPlanned() && stopPosition.Previous().vehicle().index != vehicle.index { return nil, fmt.Errorf( "planned previous stop %v of stop position %v vehicle mismatch: %v != %v", - stopPosition.previous().ModelStop().ID(), + stopPosition.Previous().ModelStop().ID(), index, - stopPosition.previous().vehicle().ModelVehicle().ID(), + stopPosition.Previous().vehicle().ModelVehicle().ID(), vehicle.ModelVehicle().ID(), ) } - if stopPosition.next().IsPlanned() && stopPosition.next().vehicle().index != vehicle.index { + if stopPosition.Next().IsPlanned() && stopPosition.Next().vehicle().index != vehicle.index { return nil, fmt.Errorf( "planned next stop %v of stop position %v vehicle mismatch: %v != %v", - stopPosition.next().ModelStop().ID(), + stopPosition.Next().ModelStop().ID(), index, - stopPosition.next().vehicle().ModelVehicle().ID(), + stopPosition.Next().vehicle().ModelVehicle().ID(), vehicle.ModelVehicle().ID(), ) } diff --git a/solution_move_stops_generator.go b/solution_move_stops_generator.go index ffdac5e..76e5bbb 100644 --- a/solution_move_stops_generator.go +++ b/solution_move_stops_generator.go @@ -221,12 +221,12 @@ func generate( stopPositions[positionIdx-1].nextStopIndex = stopPositions[positionIdx].stopIndex } else { stopPositions[positionIdx-1].nextStopIndex = target[combination[positionIdx-1]].index - if mustBeNeighbours(model, stopPositions[positionIdx-1].stop(), stopPositions[positionIdx].stop()) { + if mustBeNeighbours(model, stopPositions[positionIdx-1].Stop(), stopPositions[positionIdx].Stop()) { break } } - if isNotAllowed(model, stopPositions[positionIdx-1].stop(), stopPositions[positionIdx-1].next()) { + if isNotAllowed(model, stopPositions[positionIdx-1].Stop(), stopPositions[positionIdx-1].Next()) { combination = combination[:positionIdx] if stopPositions[positionIdx-1].nextStopIndex != stopPositions[positionIdx].previousStopIndex { break @@ -235,7 +235,7 @@ func generate( } } - if isNotAllowed(model, stopPositions[positionIdx].previous(), stopPositions[positionIdx].stop()) { + if isNotAllowed(model, stopPositions[positionIdx].Previous(), stopPositions[positionIdx].Stop()) { combination = combination[:positionIdx] continue } diff --git a/solution_stop.go b/solution_stop.go index 47633e5..414195f 100644 --- a/solution_stop.go +++ b/solution_stop.go @@ -279,7 +279,7 @@ func (v SolutionStop) Vehicle() SolutionVehicle { if v.solution.next[v.index] == v.solution.previous[v.index] { panic("cannot get route of unplanned visit") } - return v.solution.solutionVehicles[v.solution.inVehicle[v.index]] + return v.vehicle() } func (v SolutionStop) vehicle() SolutionVehicle { diff --git a/solution_stop_generator.go b/solution_stop_generator.go index 404445c..d839189 100644 --- a/solution_stop_generator.go +++ b/solution_stop_generator.go @@ -60,7 +60,7 @@ func newSolutionStopGenerator( ) *solutionStopGeneratorImpl { nextStop := move.Vehicle().First() if !startAtFirst { - nextStop = move.stopPositions[0].previous() + nextStop = move.stopPositions[0].Previous() } solutionStopGenerator := solutionGeneratorPool.Get().(*solutionStopGeneratorImpl) solutionStopGenerator.stopPositions = solutionStopGenerator.stopPositions[:0] @@ -102,9 +102,9 @@ func (s *solutionStopGeneratorImpl) next() (SolutionStop, bool) { returnStop := s.nextStop if s.startAtFirst { - if s.nextStop == s.stopPositions[s.activeStopPositionIndex].previous() { + if s.nextStop == s.stopPositions[s.activeStopPositionIndex].Previous() { s.startAtFirst = false - s.nextStop = s.stopPositions[s.activeStopPositionIndex].stop() + s.nextStop = s.stopPositions[s.activeStopPositionIndex].Stop() } else { s.nextStop = s.nextStop.Next() } @@ -112,18 +112,18 @@ func (s *solutionStopGeneratorImpl) next() (SolutionStop, bool) { } if s.activeStopPositionIndex < len(s.stopPositions) { - if s.nextStop == s.stopPositions[s.activeStopPositionIndex].stop() { - s.nextStop = s.stopPositions[s.activeStopPositionIndex].next() + if s.nextStop == s.stopPositions[s.activeStopPositionIndex].Stop() { + s.nextStop = s.stopPositions[s.activeStopPositionIndex].Next() s.activeStopPositionIndex++ return returnStop, true } - if s.nextStop == s.stopPositions[s.activeStopPositionIndex].previous() { - s.nextStop = s.stopPositions[s.activeStopPositionIndex].stop() + if s.nextStop == s.stopPositions[s.activeStopPositionIndex].Previous() { + s.nextStop = s.stopPositions[s.activeStopPositionIndex].Stop() s.activeStopPositionIndex++ return returnStop, true } if !s.nextStop.IsPlanned() { - s.nextStop = s.stopPositions[s.activeStopPositionIndex-1].next() + s.nextStop = s.stopPositions[s.activeStopPositionIndex-1].Next() } else { if s.nextStop.IsLast() { s.endReached = true @@ -136,7 +136,7 @@ func (s *solutionStopGeneratorImpl) next() (SolutionStop, bool) { } if !s.nextStop.IsPlanned() { - s.nextStop = s.stopPositions[s.activeStopPositionIndex-1].next() + s.nextStop = s.stopPositions[s.activeStopPositionIndex-1].Next() return returnStop, true } diff --git a/solution_stop_position.go b/solution_stop_position.go index 6f12fb3..7393b82 100644 --- a/solution_stop_position.go +++ b/solution_stop_position.go @@ -67,12 +67,12 @@ func newStopPosition( func (v StopPosition) String() string { return fmt.Sprintf("stopPosition{%s[%v]->%s[%v]->%s[%v]", - v.previous().ModelStop().ID(), - v.previous().Index(), - v.stop().ModelStop().ID(), - v.stop().Index(), - v.next().ModelStop().ID(), - v.next().Index(), + v.Previous().ModelStop().ID(), + v.Previous().Index(), + v.Stop().ModelStop().ID(), + v.Stop().Index(), + v.Next().ModelStop().ID(), + v.Next().Index(), ) } @@ -80,38 +80,26 @@ func (v StopPosition) String() string { // involving the stop position is executed. It's worth noting that // the previous stop may not have been planned yet. func (v StopPosition) Previous() SolutionStop { - return v.previous() -} - -// Next denotes the upcoming stop's next stop if the associated move -// involving the stop position is executed. It's worth noting that -// the next stop may not have been planned yet. -func (v StopPosition) Next() SolutionStop { - return v.next() -} - -// Stop returns the stop which is not yet part of the solution. This stop -// is not planned yet if the move where the invoking stop position belongs -// to, has not been executed yet. -func (v StopPosition) Stop() SolutionStop { - return v.stop() -} - -func (v StopPosition) previous() SolutionStop { return SolutionStop{ index: v.previousStopIndex, solution: v.solution, } } -func (v StopPosition) next() SolutionStop { +// Next denotes the upcoming stop's next stop if the associated move +// involving the stop position is executed. It's worth noting that +// the next stop may not have been planned yet. +func (v StopPosition) Next() SolutionStop { return SolutionStop{ index: v.nextStopIndex, solution: v.solution, } } -func (v StopPosition) stop() SolutionStop { +// Stop returns the stop which is not yet part of the solution. This stop +// is not planned yet if the move where the invoking stop position belongs +// to, has not been executed yet. +func (v StopPosition) Stop() SolutionStop { return SolutionStop{ index: v.stopIndex, solution: v.solution, diff --git a/solution_vehicle.go b/solution_vehicle.go index 7571ff3..1647810 100644 --- a/solution_vehicle.go +++ b/solution_vehicle.go @@ -604,8 +604,8 @@ func (v SolutionVehicle) Unplan() (bool, error) { if constraint != nil { for i := len(stopPositions) - 1; i >= 0; i-- { stopPosition := stopPositions[i] - beforeStop := stopPosition.next() - stopPosition.stop().attach( + beforeStop := stopPosition.Next() + stopPosition.Stop().attach( beforeStop.PreviousIndex(), ) }