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.");
 }
Beispiel #8
0
 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));
 }