示例#1
0
        /// <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;
        }
示例#2
0
        /// <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;
        }