コード例 #1
0
ファイル: ProblemAndSolver.cs プロジェクト: tnelsonw/TSP
        private Node getPartialRoute(Node node, int rowNum, int colNum)
        {
            double[,] updated = new double[Cities.Length, Cities.Length];
            for (int i = 0; i < Cities.Length; i++)
            {
                for (int k = 0; k < Cities.Length; k++)
                {
                    updated[i, k] = node.getMatrix()[i, k];
                }
            }
            ArrayList partialRoute = new ArrayList();

            for (int i = 0; i < node.getRoute().Count; i++)
            {
                partialRoute.Add(node.getRoute()[i]);
            }

            double newbssf = node.getbssf() + node.getMatrix()[rowNum, colNum];

            for (int i = 0; i < Cities.Length; i++)
            {
                updated[rowNum, i] = double.PositiveInfinity;
                updated[i, colNum] = double.PositiveInfinity;
            }
            updated[rowNum, colNum] = double.PositiveInfinity;
            updated[colNum, rowNum] = double.PositiveInfinity;
            partialRoute.Add(Cities[colNum]);
            Node newNode = new Node(newbssf, updated, partialRoute);

            newNode.setNum(colNum);
            return(reduceMatrix(newNode));
        }
コード例 #2
0
ファイル: ProblemAndSolver.cs プロジェクト: tnelsonw/TSP
        private Node reduceMatrix(Node node)
        {
            double[,] updated = new double[Cities.Length, Cities.Length];
            double updatedbssf = node.getbssf();

            for (int i = 0; i < Cities.Length; i++)
            {
                for (int k = 0; k < Cities.Length; k++)
                {
                    updated[i, k] = node.getMatrix()[i, k];
                }
            }

            for (int i = 0; i < Cities.Length; i++)     //for each row
            {
                double min = double.PositiveInfinity;
                for (int k = 0; k < Cities.Length; k++)     //get minimum for each row
                {
                    if (updated[i, k] < min)
                    {
                        min = updated[i, k];
                    }
                }
                if (min != 0 && min != double.PositiveInfinity)
                {
                    for (int k = 0; k < Cities.Length; k++) //subtract minimum from each value
                    {
                        updated[i, k] -= min;
                    }
                    updatedbssf += min;
                }
            }

            for (int i = 0; i < Cities.Length; i++)     //for each column
            {
                double min = double.PositiveInfinity;
                for (int k = 0; k < Cities.Length; k++)     //get minimum for each column
                {
                    if (updated[k, i] < min)
                    {
                        min = updated[k, i];
                    }
                }
                if (min != 0 && min != double.PositiveInfinity)
                {
                    for (int k = 0; k < Cities.Length; k++) //subtract minimum from each value
                    {
                        updated[k, i] -= min;
                    }
                    updatedbssf += min;
                }
            }
            Node newNode = new Node(updatedbssf, updated, node.getRoute());

            newNode.setNum(node.getNum());
            return(newNode);
        }
コード例 #3
0
        /// <summary>
        ///  solve the problem.  This is the entry point for the solver when the run button is clicked
        /// right now it just picks a simple solution.
        /// </summary>
        public void solveProblem()
        {
            Stopwatch timer = new Stopwatch();

            timer.Start();

            l = Cities.Length;

            includeMatrix = new double[l, l];

            double[,] costMatrix = new double[l, l];


            //make the initial cost matrix
            for (int i = 0; i < l; i++)
            {
                for (int j = 0; j < l; j++)
                {
                    if (i == j)
                    {
                        costMatrix[i, j] = double.PositiveInfinity;
                    }
                    else
                    {
                        costMatrix[i, j] = Cities[i].costToGetTo(Cities[j]);
                    }
                }
            }



            //use greedy algorithm to get an initial bssf
            int startIndex = 0;

            while (bssF == double.PositiveInfinity)
            {
                bssF = greedy(costMatrix, startIndex);
                startIndex++;
            }

            //reduce the original cost Matrix
            double cost = reduceMatrix(costMatrix);



            //---------------------------------------------------------
            //put a starter node on the heap with the reduced cost and the matrix,
            //       an empty path, and and edgeCount of 0
            //----------------------------------------------------------
            BinaryHeap bh = new BinaryHeap(heapSize);

            int[] pathArray = new int[l];

            for (int i = 0; i < l; i++)
            {
                pathArray[i] = -1;
            }

            bh.insert(new Node(cost, costMatrix, pathArray, 0));



            //while queue is not empty
            while (bh.getQueueSize() > 0)
            {
                //since we increase the number of states whether or not they are put on the queue
                numStatesCreated += 2;

                //pop the lowest cost node off the queue
                Node n = bh.deleteMin();

                int[] nodePath = n.getPathArray();


                //this should be a valid path, we successfully included enough edges
                if (n.getEdgeCount() == l)
                {
                    //update bssf, path,
                    bssF          = n.getKey();
                    bestPathSoFar = n.getPathArray();

                    //keep track of updates
                    numBSSFupdates++;



                    BinaryHeap temp = new BinaryHeap(heapSize);

                    int preCount = bh.getQueueSize();

                    // go through the queue and get rid of too high LB's
                    while (bh.getQueueSize() > 0)
                    {
                        Node node = bh.deleteMin();

                        if (node.getKey() < bssF)
                        {
                            temp.insert(node);
                        }

                        bh = temp;
                    }

                    //when I tried to increment numStatesPruned in the while loop it was optimized out
                    //  or something, so this is where I find out how many states I pruned
                    int postCount = bh.getQueueSize();
                    numStatesPruned += preCount - postCount;
                }
                else
                {
                    //was not a complete path.  We now go to the method that makes an include and exclude state
                    splitDecision(n.getMatrix(), nodePath, n.getEdgeCount());


                    //check to see if an include improved the bssf
                    //if not do nothing, don't put it on the queue
                    if (((n.getKey() + maxInclude) < bssF))
                    {
                        int[] includePath = new int[l];

                        //must make a copy of the path array since our queue might be expanding
                        for (int i = 0; i < includePath.Length; i++)
                        {
                            includePath[i] = nodePath[i];
                        }

                        //includes one edge
                        includePath[maxI] = maxJ;

                        //we must also make a copy of the cost matrix
                        double[,] copyIncludeMatrix = new double[l, l];

                        if (includeMatrix != null)
                        {
                            for (int i = 0; i < l; i++)
                            {
                                for (int j = 0; j < l; j++)
                                {
                                    copyIncludeMatrix[i, j] = includeMatrix[i, j];
                                }
                            }
                        }

                        Node includeNode = new Node(n.getKey() + maxInclude, copyIncludeMatrix, includePath, n.getEdgeCount() + 1);
                        bh.insert(includeNode);
                    }
                    else
                    {
                        numStatesPruned++;
                    }

                    //only insert the exclude state if the lower bound is less than bssf
                    if ((n.getKey() + maxExclude < bssF) && (bh.getQueueSize() < queueLimit))
                    {
                        //save some time by just using the parents' path and almost the parent's cost matrix
                        n.getMatrix()[maxI, maxJ] = double.PositiveInfinity;
                        reduceMatrix(n.getMatrix());

                        Node excludeNode = new Node(n.getKey() + maxExclude, n.getMatrix(), nodePath, n.getEdgeCount());
                        bh.insert(excludeNode);
                    }
                    else
                    {
                        numStatesPruned++;
                    }
                }

                //keep track of the highest number of stored states
                if (bh.getQueueSize() > maxQueueSize)
                {
                    maxQueueSize = bh.getQueueSize();
                }

                //time out after 30 seconds
                if (timer.ElapsedMilliseconds > 30000)
                {
                    numStatesPruned = numStatesCreated - bh.getQueueSize();
                    break;
                }
            }


            //------------------------------------------------------------------
            //report the route and bssf just like in the demo, and time elapsed
            //------------------------------------------------------------------
            Route = new ArrayList();

            int city  = 0;
            int count = 0;

            Route.Add(Cities[0]);

            while (count != l)
            {
                city = bestPathSoFar[city];
                Route.Add(Cities[city]);
                count++;
            }

            // call this the best solution so far.  bssf is the route that will be drawn by the Draw method.
            bssf = new TSPSolution(Route);

            // update the cost of the tour.
            //some values we needed for the table
            Program.MainForm.tbCostOfTour.Text = " " + bssf.costOfRoute() + "   " + maxQueueSize + "    "
                                                 + numBSSFupdates + "    " + numStatesCreated + "    " + numStatesPruned + "    ";

            //report the time elapsed
            timer.Stop();
            Program.MainForm.tbElapsedTime.Text = timer.Elapsed.ToString();

            // do a refresh.
            Program.MainForm.Invalidate();
        }
コード例 #4
0
ファイル: ProblemAndSolver.cs プロジェクト: tnelsonw/TSP
        /// <summary>
        /// performs a Branch and Bound search of the state space of partial tours
        /// stops when time limit expires and uses BSSF as solution
        /// </summary>
        /// <returns>results array for GUI that contains three ints: cost of solution, time spent to find solution, number of solutions found during search (not counting initial BSSF estimate)</returns>
        public string[] bBSolveProblem()
        {
            string[] results     = new string[3];
            string[] origResults = defaultSolveProblem();
            double   origbssf    = Convert.ToDouble(origResults[COST]);

            double[,] originalDistances = new double[Cities.Length, Cities.Length];
            List <Node> todoNodes      = new List <Node>();
            int         numSolutions   = 0;
            int         numChildStates = 0;
            int         statesPruned   = 0;
            int         numBSSF        = 0;
            int         maxNumOfStates = 0;
            double      bestSolution   = origbssf;
            ArrayList   routeSolution  = new ArrayList();

            for (int i = 0; i < Cities.Length; i++) //make original matrix from default route
            {
                for (int k = 0; k < Cities.Length; k++)
                {
                    if (i == k)
                    {
                        originalDistances[i, k] = double.PositiveInfinity;
                    }
                    else
                    {
                        originalDistances[i, k] = Cities[i].costToGetTo(Cities[k]);
                    }
                }
            }

            Stopwatch timer = new Stopwatch();

            timer.Start();
            routeSolution.Add(Cities[0]);
            Node startNode = new Node(0, originalDistances, routeSolution);

            //put nodes in queue
            todoNodes.Add(reduceMatrix(startNode));

            while (todoNodes.Count > 0)  //while the list is not empty
            {
                if (timer.Elapsed.TotalSeconds >= TIME_LIMIT)
                {
                    break;
                }
                Node node = todoNodes[0];                   //get first element
                if (node.getRoute().Count == Cities.Length) //if a leaf node
                {
                    numSolutions++;
                    TSPSolution sol = new TSPSolution(node.getRoute());
                    if (sol.costOfRoute() < bestSolution)   //reset the best solution if it is lower
                    {
                        bestSolution  = sol.costOfRoute();
                        routeSolution = node.getRoute();
                        numBSSF++;
                    }
                }
                else                                    //if not a leaf node
                {
                    if (node.getbssf() <= bestSolution) //pruning not needed
                    {
                        for (int i = 1; i < Cities.Length; i++)
                        {
                            if (node.getMatrix()[node.getNum(), i] != double.PositiveInfinity)
                            {
                                todoNodes.Add(getPartialRoute(node, node.getNum(), i));
                                numChildStates++;
                            }
                        }
                    }
                    else
                    {
                        statesPruned++;
                    }
                }

                if (todoNodes.Count > maxNumOfStates)
                {
                    maxNumOfStates = todoNodes.Count;
                }
                todoNodes.RemoveAt(0); //remove the node when finished calculating
                todoNodes.Sort();      //sorting based on priority
            }
            timer.Stop();
            bssf = new TSPSolution(routeSolution);
            Console.WriteLine("Number of child states is " + numChildStates);
            Console.WriteLine("Number of states pruned is " + statesPruned);
            Console.WriteLine("Number of bssf updates is " + numBSSF);
            Console.WriteLine("Number of stored states is " + maxNumOfStates);

            results[COST]  = bssf.costOfRoute().ToString();   // load results into array here, replacing these dummy values
            results[TIME]  = timer.Elapsed.ToString();
            results[COUNT] = numSolutions.ToString();
            return(results);
        }