Ejemplo n.º 1
0
        /*
         *  procedure Greedy Randomized Construction(α, Seed)
         *      1 Solution ← ∅;
         *      2 Initialize the candidate set: C ← E;
         *      3 Evaluate the incremental cost c(e) for all e ∈ C;
         *      4 while C 6= ∅ do
         *      5 cMin ← min{c(e) | e ∈ C};
         *      6 cMax ← max{c(e) | e ∈ C};
         *      7 RCL ← {e ∈ C | c(e) ≤ cMin + α(cMax − cMin)};
         *      8 Select an element s from the RCL at random;
         *      9 Solution ← Solution ∪ {s};
         *      10 Update the candidate set C;
         *      11 Reevaluate the incremental costs c(e) for all e ∈ C;
         *      12 end;
         *      13 return Solution;
         *  end Greedy Randomized Construction.
         */

        public static VCRPSolution GreedyRandomizedSolution(double alpha, int seed)
        {
            // Instanciate solution
            VCRPSolution solution = new VCRPSolution(VCRPInstance.n_vehicles, VCRPInstance.n_nodes);

            // Get all clients as candidates for candidatesSet; Cost(Depot -> Client)
            List <Tuple <int, int, double> > candidatesSet = getCandidates();

            // Restricted Candidate List (RCL)
            List <Tuple <int, int, double> > RCL = new List <Tuple <int, int, double> >();

            // Instanciate random
            Random rand = new Random();

            while (candidatesSet.Count != 0)
            {
                // Evaluate Min and Max cost of the candidatesSet
                Tuple <double, double> cMinMax = getcMinMax(candidatesSet);
                double cMin = cMinMax.Item1;
                double cMax = cMinMax.Item2;

                // Creates new RCL
                foreach (var candidate in candidatesSet)
                {
                    double currentCost = candidate.Item3;
                    if (currentCost <= cMin + alpha * (cMax - cMin))
                    {
                        RCL.Add(candidate);
                    }
                }

                // Select a random candidate from RCL ; Candidate = <Client,Vehicle,Cost>
                int chosenIndex = rand.Next(0, RCL.Count - 1);
                Tuple <int, int, double> chosenCandidate = RCL.ElementAt(chosenIndex);

                // Check if it's feasible to insert the candidate in the solution
                insertSolutionElement(chosenCandidate, solution);

                // Remove chosen candidate from candidateSet
                candidatesSet.RemoveAll(candidate => candidate.Item1 == chosenCandidate.Item1);

                // List of elements to update cost, where route is the same of the chosenCandidate
                IEnumerable <Tuple <int, int, double> > candidatesToUpdate = candidatesSet.Where(candidate => candidate.Item2 == chosenCandidate.Item2);
                List <Tuple <int, int, double> >        candidatesToInsert = new List <Tuple <int, int, double> >();
                foreach (var candidate in candidatesToUpdate)
                {
                    double newCost = VCRPInstance.weight_matrix[chosenCandidate.Item1, candidate.Item1];
                    candidatesToInsert.Add(Tuple.Create(candidate.Item1, candidate.Item2, newCost));
                }
                candidatesSet.RemoveAll(candidate => candidate.Item2 == chosenCandidate.Item2);
                candidatesSet.AddRange(candidatesToInsert);

                // Clear RCL
                RCL.Clear();
            }
            // Routes must return to depot
            addDepotToRoutes(solution);

            return(solution);
        }
Ejemplo n.º 2
0
        public static Tuple <double, int> Inter10(VCRPSolution solution, int client, int brokenRouteIndex, int k)
        {
            //passa c1 de k1 para k2, na melhor posicao possivel. Nao aplica realmente, só calcula
            List <int> modifiedRoute = solution.routes[k];

            int clientPosition = solution.routes[brokenRouteIndex].IndexOf(client);

            Tuple <double, int> move = new Tuple <double, int>(double.MaxValue, -1);

            // Get best client to insert before
            for (int i = 1; i < modifiedRoute.Count() - 1; i++)
            {
                double cost = solution.cost;

                // Remove cost of old link
                cost -= (VCRPInstance.weight_matrix[modifiedRoute.ElementAt(i - 1), modifiedRoute.ElementAt(i)]);

                // Costs of inserting client
                cost += (VCRPInstance.weight_matrix[modifiedRoute.ElementAt(i - 1), client]);
                cost += (VCRPInstance.weight_matrix[client, modifiedRoute.ElementAt(i)]);

                // New vert in the broken route
                cost += (VCRPInstance.weight_matrix[solution.routes[brokenRouteIndex][clientPosition - 1], solution.routes[brokenRouteIndex][clientPosition + 1]]);

                // Costs of removing client from broken route
                cost -= (VCRPInstance.weight_matrix[solution.routes[brokenRouteIndex].ElementAt(clientPosition - 1), client]);
                cost -= (VCRPInstance.weight_matrix[client, solution.routes[brokenRouteIndex].ElementAt(clientPosition + 1)]);

                if (cost < move.Item1)
                {
                    move = new Tuple <double, int>(cost, i);
                }
            }
            return(move);
        }
 private static void updateBestSolution(VCRPSolution bestSolution, VCRPSolution newSolution)
 {
     if (bestSolution.cost > newSolution.cost)
     {
         bestSolution.cost   = newSolution.cost;
         bestSolution.routes = newSolution.routes;
     }
 }
Ejemplo n.º 4
0
        // Force routes to return to depot and add the corresponding cost
        public static void addDepotToRoutes(VCRPSolution solution)
        {
            for (int k = 0; k < VCRPInstance.n_vehicles; k++)
            {
                int lastClient = solution.routes[k].Last();

                solution.routes[k].Add(VCRPInstance.depot);
                solution.cost += VCRPInstance.weight_matrix[lastClient, VCRPInstance.depot];
            }
        }
Ejemplo n.º 5
0
        public static void LocalSearch(VCRPSolution solution)
        {
            // Execute 2-opt for each route of the current solution
            double newTotalCost = 0;

            for (int k = 0; k < VCRPInstance.n_vehicles; k++)
            {
                newTotalCost += TwoOpt(solution.routes[k]);
            }

            solution.cost = newTotalCost;
        }
Ejemplo n.º 6
0
        static void Main(string[] args)
        {
            Console.Clear();
            Console.WriteLine("=========================================================================");
            Console.WriteLine("Capacitated Vehicle Routing Problem (CVRP) with GRASP \n Mateus Riad (228157) \n Ricardo Pires (208784) \n");
            Console.WriteLine("(All the instances can be found inside this project, dir: instances) \n");
            Console.WriteLine("=========================================================================");
            Console.WriteLine("Name of the instance to execute: ");
            string fileName = Console.ReadLine();

            // Pega as informaçoes do arquivo de instancia passado
            Parser.parserFile(fileName);

            Console.WriteLine("=== EXECUTING GRASP ===\n");
            // Inicializa timer
            Stopwatch stopWatch = new Stopwatch();

            stopWatch.Start();

            // GRASP
            VCRPInstance instance     = new VCRPInstance();
            VCRPSolution bestSolution = Grasp.Execute(instance);

            stopWatch.Stop();

            Console.WriteLine("=== SOLUTION FOUND ===\n");
            Console.WriteLine("Best solution found: " + bestSolution.cost);
            Console.WriteLine("Executiond Time:" + stopWatch.Elapsed + " seconds.");

            for (int k = 0; k < VCRPInstance.n_vehicles; k++)
            {
                Console.Write("Rota " + k + ":");
                List <int> range = bestSolution.routes[k];
                foreach (int value in range)
                {
                    Console.Write(value + " - ");
                }
                Console.WriteLine("\n");
            }


            string wait = Console.ReadLine();
        }
        public static VCRPSolution Execute(VCRPInstance instance)
        {
            /*
             * procedure GRASP(Max Iterations,Seed)
             *  1 Read Input();
             *  2 for k = 1, . . . , Max Iterations do
             *  3 Solution ← Greedy Randomized Construction(Seed);
             *  4 Solution ← Local Search(Solution);
             *  5 Update Solution(Solution,Best Solution);
             *  6 end;
             *  7 return Best Solution;
             * end GRASP.
             */

            // Grasp Parameters
            int    maxIterations = 200;
            double alpha         = 1;
            int    seed          = 0; // ?

            // Initialize best solution with worst cost
            const int    worstSolution = UInt16.MaxValue;
            VCRPSolution bestSolution  = new VCRPSolution(VCRPInstance.n_vehicles, VCRPInstance.n_nodes);

            bestSolution.cost = worstSolution;

            // Solution instance used for grasp iterations
            VCRPSolution currentSolution;

            for (int k = 0; k < maxIterations; k++)
            {
                // Constructive Heuristic Phase
                currentSolution = GreedyRandomizedSolution(alpha, seed);

                Console.WriteLine("=============================================\n");
                Console.WriteLine("GREEDY - INITIAL SOLUTION\n");
                for (int v = 0; v < VCRPInstance.n_vehicles; v++)
                {
                    Console.Write("Rota " + v + ": ");
                    List <int> range = currentSolution.routes[v];
                    foreach (int value in range)
                    {
                        Console.Write(value + " - ");
                    }
                    Console.WriteLine("\n");
                }
                Console.WriteLine("Custo total: " + currentSolution.cost + "\n");

                // Check and repair solution in case it's not feasible (YET!)
                GreedyPostProcessing(currentSolution);

                Console.WriteLine("=============================================\n");
                Console.WriteLine("GREEDY - POST PROCESSING\n");
                for (int v = 0; v < VCRPInstance.n_vehicles; v++)
                {
                    Console.Write("Rota " + v + ":");
                    List <int> range = currentSolution.routes[v];
                    foreach (int value in range)
                    {
                        Console.Write(value + " - ");
                    }
                    Console.WriteLine(getRouteDemand(currentSolution.routes[v]));
                    Console.WriteLine("\n");
                }
                Console.WriteLine("Custo total: " + currentSolution.cost + "\n");

                // Local Search
                //LocalSearch(currentSolution);

                /*
                 * Console.WriteLine("=============================================\n");
                 * Console.WriteLine("AFTER LOCAL SEARCH\n");
                 * for (int v = 0; v < VCRPInstance.n_vehicles; v++)
                 * {
                 *  Console.Write("Rota " + v + ": ");
                 *  List<int> range = currentSolution.routes[v];
                 *  foreach (int value in range)
                 *  {
                 *      Console.Write(value + " - ");
                 *  }
                 *  Console.WriteLine("\n");
                 * }*/
                // Check and update best solution
                updateBestSolution(bestSolution, currentSolution);
            }

            return(bestSolution);
        }
Ejemplo n.º 8
0
        // Insert new element in the current solution
        public static void insertSolutionElement(Tuple <int, int, double> currentCandidate, VCRPSolution solution)
        {
            int    client = currentCandidate.Item1;
            int    route  = currentCandidate.Item2;
            double cost   = currentCandidate.Item3;

            solution.routes[route].Add(client);
            solution.cost += cost;
        }
Ejemplo n.º 9
0
        // Check if solution is feasible and repair it if not
        public static void GreedyPostProcessing(VCRPSolution solution)
        {
            // List contains the total sum of demands in each route
            int[] routesDemand = new int[VCRPInstance.n_vehicles];
            // List of unfeasible routes and it's excess over capacity
            List <int> brokenRoutes = new List <int>();

            int[] excessError = new int[VCRPInstance.n_vehicles];

            // get sum of client's demand for each route
            for (int k = 0; k < VCRPInstance.n_vehicles; k++)
            {
                int currentRouteDemand = getRouteDemand(solution.routes[k]);
                Console.Write(currentRouteDemand + " - ");
                routesDemand[k] = currentRouteDemand;
                if (currentRouteDemand > VCRPInstance.g_capacity)
                {
                    brokenRoutes.Add(k);
                    excessError[k] = currentRouteDemand - VCRPInstance.g_capacity;
                }
            }

            // TODO: Kill them!
            Tuple <double, int, int, int, int> bestFact = new Tuple <double, int, int, int, int>(double.MaxValue, -1, -1, -1, -1);
            Tuple <double, int, int, int, int> bestF    = new Tuple <double, int, int, int, int>(double.MaxValue, -1, -1, -1, -1);

            // If there is any item in brokenRoutes, current solution is not feasible;
            // Then repair it;
            while (brokenRoutes.Count != 0)
            {
                Console.WriteLine("Count: " + brokenRoutes.Count);
                // Find movement to improve feasibility of current solution
                foreach (int brokenRouteIndex in brokenRoutes)
                {
                    Console.WriteLine("Broken: " + brokenRouteIndex);
                    for (int k = 0; k < VCRPInstance.n_vehicles; k++)
                    {
                        int a = routesDemand[k];

                        // check movement to another route
                        if (brokenRouteIndex != k)
                        {
                            // One of the clients can reduce excessError?
                            foreach (int client in solution.routes[brokenRouteIndex].Where(x => x > 0))
                            {
                                int b = VCRPInstance.nodes[client].demand;
                                // Check if the demand of a client inside a broken route can be inserted in a feasible route without breaking it
                                if (VCRPInstance.nodes[client].demand + routesDemand[k] <= VCRPInstance.g_capacity)
                                {
                                    if (routesDemand[brokenRouteIndex] - VCRPInstance.nodes[client].demand <= VCRPInstance.g_capacity)
                                    {
                                        // Get best movement
                                        Tuple <double, int> movement = Inter10(solution, client, brokenRouteIndex, k);
                                        if (bestFact.Item1 > movement.Item1)
                                        {
                                            bestFact = new Tuple <double, int, int, int, int>(movement.Item1, movement.Item2, client, k, brokenRouteIndex);
                                        }
                                    }
                                }
                                if (VCRPInstance.nodes[client].demand + routesDemand[k] <= VCRPInstance.g_capacity)
                                {
                                    if (routesDemand[brokenRouteIndex] - VCRPInstance.nodes[client].demand > VCRPInstance.g_capacity)
                                    {
                                        Tuple <double, int> movement = Inter10(solution, client, brokenRouteIndex, k);
                                        // Movement reduces excess error
                                        if (bestF.Item1 > movement.Item1)
                                        {
                                            bestF = new Tuple <double, int, int, int, int>(movement.Item1, movement.Item2, client, k, brokenRouteIndex);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }

                // Execute movement
                // There is a movement that makes broken route feasible without breaking another one
                if (bestFact.Item2 != -1 && brokenRoutes.Contains(bestFact.Item5))
                {
                    // Update solution and remove route from brokenRoutes
                    Console.WriteLine("Movimento pra resolver o erro! Rota: " + bestFact.Item5);
                    solution.cost = bestFact.Item1;

                    // Insert client in a new route / Remove it from current
                    solution.routes[bestFact.Item4].Insert(bestFact.Item2, bestFact.Item3);
                    solution.routes[bestFact.Item5].Remove(bestFact.Item3);

                    // Now, route if feasible
                    brokenRoutes.Remove(bestFact.Item5);

                    // Update Demands
                    routesDemand[bestFact.Item4] += VCRPInstance.nodes[bestFact.Item3].demand;
                    routesDemand[bestFact.Item5] -= VCRPInstance.nodes[bestFact.Item3].demand;

                    bestFact = new Tuple <double, int, int, int, int>(double.MaxValue, -1, -1, -1, -1);
                }
                else if (bestF.Item2 != -1)
                {
                    Console.WriteLine("Movimento pra reduzir o erro rota:" + bestF.Item5);
                    solution.cost = bestF.Item1;

                    // Insert client in a new route / Remove it from current
                    solution.routes[bestF.Item4].Insert(bestF.Item2, bestF.Item3);
                    solution.routes[bestF.Item5].Remove(bestF.Item3);

                    // Update Demands
                    routesDemand[bestF.Item4] += VCRPInstance.nodes[bestF.Item3].demand;
                    routesDemand[bestF.Item5] -= VCRPInstance.nodes[bestF.Item3].demand;

                    // Inserting in a route that reduce excess error but breaks it
                    if (!brokenRoutes.Contains(bestF.Item4))
                    {
                        brokenRoutes.Add(bestF.Item4);
                    }

                    bestF = new Tuple <double, int, int, int, int>(double.MaxValue, -1, -1, -1, -1);
                }
            }
        }