/// <summary> /// Considers one customer for relocation. /// </summary> /// <param name="problem"></param> /// <param name="route"></param> /// <param name="previous"></param> /// <param name="current"></param> /// <param name="next"></param> /// <param name="route_weight"></param> /// <param name="max"></param> /// <returns></returns> private bool ConsiderCustomer(IProblemWeights problem, IRoute route, int previous, int current, int next, double route_weight, double max) { // calculate the removal gain of the customer. double removal_gain = problem.WeightMatrix[previous][current] + problem.WeightMatrix[current][next] - problem.WeightMatrix[previous][next]; if (removal_gain > 0.0001) { // try and place the customer in the next route. CheapestInsertionResult result = CheapestInsertionHelper.CalculateBestPlacement(problem, route, current); if (result.Increase < removal_gain - 0.001 && route_weight + result.Increase < max) { // there is a gain in relocating this customer. int count_before = route.Count; string route_string = route.ToString(); // and the route is still within bounds! route.ReplaceEdgeFrom(result.CustomerBefore, result.Customer); route.ReplaceEdgeFrom(result.Customer, result.CustomerAfter); int count_after = route.Count; if (count_before + 1 != count_after) { throw new Exception(); } return(true); } } return(false); }
/// <summary> /// Tries a relocation of the customers in route1 to route2. /// </summary> /// <param name="problem"></param> /// <param name="solution"></param> /// <param name="route1_idx"></param> /// <param name="route2_idx"></param> /// <param name="max"></param> /// <returns></returns> private bool RelocateFromTo(MaxTimeProblem problem, MaxTimeSolution solution, int route1_idx, int route2_idx, double max) { int previous = -1; int current = -1; IRoute route1 = solution.Route(route1_idx); IRoute route2 = solution.Route(route2_idx); double route2_weight = solution[route2_idx]; foreach (int next in route1) { if (previous >= 0 && current >= 0) { // consider the next customer. int count_before1 = route1.Count; int count_before2 = route2.Count; string route1_string = route1.ToString(); string route2_string = route2.ToString(); if (this.ConsiderCustomer(problem, route2, previous, current, next, route2_weight, max)) { route1.ReplaceEdgeFrom(previous, next); int count_after = route1.Count + route2.Count; if ((count_before1 + count_before2) != count_after) { throw new Exception(); } return(true); } } previous = current; current = next; } return(false); }
public override string ToString() { return("Routes " + routeA.ToString() + " and " + routeB.ToString() + " on connection between stations " + stations.StationAKey + " and " + stations.StationBKey + "."); }
public Individual <MaxTimeSolution, MaxTimeProblem, Fitness> CrossOver( Solver <MaxTimeSolution, MaxTimeProblem, Fitness> solver, Individual <MaxTimeSolution, MaxTimeProblem, Fitness> parent1, Individual <MaxTimeSolution, MaxTimeProblem, Fitness> parent2) { MaxTimeCalculator calculator = new MaxTimeCalculator(solver.Problem); MaxTimeSolution route1 = parent1.Genomes; MaxTimeSolution route2 = parent2.Genomes; // get the minimum size of both routes. int size = route1.Count; if (route2.Count < size) { size = route2.Count; } // select a random number of routes. HashSet <int> selected_first = new HashSet <int>(); HashSet <int> selected_second = new HashSet <int>(); List <IRoute> selected_routes = new List <IRoute>(); bool first = true; while (selected_routes.Count < size) { // select route. int selected_route = -1; if (first) { selected_route = this.ChooseNextFrom(selected_routes, route1, selected_first); selected_first.Add(selected_route); selected_routes.Add(route1.Route(selected_route)); } else { selected_route = this.ChooseNextFrom(selected_routes, route2, selected_second); selected_second.Add(selected_route); selected_routes.Add(route2.Route(selected_route)); } first = !first; } // generate the new customer genome. MaxTimeSolution solution = new MaxTimeSolution(route1.Size, true); int previous = -1; foreach (IRoute route in selected_routes) { IRoute current_route = null; foreach (int customer in route) { MaxTimeSolution copy = (solution.Clone() as MaxTimeSolution); string solution_string = solution.ToString(); if (!solution.Contains(customer)) { if (current_route == null) { // add the route. current_route = solution.Add(customer); // safe the previous customer. previous = customer; if (!solution.IsValid()) { throw new Exception(); } } else { // add the customer. string current_route_string = current_route.ToString(); //current_route.InsertAfterAndRemove(previous, customer, current_route.First); current_route.InsertAfter(previous, customer); //current_route.InsertAfter(customer, current_route.First); if (!solution.IsValid()) { throw new Exception(); } // safe the previous customer. previous = customer; } } } } if (!solution.IsValid()) { throw new Exception(); } this.FillRoutes(calculator, route1, solution, solver.Problem); if (!solution.IsValid()) { throw new Exception(); } return(new Individual <MaxTimeSolution, MaxTimeProblem, Fitness>(solution)); }
public override string ToString() { return("Routes " + routeA.ToString() + " and " + routeB.ToString() + " at station " + stationKey + "."); }
public void TestDepotDynamicAsymmetricMultiRouteExchanges() { // create two routes. // 0->11->12->13->14->15->0 // 0->21->22->23->24->25->0 var multiRoute = new MaxTimeSolution(0); IRoute route1 = multiRoute.Add(); var customers = new List <int>(route1); Assert.AreEqual(1, customers.Count); Assert.AreEqual(0, customers[0]); route1.InsertAfter(0, 11); Assert.AreEqual("0->11", route1.ToString()); route1.InsertAfter(11, 12); route1.InsertAfter(12, 13); route1.InsertAfter(13, 14); route1.InsertAfter(14, 15); IRoute route2 = multiRoute.Add(); customers = new List <int>(route2); Assert.AreEqual(1, customers.Count); Assert.AreEqual(0, customers[0]); route2.InsertAfter(0, 21); Assert.AreEqual("0->21", route2.ToString()); route2.InsertAfter(21, 22); route2.InsertAfter(22, 23); route2.InsertAfter(23, 24); route2.InsertAfter(24, 25); customers = new List <int>(route1); Assert.AreEqual(6, customers.Count); Assert.AreEqual(0, customers[0]); Assert.AreEqual(11, customers[1]); Assert.AreEqual(12, customers[2]); Assert.AreEqual(13, customers[3]); Assert.AreEqual(14, customers[4]); Assert.AreEqual(15, customers[5]); customers = new List <int>(route2); Assert.AreEqual(6, customers.Count); Assert.AreEqual(0, customers[0]); Assert.AreEqual(21, customers[1]); Assert.AreEqual(22, customers[2]); Assert.AreEqual(23, customers[3]); Assert.AreEqual(24, customers[4]); Assert.AreEqual(25, customers[5]); // replace the entire first route. route1.ReplaceEdgeFrom(0, 0); route2.ReplaceEdgeFrom(25, 11); route2.ReplaceEdgeFrom(11, 12); route2.ReplaceEdgeFrom(12, 13); route2.ReplaceEdgeFrom(13, 14); route2.ReplaceEdgeFrom(14, 15); Assert.IsTrue(multiRoute.IsValid()); // create two routes. // 0->11->12->13->14->15->0 // 0->21->22->23->24->25->0 multiRoute = new MaxTimeSolution(0); route1 = multiRoute.Add(); customers = new List <int>(route1); Assert.AreEqual(1, customers.Count); Assert.AreEqual(0, customers[0]); route1.InsertAfter(0, 11); Assert.AreEqual("0->11", route1.ToString()); route1.InsertAfter(11, 12); route1.InsertAfter(12, 13); route1.InsertAfter(13, 14); route1.InsertAfter(14, 15); route2 = multiRoute.Add(); customers = new List <int>(route2); Assert.AreEqual(1, customers.Count); Assert.AreEqual(0, customers[0]); route2.InsertAfter(0, 21); Assert.AreEqual("0->21", route2.ToString()); route2.InsertAfter(21, 22); route2.InsertAfter(22, 23); route2.InsertAfter(23, 24); route2.InsertAfter(24, 25); // exchange parts. var part1 = new List <int>(route1.Between(11, 13)); var part2 = new List <int>(route2.Between(23, 25)); route1.ReplaceEdgeFrom(0, 14); route2.ReplaceEdgeFrom(22, 0); int previous = 0; for (int idx = 0; idx < part2.Count; idx++) { route1.ReplaceEdgeFrom(previous, part2[idx]); previous = part2[idx]; } route1.ReplaceEdgeFrom(previous, 14); previous = 22; for (int idx = 0; idx < part1.Count; idx++) { route2.ReplaceEdgeFrom(previous, part1[idx]); previous = part1[idx]; } route2.ReplaceEdgeFrom(previous, 0); Assert.IsTrue(multiRoute.IsValid()); customers = new List <int>(route1); Assert.AreEqual(6, customers.Count); Assert.AreEqual(0, customers[0]); Assert.AreEqual(23, customers[1]); Assert.AreEqual(24, customers[2]); Assert.AreEqual(25, customers[3]); Assert.AreEqual(14, customers[4]); Assert.AreEqual(15, customers[5]); customers = new List <int>(route2); Assert.AreEqual(6, customers.Count); Assert.AreEqual(0, customers[0]); Assert.AreEqual(21, customers[1]); Assert.AreEqual(22, customers[2]); Assert.AreEqual(11, customers[3]); Assert.AreEqual(12, customers[4]); Assert.AreEqual(13, customers[5]); // create two routes. // 0->11->12->13->14->15->0 // 0->21->22->23->24->25->0 multiRoute = new MaxTimeSolution(0); route1 = multiRoute.Add(); customers = new List <int>(route1); Assert.AreEqual(1, customers.Count); Assert.AreEqual(0, customers[0]); route1.InsertAfter(0, 11); Assert.AreEqual("0->11", route1.ToString()); route1.InsertAfter(11, 12); route1.InsertAfter(12, 13); route1.InsertAfter(13, 14); route1.InsertAfter(14, 15); route2 = multiRoute.Add(); customers = new List <int>(route2); Assert.AreEqual(1, customers.Count); Assert.AreEqual(0, customers[0]); route2.InsertAfter(0, 21); Assert.AreEqual("0->21", route2.ToString()); route2.InsertAfter(21, 22); route2.InsertAfter(22, 23); route2.InsertAfter(23, 24); route2.InsertAfter(24, 25); route1.ReplaceEdgeFrom(12, 15); route1.ReplaceEdgeFrom(14, 11); route1.ReplaceEdgeFrom(0, 13); customers = new List <int>(route1); Assert.AreEqual(6, customers.Count); Assert.AreEqual(0, customers[0]); Assert.AreEqual(13, customers[1]); Assert.AreEqual(14, customers[2]); Assert.AreEqual(11, customers[3]); Assert.AreEqual(12, customers[4]); Assert.AreEqual(15, customers[5]); route1.ToString(); }
/// <summary> /// Tries to improve the existing route using CI and return true if succesful. /// </summary> /// <param name="problem"></param> /// <param name="route"></param> /// <param name="difference"></param> /// <returns></returns> public bool Improve(IProblemWeights problem, IRoute route, out double difference) { bool improvement = false; difference = 0; if (route.Count > 3) { // loop over all customers and try cheapest insertion. for (int customer = 0; customer < problem.Size; customer++) { string route_string = route.ToString(); //IRoute previous = route.Clone() as IRoute; if (route.Contains(customer)) { // remove customer and keep position. int next = route.GetNeigbours(customer)[0]; route.Remove(customer); // insert again. ArbitraryInsertionSolver.InsertOne(problem, route, customer, out difference); if (!route.IsValid()) { throw new Exception(); } if (route.GetNeigbours(customer)[0] != next && difference < 0) { // another customer was found as the best, improvement is succesful. improvement = true; break; } } } } return improvement; }
/// <summary> /// Tries all 3Opt Moves for the neighbourhood of v_1 containing v_3. /// </summary> /// <param name="problem"></param> /// <param name="weights"></param> /// <param name="route"></param> /// <param name="v1"></param> /// <param name="v_2"></param> /// <param name="v_3"></param> /// <param name="weights_3"></param> /// <param name="v_4"></param> /// <param name="weight_1_2_plus_3_4"></param> /// <param name="weight_1_4"></param> /// <returns></returns> public bool Try3OptMoves(IProblemWeights problem, double[][] weights, IRoute route, int v1, int v_2, int v_3, double[] weights_3, int v_4, double weight_1_2_plus_3_4, double weight_1_4) { //IEnumerable<int> between_v_4_v_1 = route.Between(v_4, v_1); //foreach (int v_5 in between_v_4_v_1) //{ // if (v_5 != v_1) // { // if (this.Try3OptMove(problem, weights, route, v_1, v_2, v_3, weights_3, v_4, weight_1_2_plus_3_4, weight_1_4, v_5)) // { // return true; // } // } //} //return false; IEnumerator<int> between_v_4_v_1_enumerator = route.Between(v_4, v1).GetEnumerator(); if (between_v_4_v_1_enumerator.MoveNext()) { int v_5 = between_v_4_v_1_enumerator.Current; if (v_5 != v1) { while (between_v_4_v_1_enumerator.MoveNext()) { int v_6 = between_v_4_v_1_enumerator.Current; //Console.WriteLine(v_6); //if (this.Try3OptMove(problem, weights, // route, v_1, v_2, v_3, weights_3, v_4, // weight_1_2_plus_3_4, weight_1_4, v_5, v_6)) //{ // calculate the total weight of the 'new' arcs. double weight_new = weight_1_4 + weights_3[v_6] + weights[v_5][v_2]; // calculate the total weights. double weight = weight_1_2_plus_3_4 + weights[v_5][v_6]; if (weight - weight_new > _epsilon) { // actually do replace the vertices. int count_before = route.Count; string route_string = route.ToString(); route.ReplaceEdgeFrom(v1, v_4); route.ReplaceEdgeFrom(v_3, v_6); route.ReplaceEdgeFrom(v_5, v_2); int count_after = route.Count; if (count_before != count_after) { throw new Exception(); } // set bits. //this.Set(problem, v_1, false); this.Set(problem, v_3, false); this.Set(problem, v_5, false); if (!route.IsValid()) { throw new Exception(); } return true; // move succeeded. } //} v_5 = v_6; } } } return false; }
/// <summary> /// Considers one customer for relocation. /// </summary> /// <param name="problem"></param> /// <param name="route"></param> /// <param name="previous"></param> /// <param name="current"></param> /// <param name="next"></param> /// <param name="route_weight"></param> /// <param name="max"></param> /// <returns></returns> private bool ConsiderCustomer(IProblemWeights problem, IRoute route, int previous, int current, int next, double route_weight, double max) { // calculate the removal gain of the customer. double removal_gain = problem.WeightMatrix[previous][current] + problem.WeightMatrix[current][next] - problem.WeightMatrix[previous][next]; if (removal_gain > 0.0001) { // try and place the customer in the next route. CheapestInsertionResult result = CheapestInsertionHelper.CalculateBestPlacement(problem, route, current); if (result.Increase < removal_gain - 0.001 && route_weight + result.Increase < max) { // there is a gain in relocating this customer. int count_before = route.Count; string route_string = route.ToString(); // and the route is still within bounds! route.ReplaceEdgeFrom(result.CustomerBefore, result.Customer); route.ReplaceEdgeFrom(result.Customer, result.CustomerAfter); int count_after = route.Count; if (count_before + 1 != count_after) { throw new Exception(); } return true; } } return false; }