예제 #1
0
        public IEnumerable<int> FindRandomDisjointTour(IntegerPermutation otherTour)
        {
            this.InitializeVisit();
            this.tabuEdgeList = TabuEdgeCollection.CreateFromTour(otherTour);

            var randomEdge = this.GetRandomEdge();

            while (tabuEdgeList.IsTabu(randomEdge))
                randomEdge = this.GetRandomEdge();

            this.VisitNode(randomEdge.Head);
            yield return randomEdge.Head;

            this.VisitNode(randomEdge.Tail);
            yield return randomEdge.Tail;

            int currentNode = randomEdge.Tail;

            TaskLogger.Text = "Computing greedy and tabu search to generate a disjoint tour...";

            while (unvisitedNodes.ItemsCount > 0)
            {
                int nearestUnvisitedNode = this.FindNearestUnvisitedNonTabuNode(currentNode);

                this.VisitNode(nearestUnvisitedNode);
                yield return nearestUnvisitedNode;

                currentNode = nearestUnvisitedNode;

                TaskLogger.Progress = 100.0 * visitedNodes.ItemsCount / nodes.Length;
            }
        }
예제 #2
0
        public static TabuEdgeCollection CreateFromTour(IntegerPermutation otherTour)
        {
            var result = new TabuEdgeCollection();

            result.tabuDirectArcs = new int[otherTour.Length];
            result.tabuReverseArcs = new int[otherTour.Length];

            int upperBound = otherTour.Length - 1;

            for (int i = 0; i < upperBound; i++)
            {
                int head = otherTour[i];
                int tail = otherTour[i + 1];

                result.tabuDirectArcs[head] = tail;
                result.tabuReverseArcs[tail] = head;
            }

            result.tabuDirectArcs[otherTour[upperBound]] = otherTour[0];
            result.tabuReverseArcs[otherTour[0]] = otherTour[upperBound];

            return result;
        }
예제 #3
0
        public void CrossOptimize(IntegerPermutation solution, IntegerPermutation betterSolution)
        {
            var tabuList = TabuEdgeCollection.CreateFromTour(betterSolution);
            var currentDistance = nodes.GetDistance(solution);
            var betterDistance = nodes.GetDistance(betterSolution);
            int end = nodes.Length - 1;

            this.currentSolution = solution;
            this.betterSolution = betterSolution;
            this.tabuList = tabuList;

            double overallGain = 0, overallCost = 0;

            TaskLogger.Text = "Running cross 2-opt heuristic on both solutions...";

            for (int i = 0; i < end; i++)
            {
                for (int j = i + 2; j < end; j++)
                {
                    int a = solution[i];
                    int b = solution[i + 1];
                    int c = solution[j];
                    int d = solution[j + 1];

                    bool acTabu = tabuList.IsTabu(a, c);
                    bool bdTabu = tabuList.IsTabu(b, d);

                    // Only one edge can be swapped between solution, otherwise it's a mess
                    if (acTabu && bdTabu)
                        continue;

                    var acDistance = nodes.GetDistance(a, c);
                    var bdDistance = nodes.GetDistance(b, d);
                    var abDistance = nodes.GetDistance(a, b);
                    var cdDistance = nodes.GetDistance(c, d);

                    bool improvable = (acDistance + bdDistance < abDistance + cdDistance);

                    // If the solution cannot be improved, skip this
                    if (!improvable)
                        continue;

                    // If target edge switches are not prohibited, proceed as usual
                    if (!acTabu && !bdTabu)
                    {
                        solution.ReverseSubsequence(i + 1, j);
                    }
                    else
                    {
                        int startNode, middleNode, endNode;
                        double delta = 0;

                        if (acTabu)
                        {
                            startNode = a;
                            endNode = c;
                            middleNode = this.FindTwoEdgesPathMiddleNode(a, c);
                            delta = this.ComputeCostOfTraversing(a, middleNode, c);
                        }
                        else // if (bdTabu)
                        {
                            startNode = b;
                            endNode = d;
                            middleNode = this.FindTwoEdgesPathMiddleNode(b, d);
                            delta = this.ComputeCostOfTraversing(b, middleNode, d);
                        }

                        // Increase in distance of the best solution
                        var cost = delta;
                        // Decerase in distance of the second solution
                        var gain = (abDistance + cdDistance) - (acDistance + bdDistance);

                        if ((gain > 0) && (gain > cost))
                        {
                            var newBetterDistance = betterDistance + cost;
                            var newCurrentDistance = currentDistance - gain;

                            // By performing this move, the solution would be worse, so end here
                            if (newBetterDistance > newCurrentDistance)
                                return;

                            solution.ReverseSubsequence(i + 1, j);

                            int destinationIndex = betterSolution.IndexOf(endNode);
                            betterSolution.MoveBefore(middleNode, destinationIndex);

                            betterDistance = newBetterDistance;
                            currentDistance = newCurrentDistance;

                            overallGain += gain;
                            overallCost += cost;

                            TaskLogger.Text = String.Format("Overall gain: {0:N0}, Overall cost: {1:N0}", overallGain, overallCost);
                        }
                    }
                }

                TaskLogger.Progress = 100.0 * i / end;
            }
        }