private void IncludeNewPoints(List<int> tour, List<int> visitablePoints, DistanceMatrix distances, double pointVisitingCosts, double maxLength, DoubleArray scores, ref double tourLength, ref double tourScore, ref int evaluations, ref bool solutionChanged) { for (int tourPosition = 1; tourPosition < tour.Count; tourPosition++) { // If an optimization has been done, start from the beginning if (solutionChanged) break; for (int i = 0; i < visitablePoints.Count; i++) { // If an optimization has been done, start from the beginning if (solutionChanged) break; evaluations++; double detour = distances.CalculateInsertionCosts(tour, tourPosition, visitablePoints[i], pointVisitingCosts); // Determine if including the point does not violate any constraint if (tourLength + detour <= maxLength) { // Insert the new point at this position tour.Insert(tourPosition, visitablePoints[i]); // Update the overall tour tourLength and score tourLength += detour; tourScore += scores[visitablePoints[i]]; // Re-run this optimization solutionChanged = true; } } } }
private void ReplacePoints(List<int> tour, List<int> visitablePoints, DistanceMatrix distances, double maxLength, DoubleArray scores, ref double tourLength, ref double tourScore, ref int evaluations, ref bool solutionChanged) { for (int tourPosition = 1; tourPosition < tour.Count - 1; tourPosition++) { // If an optimization has been done, start from the beginning if (solutionChanged) break; for (int i = 0; i < visitablePoints.Count; i++) { // If an optimization has been done, start from the beginning if (solutionChanged) break; evaluations++; double detour = distances.CalculateReplacementCosts(tour, tourPosition, visitablePoints[i]); double oldPointScore = scores[tour[tourPosition]]; double newPointScore = scores[visitablePoints[i]]; if ((tourLength + detour <= maxLength) && (newPointScore > oldPointScore)) { // Replace the old point by the new one tour[tourPosition] = visitablePoints[i]; // Update the overall tour tourLength tourLength += detour; // Update the scores achieved by visiting this point tourScore += newPointScore - oldPointScore; // Re-run this optimization solutionChanged = true; } } } }
public static OrienteeringEvaluationResult Apply(IntegerVector solution, DoubleArray scores, DistanceMatrix distances, double maximumDistance, double pointVisitingCosts, double distancePenaltyFactor) { double score = solution.Sum(t => scores[t]); double distance = distances.CalculateTourLength(solution.ToList(), pointVisitingCosts); double distanceViolation = distance - maximumDistance; double penalty = 0.0; penalty += distanceViolation > 0 ? distanceViolation * distancePenaltyFactor : 0; double quality = score - penalty; return new OrienteeringEvaluationResult { Quality = new DoubleValue(quality), Penalty = new DoubleValue(penalty), Distance = new DoubleValue(distance) }; }
private void ShortenPath(List<int> tour, DistanceMatrix distances, int maxBlockLength, bool useMaxBlockLength, ref double tourLength, ref int evaluations) { bool solutionChanged; int pathSize = tour.Count; maxBlockLength = (useMaxBlockLength && (pathSize > maxBlockLength + 1)) ? maxBlockLength : (pathSize - 2); // Perform a 2-opt do { solutionChanged = false; for (int blockLength = 2; blockLength < maxBlockLength; blockLength++) { // If an optimization has been done, start from the beginning if (solutionChanged) break; for (int position = 1; position < (pathSize - blockLength); position++) { // If an optimization has been done, start from the beginning if (solutionChanged) break; evaluations++; double newLength = tourLength; // Recalculate length of whole swapped part, in case distances are not symmetric for (int index = position - 1; index < position + blockLength; index++) newLength -= distances[tour[index], tour[index + 1]]; for (int index = position + blockLength - 1; index > position; index--) newLength += distances[tour[index], tour[index - 1]]; newLength += distances[tour[position - 1], tour[position + blockLength - 1]]; newLength += distances[tour[position], tour[position + blockLength]]; if (newLength < tourLength - 0.00001) { // Avoid cycling caused by precision var reversePart = tour.GetRange(position, blockLength).AsEnumerable().Reverse(); tour.RemoveRange(position, blockLength); tour.InsertRange(position, reversePart); tourLength = newLength; // Re-run the optimization solutionChanged = true; } } } } while (solutionChanged); }
public OrienteeringEvaluationResult Evaluate(IntegerVector solution, DoubleArray scores, DistanceMatrix distances, double maximumDistance, double pointVisitingCosts) { return Apply(solution, scores, distances, maximumDistance, pointVisitingCosts, ((IValueParameter<DoubleValue>)DistancePenaltyFactorParameter).Value.Value); }
private void CleanupTour(List<int> actualTour, DistanceMatrix distances, double maxDistance, double pointVisitingCosts) { // Sort the points on the tour according to their costs savings when removed var distanceSavings = ( from removePosition in Enumerable.Range(1, actualTour.Count - 2) let saving = distances.CalculateRemovementSaving(actualTour, removePosition, pointVisitingCosts) orderby saving descending select new SavingInfo { Index = removePosition, Saving = saving } ).ToList(); double tourLength = distances.CalculateTourLength(actualTour, pointVisitingCosts); // As long as the created path is infeasible, remove elements while (tourLength > maxDistance) { // Remove the point that frees the largest distance // Note, distance savings are not updated after removal tourLength -= distances.CalculateRemovementSaving(actualTour, distanceSavings[0].Index, pointVisitingCosts); actualTour.RemoveAt(distanceSavings[0].Index); // Shift indices due to removal of a point in the tour for (int i = 1; i < distanceSavings.Count; i++) { if (distanceSavings[i].Index > distanceSavings[0].Index) { distanceSavings[i].Index--; } } distanceSavings.RemoveAt(0); } }
private DistanceMatrix(DistanceMatrix original, Cloner cloner) { throw new NotSupportedException("Distance matrices cannot be cloned."); }
private DistanceMatrix(DistanceMatrix original, Cloner cloner) { throw new NotSupportedException("Distance matrices cannot be cloned."); }
public OrienteeringEvaluationResult Evaluate(IntegerVector solution, DoubleArray scores, DistanceMatrix distances, double maximumDistance, double pointVisitingCosts) { return(Apply(solution, scores, distances, maximumDistance, pointVisitingCosts, ((IValueParameter <DoubleValue>)DistancePenaltyFactorParameter).Value.Value)); }