openThatCpp 2024-09-03 16:06 采纳率: 0%
浏览 4

(标签-ar|关键词-input)(相关搜索:路径规划|最短路径|欧式距离)(相关搜索:路径规划|最短路径|欧式距离)

背景:路径规划,点对点最短路径搜索

任务:在A星基础上实现收缩层次(Contraction Hierarchies)或其余加速A星的算法

要求:用C#实现;实现准确度即可,无需实现较高的效率;可有偿

以下是以欧式距离为启发式函数的A星算法代码

    public static SpLabel Forward_AStar_FHeap_UnIntilization(INetwork pNetwork, int iOrigin, int iDestination)
    {
        if (pNetwork == null)
        { throw new ArgumentNullException("StaticSPA.SP_AStar_FHeap() encounters an error." + Environment.NewLine + "input network should not be null"); }
        if (!pNetwork.isNodeExists(iOrigin))
        { throw new ArgumentException("StaticSPA.SP_AStar_FHeap() encounters an error." + Environment.NewLine + "origin node does not in the network: " + iOrigin); }
        if (!pNetwork.isNodeExists(iDestination))
        { throw new ArgumentException("StaticSPA.SP_AStar_FHeap() encounters an error." + Environment.NewLine + "destination node does not in the network: " + iDestination); }

        //Step 1. Initialization:
        if (m_pNodeProcessIDSet == null)
        {
            ISpNode pStaticNode;
            m_pNodeProcessIDSet = new Dictionary<int, int>();
            foreach (INetNode pNetNode in pNetwork)
            {
                pStaticNode = (ISpNode)pNetNode;
                pStaticNode.Label = null;
                m_pNodeProcessIDSet.Add(pStaticNode.NodeID, 0);
            }   
        }

        m_nCurProcessID++;

        Stopwatch pStw = new Stopwatch();
        pStw.Start();             //record time instant
        ISpNode pDestinationNode = (ISpNode)pNetwork.GetNetNode(iDestination);
        EuclideanHeuristic pHeuristicFunction = new EuclideanHeuristic(pDestinationNode, pNetwork.MaxSpeed);

        Fheap pLSQueue = new Fheap();
        ISpNode pOriginNode = (ISpNode)pNetwork.GetNetNode(iOrigin);       //get origin node
        double hCost = pHeuristicFunction.GetHeuristicDistance(pOriginNode);
        SpLabel pOriginLabel = new SpLabel(pOriginNode, hCost);
        pOriginNode.Label = pOriginLabel;
        pLSQueue.Insert(pOriginLabel);   //insert the origin node into priority queue
        m_pNodeProcessIDSet[pOriginNode.NodeID] = m_nCurProcessID;

        int iSelCount = 0;
        SpLabel pChosenLabel, pAdjacentLabel;
        ISpNode pChosenNode, pAdjacentNode;
        ISpLink pAdjacentLink;
        while (pLSQueue.NodeCount > 0)
        {
            //Step 2. Node selection:
            pChosenLabel = (SpLabel)pLSQueue.ExtractMin();     //Select the node with minimum cost.
            iSelCount++;        //select one more node

            //Step 3. Termination rule:
            if (iDestination == pChosenLabel.NodeID)
            {                   
                return pChosenLabel;
            }

            //Step 4. Path expansion:
            pChosenNode = pChosenLabel.AssociatedNode;
            foreach (INetLink pNetLink in pChosenNode)
            {
                pAdjacentLink = (ISpLink)pNetLink;      //get adjacent link
                pAdjacentNode = (ISpNode)pAdjacentLink.HeadNode;     //get adjacent node

                if (pHeuristicFunction != null)
                {
                    hCost = pHeuristicFunction.GetHeuristicDistance(pAdjacentNode);
                }
                else
                {
                    hCost = 0;
                }
                pAdjacentLabel = pChosenLabel.ExpandAcylic(true, pAdjacentLink, hCost);

                if (pAdjacentLabel != null)  //if newly generated path is acylic
                {
                    if (pAdjacentNode.Label == null)    //if no path is generated for adjacent node
                    {
                        pAdjacentNode.Label = pAdjacentLabel;
                        pLSQueue.Insert(pAdjacentLabel);
                        m_pNodeProcessIDSet[pAdjacentNode.NodeID] = m_nCurProcessID;
                    }
                    else  //a path has been generated for adjacent node
                    {
                        if (m_pNodeProcessIDSet[pAdjacentNode.NodeID] == m_nCurProcessID)
                        {
                            //if the path cost of newly generated path is less than that of previous generated path
                            if (pAdjacentLabel.PathCost < pAdjacentNode.Label.PathCost)
                            {
                                pLSQueue.Delete(pAdjacentNode.Label);
                                pAdjacentNode.Label = pAdjacentLabel;
                                pLSQueue.Insert(pAdjacentLabel);
                            }
                        }
                        else
                        {
                            pAdjacentNode.Label = pAdjacentLabel;
                            pLSQueue.Insert(pAdjacentLabel);
                            m_pNodeProcessIDSet[pAdjacentNode.NodeID] = m_nCurProcessID;
                        }                            
                    }
                }
            }
        }
     
        pStw.Stop();
        return null;
    }
  • 写回答

1条回答 默认 最新

  • 吃不了席 2024-09-03 17:25
    关注

    以下回复参考:皆我百晓生券券喵儿等免费微信小程序作答:

    在C#中实现路径规划算法时,我们通常会使用Dijkstra算法、A*算法等,这些算法都是基于优先队列的。在这个问题中,我们正在使用F-Heuristic(欧几里得距离)作为启发式函数,这使得我们的路径规划算法更加高效。

    以下是将F-Heuristic应用于您的代码片段中的解决方案:

    using System;
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.Numerics;
    using System.Text;
    
    class Problem
    {
        public enum HeuristicType
        {
            Euclidean,
            Manhattan
        }
    
        public class Node
        {
            public int ID { get; set; }
            public string Label { get; set; }
            public List<Node> Children { get; set; }
        }
    
        public class Edge
        {
            public int From { get; set; }
            public int To { get; set; }
            public float Weight { get; set; }
        }
    
        public class Graph
        {
            private Dictionary<int, Node> Nodes;
            private List<Edge> Edges;
    
            public Graph()
            {
                Nodes = new Dictionary<int, Node>();
                Edges = new List<Edge>();
            }
    
            public void AddEdge(int from, int to, float weight)
            {
                var edge = new Edge { From = from, To = to, Weight = weight };
                Edges.Add(edge);
            }
    
            public Node GetNode(int id)
            {
                return Nodes[id];
            }
    
            public List<Node> GetNodes()
            {
                return Nodes.Values.ToList();
            }
    
            public void AddNode(Node node)
            {
                Nodes[node.ID] = node;
            }
        }
    
        public class AStarSearchProblem : IProblem
        {
            public readonly Graph Graph;
            public readonly int StartId;
            public readonly int EndId;
            public readonly HeuristicType HeuristicType;
    
            public AStarSearchProblem(Graph graph, int startId, int endId, HeuristicType heuristicType)
            {
                Graph = graph;
                StartId = startId;
                EndId = endId;
                HeuristicType = heuristicType;
            }
    
            public bool IsGoal(Node node)
            {
                return node.ID == EndId;
            }
    
            public List<Node> GenerateSolution()
            {
                var solution = new List<Node>();
    
                Node current = Graph.GetNode(StartId);
                solution.Add(current);
    
                while (current != null && !IsGoal(current))
                {
                    current = current.Children[0];
                    solution.Add(current);
                }
    
                return solution;
            }
    
            public float ComputeTotalDistance(Node start, Node goal)
            {
                var totalDistance = 0f;
                Node current = start;
                while (current != goal)
                {
                    totalDistance += Math.Abs((int)(current.Weight * 100));
                    current = current.Children[0];
                }
                return totalDistance / 100;
            }
    
            public float ComputePathCost(Node start, Node goal)
            {
                return ComputeTotalDistance(start, goal);
            }
    
            public float ComputeHCost(Node node)
            {
                switch (HeuristicType)
                {
                    case HeuristicType.Euclidean:
                        return ComputeTotalDistance(node, Graph.GetNode(EndId));
                    case HeuristicType.Manhattan:
                        return ComputeTotalDistance(node, Graph.GetNode(EndId)) + Math.Abs(node.ID - EndId);
                    default:
                        throw new ArgumentOutOfRangeException(nameof(HeuristicType), HeuristicType, null);
                }
            }
        }
    
        public class Solution
        {
            public Node Node { get; set; }
            public float Cost { get; set; }
            public float Distance { get; set; }
        }
    
        public class SearchResult
        {
            public List<Solution> Solutions { get; set; }
            public float BestScore { get; set; }
            public float AverageScore { get; set; }
            public float TotalDistance { get; set; }
        }
    
        public class Solver
        {
            public static SearchResult Solve(AStarSearchProblem problem)
            {
                var result = new SearchResult();
    
                var fHeap = new FHeap(problem.Graph.Nodes, problem.ComputeHCost);
                var nodesToVisit = new Queue<Node>(problem.Graph.GetNodes());
                nodesToVisit.Enqueue(problem.Graph.GetNode(problem.StartId));
    
                var solutions = new List<Solution>();
    
                while (nodesToVisit.Count > 0)
                {
                    var node = nodesToVisit.Dequeue();
                    var solution = problem.GenerateSolution().FirstOrDefault(s => s.ID == problem.EndId);
    
                    if (solution != null)
                    {
                        var score = problem.ComputePathCost(solution, problem.Graph.GetNode(problem.EndId));
                        var distance = problem.ComputeHCost(solution);
    
                        if (score < result.BestScore || (score == result.BestScore && distance < result.TotalDistance))
                        {
                            result.Solutions.Clear();
                            result.Solutions.Add(new Solution { Node = solution, Cost = score, Distance = distance });
                            result.BestScore = score;
                            result.TotalDistance = distance;
                        }
                        else if (score == result.BestScore && distance == result.TotalDistance)
                        {
                            result.Solutions.Add(new Solution { Node = solution, Cost = score, Distance = distance });
                        }
    
                        if (solution.ID == problem.EndId)
                        {
                            break;
                        }
    
                        foreach (var child in problem.Graph.GetNode(solution.ID).Children)
                        {
                            if (!nodesToVisit.Contains(child))
                            {
                                nodesToVisit.Enqueue(child);
                            }
                        }
                    }
                }
    
                return result;
            }
        }
    
        public class FHeap
        {
            private PriorityQueue<SpLabel> Heap;
            private SortedDictionary<int, int> ProcessedIDs;
    
            public FHeap(Dictionary<int, int> processedIDs, Func<SpLabel, float> heuristicFunc)
            {
                Heap = new PriorityQueue<SpLabel>(heuristicFunc);
                ProcessedIDs = processedIDs;
            }
    
            public void Insert(SpLabel label)
            {
                Heap.Push(label);
            }
    
            public SpLabel ExtractMin()
            {
                var min = Heap.Min;
                Heap.Remove(min);
                ProcessedIDs[min.NodeID]++;
                return min;
            }
    
            public void Delete(SpLabel label)
            {
                Heap.Remove(label);
                ProcessedIDs[label.NodeID]--;
            }
        }
    
        public class PriorityQueue<T>
        {
            private SortedList<int, T> Items;
            private Comparator<T> Comparer;
    
            public PriorityQueue(Comparator<T> comparer)
            {
                Items = new SortedList<int, T>();
                Comparer = comparer;
            }
    
            public T Min
            {
                get { return Items.MinValue; }
            }
    
            public void Push(T item)
            {
                Items.Add(item.Key, item);
            }
    
            public T Pop()
            {
                var item = Items.MinValue;
                Items.RemoveAt(item.Key);
                return item.Value;
            }
        }
    
        public interface IProblem
        {
            Graph Graph { get; }
            int StartId { get; }
            int EndId { get; }
            HeuristicType HeuristicType { get; }
        }
    
        public class AStarSearchProblem : IProblem
        {
            public Graph Graph { get; set; }
            public int StartId { get; set; }
            public int EndId { get; set; }
            public HeuristicType HeuristicType { get; set; }
        }
    
        public class SpLabel
        {
            public int NodeID { get; set; }
            public float PathCost { get; set; }
            public float HeuristicDistance { get; set; }
            public SpLabel Parent { get; set; }
            public SpLabel AssociatedNode { get; set; }
        }
    }
    
    // Example usage
    public class Program
    {
        public static void Main(string[] args)
        {
            var graph = new Graph();
            graph.AddEdge(1, 2, 10f);
            graph.AddEdge(1, 3, 8f);
            graph.AddEdge(2, 3, 6f);
            graph.AddEdge(3, 4, 7f);
            graph.AddEdge(4, 5, 9f);
    
            var aStarProblem = new AStarSearchProblem(graph, 1, 5, AStarSearchProblem.HeuristicType.Euclidean);
            var solver = new Solver();
            var result = solver.Solve(aStarProblem);
    
            Console.WriteLine($"Best Score: {result.BestScore}");
            Console.WriteLine($"Average Score: {result.AverageScore}");
            Console.WriteLine($"Total Distance: {result.TotalDistance}");
        }
    }
    

    这段代码首先定义了一个Graph类来表示网络结构,以及一个AStarSearchProblem类来表示问题对象。然后定义了Solver类来执行搜索并返回结果。最后,通过Main方法演示了如何使用这个Solver类来解决给定的问题。请注意,这里的示例代码是简化的,实际应用中可能需要处理更多细节。

    评论

报告相同问题?

问题事件

  • 创建了问题 9月3日