예제 #1
0
        private static void PrintFinalSolution(Solution solution)
        {
            double totalDist = 0;

            StreamWriter sw = new StreamWriter("d:\\temp\\out.txt", false);
            string finalPath = "";
            foreach (Route route in solution.routes) {
                totalDist += route.totalDist;

                bool zeroCrossed = false;
                string part1 = "";
                string part2 = "";
                for (int i = 0; i < route.ids.Count; i++) {
                    if (route.ids[i] == 0) {
                        zeroCrossed = true;
                    } else {
                        if (zeroCrossed) {
                            part2 += route.ids[i] + " ";
                        } else {
                            part1 += route.ids[i] + " ";
                        }
                    }
                }

                string path = "0 " + part2.Trim() + " " + part1.Trim() + " 0";
                path = path.Replace("  ", " ");
                finalPath += path + "\r\n";

            }
            sw.WriteLine((int)totalDist + " 0");

            ////for (int i = 0; i < numTrucks - solution.routes.Count; i++) {
            ////    finalPath += "0 0\r\n";
            ////}

            sw.WriteLine(finalPath);

            sw.Close();
        }
예제 #2
0
        private static void PrintSolution(Solution solution)
        {
            double totalDist = 0;

            StreamWriter sw = new StreamWriter("d:\\temp\\vrp\\out\\" + problem + ".txt", false);

            foreach (Route route in solution.routes) {
                string thisPath = "";
                int truckId = route.truckId;
                double thisDist = route.totalDist;
                totalDist += thisDist;
                int thisCap = truckCapacity - route.unusedDemand;

                foreach (int id in route.ids) {
                    thisPath += id + " ";
                }

                string pathStr = String.Format("TruckId = {0} Dist = {1:N} DemandSatisfied = {2} :: Path = {3}", truckId, thisDist, thisCap, thisPath);
                Console.WriteLine(pathStr);
                sw.WriteLine(pathStr);
            }

            string totalDistStr = String.Format("Totaldist = {0:N}", totalDist);
            Console.WriteLine(totalDistStr);
            sw.WriteLine(totalDistStr);

            sw.Close();
        }
예제 #3
0
        //Take pairs of points (p1,p2) from 2 trucks and try to swap them if the capacity
        //constraints are satisfied. Now perform 2-opt on both the trucks and report new neighbour
        //if the cost is improved.
        private static Solution LS2(Solution basicSoln)
        {
            int currLs2Count = 0;
            Solution currBestSol = basicSoln;
            bool doMore = true;
            while (doMore && currLs2Count++ < LS2Count) {
                Console.Write("\n\tLS2 : Trial " + currLs2Count + " ");
                double costSavings = 0;
                int t1 = 0, t2 = 0;
                int nodei = 0, nodej = 0;

                Solution betterSol = LS2Step(currBestSol, ref costSavings, ref t1, ref t2, ref nodei, ref nodej, true);
                if (betterSol == null) {
                    doMore = false;
                } else {
                    currBestSol = betterSol;
                    Console.Write(" : Move a point from {0} to {1} for cost savings = {2:N} :: Curr Total Cost = {3:N}", t1, t2, costSavings, GetSolutionCost(currBestSol));
                }
            }
            return currBestSol;
        }
예제 #4
0
        private static Solution LS2Step(Solution basicSoln, ref double costSavings, ref int trucki, ref int truckj, ref int nodei, ref int nodej, bool exploreAll)
        {
            Solution betterSol = new Solution();
            costSavings = 0;

            bool foundBetter = false;
            /*try to swap nodes pi and pj between truck_i and truck_j if the capccity constraints are satisfied*/
            Route iRoute, jRoute;
            for (int i = 0; i < numTrucks - 1; i++) {
                iRoute = basicSoln.routes[i];
                int freeCapacityIni = iRoute.unusedDemand;
                for (int j = i + 1; j < numTrucks; j++) {
                    jRoute = basicSoln.routes[j];
                    int freeCapacityInj = jRoute.unusedDemand;

                    if (iRoute.ids.Count == 0 || jRoute.ids.Count == 0) continue;

                    double origCost = iRoute.totalDist + jRoute.totalDist;

                    for (int piIdx = 0; piIdx < iRoute.ids.Count; piIdx++) {
                        int pi = iRoute.ids[piIdx];
                        if (pi == 0) continue;

                        for (int pjIdx = 0; pjIdx < jRoute.ids.Count; pjIdx++) {
                            int pj = jRoute.ids[pjIdx];
                            if (pj == 0) continue;

                            int demi = demands[pi];
                            int demj = demands[pj];

                            if ((freeCapacityIni + demi - demj >= 0) && (freeCapacityInj + demj - demi >= 0)) {
                                List<int> newiPath = new List<int>(iRoute.ids);
                                newiPath.Remove(pi);
                                newiPath.Add(pj);

                                List<int> newjPath = new List<int>(jRoute.ids);
                                newjPath.Remove(pj);
                                newjPath.Add(pi);

                                bool foundBetteri = false, foundBetterj = false;
                                double newLeni = 0, newLenj = 0;
                                int[] betteriRoute = TwoOpt(newiPath.ToArray(), ref foundBetteri, ref newLeni, false);
                                int[] betterjRoute = TwoOpt(newjPath.ToArray(), ref foundBetterj, ref newLenj, false);

                                double newCost = newLeni + newLenj;

                                double thisCostSavings = origCost - newCost;
                                if (thisCostSavings > 0.000001) {

                                    if (thisCostSavings > costSavings) {
                                        costSavings = thisCostSavings;

                                        trucki = i;
                                        truckj = j;
                                        nodei = pi;
                                        nodej = pj;

                                        foundBetter = true;

                                        Route newiRoute = new Route();
                                        if (foundBetteri && betteriRoute != null) {
                                            newiRoute.ids = betteriRoute.ToList();
                                        } else {
                                            newiRoute.ids = newiPath;
                                        }
                                        newiRoute.totalDist = newLeni;
                                        newiRoute.truckId = iRoute.truckId;
                                        newiRoute.unusedDemand = iRoute.unusedDemand + demi - demj;

                                        Route newjRoute = new Route();
                                        if (foundBetterj && betterjRoute != null) {
                                            newjRoute.ids = betterjRoute.ToList();
                                        } else {
                                            newjRoute.ids = newjPath;
                                        }
                                        newjRoute.totalDist = newLenj;
                                        newjRoute.truckId = jRoute.truckId;
                                        newjRoute.unusedDemand = jRoute.unusedDemand + demj - demi;

                                        betterSol = new Solution();
                                        //create the new solution with modified i and j routes
                                        for (int t = 0; t < basicSoln.routes.Count; t++) {
                                            if (t == i) {
                                                betterSol.routes.Add(newiRoute);
                                            } else if (t == j) {
                                                betterSol.routes.Add(newjRoute);
                                            } else {
                                                betterSol.routes.Add(basicSoln.routes[t]);
                                            }
                                        }

                                        if (!exploreAll) {
                                            goto end;
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }

            end:
            if (foundBetter) {
                return betterSol;
            } else {
                return null;
            }
        }
예제 #5
0
        //Take p2 from route1 and add to route2 if the capacity constraints are satisfied in route2
        //Then, via a sequence of 2-opt moves in route2 and route1, optimize both the routes.
        //if(new_dist_r2+new_dist_r1 < old_dist_r2_old_dist_r1), then we got a better neighbour
        private static Solution LS1(Solution basicSoln)
        {
            int currLs1Count = 0;
            Solution currBestSol = basicSoln;
            bool doMore = true;
            while (doMore && currLs1Count++ < LS1Count) {
                Console.Write("\n\tLS1 : Trial " + currLs1Count + " ");
                double costSavings = 0;
                int t1 = 0, t2 = 0;

                Solution betterSol = LS1Step(currBestSol, ref costSavings, ref t1, ref t2);
                if (betterSol == null) {
                    doMore = false;
                } else {
                    currBestSol = betterSol;
                    Console.Write(" : Move a point from {0} to {1} for cost savings = {2:N}", t1, t2, costSavings);
                }
            }
            return currBestSol;
        }
예제 #6
0
        //Perform 2-OPT optimization for all the routes in the basic solution
        //return the optimized solution if one is found.
        private static Solution LS0(Solution basicSoln)
        {
            Solution newSol = new Solution();
            for (int i = 0; i < basicSoln.routes.Count; i++) {
                Route thisRoute = basicSoln.routes[i];
                Console.WriteLine("\tLS 0 : Truck : " + thisRoute.truckId);

                int currCount = 0;
                bool doMore = true;
                Route bestRouteSoFarForThisTruck = thisRoute;
                while (doMore && currCount++ < LS0Count) {
                    double costSavings = 0;
                    Route newRoute = TwoOpt(bestRouteSoFarForThisTruck, ref costSavings);
                    if (newRoute == null) {
                        doMore = false;
                    } else {
                        bestRouteSoFarForThisTruck = newRoute;
                    }
                }
                newSol.routes.Add(bestRouteSoFarForThisTruck);
            }
            return newSol;
        }
예제 #7
0
 private static double GetSolutionCost(Solution solution)
 {
     double totalDist = 0;
     foreach (Route route in solution.routes) {
         totalDist += route.totalDist;
     }
     return totalDist;
 }
예제 #8
0
        private static Solution GetInitialFeasibleSolution(NodeInfo[] nodes)
        {
            Solution soln = new Solution();

            int currTruck = 1;
            bool allDemandSatisfied = false;
            HashSet<int> assignedNodes = new HashSet<int>();
            while (!allDemandSatisfied && currTruck <= numTrucks) {
                int availableCap = truckCapacity;
                //iterate over each of the nodes and if any node has not been assigned yet
                //to any truck and the capacity constraints of the truck are satisfied, then
                //assign this node to this truck.
                Route thisRoute = new Route();
                thisRoute.ids.Add(0);
                thisRoute.truckId = currTruck;
                thisRoute.unusedDemand = availableCap;

                for (int i = 0; i < nodes.Length; i++) {
                    if (nodes[i].id != 0) {
                        int thisNodeId = nodes[i].id;
                        int thisNodeDemand = demands[thisNodeId];
                        if (!assignedNodes.Contains(thisNodeId) && availableCap >= thisNodeDemand) {
                            availableCap -= thisNodeDemand;
                            assignedNodes.Add(thisNodeId);

                            thisRoute.ids.Add(thisNodeId);
                            thisRoute.unusedDemand = availableCap;

                            if (assignedNodes.Count == nodes.Length - 1) {
                                allDemandSatisfied = true;
                                break;
                            }
                        }
                    }
                }
                //thisRoute.ids.Add(0); /*to keep it consistent with tsp routines*/
                CalculateRouteDistance(thisRoute);
                soln.routes.Add(thisRoute);
                currTruck++;
            }

            if (!allDemandSatisfied) {
                return null;
            } else {

                //fill up additional trucks with path : 0-0
                int usedTrucks = soln.routes.Count;
                for (int i = 0; i < numTrucks - usedTrucks; i++) {
                    soln.routes.Add(new Route() {
                        ids = new List<int>() {0},
                        totalDist = 0,
                        unusedDemand = truckCapacity,
                        truckId = currTruck++
                    });
                }

                return soln;
            }
        }
예제 #9
-1
        private static Solution LS1Step(Solution basicSoln, ref double costSavings, ref int trucki, ref int truckj)
        {
            Solution betterSol = new Solution();

            bool foundBetter = false;
            /*try to move a node from truck_i to truck_j if the capccity constraints are satisfied*/
            Route iRoute, jRoute;
            for (int i = 0; i < numTrucks; i++) {
                iRoute = basicSoln.routes[i];
                for (int j = 0; j < numTrucks; j++) {
                    jRoute = basicSoln.routes[j];
                    int freeCapacityInj = jRoute.unusedDemand;

                    if (i == j) continue;
                    if (freeCapacityInj == 0) continue;
                    if (iRoute.ids.Count == 0) continue;

                    List<int> idsToProbe = iRoute.ids.Where(x => x != 0 && demands[x] <= freeCapacityInj).ToList();
                    for (int k = 0; k < idsToProbe.Count; k++) {
                        if (idsToProbe[k] != 0) { /*we cannot move the origin from i to j*/
                            int demandOfThisPointIni = demands[idsToProbe[k]];
                            if (freeCapacityInj >= demandOfThisPointIni) { /*capccity constraints are satisfied*/

                                /*move ids[k] from truck_i to truck_j*/
                                List<int> newiPath = new List<int>(iRoute.ids);
                                newiPath.Remove(idsToProbe[k]); ;

                                List<int> newjPath = new List<int>(jRoute.ids);
                                newjPath.Add(idsToProbe[k]);

                                double origCost = iRoute.totalDist + jRoute.totalDist;

                                bool foundBetteri = false, foundBetterj =false;
                                double newLeni = 0, newLenj = 0;
                                int[] betteriRoute = TwoOpt(newiPath.ToArray(), ref foundBetteri, ref newLeni, false);
                                int[] betterjRoute = TwoOpt(newjPath.ToArray(), ref foundBetterj, ref newLenj, false);

                                double newCost = newLeni + newLenj;

                                costSavings = origCost-newCost;
                                if (costSavings > 0.000001) {

                                    trucki = i;
                                    truckj = j;

                                    foundBetter = true;

                                    Route newiRoute = new Route();
                                    if (foundBetteri && betteriRoute != null) {
                                        newiRoute.ids = betteriRoute.ToList();
                                    } else {
                                        newiRoute.ids = iRoute.ids;
                                    }
                                    newiRoute.totalDist = newLeni;
                                    newiRoute.truckId = iRoute.truckId;
                                    newiRoute.unusedDemand = iRoute.unusedDemand + demandOfThisPointIni;

                                    Route newjRoute = new Route();
                                    if (foundBetterj && betterjRoute != null) {
                                        newjRoute.ids = betterjRoute.ToList();
                                    } else {
                                        newjRoute.ids = jRoute.ids;
                                    }
                                    newjRoute.totalDist = newLenj;
                                    newjRoute.truckId = jRoute.truckId;
                                    newjRoute.unusedDemand = jRoute.unusedDemand - demandOfThisPointIni;

                                    //create the new solution with modified i and j routes
                                    for (int t = 0; t < basicSoln.routes.Count; t++) {
                                        if (t == i) {
                                            betterSol.routes.Add(newiRoute);
                                        } else if (t == j) {
                                            betterSol.routes.Add(newjRoute);
                                        } else {
                                            betterSol.routes.Add(basicSoln.routes[t]);
                                        }
                                    }

                                    goto end;
                                }

                            }
                        }
                    }
                }
            }

            end:
            if (foundBetter) {
                return betterSol;
            } else {
                return null;
            }
        }