IDA *(迭代加深星标)解决了C#中的寻路搜索

时间:2019-05-07 20:00:54

标签: c# path-finding a-star heuristics

我创建了IDA *的通用版本来解决寻路问题。我使用了罗马尼亚的路线图,但遇到了一些问题。

我使用的罗马尼亚地图:https://dzone.com/storage/temp/11185033-romanianmap-astar.jpg

例如,对于通往Arad到布加勒斯特的道路,最终结果是Timisoara-Lugoj-Mehadia-Drobeta-Craiova-RâmnicuVâlcea-Sibiu-Făgăraș-Bucharest。同样在布加勒斯特至阿拉德的道路上,最终结果是皮特蒂-拉姆尼库·瓦尔恰-西比乌-阿拉德(正确的结果)。在同一条道路上获得不同的结果是否正常?有一种方法可以优化算法以更快地显示结果?

最初,我开始实现受Leniel Maccaferri启发的A *:https://github.com/leniel/AStar,并将类用于IDA *。

对于启发式算法,我使用了曼哈顿距离和Haversine公式进行了以公里为单位的估算。

这是我尝试过的:

public async Task<List<string>> ResolveIDAStarAlgorithm(string startCity, string destinationCity)
{
            /* Creating the graph. */
            Graph graph = new Graph();
            await CreateGraph(graph);

            /* Store the start Node */
            Node start = graph.Nodes[startCity];
            /* Store the destination Node */
            Node destination = graph.Nodes[destinationCity];

            /* Sets the cost of the start node. */
            start.GCost = 0;

            /* Sets the heuristic cost. */
            start.HCost = Haversine.Distance(start, destination);

            /* Sets the f cost limit. */
            double fCostLimit = start.GCost + start.HCost;

            List<string> path = new List<string>();

            while (true)
            {
                /* Start IDA Star pathfinding search. */
                Node foundTemp = await SearchPath(start, destination, start.GCost, fCostLimit);

                switch (foundTemp.Status)
                {
                    /* A new cost limit has been found. */
                    case SEARCHRETURN.BOUND:

                        fCostLimit = foundTemp.HCost;
                        break;

                    /* The path was found. */
                    case SEARCHRETURN.FOUND:

                        path = RetracePath(start, destination);
                        return path;

                    /* No path has been found. */
                    case SEARCHRETURN.NOT_FOUND:
                        return null;
                }
            }

        }


        public async Task<Node> SearchPath(Node currentNode, Node targetNode, double gCost, double fCostLimit)
        {
            Node retNode = new Node();
            Path<Node> path = new Path<Node>(currentNode);

            double distance(Node node1, Node node2) =>
                                                   node1.Neighbors.Cast<EdgeToNeighbor>().Single(
                                                       etn => etn.Neighbor.Key == node2.Key).Cost;

            /* If the current node is the target, the search process will finish. */
            if (currentNode == targetNode)
            {
                retNode.Status = SEARCHRETURN.FOUND;
                return retNode;
            }

            double newFCostLimit = gCost + Haversine.Distance(currentNode, targetNode);


            if (newFCostLimit > fCostLimit)
            {
                retNode.Status = SEARCHRETURN.BOUND;
                retNode.HCost = newFCostLimit;
                return retNode;
            }


            if (!_visitedNodes.Contains(currentNode.Key))
            {
                _visitedNodes.Add(currentNode.Key);
            }


            foreach (Node neighbor in path.LastStep.Neighbours)
            {

                if (_visitedNodes.Contains(neighbor.Key))
                {
                    continue;
                }


                if (!_visitedNodes.Contains(neighbor.Key))
                {
                    double newCostNeighbor =  distance(currentNode, neighbor) + Haversine.Distance(currentNode, neighbor);
                    if (newCostNeighbor < neighbor.GCost || !_visitedNodes.Contains(neighbor.Key))
                    {
                        neighbor.GCost = gCost + newCostNeighbor;
                        neighbor.HCost = Haversine.Distance(neighbor, targetNode);
                        neighbor.PathParent = currentNode;
                    }

                    Node t = await SearchPath(neighbor, targetNode, newCostNeighbor, fCostLimit);
                    switch (t.Status)
                    {
                        case SEARCHRETURN.BOUND:
                            if (t.HCost < _costLimit)
                            {
                                _costLimit = t.HCost;
                            }
                            break;
                        case SEARCHRETURN.FOUND:
                            return t;
                        case SEARCHRETURN.NOT_FOUND:
                            continue;
                    }
                }

            }

            if (_costLimit == _minValue)
            {
                retNode.Status = SEARCHRETURN.NOT_FOUND;
            }
            else
            {
                retNode.HCost = _costLimit;
                retNode.Status = SEARCHRETURN.BOUND;
            }

            _visitedNodes.Remove(currentNode.Key);
            return retNode;

        }


        public List<string> RetracePath(Node start, Node destination)
        {
            List<string> path = new List<string>();
            Node currentNode = destination;

            double totalCost = 0;
            double distance(Node node1, Node node2) =>
                                                  node1.Neighbors.Cast<EdgeToNeighbor>().Single(
                                                      etn => etn.Neighbor.Key == node2.Key).Cost;

            while (currentNode != start)
            {
                path.Add(currentNode.Key);

                totalCost += distance(currentNode, currentNode.PathParent);

                currentNode = currentNode.PathParent;

            }

            path.Add((totalCost * 0.99).ToString());

            path.Reverse();

            return path;

        }

0 个答案:

没有答案