예제 #1
0
        //Perform a 2-opt optimization on the given route and return the new route
        private static Route TwoOpt(Route orig, ref double costSavings)
        {
            /*for empty trucks, we cannot find a better path*/
            if (orig.ids.Count == 0) {
                return null;
            } else {
                bool foundBetter = false;
                double newLen = 0;
                int[] betterPath = TwoOpt(orig.ids.ToArray(), ref foundBetter, ref newLen, false);

                if (foundBetter) {
                    Console.WriteLine("** Truck Id {0} : New best Route len : {1:N} Savings = {2:N}", orig.truckId, newLen, newLen - orig.totalDist);
                    costSavings = orig.totalDist - newLen;
                    return new Route() {
                        ids = betterPath.ToList(),
                        totalDist = newLen,
                        truckId = orig.truckId,
                        unusedDemand = orig.unusedDemand
                    };
                } else {
                    costSavings = 0;
                    return null;
                }
            }
        }
예제 #2
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;
            }
        }
예제 #3
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;
            }
        }
예제 #4
0
        private static void CalculateRouteDistance(Route route)
        {
            double dist = 0;
            /*from origin till last node*/
            for (int i = 0; i < route.ids.Count - 1; i++) {
                dist += distMatrix[route.ids[i], route.ids[i + 1]];
            }

            dist += distMatrix[route.ids[route.ids.Count - 1], route.ids[0]]; /*add last node to origin*/
            route.totalDist = dist;
        }
예제 #5
-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;
            }
        }