/// <summary> /// Executes a solver procedure. /// </summary> /// <param name="problem"></param> /// <returns></returns> internal override MaxTimeSolution Solve(MaxTimeProblem problem) { float lambda = _lambda; var vrpRouter = new CheapestInsertionSolverWithImprovements(problem.Max.Value, problem.DeliveryTime.Value, 10, 0.10f, true, _thresholdPercentage, true, 0.75f); MaxTimeSolution originalSolution = vrpRouter.Solve( problem); for (int roundX = 0; roundX < originalSolution.Count; roundX++) { // keep looping on rounds. for (int roundY = 0; roundY < roundX; roundY++) { // keep looping on rounds with a smaller index not equal to the current round. if (roundX != roundY) { // routes are different. if (this.Overlaps(problem, originalSolution.Route(roundX), originalSolution.Route(roundY))) { // only check routes that overlap. double tau = double.MinValue; var penalizations = new Dictionary<Edge, int>(); //bool improvement = true; //while (improvement) //{ // keep looping until no more improvement is found. // improvement = false; while (true) { // keep trying to improve until the tau limit is exceeded. // calculate the route sizes before. double route1ActualBefore = problem.Time(originalSolution.Route(roundX)); double route2ActualBefore = problem.Time(originalSolution.Route(roundY)); // copy orignal solution. var solution = (originalSolution.Clone() as MaxTimeSolution); // apply penalties. foreach (KeyValuePair<Edge, int> penalty in penalizations) { problem.Penalize(penalty.Key, (double)penalty.Value * lambda); } // apply the inter-route improvements. int countBefore = solution.Route(roundX).Count + solution.Route(roundY).Count; int countAfter; if (this.ImproveInterRoute(problem, solution, roundX, roundY, problem.Max.Value)) { // the improve inter route succeeded. if (!solution.IsValid()) { throw new Exception(); } //improvement_inter = true; countAfter = solution.Route(roundX).Count + solution.Route(roundY).Count; if (countBefore != countAfter) { throw new Exception(); } // apply the intra-route improvements. solution[roundX] = this.ImproveIntraRoute(problem, solution.Route(roundX), solution[roundX]); solution[roundY] = this.ImproveIntraRoute(problem, solution.Route(roundY), solution[roundY]); // recalculate weights. solution[roundX] = problem.Time(solution.Route(roundX)); solution[roundY] = problem.Time(solution.Route(roundY)); } // check customer counts. countAfter = solution.Route(roundX).Count + solution.Route(roundY).Count; if (countBefore != countAfter) { throw new Exception(); } // undo the penalizations. problem.ResetPenalizations(); // check against the orginal objective function. double route1ActualAfter = problem.Time(solution.Route(roundX)); double route2ActualAfter = problem.Time(solution.Route(roundY)); if (route1ActualAfter + route2ActualAfter < route1ActualBefore + route2ActualBefore - 0.001 && route1ActualAfter < problem.Max.Value && route2ActualAfter < problem.Max.Value) { // there is improvement! originalSolution = solution; //improvement = true; OsmSharp.Logging.Log.TraceEvent("OsmSharp.Routing.VRP.NoDepot.MaxTime.VNS.GuidedVNS", TraceEventType.Information, "IMPROVEMENT: {0}->{1}", route1ActualBefore + route2ActualBefore, route1ActualAfter + route2ActualAfter); } // select arc to be penalized. IRoute route1 = originalSolution.Route(roundX); IRoute route2 = originalSolution.Route(roundY); double u = double.MinValue; var penalizingEdge = new Edge(); double totalP = 0; foreach (Edge edge in route1.Edges()) { int edgeP; if (!penalizations.TryGetValue(edge, out edgeP)) { edgeP = 0; } totalP = totalP + edgeP; double edgeU = ((lambda * (double)edgeP) + problem.WeightMatrix[edge.From][edge.To]) / ((double)edgeP + 1.0); if (u <= edgeU) { penalizingEdge = edge; u = edgeU; } } foreach (Edge edge in route2.Edges()) { int edgeP; if (!penalizations.TryGetValue(edge, out edgeP)) { edgeP = 0; } totalP = totalP + edgeP; double edgeU = ((lambda * (double)edgeP) + problem.WeightMatrix[edge.From][edge.To]) / ((double)edgeP + 1.0); if (u <= edgeU) { penalizingEdge = edge; u = edgeU; } } // actually penalize the edge. int p; if (!penalizations.TryGetValue(penalizingEdge, out p)) { p = 1; } else { p++; } penalizations[penalizingEdge] = p; // evaluate or set tau. if (tau > double.MinValue) { // evaluate if penalizations should end. if (tau <= lambda * totalP) { // the penalization should end! break; } } else { // first edge being penalized. tau = lambda * problem.WeightMatrix[penalizingEdge.From][penalizingEdge.To] / 10; } } } } } } return originalSolution; }
/// <summary> /// Executes a solver procedure. /// </summary> /// <param name="problem"></param> /// <returns></returns> internal override MaxTimeSolution Solve(MaxTimeProblem problem) { float lambda = _lambda; CheapestInsertionSolverWithImprovements vrp_router = new CheapestInsertionSolverWithImprovements(problem.Max.Value, problem.DeliveryTime.Value, 10, 0.10f, true, _threshold_percentage, true, 0.75f); MaxTimeSolution original_solution = vrp_router.Solve( problem); for (int round_x = 0; round_x < original_solution.Count; round_x++) { // keep looping on rounds. for (int round_y = 0; round_y < round_x; round_y++) { // keep looping on rounds with a smaller index not equal to the current round. if (round_x != round_y) { // routes are different. if (this.Overlaps(problem, original_solution.Route(round_x), original_solution.Route(round_y))) { // only check routes that overlap. double tau = double.MinValue; Dictionary<Edge, int> penalizations = new Dictionary<Edge, int>(); //bool improvement = true; //while (improvement) //{ // keep looping until no more improvement is found. // improvement = false; while (true) { // keep trying to improve until the tau limit is exceeded. // calculate the route sizes before. double route1_actual_before = problem.Time(original_solution.Route(round_x)); double route2_actual_before = problem.Time(original_solution.Route(round_y)); // copy orignal solution. MaxTimeSolution solution = (original_solution.Clone() as MaxTimeSolution); // apply penalties. foreach (KeyValuePair<Edge, int> penalty in penalizations) { problem.Penalize(penalty.Key, (double)penalty.Value * lambda); } // apply the inter-route improvements. int count_before = solution.Route(round_x).Count + solution.Route(round_y).Count; int count_after; if (this.ImproveInterRoute(problem, solution, round_x, round_y, problem.Max.Value)) { // the improve inter route succeeded. if (!solution.IsValid()) { throw new Exception(); } //improvement_inter = true; count_after = solution.Route(round_x).Count + solution.Route(round_y).Count; if (count_before != count_after) { throw new Exception(); } // apply the intra-route improvements. solution[round_x] = this.ImproveIntraRoute(problem, solution.Route(round_x), solution[round_x]); solution[round_y] = this.ImproveIntraRoute(problem, solution.Route(round_y), solution[round_y]); // recalculate weights. solution[round_x] = problem.Time(solution.Route(round_x)); solution[round_y] = problem.Time(solution.Route(round_y)); } // check customer counts. count_after = solution.Route(round_x).Count + solution.Route(round_y).Count; if (count_before != count_after) { throw new Exception(); } // undo the penalizations. problem.ResetPenalizations(); // check against the orginal objective function. double route1_actual_after = problem.Time(solution.Route(round_x)); double route2_actual_after = problem.Time(solution.Route(round_y)); if (route1_actual_after + route2_actual_after < route1_actual_before + route2_actual_before - 0.001 && route1_actual_after < problem.Max.Value && route2_actual_after < problem.Max.Value) { // there is improvement! original_solution = solution; //improvement = true; OsmSharp.Tools.Output.OutputStreamHost.WriteLine("IMPROVEMENT: {0}->{1}", route1_actual_before + route2_actual_before, route1_actual_after + route2_actual_after); } // select arc to be penalized. IRoute route1 = original_solution.Route(round_x); IRoute route2 = original_solution.Route(round_y); double u = double.MinValue; Edge penalizing_edge = new Edge(); double total_p = 0; foreach (Edge edge in route1.Edges()) { int edge_p; if (!penalizations.TryGetValue(edge, out edge_p)) { edge_p = 0; } total_p = total_p + edge_p; double edge_u = ((lambda * (double)edge_p) + problem.WeightMatrix[edge.From][edge.To]) / ((double)edge_p + 1.0); if (u <= edge_u) { penalizing_edge = edge; u = edge_u; } } foreach (Edge edge in route2.Edges()) { int edge_p; if (!penalizations.TryGetValue(edge, out edge_p)) { edge_p = 0; } total_p = total_p + edge_p; double edge_u = ((lambda * (double)edge_p) + problem.WeightMatrix[edge.From][edge.To]) / ((double)edge_p + 1.0); if (u <= edge_u) { penalizing_edge = edge; u = edge_u; } } // actually penalize the edge. int p; if (!penalizations.TryGetValue(penalizing_edge, out p)) { p = 1; } else { p++; } penalizations[penalizing_edge] = p; // evaluate or set tau. if (tau > double.MinValue) { // evaluate if penalizations should end. if (tau <= lambda * total_p) { // the penalization should end! break; } } else { // first edge being penalized. tau = lambda * problem.WeightMatrix[penalizing_edge.From][penalizing_edge.To] / 10; } } } } } } return original_solution; }