Пример #1
0
        public override IEnumerable <Node> AStar(Node from, Node to)
        {
            var openSet = new FastPriorityQueue <Node>(Width * Height);

            openSet.Enqueue(from, 0f);

            while (openSet.Count > 0)
            {
                var currentNode = openSet.Dequeue();
                if (currentNode == to)
                {
                    var path = ReconstructPath(currentNode);

                    foreach (var node in this)
                    {
                        node.Reset();
                    }

                    return(path);
                }

                currentNode.InClosedSet = true;

                foreach (var neighbor in currentNode.Neighbors)
                {
                    if (neighbor.InClosedSet)
                    {
                        continue;
                    }

                    var tentativeGScore = currentNode.GScore + currentNode.Distance(neighbor);

                    if (openSet.Contains(neighbor) && tentativeGScore >= neighbor.GScore)
                    {
                        continue;
                    }

                    neighbor.CameFrom = currentNode;
                    neighbor.GScore   = tentativeGScore;

                    var fs = tentativeGScore + HeuristicCostEstimate(neighbor, to);

                    if (openSet.Contains(neighbor))
                    {
                        openSet.UpdatePriority(neighbor, fs);
                    }
                    else
                    {
                        openSet.Enqueue(neighbor, fs);
                    }
                }
            }

            foreach (var node in this)
            {
                node.Reset();
            }

            return(new List <Node>());
        }
        public void AddSeed(int id, float seed_dist)
        {
            GraphNode g = get_node(id);

            Debug.Assert(Queue.Contains(g) == false);
            enqueue_node(g, seed_dist);
            Seeds.Add(id);
        }
Пример #3
0
    void FindPath(Vector3 a_StartPos, Vector3 a_TargetPos)
    {
        Node StartNode  = nodeMesh.NodeFromWorldPoint(a_StartPos);  //Gets the node closest to the starting position
        Node TargetNode = nodeMesh.NodeFromWorldPoint(a_TargetPos); //Gets the node closest to the target position

        if (StartNode != null && TargetNode != null)
        {
            FastPriorityQueue <Node> OpenList = new FastPriorityQueue <Node>(200);
            //SimplePriorityQueue<Node> OpenList = new FastPriorityQueue<Node>(maxN_Calculations);//List of nodes for the open list
            HashSet <Node> ClosedList = new HashSet <Node>(); //Hashset of nodes for the closed list

            OpenList.Enqueue(StartNode, StartNode.FCost);     //Add the starting node to the open list to begin the program
            while (OpenList.Count > 0)                        //Whilst there is something in the open list
            {
                Node CurrentNode = OpenList.Dequeue();        //Create a node and set it to the first item in the open list
                OpenList.ResetNode(CurrentNode);
                //OpenList.Remove(CurrentNode);//Remove that from the open list
                ClosedList.Add(CurrentNode);             //And add it to the closed list

                if (CurrentNode == TargetNode)           //If the current node is the same as the target node
                {
                    GetFinalPath(StartNode, TargetNode); //Calculate the final path
                }
                //Debug.Log("el nodo en cuestion tiene x vecinos" + CurrentNode.NeighbNodes.Count);
                Node[] nNodes = nodeMesh.GetNeighbNodes(CurrentNode);
                for (int i = 0; i < nNodes.Length; i++)
                {
                    Node NeighborNode = nNodes[i];
                    if (NeighborNode == null)
                    {
                        continue;
                    }
                    if (NeighborNode.BIsWall || ClosedList.Contains(NeighborNode))
                    {
                        continue;                                                                        //If the neighbor is a wall or has already been checked // Skip it
                    }
                    int MoveCost = CurrentNode.IgCost + GetManhattenDistance(CurrentNode, NeighborNode); //Get the F cost of that neighbor

                    if (MoveCost < NeighborNode.IgCost || !OpenList.Contains(NeighborNode))              //If the f cost is greater than the g cost or it is not in the open list
                    {
                        NeighborNode.IgCost      = MoveCost;                                             //Set the g cost to the f cost
                        NeighborNode.IhCost      = GetManhattenDistance(NeighborNode, TargetNode);       //Set the h cost
                        NeighborNode.ParentNode1 = CurrentNode;                                          //Set the parent of the node for retracing steps

                        if (!OpenList.Contains(NeighborNode))                                            //If the neighbor is not in the openlist
                        {
                            //Add it to the list
                            OpenList.Enqueue(NeighborNode, NeighborNode.FCost);
                        }
                    }
                }
            }
            //while (OpenList.Count > 0)
            //{
            //    OpenList.ResetNode(OpenList.Dequeue());
            //}
        }
    }
Пример #4
0
        public override IEnumerable <Node> AStar(Node from, Node to)
        {
            var closedSet = new HashSet <Node>();
            var openSet   = new FastPriorityQueue <Node>(Width * Height);

            openSet.Enqueue(@from, 0f);

            var cameFrom = new Dictionary <Node, Node>();

            var gScore = new Dictionary <Node, float> {
                { from, 0f }
            };

            while (openSet.Count > 0)
            {
                var currentNode = openSet.Dequeue();
                if (currentNode == to)
                {
                    return(ReconstructPath(cameFrom, currentNode));
                }

                closedSet.Add(currentNode);

                foreach (var neighbor in currentNode.Neighbors)
                {
                    if (closedSet.Contains(neighbor))
                    {
                        continue;
                    }

                    var tentativeGScore = gScore[currentNode] + currentNode.Distance(neighbor);

                    if (openSet.Contains(neighbor) && tentativeGScore >= gScore[neighbor])
                    {
                        continue;
                    }

                    cameFrom[neighbor] = currentNode;
                    gScore[neighbor]   = tentativeGScore;

                    var fs = tentativeGScore + HeuristicCostEstimate(neighbor, to);

                    if (openSet.Contains(neighbor))
                    {
                        openSet.UpdatePriority(neighbor, fs);
                    }
                    else
                    {
                        openSet.Enqueue(neighbor, fs);
                    }
                }
            }

            return(new List <Node>());
        }
    protected void AddToFastOpen(Node child, Node parent, FastPriorityQueue <Node> list)
    {
        double newFValue, gValue;

        if (!useThetaStar)
        {
            newFValue = CalculateFValue(child, parent, out gValue);
        }
        else
        {
            newFValue = CalculateFValue(child, parent, out gValue, out parent);
        }

        if (newFValue == Mathf.Infinity)
        {
            return;
        }
        if (!list.Contains(child))                                          //if child is not already in open list
        {
            list.Enqueue(child, (float)newFValue);                          //add to open list
            SetValues(child, parent, gValue);
        }
        else                                                        //child is already in open list
        {
            float oldFValue = child.Priority;
            if (newFValue < oldFValue)                              //if f-value of child in open list is greather than current f-value
            {
                list.UpdatePriority(child, (float)newFValue);
                SetValues(child, parent, gValue);
            }
        }
    }
    public override bool Find(DirectionGraph graph, Node start, Node end)
    {
        priorityQueue = new FastPriorityQueue <Node>(graph.VerticeCount());
        searchSteps   = new Queue <Node>();

        System.Diagnostics.Stopwatch watch = new System.Diagnostics.Stopwatch();
        watch.Start();

        costForStartToTarget        = new Dictionary <Node, int>();
        costForStartToTarget[start] = 0;

        priorityQueue.Enqueue(start, 0);
        while (priorityQueue.Count > 0)
        {
            Node min = priorityQueue.Dequeue();
            if (min == end)
            {
                watch.Stop();
                executionTimes = watch.Elapsed.TotalMilliseconds;
                CalculateCostAndGeneratePath(start, end, graph);
                return(true);
            }
            List <DirectionEdge> minNeighbors = graph.GetNeighborEdge(min);
            int costForStartToMin             = costForStartToTarget[min];
            for (int i = 0, count = minNeighbors.Count; i < count; i++)
            {
                Node neighbor = minNeighbors[i].to;
                int  costForStartToNeighbor = int.MaxValue;
                if (costForStartToTarget.ContainsKey(neighbor))
                {
                    costForStartToNeighbor = costForStartToTarget[neighbor];
                }
                int newCostSoFar = costForStartToMin + minNeighbors[i].weight;
                if (newCostSoFar < costForStartToNeighbor)
                {
                    costForStartToTarget[neighbor] = newCostSoFar;
                    nodesComeFrom[neighbor]        = min;
                    if (priorityQueue.Contains(neighbor))
                    {
                        priorityQueue.UpdatePriority(neighbor, newCostSoFar);
                    }
                    else
                    {
                        priorityQueue.Enqueue(neighbor, newCostSoFar);
                    }
                }
            }
            if (min != start)
            {
                searchSteps.Enqueue(min);
            }
        }
        watch.Stop();
        executionTimes = watch.Elapsed.TotalMilliseconds;
        searchSteps.Clear();
        return(false);
    }
        /// <summary>
        /// Finds a shortest path from the <paramref name="start"/> to the <paramref name="end"/>.
        /// It uses a Dijkstra's algorithm with a priority queue.
        /// </summary>
        string Solve(Map map, Cell start, Cell end)
        {
            var vertices  = new FastPriorityQueue <Cell>(map.TotalMapSize);
            var distances = new Dictionary <Cell, float>();
            var previous  = new Dictionary <Cell, Cell>();

            foreach (var cell in map.AllCells())
            {
                if (!cell.Equals(start))
                {
                    distances[cell] = float.PositiveInfinity;
                    previous[cell]  = null;
                    vertices.Enqueue(cell, float.PositiveInfinity);
                }
            }
            vertices.Enqueue(start, 0);
            distances[start] = 0;

            int oneTenth = map.TotalMapSize > 10 ? map.TotalMapSize / 10 : 1;

            while (vertices.Any())
            {
                var u = vertices.Dequeue();

                if (reportProgress && vertices.Count % oneTenth == 0)
                {
                    Console.WriteLine($"Remaining nodes {vertices.Count}/{map.TotalMapSize}");
                }

                foreach (var v in map.GetNeighbors(u))
                {
                    if (!vertices.Contains(v))
                    {
                        continue;
                    }

                    var currentDistance = distances[v];
                    var newDistance     = distances[u] + v.Difficulty;
                    if (newDistance < currentDistance)
                    {
                        vertices.UpdatePriority(v, newDistance);
                        distances[v] = newDistance;
                        previous[v]  = u;

                        if (v.Equals(end))
                        {
                            vertices.Clear();
                            break;
                        }
                    }
                }
            }

            return(GeneratePath(end, previous, map));
        }
Пример #8
0
        /// <inheritdoc/>
        public void ImmediateEvent(IEvent eventToSchedule)
        {
            if (eventToSchedule == null)
            {
                throw new ArgumentNullException(nameof(eventToSchedule));
            }

            if (!(eventToSchedule is BaseEvent castedEvent))
            {
                throw new ArgumentException($"Argument must be of type {nameof(BaseEvent)}.", nameof(eventToSchedule));
            }

            lock (_eventsAvailableLock) {
                lock (_queueLock) {
                    if (_priorityQueue.Contains(castedEvent))
                    {
                        throw new ArgumentException($"The event is already scheduled.", nameof(eventToSchedule));
                    }

                    _priorityQueue.Enqueue(castedEvent, 0);
                }

                // check and add event attribution to the requestor
                if (castedEvent.RequestorId > 0)
                {
                    lock (_eventsPerRequestorLock) {
                        if (!_eventsPerRequestor.ContainsKey(castedEvent.RequestorId))
                        {
                            _eventsPerRequestor.Add(castedEvent.RequestorId, new HashSet <string>());
                        }

                        try {
                            _eventsPerRequestor[castedEvent.RequestorId].Add(castedEvent.EventId);
                        } catch {
                            // ignore clashes, it was our goal to add it anyways.
                        }
                    }
                }

                Monitor.Pulse(_eventsAvailableLock);
            }
        }
Пример #9
0
        /// <summary>
        /// Benchmark
        /// </summary>
        public bool EnqueueContains()
        {
            Enqueue();
            bool ret = true; // to ensure the compiler doesn't optimize the contains calls out of existence

            for (int i = 0; i < QueueSize; i++)
            {
                ret &= Queue.Contains(Nodes[i]);
            }
            return(ret);
        }
    void GenerateChunkByTargetPosition()
    {
        if (target == null)
        {
            return;
        }

        Vector3Int targetPosition = VoxelUtil.WorldToChunk(target.position, chunkSize);

        if (lastTargetChunkPosition == targetPosition)
        {
            return;
        }

        foreach (ChunkNode chunkNode in generateChunkQueue)
        {
            Vector3Int deltaPosition = targetPosition - chunkNode.chunkPosition;
            if (chunkSpawnSize.x < Mathf.Abs(deltaPosition.x) || chunkSpawnSize.y < Mathf.Abs(deltaPosition.y) || chunkSpawnSize.z < Mathf.Abs(deltaPosition.z))
            {
                generateChunkQueue.Remove(chunkNode);
                continue;
            }

            generateChunkQueue.UpdatePriority(chunkNode, (targetPosition - chunkNode.chunkPosition).sqrMagnitude);
        }

        for (int x = targetPosition.x - chunkSpawnSize.x; x <= targetPosition.x + chunkSpawnSize.x; x++)
        {
            for (int y = targetPosition.y - chunkSpawnSize.y; y <= targetPosition.y + chunkSpawnSize.y; y++)
            {
                for (int z = targetPosition.z - chunkSpawnSize.z; z <= targetPosition.z + chunkSpawnSize.z; z++)
                {
                    Vector3Int chunkPosition = new Vector3Int(x, y, z);
                    if (chunks.ContainsKey(chunkPosition))
                    {
                        continue;
                    }

                    ChunkNode newNode = new ChunkNode {
                        chunkPosition = chunkPosition
                    };

                    if (generateChunkQueue.Contains(newNode))
                    {
                        continue;
                    }

                    generateChunkQueue.Enqueue(newNode, (targetPosition - chunkPosition).sqrMagnitude);
                }
            }
        }

        lastTargetChunkPosition = targetPosition;
    }
Пример #11
0
        private void AddToQueue(FastPriorityQueue <ChunkNode> queue, int3 position, float priority)
        {
            ChunkNode node = new ChunkNode(position);

#if DEBUG
            if (queue.Contains(node))
            {
                Debug.LogWarning("Wants to enqueue generator job but it already exists.");
                return;
            }
#endif
            if (queue.Count + 1 >= queue.MaxSize)
            {
                queue.Resize(queue.Count + 32);
            }

            queue.Enqueue(node, priority);
        }
Пример #12
0
    protected void AddToFastOpen(Node child)
    {
        newKeyValue = CalculateKeyValue(child);
        if (newKeyValue[0] >= float.MaxValue)
        {
            return;
        }

        child.priorityKey = newKeyValue;
        if (!fastOpenListPrim.Contains(child))
        {
            fastOpenListPrim.Enqueue(child, (float)newKeyValue[0]);
        }
        else
        {
            fastOpenListPrim.UpdatePriority(child, (float)newKeyValue[0]);
        }
        if (isUpdatingNodes && visualize)
        {
            child.isInOpenAfterChange = true;   //DEBUG
        }
    }
Пример #13
0
        public int[] Work(bool print = true, int startIndex = 0)
        {
            int  NumberOfNodes = Graph.ListOfNodes.Count;
            var  queue         = new FastPriorityQueue <Node>(100 * 1000);
            Node u;
            int  du;
            int  dv;
            int  wuv;

            int[] d = new int[NumberOfNodes];

            for (int i = 0; i < NumberOfNodes; i++)
            {
                d[i] = Int32.MaxValue / 10;
            }

            if (startIndex + 1 > NumberOfNodes)
            {
                startIndex = 0;
            }

            d[startIndex] = 0;

            for (int i = 0; i < NumberOfNodes; i++)
            {
                queue.Enqueue(Graph.GetNode(i), 0);
            }

            while (queue.Any()) // while queue is not empty
            {
                u = queue.Dequeue();

                foreach (var v in u.ListOfEdges)
                {
                    du  = d[u.Id];
                    dv  = d[v.Target.Id];
                    wuv = v.Weight;

                    if (du + wuv < dv)
                    {
                        d[v.Target.Id] = du + wuv;
                        if (queue.Contains(v.Target))
                        {
                            queue.UpdatePriority(v.Target, d[v.Target.Id]);
                        }
                        else
                        {
                            queue.Enqueue(v.Target, d[v.Target.Id]);
                        }
                    }
                }
            }

            if (print)
            {
                for (int i = 0; i < NumberOfNodes; i++)
                {
                    Console.WriteLine("Id: {0}, distance: {1}", i, d[i]);
                }
            }

            return(d);
        }
Пример #14
0
        public virtual T FindPath()
        {
            var startNode = CreateNode(Start);

            startNode.StartCost = 0;
            OpenSet.Enqueue(startNode, startNode.TotalCost);
            _loopLimiter.Reset();
            while (_loopLimiter.Advance())
            {
                if (OpenSet.Count == 0)
                {
                    break;
                }
                var centerNode = GetLowest();
                if (centerNode.Value.Equals(End))
                {
                    return(centerNode);
                }
                ClosedSet.Add(centerNode.Value);
                //OpenSet.Remove(centerNode);
                var surrounding = GetSurrounding(centerNode);
                for (int i = 0; i < surrounding.Count; i++)
                {
                    var neighborPos = surrounding[i];
                    if (neighborPos == null)
                    {
                        continue;
                    }
                    if (ClosedSet.Contains(neighborPos))
                    {
                        continue;
                    }
                    if (!CheckWalkable(centerNode.Value, neighborPos))
                    {
                        continue;
                    }
                    var neighbor = Get(neighborPos);
                    if (neighbor == null)
                    {
                        //if (CheckWalkable(centerNode.Value, neighborPos)) {
                        neighbor = CreateNode(neighborPos);
                        //}
                        // else {
                        //     ClosedSet.Add(neighborPos);
                        // }
                    }
                    if (neighborPos.Equals(End))
                    {
                        if (neighbor != null)
                        {
                            neighbor.Parent = centerNode;
                            return(neighbor);
                        }
                        if (IgnoreEndWalkable)
                        {
                            return(centerNode);
                        }
                    }

                    if (neighbor == null)
                    {
                        continue;
                    }
                    var newStartCost = centerNode.StartCost + neighbor.GetTravelCost(centerNode);
                    if (newStartCost < neighbor.StartCost)
                    {
                        neighbor.Parent    = centerNode;
                        neighbor.StartCost = newStartCost;
                        if (OpenSet.Contains(neighbor))
                        {
                            OpenSet.UpdatePriority(neighbor, neighbor.TotalCost);
                        }
                        else
                        {
                            OpenSet.Enqueue(neighbor, neighbor.TotalCost);
                        }
                    }
                }
            }
            return(null);
        }
Пример #15
0
        /// <summary>
        /// FindPathReverse, finds the fastes route between a and b
        /// </summary>
        /// <param name="a">stop number of the departuring station</param>
        /// <param name="b">stop number of the arrival station</param>
        /// <param name="finalArrivalTime">ArrivalTime in UTC format.</param>
        /// <returns>List of TimeTableId, describing the route for the path</returns>
        private List <PathItem> FindPathReverse(int a, int b, long finalArrivalTime)
        {
            // the path we find as shortest
            var cameFrom = new Dictionary <int, TraceBackNode>();

            // gScore is the actual UTCtime to get to a stop
            var gScore = new Dictionary <int, long>();

            gScore[b] = finalArrivalTime;

            // a min heap, now 'turned' into a max heap
            var heap = new FastPriorityQueue <QueueNode>(5000);

            heap.Enqueue(new QueueNode {
                StopId = b, Time = finalArrivalTime, TripId = -1
            }, -DistanceTime(a, b));

            while (heap.Count != 0)
            {
                var currentNode = heap.Dequeue();
                // is arrival station found?
                if (currentNode.StopId == a)
                {
                    return(ReconstructPath(cameFrom, currentNode.StopId));
                }

                // get the neighbours to the currentNode
                var neighbours = ts.Edges
                                 .Where(e => e.ToStop == currentNode.StopId)
                                 .Select(e => new { e.EdgeId, e.FromStop, e.DistanceWalk });

                foreach (var n in neighbours)
                {
                    Iterations += 1;
                    long departureTime;  // utctime when departing from n.ToStop
                    int  timeTableId = -1;
                    int  tripId      = -1;
                    if (n.DistanceWalk > 0)
                    {
                        if ((TimeToWalkSeconds(n.DistanceWalk) > cachedGlobal.MaxWalkingtime) & (currentNode.TripId == -1))
                        {
                            continue; // to long to walk, or 2 sections in a row is walking!
                        }
                        departureTime = gScore[currentNode.StopId] - TimeToWalkSeconds(n.DistanceWalk);
                    }
                    else
                    {
                        long      gScoreTemp = gScore[currentNode.StopId];
                        TimeTable timeTableEntry;
                        timeTableEntry = GetNextArrival(n.EdgeId, gScoreTemp);
                        if (timeTableEntry == null)
                        {
                            continue;
                        }

                        // now chek if previous node is not walking, and change of transport and changetime is available
                        // othwise add changeTime, and search again.
                        if ((currentNode.TripId != -1)
                            & (currentNode.TripId != timeTableEntry.TripId)
                            & (timeTableEntry.ArrivalTime < gScoreTemp - cachedGlobal.TimeToChangeTransport))
                        {
                            gScoreTemp    -= cachedGlobal.TimeToChangeTransport;
                            timeTableEntry = GetNextArrival(n.EdgeId, gScoreTemp);

                            if (timeTableEntry == null)  // no path found
                            {
                                continue;
                            }
                        }

                        departureTime = timeTableEntry.DepartureTime;
                        timeTableId   = timeTableEntry.TimeTableId;
                        tripId        = timeTableEntry.TripId;
                    }

                    if (departureTime > gScore.TryGetValueOrMin(n.FromStop))  // quicker way found, with a smaller value
                    {
                        cameFrom[n.FromStop] = new TraceBackNode {
                            ToStop = currentNode.StopId, EdgeId = n.EdgeId, TimeTableId = timeTableId
                        };
                        gScore[n.FromStop] = departureTime;
                        QueueNode qn = new QueueNode {
                            StopId = n.FromStop, Time = departureTime, TripId = tripId
                        };
                        if (!heap.Contains(qn))
                        {
                            int heuristik = DistanceTime(n.FromStop, a);  // estimated traveltime from this node to the start
                            heap.Enqueue(qn, heuristik - departureTime);
                        }
                    }
                }
            }
            // no path found!
            return(null);

            // Local: Get the next timeTable entry in respect to arrival time given
            TimeTable GetNextArrival(int edgeId, long arrivalTime)
            {
                return(ts.TimeTables
                       .Where(t => t.EdgeId == edgeId && (t.ArrivalTime <= arrivalTime))
                       .OrderByDescending(t => t.ArrivalTime)
                       .FirstOrDefault());
            }
        }
Пример #16
0
        private static List <Vector2> ShortestPath(Graph graph, Vertex start, Vertex target, bool strict = true)
        {
            var queue       = new FastPriorityQueue <Vertex>(graph.VertexCount);
            var predecessor = new Dictionary <Vertex, Vertex>();
            var gValue      = new Dictionary <Vertex, float>();
            var processed   = new HashSet <Vertex>();

            // Initialize all necessary components
            gValue[start] = 0;
            queue.Enqueue(start, HeuristicCost(start, target));

            // Calculate shortest path
            while (queue.Count != 0)
            {
                var current = queue.Dequeue();
                if (current == target)
                {
                    return(ReconstructPath(predecessor, target));
                }

                processed.Add(current);

                foreach (var edge in current.Edges)
                {
                    if (strict && edge.Weight > Vector2.Distance(current.Position, edge.TargetVertex.Position))
                    {
                        continue;
                    }
                    var neighbour = edge.TargetVertex;
                    if (!gValue.ContainsKey(neighbour))
                    {
                        gValue[neighbour] = float.PositiveInfinity;
                    }
                    if (processed.Contains(neighbour))
                    {
                        continue;
                    }

                    var tentativeValue = gValue[current] + edge.Weight;
                    try
                    {
                        if (tentativeValue >= gValue[neighbour])
                        {
                            continue;
                        }
                    }
                    catch
                    {
                        Debug.WriteLine("Graph vertex count and number of vertices match: " + graph.CheckGraph());
                    }

                    predecessor[neighbour] = current;
                    gValue[neighbour]      = tentativeValue;
                    if (queue.Contains(neighbour))
                    {
                        queue.UpdatePriority(neighbour, tentativeValue + HeuristicCost(neighbour, target));
                    }
                    else
                    {
                        queue.Enqueue(neighbour, tentativeValue + HeuristicCost(neighbour, target));
                    }
                }
            }

            return(new List <Vector2> {
                start.Position, start.Position
            });
        }
Пример #17
0
        /// <summary>
        /// FindPathForward, finds the fastes route between a and b
        /// </summary>
        /// <param name="a">stop number of the departuring station</param>
        /// <param name="b">stop number of the arrival station</param>
        /// <param name="utcStart">Departuretime in UTC format.</param>
        /// <returns>List of TimeTableId, describing the route for the path</returns>
        private List <PathItem> FindPathForward(int a, int b, long utcStart)
        {
            // the path we find as shortest
            var cameFrom = new Dictionary <int, TraceBackNode>();

            // gScore is the actual linuxtime to arrive at a stop: <stopId, arrival time>
            var gScore = new Dictionary <int, long>();

            gScore[a] = utcStart;

            // a min heap
            var heap = new FastPriorityQueue <QueueNode>(5000);

            heap.Enqueue(new QueueNode {
                StopId = a, Time = utcStart, TripId = -1
            }, DistanceTime(a, b));

            while (heap.Count != 0)
            {
                var currentNode = heap.Dequeue();
                // is arrival station found?
                if (currentNode.StopId == b)
                {
                    var path = ReconstructPath(cameFrom, currentNode.StopId);
                    path.Reverse();
                    return(path);
                }

                // get the neighbours to the currentNode
                var neighbours = ts.Edges
                                 .Where(e => e.FromStop == currentNode.StopId)
                                 .Select(e => new { e.EdgeId, e.ToStop, e.DistanceWalk });
                foreach (var n in neighbours)
                {
                    Iterations += 1;
                    long arrivalTime;  // time when arriving to n.ToStop
                    int  timeTableId = -1;
                    int  tripId      = -1;
                    if (n.DistanceWalk > 0)
                    {
                        if ((TimeToWalkSeconds(n.DistanceWalk) > cachedGlobal.MaxWalkingtime) | (currentNode.TripId == -1))
                        {
                            continue;  // to long to walk, or 2 sections in a row is walking!
                        }
                        arrivalTime = gScore[currentNode.StopId] + TimeToWalkSeconds(n.DistanceWalk);
                    }

                    else
                    {
                        long      gScoreTemp = gScore[currentNode.StopId]; // TryGetValueOrMax (currentNode.StopId)??
                        TimeTable timeTableEntry;
                        timeTableEntry = GetNextDeparture(n.EdgeId, gScoreTemp);

                        if (timeTableEntry == null) // no path found
                        {
                            continue;
                        }

                        // now chek if previous node is not walking, and change of transport and changetime is available
                        // othwise add changeTime, and search again.
                        if ((currentNode.TripId != -1)
                            & (currentNode.TripId != timeTableEntry.TripId)
                            & (timeTableEntry.DepartureTime < gScoreTemp + cachedGlobal.TimeToChangeTransport))
                        {
                            gScoreTemp    += cachedGlobal.TimeToChangeTransport;
                            timeTableEntry = GetNextDeparture(n.EdgeId, gScoreTemp);

                            if (timeTableEntry == null)  // no path found
                            {
                                continue;
                            }
                        }

                        arrivalTime = timeTableEntry.ArrivalTime;
                        timeTableId = timeTableEntry.TimeTableId;
                        tripId      = timeTableEntry.TripId;
                    }
                    if (arrivalTime < gScore.TryGetValueOrMax(n.ToStop))  // quicker way found
                    {
                        cameFrom[n.ToStop] = new TraceBackNode {
                            ToStop = currentNode.StopId, EdgeId = n.EdgeId, TimeTableId = timeTableId
                        };
                        gScore[n.ToStop] = arrivalTime;
                        QueueNode qn = new QueueNode {
                            StopId = n.ToStop, Time = arrivalTime, TripId = tripId
                        };
                        if (!heap.Contains(qn))
                        {
                            int heuristik = DistanceTime(n.ToStop, b);  // estimated traveltime from this node to the end
                            heap.Enqueue(qn, heuristik + arrivalTime);
                        }
                    }
                }
            }

            return(null);


            // Local: Get the next timetable entry in respect to departuetime given
            TimeTable GetNextDeparture(int edgeId, long departureTime)
            {
                return(ts.TimeTables
                       .Where(t => t.EdgeId == edgeId && (t.DepartureTime >= departureTime))
                       .OrderBy(t => t.DepartureTime)
                       .FirstOrDefault());
            }
        }
Пример #18
0
    public static void FlowFieldQuadTree(QuadTree quadTree, QuadTree end, out Dictionary <QuadTree, QuadTree> flowField)
    {
#if LOG_TIME
        var bench = new Stopwatch( );
        var avgNeighbourLookup = new List <long> ( );
#endif

#if DEBUG
        var timeout = new Stopwatch( );
        timeout.Start( );
#endif

        flowField = new Dictionary <QuadTree, QuadTree> ( );

        var openset    = new FastPriorityQueue <QuadTree> (quadTree.SubdivisionCount( ));
        var neighbours = new List <QuadTree> ( );

        openset.Enqueue(end, 0f);
        flowField[end] = end;

        QuadTree current = null;
        float    newcost = 0f;

        while (openset.Count > 0)
        {
#if DEBUG
            if (timeout.ElapsedMilliseconds > 1000)
            {
                throw new System.OperationCanceledException("flowField Generation Timed Out");
            }
#endif

            current = openset.Dequeue( );

#if LOG_TIME
            bench.Restart( );
#endif

            quadTree.Neighbours(current, ref neighbours);

#if LOG_TIME
            bench.Stop( );
            avgNeighbourLookup.Add(bench.ElapsedTicks);
#endif

            foreach (var neighbour in neighbours)
            {
                if (neighbour.Count != 0)
                {
                    continue;
                }

                newcost = current.Priority + (current.center - neighbour.center).sqrMagnitude + (neighbour.center - end.center).sqrMagnitude;

                if (newcost < neighbour.Priority)
                {
                    if (!openset.Contains(neighbour))
                    {
                        openset.Enqueue(neighbour, newcost);
                    }
                    else
                    {
                        openset.UpdatePriority(neighbour, newcost);
                    }

                    flowField[neighbour] = current;
                }
            }

            neighbours.Clear( );
        }

#if LOG_TIME
        Debug.Log("Average Neighbour Lookup: " + avgNeighbourLookup.Average( ) + " total " + avgNeighbourLookup.Sum( ));
#endif
    }
Пример #19
0
        /// <summary>
        /// Run the A* algorithm and put the result in path.
        /// If no path was found, return 'forever' and put only the destination in path.
        /// Returns the total path time.
        /// </summary>
        public float FindPath(
            List <PathNode> path,
            Vector3 start,
            Vector3 destination,
            MobilityData mobility,
            float unitRadius,
            MoveCommandType command)
        {
            path.Clear();
            path.Add(new PathNode(destination, false));

            PathNode cameFromDest = null;
            float    gScoreDest   = Pathfinder.FindLocalPath(this,
                                                             start,
                                                             destination,
                                                             mobility,
                                                             unitRadius);

            if (gScoreDest < Pathfinder.FOREVER)
            {
                if (command == MoveCommandType.NORMAL || command == MoveCommandType.REVERSE)
                {
                    return(gScoreDest);
                }
            }

            // Initialize with all nodes accessible from the starting point
            // (this can be optimized later by throwing out some from the start)
            _openSet.Clear();

            List <PathNode> graph = _graphRegularMove;
            float           neighborSearchDistance = Pathfinder.FOREVER;

            // if we are in fast mode our graph is much more extensive and we have to
            // limit our neighor distance to use that extensive network of nodes
            if (command == MoveCommandType.FAST)
            {
                graph = _graphFastMove;
                neighborSearchDistance = ARC_MAX_DIST;
            }

            // find the nearest neighbor start A* search
            foreach (PathNode neighbor in graph)
            {
                neighbor.IsClosed = false;
                neighbor.CameFrom = null;
                neighbor.GScore   = Pathfinder.FOREVER;

                Vector3 neighborPos = Position(neighbor);

                // and optimal search
                if ((start - neighborPos).magnitude < neighborSearchDistance)
                {
                    float gScoreNew = Pathfinder.FindLocalPath(this,
                                                               start,
                                                               neighborPos,
                                                               mobility,
                                                               unitRadius);
                    if (gScoreNew < Pathfinder.FOREVER)
                    {
                        neighbor.GScore = gScoreNew;

                        float fScoreNew = gScoreNew + TimeHeuristic(neighborPos, destination, mobility);
                        _openSet.Enqueue(neighbor, fScoreNew);
                    }
                }
            }

            // generic A* algorithm based on distance to destination and arc time's as hueristic function weights
            while (_openSet.Count > 0)
            {
                PathNode current = _openSet.Dequeue();
                current.IsClosed = true;

                if (gScoreDest < current.Priority)
                {
                    break;
                }

                foreach (PathArc arc in current.Arcs)
                {
                    PathNode neighbor = arc.Node1 == current ? arc.Node2 : arc.Node1;

                    if (neighbor.IsClosed)
                    {
                        continue;
                    }

                    float arcTime = arc.Time[mobility.Index];
                    if (arcTime >= Pathfinder.FOREVER)
                    {
                        continue;
                    }

                    float gScoreNew = current.GScore + arcTime;
                    if (gScoreNew >= neighbor.GScore)
                    {
                        continue;
                    }

                    float fScoreNew = gScoreNew + TimeHeuristic(Position(neighbor),
                                                                destination,
                                                                mobility);

                    if (!_openSet.Contains(neighbor))
                    {
                        _openSet.Enqueue(neighbor, fScoreNew);
                    }
                    else
                    {
                        _openSet.UpdatePriority(neighbor, fScoreNew);
                    }
                    neighbor.GScore   = gScoreNew;
                    neighbor.CameFrom = current;
                }

                float arcTimeDest = Pathfinder.FOREVER;
                // checks can we get to the last mile without more pathfinding
                if (Vector3.Distance(Position(current), destination) < neighborSearchDistance)
                {
                    arcTimeDest = Pathfinder.FindLocalPath(this, Position(current), destination, mobility, unitRadius);
                }
                // Debug.Log(openSet.Count + " " + Position(current) + " " + current.isRoad + " " + Vector3.Distance(Position(current), destination) + " " + (current.gScore + arcTimeDest) + " " + gScoreDest);
                if (arcTimeDest >= Pathfinder.FOREVER)
                {
                    continue;
                }
                if (arcTimeDest < Pathfinder.FOREVER && command == MoveCommandType.NORMAL)
                {
                    arcTimeDest = 0f;
                }

                float gScoreDestNew = current.GScore + arcTimeDest;
                if (gScoreDestNew < gScoreDest)
                {
                    gScoreDest   = gScoreDestNew;
                    cameFromDest = current;
                }
            }

            // Reconstruct best path
            PathNode node = cameFromDest;

            while (node != null)
            {
                path.Add(node);
                node = node.CameFrom;
            }
            return(gScoreDest);
        }
Пример #20
0
    void EikonalUpdateFormula(fastLocation l)
    {
        float phi_proposed = Mathf.Infinity;
        int   xInto, yInto;

        // cycle through directions to check all neighbors and perform the eikonal
        // update cycle on them
        for (int d = 0; d < DIR_ENWS.Length; d++)
        {
            xInto = l.x + (int)DIR_ENWS[d].x;
            yInto = l.y + (int)DIR_ENWS[d].y;

            neighbor = new fastLocation(xInto, yInto);

            if (isEikonalLocationValidAsNeighbor(neighbor))
            {
                // The point is valid. Now, we pull values from THIS location's
                // 4 neighbors and use them in the calculation

                int     xIInto, yIInto;
                float   phi_mx, phi_my, C_mx, C_my;
                Vector4 phi_m;
                phi_m = Vector4.one * Mathf.Infinity;

                // track cost of moving into each nearby space
                for (int dd = 0; dd < DIR_ENWS.Length; dd++)
                {
                    xIInto = neighbor.x + (int)DIR_ENWS[dd].x;
                    yIInto = neighbor.y + (int)DIR_ENWS[dd].y;

                    if (isEikonalLocationValidToMoveInto(new fastLocation(xIInto, yIInto)))
                    {
                        phi_m[dd] = Phi[xIInto, yIInto] + C[neighbor.x, neighbor.y][dd];
                    }
                }
                // select out cheapest
                phi_mx = Math.Min(phi_m[0], phi_m[2]);
                phi_my = Math.Min(phi_m[1], phi_m[3]);

                // now assign C_mx based on which direction was chosen
                if (phi_mx == phi_m[0])
                {
                    C_mx = C[neighbor.x, neighbor.y][0];
                }
                else
                {
                    C_mx = C[neighbor.x, neighbor.y][2];
                }
                // now assign C_mx based on which direction was chosen
                if (phi_my == phi_m[1])
                {
                    C_my = C[neighbor.x, neighbor.y][1];
                }
                else
                {
                    C_my = C[neighbor.x, neighbor.y][3];
                }

                // solve for our proposed Phi[neighbor] value using the quadratic solution to the
                // approximation of the eikonal equation
                float C_mx_Sq      = C_mx * C_mx;
                float C_my_Sq      = C_my * C_my;
                float phi_mDiff_Sq = (phi_mx - phi_my) * (phi_mx - phi_my);

                float valTest;
                //				valTest = C_mx_Sq + C_my_Sq - 1f/(C_mx_Sq*C_my_Sq);
                valTest = C_mx_Sq + C_my_Sq - 1f;

                // test the quadratic
                if (phi_mDiff_Sq > valTest)
                {
                    // use the simplified solution for phi_proposed
                    float phi_min = Math.Min(phi_mx, phi_my);
                    float cost_min;
                    if (phi_min == phi_mx)
                    {
                        cost_min = C_mx;
                    }
                    else
                    {
                        cost_min = C_my;
                    }
                    phi_proposed = cost_min + phi_min;
                }
                else
                {
                    // solve the quadratic
                    float radical = (float)Math.Sqrt((double)(C_mx_Sq * C_my_Sq * (C_mx_Sq + C_my_Sq - phi_mDiff_Sq)));

                    float soln1 = (C_my_Sq * phi_mx + C_mx_Sq * phi_my + radical) / (C_mx_Sq + C_my_Sq);
                    float soln2 = (C_my_Sq * phi_mx + C_mx_Sq * phi_my - radical) / (C_mx_Sq + C_my_Sq);
                    phi_proposed = Math.Max(soln1, soln2);
                }

                // we now have a phi_proposed

                // we are re-writing the phi-array real time, so we simply compare to the current slot
                if (phi_proposed < Phi[neighbor.x, neighbor.y])
                {
                    // save the value of the lower phi
                    Phi[neighbor.x, neighbor.y] = phi_proposed;

                    if (considered.Contains(neighbor))
                    {
                        // re-write the old value in the queue
                        considered.UpdatePriority(neighbor, phi_proposed);
                    }
                    else
                    {
                        // -OR- add this value to the queue
                        considered.Enqueue(neighbor, Phi[neighbor.x, neighbor.y]);
                    }
                }
            }
        }
    }
Пример #21
0
        /// <summary>
        /// A* forward search for a path that reaches the given goal.
        /// </summary>
        /// <returns>Returns null if a path could not be found, or a list of the
        /// transitions that must be followed, in order.</returns>
        public static Queue <ITransition> Search(
            ISearchContext agent,
            IState worldState,
            IGoal goal,
            bool reversePath = false)
        {
            // This is used to get the nodes from the state we're currently exploring.
            var exploredNodes = new Dictionary <IState, Node>(worldState.GetComparer());
            var closedSet     = new HashSet <IState>(worldState.GetComparer());
            var openSet       = new FastPriorityQueue <Node>(MAX_FRINGE_NODES);

            var currentNode = Node.Borrow(null, 0f, worldState, null);

            openSet.Enqueue(currentNode, 0f);

            IState nextState;
            Node   nextNode;

            while (openSet.Count > 0)
            {
                // Examine the next node.
                currentNode = openSet.Dequeue();

                // Check if the node satisfies the goal.
                if (currentNode.state.IsGoalState(goal, false))
                {
                    DebugUtils.Log("Selected path with cost: " + currentNode.Score + " Visited nodes: " + (closedSet.Count + openSet.Count));
                    var plan = UnwrapPath(currentNode, reversePath);
                    // Return all nodes.
                    Node.ReturnAll();

                    // Monitor nodes pool size to see if there are problems in the search.
                    Node.ReportLeaks();

                    return(plan);
                }

                // Mark this node as closed - don't explore it again.
                closedSet.Add(currentNode.state);
                exploredNodes.Remove(currentNode.state);

                // Go over all possible transitions.
                var possibleTransitions = currentNode.state.GetPossibleTransitions(agent);
                foreach (var transition in possibleTransitions)
                {
                    var cost = transition.CalculateCost(currentNode.state);
                    // Apply the transition to get the next state.
                    nextState = transition.ApplyToState(currentNode.state);

                    //DebugUtils.LogError("Checking transition: " + currentNode.state + " -(" + transition + ")-> " + nextState);
                    //UnityEngine.Debug.Break();

                    // Now that we have the new state, we can check if it was
                    // already evaluated and if so, we ignore it. We can ignore it
                    // thanks to the priority queue - we always check the state whose
                    // path to the starting state is the cheapest and so all the next
                    // states can only add to this cost.
                    if (closedSet.Contains(nextState))
                    {
                        transition.ReturnSelf();
                        nextState.ReturnSelf();
                        continue;
                    }

                    float newRunningCost = currentNode.runningCost + cost;
                    // Check if we explored this node in the past.
                    if (!exploredNodes.TryGetValue(nextState, out nextNode))
                    {
                        // Found a new node.
                        nextNode = Node.Borrow(currentNode, newRunningCost, nextState, transition);
                        // Cache the node for later.
                        exploredNodes[nextState] = nextNode;

                        DebugUtils.Assert(!openSet.Contains(nextNode), "Open set contains new node... How can this be?");

                        // This is a new node.
                        nextNode.CalculateHeuristicCost(agent, goal);
                        openSet.Enqueue(nextNode, nextNode.Score);
                        //DebugUtils.LogError("New node cost: " + newRunningCost + " " + nextNode.PathToString());
                    }
                    else if (newRunningCost < nextNode.runningCost)
                    {
                        // Found the best path so far to this node.
                        nextNode.parent      = currentNode;
                        nextNode.runningCost = newRunningCost;
                        nextNode.transition.ReturnSelf();
                        nextNode.transition = transition;
                        nextState.ReturnSelf();
                        //DebugUtils.LogError("!!! Best cost: " + newRunningCost + " " + nextNode.PathToString());
                    }
                    else
                    {
                        // Transition is not needed as it is known to be sub optimal.
                        transition.ReturnSelf();
                        nextState.ReturnSelf();
                    }
                }
            }
            DebugUtils.Log("NO PLAN. Closed nodes: " + closedSet.Count);
            Node.ReturnAll();
            return(null);
        }
Пример #22
0
    // Run the A* algorithm and put the result in path
    // If no path was found, return 'forever' and put only the destination in path
    // Returns the total path time
    public float FindPath(
        List <PathNode> path,
        Vector3 start, Vector3 destination,
        MobilityType mobility, float unitRadius,
        MoveCommandType command)
    {
        path.Clear();
        path.Add(new PathNode(destination, false));

        PathNode cameFromDest = null;
        float    gScoreDest   = Pathfinder.FindLocalPath(this, start, destination, mobility, unitRadius);

        if (gScoreDest < Pathfinder.Forever)
        {
            if (command == MoveCommandType.Slow || command == MoveCommandType.Reverse)
            {
                return(gScoreDest);
            }
        }

        // Initialize with all nodes accessible from the starting point
        // (this can be optimized later by throwing out some from the start)
        openSet.Clear();
        foreach (PathNode neighbor in graph)
        {
            neighbor.isClosed = false;
            neighbor.cameFrom = null;
            neighbor.gScore   = Pathfinder.Forever;
            Vector3 neighborPos = Position(neighbor);

            if ((start - neighborPos).magnitude < ArcMaxDist)
            {
                float gScoreNew = Pathfinder.FindLocalPath(this, start, neighborPos, mobility, unitRadius);
                if (gScoreNew < Pathfinder.Forever)
                {
                    neighbor.gScore = gScoreNew;
                    float fScoreNew = gScoreNew + TimeHeuristic(neighborPos, destination, mobility);
                    openSet.Enqueue(neighbor, fScoreNew);
                }
            }
        }

        while (openSet.Count > 0)
        {
            PathNode current = openSet.Dequeue();
            current.isClosed = true;

            if (gScoreDest < current.Priority)
            {
                break;
            }

            foreach (PathArc arc in current.arcs)
            {
                PathNode neighbor = arc.node1 == current ? arc.node2 : arc.node1;

                if (neighbor.isClosed)
                {
                    continue;
                }

                float arcTime = arc.time[mobility.Index];
                if (arcTime >= Pathfinder.Forever)
                {
                    continue;
                }

                float gScoreNew = current.gScore + arcTime;
                if (gScoreNew >= neighbor.gScore)
                {
                    continue;
                }

                float fScoreNew = gScoreNew + TimeHeuristic(Position(neighbor), destination, mobility);

                if (!openSet.Contains(neighbor))
                {
                    openSet.Enqueue(neighbor, fScoreNew);
                }
                else
                {
                    openSet.UpdatePriority(neighbor, fScoreNew);
                }
                neighbor.gScore   = gScoreNew;
                neighbor.cameFrom = current;
            }

            float arcTimeDest = Pathfinder.Forever;
            if (Vector3.Distance(Position(current), destination) < ArcMaxDist)
            {
                arcTimeDest = Pathfinder.FindLocalPath(this, Position(current), destination, mobility, unitRadius);
            }
            // Debug.Log(openSet.Count + " " + Position(current) + " " + current.isRoad + " " + Vector3.Distance(Position(current), destination) + " " + (current.gScore + arcTimeDest) + " " + gScoreDest);
            if (arcTimeDest >= Pathfinder.Forever)
            {
                continue;
            }
            if (arcTimeDest < Pathfinder.Forever && command == MoveCommandType.Slow)
            {
                arcTimeDest = 0f;
            }

            float gScoreDestNew = current.gScore + arcTimeDest;
            if (gScoreDestNew < gScoreDest)
            {
                gScoreDest   = gScoreDestNew;
                cameFromDest = current;
            }
        }

        // Reconstruct best path
        PathNode node = cameFromDest;

        while (node != null)
        {
            path.Add(node);
            node = node.cameFrom;
        }
        return(gScoreDest);
    }
Пример #23
0
    //public int getCostBetweenPoints(Vector2Int pointOne, Vector2Int pointTwo)
    //{

    //}


    private List <PathNode> AStar(MapTile[,] mapTiles, Vector2Int start, Vector2Int goal, float maxCost, bool pathMode, MapUnit c)//True: return path, False, return all possibilities
    {
        List <PathNode> nodesInRange = new List <PathNode>();

        aStarNodeArray = new AStarNode[mapTiles.GetLength(0), mapTiles.GetLength(1)];
        for (int x = 0; x < mapTiles.GetLength(0); x++)
        {
            for (int y = 0; y < mapTiles.GetLength(1); y++)
            {
                aStarNodeArray[x, y]        = new AStarNode(new Vector2Int(x, y));
                aStarNodeArray[x, y].gScore = float.PositiveInfinity;
                if (pathMode)
                {
                    aStarNodeArray[x, y].hScore = Distance(new Vector2Int(x, y), goal);
                }
                else
                {
                    aStarNodeArray[x, y].hScore = 0;
                }
            }
        }
        aStarNodeArray[start.x, start.y].gScore = 0;
        FastPriorityQueue <AStarNode> openSet = new FastPriorityQueue <AStarNode>(aStarNodeArray.GetLength(0) * aStarNodeArray.GetLength(1));

        openSet.Enqueue(aStarNodeArray[start.x, start.y], aStarNodeArray[start.x, start.y].fScore);



        //worldMap.SetDebugTile(start, Color.cyan);
        //worldMap.SetDebugTile(start, Color.red);
        if (pathMode && (!mapTiles[start.x, start.y].GetPassable(c) || !mapTiles[goal.x, goal.y].GetPassable(c)))
        {
            return(ReconstructPath(start, goal, aStarNodeArray, maxCost));
        }
        while (openSet.Count != 0)
        {
            AStarNode currentNode = openSet.Dequeue();

            if (currentNode.gScore > maxCost && !pathMode)
            {
                return(nodesInRange);
            }

            if (pathMode && currentNode.pos == goal)
            {
                //worldMap.SetDebugTile(goal, Color.green);
                return(ReconstructPath(start, goal, aStarNodeArray, maxCost));
            }
            currentNode.closed = true;
            // worldMap.SetDebugTile(currentNode.pos, Color.blue);
            if (!pathMode)
            {
                nodesInRange.Add(new PathNode(currentNode.pos, currentNode.gScore));
            }
            foreach (Vector2Int v in GetNeighbors(currentNode, mapTiles, c))
            {
                AStarNode currentNeighbor = aStarNodeArray[v.x, v.y];
                if (currentNeighbor.closed)
                {
                    continue;
                }
                if (!openSet.Contains(currentNeighbor))
                {
                    openSet.Enqueue(currentNeighbor, currentNeighbor.fScore);
                    //worldMap.SetDebugTile(currentNeighbor.pos, Color.magenta);
                    currentNeighbor.prevPos = currentNode.pos;
                }
                float tentative_gScore = currentNode.gScore + Cost(mapTiles, currentNode.pos, currentNeighbor.pos, c);
                if (tentative_gScore < currentNeighbor.gScore)
                {
                    // This path to neighbor is better than any previous one. Record it!
                    currentNeighbor.prevPos = currentNode.pos;
                    currentNeighbor.gScore  = tentative_gScore;
                    openSet.UpdatePriority(currentNeighbor, currentNeighbor.fScore);
                }
            }
        }
        if (pathMode)
        {
            return(ReconstructPath(start, goal, aStarNodeArray, maxCost));
        }
        else
        {
            return(nodesInRange);
        }
    }
Пример #24
0
        public static List <Tile> GetPath(Vector2Int from, Vector2Int to)
        {
            finalPath.Clear();

            int fromIndex = gridController.TilePosToIndex(from.x, from.y);
            int toIndex   = gridController.TilePosToIndex(to.x, to.y);

            Tile initialTile     = gridController.Tiles[fromIndex];
            Tile destinationTile = gridController.Tiles[toIndex];

            openListPriorityQueue.Enqueue(initialTile, 0);

            Tile currentTile = null;

            while (openListPriorityQueue.Count > 0)
            {
                currentTile = openListPriorityQueue.Dequeue();

                closeDictionary.Add(currentTile.Index, currentTile);

                if (Equals(currentTile, destinationTile))
                {
                    break;
                }

                UpdateNeighbors(currentTile);

                for (int i = neighbors.Length - 1; i >= 0; --i)
                {
                    Tile neighbourPathTile = neighbors[i];
                    if (neighbourPathTile == null)
                    {
                        continue;
                    }

                    if (closeDictionary.ContainsKey(neighbourPathTile.Index))
                    {
                        continue;
                    }

                    bool isAtOpenList = openListPriorityQueue.Contains(neighbourPathTile);

                    float movementCostToNeighbour = currentTile.GCost + GetDistance(currentTile, neighbourPathTile);
                    if (movementCostToNeighbour < neighbourPathTile.GCost || !isAtOpenList)
                    {
                        neighbourPathTile.SetGCost(movementCostToNeighbour);
                        neighbourPathTile.SetHCost(GetDistance(neighbourPathTile, destinationTile));
                        neighbourPathTile.SetParent(currentTile);

                        if (!isAtOpenList)
                        {
                            openListPriorityQueue.Enqueue(neighbourPathTile,
                                                          neighbourPathTile.FCost);
                        }
                        else
                        {
                            openListPriorityQueue.UpdatePriority(neighbourPathTile, neighbourPathTile.FCost);
                        }
                    }
                }
            }

            while (currentTile.Parent != null && !Equals(currentTile, initialTile))
            {
                finalPath.Add(currentTile);

                currentTile = currentTile.Parent;
            }

            finalPath.Add(initialTile);

            openListPriorityQueue.Clear();
            closeDictionary.Clear();
            return(finalPath);
        }
Пример #25
0
    public List <Vector2Int> search(MazeManager maze)
    {
        Vector2Int start = maze.getStart();


        int openSetSize = maze.rows * maze.cols;
        FastPriorityQueue <openSetElement> openSet = new FastPriorityQueue <openSetElement>(openSetSize);

        //HashSet<Vector2Int> openSet = new HashSet<Vector2Int>();
        HashSet <Vector2Int> closedSet = new HashSet <Vector2Int>();


        List <Vector2Int> goals = maze.getGoals();

        Vector2Int goal = goals[0];

        if (maze.isObstacle(ref goal))
        {
            // Debug.Log("FAIL!");
            return(new List <Vector2Int>());
        }


        Dictionary <Vector2Int, Vector2Int> predecessor = new Dictionary <Vector2Int, Vector2Int>();
        Dictionary <Vector2Int, double>     gScore      = new Dictionary <Vector2Int, double>();
        Dictionary <Vector2Int, double>     fScore      = new Dictionary <Vector2Int, double>();

        gScore.Add(start, 0);
        fScore.Add(start, heuristicDistance(start, goal));

        openSetElement startInOpenSet = new openSetElement(start);

        openSet.Enqueue(startInOpenSet, (float)fScore[start]);

        Vector2Int curPoint   = new Vector2Int();
        double     nei_gscore = 0.0;

        while (openSet.Count > 0)
        {
            /*
             * double minfScore = Math.Sqrt(Math.Pow(maze.rows, 2.0) + Math.Pow(maze.cols, 2.0));
             * foreach(Vector2Int point in openSet)
             * {
             *  double curfScore = (double)fScore[point];
             *  if (minfScore > curfScore)
             *  {
             *      curPoint = point;
             *      minfScore = curfScore;
             *  }
             * }
             */
            curPoint = openSet.Dequeue().pos_;
            double minfScore = fScore[curPoint];


            if (curPoint == goal)
            {
                List <Vector2Int> zig_zag_path = reconstructZigZagPath(predecessor, goal);
                //Debug.Log("zig_zag_SUCCESS!!!");

                List <Vector2Int> straight_path = reconstructStraightPath(ref maze, ref zig_zag_path);
                //Debug.Log("straight_SUCCESS!!!");

                return(straight_path);
            }

            closedSet.Add(curPoint);
            // openSet.Remove(curPoint);

            foreach (KeyValuePair <Vector2Int, bool> neighbor in getNeighbors(ref maze, curPoint))
            {
                if (closedSet.Contains(neighbor.Key))
                {
                    continue;
                }

                if (neighbor.Value)
                {
                    // Short Edges
                    nei_gscore = gScore[curPoint] + 1.0;
                }
                else
                {
                    // Long Edges
                    nei_gscore = gScore[curPoint] + Math.Sqrt(2.0);
                }

                if (!gScore.ContainsKey(neighbor.Key) || (nei_gscore < gScore[neighbor.Key]))
                {
                    predecessor[neighbor.Key] = curPoint;
                    gScore[neighbor.Key]      = nei_gscore;
                    fScore[neighbor.Key]      = nei_gscore + heuristicDistance(neighbor.Key, goal);
                    openSetElement neighborInOpenSet = new openSetElement(neighbor.Key);
                    if (!openSet.Contains(neighborInOpenSet))
                    {
                        openSet.Enqueue(neighborInOpenSet, (float)fScore[neighbor.Key]);
                    }
                }
            }
        }

        // Debug.Log("FAIL!!!");


        return(new List <Vector2Int>());
    }
Пример #26
0
        public static Solution Solve(Planet planet)
        {
            var areas = planet.Areas;

            var currentArea = areas[planet.Sugar];

            currentArea.Duration          = 0;
            currentArea.DurationFromStart = 0;

            var endArea = planet.Areas[planet.Astroants];

            endArea.Duration = 0;

            var areaQueue = new FastPriorityQueue <Area>(areas.Length);

            while (true)
            {
                if (currentArea == endArea)
                {
                    return(GetSolution(planet));
                }

                currentArea.Visited = true;

                for (var i = 0; i < currentArea.Neighbors.Length; i++)
                {
                    var direction = currentArea.Neighbors[i];
                    var neighbor  = areas.GetNeighbor(currentArea.Coords, direction);
                    if (neighbor.Visited)
                    {
                        continue;
                    }

                    var durationFromStart = currentArea.DurationFromStart + neighbor.Duration;
                    if (durationFromStart >= neighbor.DurationFromStart)
                    {
                        continue;
                    }

                    neighbor.CameFrom          = direction;
                    neighbor.DurationFromStart = durationFromStart;

                    if (areaQueue.Contains(neighbor))
                    {
                        areaQueue.UpdatePriority(neighbor, neighbor.TotalEstimatedDuration);
                    }
                    else
                    {
                        neighbor.SetEstimatedDurationTo(endArea.Coords);
                        areaQueue.Enqueue(neighbor, neighbor.TotalEstimatedDuration);
                    }
                }

                if (areaQueue.Count == 0)
                {
                    return(null);
                }

                currentArea = areaQueue.Dequeue();
            }
        }
Пример #27
0
    /// <summary>
    /// The EikonalUpdateFormula computes the actual solution potential
    /// </summary>
    /// <param name="l"></param>
    private void EikonalUpdateFormula(FastLocation l)
    {
        float phi_proposed = Mathf.Infinity;

        // cycle through directions to check all neighbors and perform the eikonal
        // update cycle on them
        for (int d = 0; d < DIR_ENWS.Length; d++)
        {
            int xInto = l.x + (int)DIR_ENWS[d].x;
            int yInto = l.y + (int)DIR_ENWS[d].y;

            neighbor = new FastLocation(xInto, yInto);

            if (isEikonalLocationValidAsNeighbor(neighbor))
            {
                // The point is valid. Now, we pull values from THIS location's
                // 4 neighbors and use them in the calculation
                Vector4 phi_m;

                phi_m = Vector4.one * Mathf.Infinity;

                // track cost of moving into each nearby space
                for (int dd = 0; dd < DIR_ENWS.Length; dd++)
                {
                    int xIInto = neighbor.x + (int)DIR_ENWS[dd].x;
                    int yIInto = neighbor.y + (int)DIR_ENWS[dd].y;

                    if (isEikonalLocationValidToMoveInto(new FastLocation(xIInto, yIInto)))
                    {
                        phi_m[dd] = Phi[xIInto, yIInto] + C[neighbor.x, neighbor.y][dd];
                    }
                }
                // select out cheapest
                float phi_mx = Math.Min(phi_m[0], phi_m[2]);
                float phi_my = Math.Min(phi_m[1], phi_m[3]);

                // now assign C_mx based on which direction was chosen
                float C_mx = phi_mx == phi_m[0] ? C[neighbor.x, neighbor.y][0] : C[neighbor.x, neighbor.y][2];
                // now assign C_my based on which direction was chosen
                float C_my = phi_my == phi_m[1] ? C[neighbor.x, neighbor.y][1] : C[neighbor.x, neighbor.y][3];

                // solve for our proposed Phi[neighbor] value using the quadratic solution to the
                // approximation of the eikonal equation
                float C_mx_Sq      = C_mx * C_mx;
                float C_my_Sq      = C_my * C_my;
                float phi_mDiff_Sq = (phi_mx - phi_my) * (phi_mx - phi_my);

                float valTest = C_mx_Sq + C_my_Sq - 1f / (C_mx_Sq * C_my_Sq);
                //float valTest = C_mx_Sq + C_my_Sq - 1f;

                // test the quadratic
                if (phi_mDiff_Sq > valTest)
                {
                    // use the simplified solution for phi_proposed
                    float phi_min  = Math.Min(phi_mx, phi_my);
                    float cost_min = phi_min == phi_mx ? C_mx : C_my;
                    phi_proposed = cost_min + phi_min;
                }
                else
                {
                    // solve the quadratic
                    var radical = Math.Sqrt(C_mx_Sq * C_my_Sq * (C_mx_Sq + C_my_Sq - phi_mDiff_Sq));

                    var soln1 = (C_my_Sq * phi_mx + C_mx_Sq * phi_my + radical) / (C_mx_Sq + C_my_Sq);
                    var soln2 = (C_my_Sq * phi_mx + C_mx_Sq * phi_my - radical) / (C_mx_Sq + C_my_Sq);

                    // max - prefers diagonals
                    //phi_proposed = (float)Math.Max(soln1, soln2);

                    // min - prefers cardinals
                    //phi_proposed = (float)Math.Min(soln1, soln2);

                    // mean - better mix but still prefer diagonals
                    //phi_proposed = (float)(soln1 + soln2) / 2;

                    // geometric mean - seems identical to mean
                    //phi_proposed = (float)Math.Sqrt(soln1 * soln2);

                    // weighted mean - appears to offer the best compromise
                    var   max  = (float)Math.Max(soln1, soln2);
                    var   min  = (float)Math.Min(soln1, soln2);
                    float wMax = CCValues.S.maxWeight;
                    float wMin = CCValues.S.minWeight;
                    phi_proposed = (float)(max * wMax + min * wMin) / (wMax + wMin);
                }

                // we now have a phi_proposed

                // we are re-writing the phi-array real time, so we simply compare to the current slot
                if (phi_proposed < Phi[neighbor.x, neighbor.y])
                {
                    // save the value of the lower phi
                    Phi[neighbor.x, neighbor.y] = phi_proposed;

                    if (considered.Contains(neighbor))
                    {
                        // re-write the old value in the queue
                        considered.UpdatePriority(neighbor, phi_proposed);
                    }
                    else
                    {
                        // -OR- add this value to the queue
                        considered.Enqueue(neighbor, Phi[neighbor.x, neighbor.y]);
                    }
                }
            }
        }
    }
Пример #28
0
        private Point Move(Person person, Point pos)
        {
            // Start by adding p to visited
            var visited = new HashSet <Point> {
                pos
            };

            var nodes = new FastPriorityQueue <VisitedNode>(64);

            var adjacentNodes = GetAdjacentNodes(pos);

            foreach (var node in adjacentNodes)
            {
                node.InitialVel = new Point(node.Pos.X - pos.X, node.Pos.Y - pos.Y);
                nodes.Enqueue(node, node.GetPriority());
                visited.Add(node.Pos);
            }

            while (nodes.Any())
            {
                var nextNodes = new FastPriorityQueue <VisitedNode>(64);

                while (nodes.Any())
                {
                    var node = nodes.Dequeue();

                    visited.Add(node.Pos);

                    if (this._people.TryGetValue(node.Pos, out var enemy) && enemy.GetType() != person.GetType())
                    {
                        // Enemy in this pos - stop searching
                        var newPos = new Point(pos.X, pos.Y);
                        newPos.Offset(node.InitialVel);
                        return(newPos);
                    }

                    // Non-empty square - cannot move here, do nothing
                    if (this._people.ContainsKey(node.Pos) || !this._emptySquares.Contains(node.Pos))
                    {
                        continue;
                    }

                    // This square is empty - add all adjacent non-visited nodes
                    adjacentNodes = GetAdjacentNodes(node.Pos);

                    foreach (var adjNode in adjacentNodes)
                    {
                        if (!visited.Contains(adjNode.Pos))
                        {
                            adjNode.InitialVel = node.InitialVel;
                            visited.Add(adjNode.Pos);
                            nextNodes.Enqueue(adjNode, adjNode.GetPriority());
                        }
                        else if (nextNodes.Contains(adjNode))
                        {
                            var queueNode = nextNodes.Single(nds => nds.Equals(adjNode));

                            if (adjNode.InitialVel.Y < queueNode.InitialVel.Y)
                            {
                                queueNode.InitialVel = adjNode.InitialVel;
                            }
                            else if (adjNode.InitialVel.Y == queueNode.InitialVel.Y &&
                                     adjNode.InitialVel.X < queueNode.InitialVel.X)
                            {
                                queueNode.InitialVel = adjNode.InitialVel;
                            }
                        }
                    }
                }

                nodes = nextNodes;
            }

            return(pos);
        }