public override double CalculateSolutionSimilarity(IScope leftSolution, IScope rightSolution) { var sol1 = leftSolution.Variables[SolutionVariableName].Value as IVRPEncoding; var sol2 = rightSolution.Variables[SolutionVariableName].Value as IVRPEncoding; var potvinSol1 = sol1 is PotvinEncoding ? sol1 as PotvinEncoding : PotvinEncoding.ConvertFrom(sol1, ProblemInstance); var potvinSol2 = sol2 is PotvinEncoding ? sol2 as PotvinEncoding : PotvinEncoding.ConvertFrom(sol2, ProblemInstance); return(CalculateSimilarity(potvinSol1, potvinSol2)); }
public static double CalculateSimilarity(PotvinEncoding left, PotvinEncoding right) { if (left == null || right == null) { throw new ArgumentException("Cannot calculate similarity because one of the provided solutions or both are null."); } if (left == right) { return(1.0); } // extract edges from first solution var edges1 = new List <Tuple <int, int> >(); foreach (Tour tour in left.Tours) { edges1.Add(new Tuple <int, int>(0, tour.Stops[0])); for (int i = 0; i < tour.Stops.Count - 1; i++) { edges1.Add(new Tuple <int, int>(tour.Stops[i], tour.Stops[i + 1])); } edges1.Add(new Tuple <int, int>(tour.Stops[tour.Stops.Count - 1], 0)); } // extract edges from second solution var edges2 = new List <Tuple <int, int> >(); foreach (Tour tour in right.Tours) { edges2.Add(new Tuple <int, int>(0, tour.Stops[0])); for (int i = 0; i < tour.Stops.Count - 1; i++) { edges2.Add(new Tuple <int, int>(tour.Stops[i], tour.Stops[i + 1])); } edges2.Add(new Tuple <int, int>(tour.Stops[tour.Stops.Count - 1], 0)); } if (edges1.Count + edges2.Count == 0) { throw new ArgumentException("Cannot calculate diversity because no tours exist."); } int identicalEdges = 0; foreach (var edge in edges1) { if (edges2.Any(x => x.Equals(edge))) { identicalEdges++; } } return(identicalEdges * 2.0 / (edges1.Count + edges2.Count)); }
private static PotvinEncoding MatchTours(PotvinEncoding initiator, PotvinEncoding guide, IVRPProblemInstance problemInstance) { var result = new PotvinEncoding(problemInstance); var used = new List <bool>(); for (int i = 0; i < initiator.Tours.Count; i++) { used.Add(false); } for (int i = 0; i < guide.Tours.Count; i++) { int bestMatch = -1; int bestTour = -1; for (int j = 0; j < initiator.Tours.Count; j++) { if (!used[j]) { int match = MatchingCities(guide.Tours[i], initiator.Tours[j]); if (match > bestMatch) { bestMatch = match; bestTour = j; } } } if (bestTour != -1) { result.Tours.Add(initiator.Tours[bestTour]); used[bestTour] = true; } } for (int i = 0; i < initiator.Tours.Count; i++) { if (!used[i]) { result.Tours.Add(initiator.Tours[i]); } } return(result); }
protected override ItemArray <IItem> Relink(ItemArray <IItem> parents, PercentValue n) { if (parents.Length != 2) { throw new ArgumentException("The number of parents is not equal to 2."); } if (!(parents[0] is PotvinEncoding)) { parents[0] = PotvinEncoding.ConvertFrom(parents[0] as IVRPEncoding, ProblemInstanceParameter.ActualValue); } if (!(parents[1] is PotvinEncoding)) { parents[1] = PotvinEncoding.ConvertFrom(parents[1] as IVRPEncoding, ProblemInstanceParameter.ActualValue); } return(Apply(parents[0] as PotvinEncoding, parents[1] as PotvinEncoding, n, SampleSizeParameter.Value.Value, IterationsParameter.Value.Value, RandomParameter.ActualValue, ProblemInstanceParameter.ActualValue)); }
public static void RelocateMove(PotvinEncoding individual, IRandom random) { int cities = individual.Cities; int city = 1 + random.Next(cities); Tour originalTour = individual.Tours.Find(t => t.Stops.Contains(city)); //consider creating new route individual.Tours.Add(new Tour()); int position = 1 + random.Next(cities + individual.Tours.Count - 1); if (position >= city) { position++; } int originalPosition = originalTour.Stops.IndexOf(city); originalTour.Stops.RemoveAt(originalPosition); Tour insertionTour; int insertionPosition; if (position <= cities) { insertionTour = individual.Tours.Find(t => t.Stops.Contains(position)); insertionPosition = insertionTour.Stops.IndexOf(position) + 1; } else { insertionTour = individual.Tours[position - cities - 1]; insertionPosition = 0; } insertionTour.Stops.Insert(insertionPosition, city); individual.Tours.RemoveAll(t => t.Stops.Count == 0); }
protected virtual IVRPEncoding GetBestKnowTour(IVRPData data, IVRPProblemInstance problemInstance) { if (data.BestKnownTour != null) { PotvinEncoding solution = new PotvinEncoding(problemInstance); for (int i = 0; i < data.BestKnownTour.GetLength(0); i++) { Tour tour = new Tour(); solution.Tours.Add(tour); foreach (int stop in data.BestKnownTour[i]) { tour.Stops.Add(stop + 1); } } if (data.BestKnownTourVehicleAssignment != null) { if (data.BestKnownTourVehicleAssignment.Length != solution.VehicleAssignment.Length) { throw new InvalidDataException("Number of vehicles of the best known tour does not match the number vehicles of the instance."); } for (int i = 0; i < data.BestKnownTourVehicleAssignment.Length; i++) { solution.VehicleAssignment[i] = data.BestKnownTourVehicleAssignment[i]; } } return(solution); } else { return(null); } }
protected override int Improve(PotvinEncoding solution) { int evaluatedSolutions = 0; var rand = RandomParameter.ActualValue; var instance = ProblemInstance; int sampleSize = SampleSizeParameter.Value.Value; int attempts = ImprovementAttemptsParameter.Value.Value; int customers = instance.Cities.Value; // store city-to-tour assignment and position of the city within the tour var tours = new Dictionary <int, Tour>(); var position = new Dictionary <int, int>(); foreach (Tour tour in solution.Tours) { for (int stop = 0; stop < tour.Stops.Count; stop++) { int city = tour.Stops[stop]; tours[city] = tour; position[city] = stop; } } for (int attempt = 0; attempt < attempts; attempt++) { for (int sample = 0; sample < sampleSize; sample++) { int chosenCust = 1 + rand.Next(customers); var custTour = tours[chosenCust]; double beforeQuality = instance.EvaluateTour(custTour, solution).Quality; evaluatedSolutions++; custTour.Stops.RemoveAt(position[chosenCust]); int place = solution.FindBestInsertionPlace(custTour, chosenCust); evaluatedSolutions += custTour.Stops.Count; custTour.Stops.Insert(place, chosenCust); if (place != position[chosenCust]) { double afterQuality = instance.EvaluateTour(custTour, solution).Quality; if (afterQuality > beforeQuality) { // revert move custTour.Stops.RemoveAt(place); custTour.Stops.Insert(position[chosenCust], chosenCust); } else { // accept move and update positions of the cities within the tour for (int stop = 0; stop < custTour.Stops.Count; stop++) { int city = custTour.Stops[stop]; position[city] = stop; } break; } } } } return(evaluatedSolutions); }
public override IOperation InstrumentedApply() { var solution = SolutionParameter.ActualValue as IVRPEncoding; var potvinSolution = solution is PotvinEncoding ? solution as PotvinEncoding : PotvinEncoding.ConvertFrom(solution, ProblemInstance); if (solution == null) { throw new ArgumentException("Cannot improve solution because it has the wrong type."); } int evaluatedSolutions = Improve(potvinSolution); SolutionParameter.ActualValue = solution; LocalEvaluatedSolutions.ActualValue = new IntValue(evaluatedSolutions); return(base.InstrumentedApply()); }
protected abstract int Improve(PotvinEncoding solution);
public static ItemArray <IItem> Apply(PotvinEncoding initiator, PotvinEncoding guide, PercentValue n, int sampleSize, int iterations, IRandom rand, IVRPProblemInstance problemInstance) { if (initiator == null || guide == null) { throw new ArgumentException("Cannot relink path because one of the provided solutions or both are null."); } double sigma = 1.5; double minPenalty = 0.001; double maxPenalty = 1000000000; var originalOverloadPenalty = new DoubleValue(); if (problemInstance is IHomogenousCapacitatedProblemInstance) { originalOverloadPenalty.Value = (problemInstance as IHomogenousCapacitatedProblemInstance).OverloadPenalty.Value; } var originalTardinessPenalty = new DoubleValue(); if (problemInstance is ITimeWindowedProblemInstance) { originalTardinessPenalty.Value = (problemInstance as ITimeWindowedProblemInstance).TardinessPenalty.Value; } PotvinEncoding current = MatchTours(initiator, guide, problemInstance); double currentSimilarity = VRPSimilarityCalculator.CalculateSimilarity(current, guide); IList <PotvinEncoding> solutions = new List <PotvinEncoding>(); int i = 0; while (i < iterations && !currentSimilarity.IsAlmost(1.0)) { var currentEval = problemInstance.Evaluate(current); currentSimilarity = VRPSimilarityCalculator.CalculateSimilarity(current, guide); if (currentSimilarity < 1.0) { for (int sample = 0; sample < sampleSize; sample++) { var next = current.Clone() as PotvinEncoding; int neighborhood = rand.Next(3); switch (neighborhood) { case 0: next = RouteBasedXOver(next, guide, rand, problemInstance); break; case 1: next = SequenceBasedXOver(next, guide, rand, problemInstance); break; case 2: GuidedRelocateMove(next, guide, rand); break; } next = MatchTours(next, guide, problemInstance); var nextEval = problemInstance.Evaluate(next); if ((nextEval.Quality < currentEval.Quality)) { current = next; solutions.Add(current); break; } } if (problemInstance is IHomogenousCapacitatedProblemInstance) { if (((CVRPEvaluation)currentEval).Overload > 0) { (problemInstance as IHomogenousCapacitatedProblemInstance).OverloadPenalty.Value = Math.Min(maxPenalty, (problemInstance as IHomogenousCapacitatedProblemInstance).OverloadPenalty.Value * sigma); } else { (problemInstance as IHomogenousCapacitatedProblemInstance).OverloadPenalty.Value = Math.Max(minPenalty, (problemInstance as IHomogenousCapacitatedProblemInstance).OverloadPenalty.Value * sigma); } } if (problemInstance is ITimeWindowedProblemInstance) { if (((CVRPTWEvaluation)currentEval).Tardiness > 0) { (problemInstance as ITimeWindowedProblemInstance).TardinessPenalty.Value = Math.Min(maxPenalty, (problemInstance as ITimeWindowedProblemInstance).TardinessPenalty.Value * sigma); } else { (problemInstance as ITimeWindowedProblemInstance).TardinessPenalty.Value = Math.Max(minPenalty, (problemInstance as ITimeWindowedProblemInstance).TardinessPenalty.Value / sigma); } } i++; } } if (problemInstance is IHomogenousCapacitatedProblemInstance) { (problemInstance as IHomogenousCapacitatedProblemInstance).OverloadPenalty.Value = originalOverloadPenalty.Value; } if (problemInstance is ITimeWindowedProblemInstance) { (problemInstance as ITimeWindowedProblemInstance).TardinessPenalty.Value = originalTardinessPenalty.Value; } return(new ItemArray <IItem>(ChooseSelection(solutions, n))); }
public static void GuidedRelocateMove(PotvinEncoding initiator, PotvinEncoding guide, IRandom random) { List <int> cities = new List <int>(); foreach (Tour tour in initiator.Tours) { foreach (int city in tour.Stops) { Tour guideTour = guide.Tours.First(t => t.Stops.Contains(city)); if (guide.Tours.IndexOf(guideTour) != initiator.Tours.IndexOf(tour)) { cities.Add(city); } } } if (cities.Count == 0) { RelocateMove(initiator, random); } else { int city = cities[random.Next(cities.Count)]; Tour tour = initiator.Tours.First(t => t.Stops.Contains(city)); tour.Stops.Remove(city); Tour guideTour = guide.Tours.First(t => t.Stops.Contains(city)); int guideTourIndex = guide.Tours.IndexOf(guideTour); if (guideTourIndex < initiator.Tours.Count) { Tour tour2 = initiator.Tours[guideTourIndex]; int guideIndex = guideTour.Stops.IndexOf(city); if (guideIndex == 0) { tour2.Stops.Insert(0, city); } else { int predecessor = guideTour.Stops[guideIndex - 1]; int initIndex = tour2.Stops.IndexOf(predecessor); if (initIndex != -1) { tour2.Stops.Insert(initIndex + 1, city); } else { if (guideIndex == guideTour.Stops.Count - 1) { tour2.Stops.Insert(tour2.Stops.Count, city); } else { int sucessor = guideTour.Stops[guideIndex + 1]; initIndex = tour2.Stops.IndexOf(sucessor); if (initIndex != -1) { tour2.Stops.Insert(initIndex, city); } else { tour2.Stops.Insert(random.Next(tour2.Stops.Count + 1), city); } } } } } else { Tour tour2 = new Tour(); tour2.Stops.Add(city); initiator.Tours.Add(tour2); } if (tour.Stops.Count == 0) { initiator.Tours.Remove(tour); } } }
public static PotvinEncoding SequenceBasedXOver(PotvinEncoding initiator, PotvinEncoding guide, IRandom random, IVRPProblemInstance problemInstance) { return(PotvinSequenceBasedCrossover.Apply(random, initiator, guide, problemInstance, false)); }