A* Star Pathfinding help! - path-finding

On many A* Start Pathfinding tutorials the last part is always something like this;
Save the path. Working backwards from the target square, go from each square to its parent square until you reach the starting square. That is your path.
I don't really get what I am suppose to do to implement this in my A * star Pathfinding. The current method I am using is the following; I save the path, reverse it, runs the pathfinder again but I get neighboring nodes by checking if they are on the original path list and adding them if they are on the list.
The problem with this method is that I get some strange path sometimes.

You simply need to keep a "came from" map for the nodes you visit.
When you reach your target, you can work your way back to the source node by recursively polling "came from" on the node until the node is the source.
Note that this will give you a reversed path. You simply reverse this path and you got your shortest path from source to target.
You don't have to run your shortest path algorithm again.

If you haven't already read this, take a look:
http://theory.stanford.edu/~amitp/GameProgramming/
That was my resource when I implemented A* for a game. The "parent" square you mentioned isn't a good name. As turbovince mentioned, it's not the "parent" node but rather where you came from. Each node has a reference from whence it came, so when you finally land on the target you should be able to traverse these references back to the origin.

Related

A-star (A*) with "correct" heuristic function and without negative edges

In A* heuristic there is a step that updates value of the node if better route to this node was found. But what if we had no negative edges and correct heuristic function (goal-aware, safe and consistent). Is it true that updating will no longer be necessary because we always get to that state first by the shortest path?
Considering the euclidean distance heuristic, it seems to me that it works but I am unable to generalize it in my thoughts as why it should. If not, can anyone provide me with a counter example or in other case confirm my initial though?
Context: I am solving a task with heuristic function which I don't really understand and I don't need to (pseudo-code is provided), but I am guaranteed it is (goal-aware, safe and consistent). The state space is huge so I am unable to build the graph so I am looking for a way how to completely omit remembering the graph and just keep a hash map so I know if I visited particular state before, therefore avoid the cycles.
So I have tested my hypothesis on various instances and it seems that even if the heuristic is (goal-aware, safe and consistent) and the "graph" is without negative edges, the first entry into the state might not be on the shortest possible path. (Some instances seemed to give proper result only if revisiting and updating the states as well as pushing them back into the openSet held by A* was supported.)
I wasn't able to isolate why, but when debugging, some states were visited multiple times and over the shorter path. My guess is that maybe it can happen when we go towards goal but add a neighbor in the graph which is in the direction away from the goal. Therefore being on the longer path that it can possibly be if we would move on the most optimized path from the start towards this node in the direction of the goal.

Limiting depth of shortest path query using Gremlin on JanusGraph

I have a fairly large graph (currently 3806702 vertices and 7774654 edges, all edges with the same label) in JanusGraph. I am interested in shortest path searches in it. Gremlin recipes mention this query:
g.V(startId).until(hasId(targetId)).repeat(out().simplePath()).path().limit(1)
This returns path that I know to be a correct one immediately but then hangs the console (top shows janusgraph and scylla to be processing stuff furiously though, so I guess it's working in the background, but it takes forever). It does the right thing and returns first (correct) shortest path if used like this:
g.V(startId).until(hasId(targetId)).repeat(out().simplePath()).path().next()
I would like to limit this query so that gremlin/janusgraph stops searching for path over, let's say, 100 hops (so I want max depth of 100 edges basically). I have tried to use .times(100) in multiple positions but if .until() is used with .times() in the same query it always crashes with a NullPointerException in gremlin traversal classes, ie:
java.lang.NullPointerException
at org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper.hasStepOfAssignableClassRecursively(TraversalHelper.java:351)
at org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.RepeatUnrollStrategy.apply(RepeatUnrollStrategy.java:61)
at org.apache.tinkerpop.gremlin.process.traversal.util.DefaultTraversalStrategies.applyStrategies(DefaultTraversalStrategies.java:86)
at org.apache.tinkerpop.gremlin.process.traversal.util.DefaultTraversal.applyStrategies(DefaultTraversal.java:119)
at org.apache.tinkerpop.gremlin.process.traversal.util.DefaultTraversal.next(DefaultTraversal.java:198)
at java_util_Iterator$next.call(Unknown Source)
...
Does anyone have any idea how can I apply such limit? I need this to return first result or fail, fast.
Thanks!
Add another break condition in your until() and also make sure to limit() the result before you ask for paths:
g.V(startId).
until(__.hasId(targetId).or().loops().is(100)).
repeat(__.both().simplePath()).
hasId(targetId).limit(1).path()
Calling tryNext() on this traversal will give you an Optional<Path>. If it's empty, then no path was found within the given distance.

A* Pathfinding - Updating Parent

I've read A* Pathfinding for Beginners and looked at several source code implementations in C++ and other languages. I understand most of what is happening, with the exception of one possible issue I think I have found, and none of the tutorials/implementations I've found cover this.
When you get to this part:
If an adjacent square is already on the open list [...], if the G cost
of the new path is lower, change the parent of the adjacent square to
the selected square. Finally, recalculate both the F and G scores of
that square.
Changing the G score of a square should also change the G score of every child, right? That is, every square that already has this square as the parent, should get a new G score now also. So, shouldn't you find every child (and child of child) square in the open list and recalculate the G values? That will also change the F value, so if using a sorted list/queue, that also means a bunch of resorting.
Is this just not an actual problem, not worth the extra CPU for the extra calculations, and that is why the implementations I've seen just ignore this issue (do not update children)?
It depends on your heuristic.
For correctness, the basic A* algorithm requires that you have an admissible heuristic, that is, one that never overestimates the minimum cost of moving from a node to the goal. However, a search using an admissible heuristic may not always find the shortest path to intermediate nodes along the way. If that's the case with your heuristic, you might later find a shorter path to a node you've already visited and need to expand that node's children again. In this situation, you shouldn't use a closed list, as you need to be able to revisit nodes multiple times if you keep finding shorter routes.
However, if you use a consistent heuristic (meaning that the estimated cost of a node is never more than the estimated cost to one of its neighbors, plus the cost of moving from the node to that neighbor), you will only ever visit a node by the shortest path to it. That means that you can use a closed list and never revisit a node once you've expanded its children.
All consistent heuristics are admissible, but not all admissible heuristics are consistent. Most admissible heuristics are also consistent though, so you'll often seen descriptions and example code for A* that assumes the heuristic is consistent, even when it doesn't say so explicitly (or only mentions admissibility).
On the page you link to, the algorithm uses a closed list, so it requires a consistent heuristic to be guaranteed of finding an optimal path. However, the heuristic it uses (Manhattan distance) is not consistent (or admissible for that matter) given the way it handles diagonal moves. So while it might find the shortest path, it could also find some other path and incorrectly believe it is the shortest one. A more appropriate heuristic (Euclidean distance, for example) would be both admissible and consistent, and you'd be sure of not running into trouble.
#eselk : As the square, whose parent and G-score are to be updated, is still in OL, so this means that it has Not been expanded yet, and therefore there would be no child of the square in the OL. So updating G-scores of children and then their further children does not arise. Please let me know if this is not clear.

A* Pathfinding - closest to unwalkable destination

I already have an A* Implementation that works. The problem is that if you pick a destination that is unwalkable, no path is returned. I want to be able to get the 'closest' I can get.
The preferable option would be completely dynamic (not just checking the 8 tiles around the destination to try to find one). That way, even if they click an unwalkable tile surrounded by a huge square of unwalkable tiles, it will still get as close as it can.
While the simple answers provided here MIGHT be sufficient enough, I think it depends on your game type and what you're trying to achieve.
For example, take this play field (sorry I'm reusing the same software I used to show you the fog of war :)) :
As you can see, an Angry Chicken is blocking the path between the left side and the right side. The Angry Chicken could be anything... if it's a static obstacle, then going with the lowest h node might be enough, but if it's a dynamic object (like a locked door, draw bridge, etc...) the following examples might help you find out how you want to solve your problem.
If we set the destination for our Hero on the other side
We need to think what we want the path to be, since obviously we can't reach it. Using a standard heuristic like manhattan distance or euclidian distance, you will get this result:
Which might be good enough, but if there's any way our little Hero could interact with the chicken to pass, it doesn't make sense at all, what you want is this
How can you do this? Well, an easy way to do this is to pathfind on hierarchical graphs. This sounds complicated but it isn't. First, you want to be able to build a new set of high level nodes and edges that will contain multiple grid nodes (or other representation, wouldn't change a thing)
As you can see, we now have a right blue node and a left red node. The arrow represents the edge between the two nodes. How to build this graph you ask? It's easy, simply start from an open node, expand all of its neighbors and add them to a high level node, when you're done, open the dynamic nodes that could lead to another part of the graph and do the same.
Now, when you ask for a path from our Hero to the red X, you first do the pathfinding on the high level... is there a way from blue node to red node? Yes! Through the chicken.
You can now easily know how to navigate on the blue side by going to the edge that will allow you to cross, which is the chicken.
If it was just a plain wall, you could determine very quickly, by visiting a single node, that there is NO way to reach on the other side and then handle it the way you want, possibly still performing an A* and returning the lowest h node.
You could keep a pointer which holds a tile with the lowest h-value, then if no path is returned simply generate a path to the tile you're holding onto instead.

Fixed length path between two graph nodes

Is there an algorithm that will, if given two nodes on a graph, find a route between them that takes the specified number of hops? Any node can be connected to any other.
The points at the moment are located in 2D space, so I'm not sure if a graph is the best approach.
Have you tried iterated-deepening DFS?
If you have nodes are seeking to find routes in terms of hops, then a graph is probably the right approach. I'm not sure I understand what you are trying to do and what the constraints are, though, especially with respect to "Any Node can be connected to any other" .. which seems a bit open ended.
Disregarding that, however; with some graph representation:
It seems like starting at the first node, and doing a depth first search from there, and terminating a search if (a) the hops taken is larger than your specified number or (b) we have arrived at the second node; this will determine the first (not only) path connecting the two nodes in (at most) that many hops.
If it has to be exactly the specified hops, terminate any branch of the search if the hops have gone over, and terminate with success if you have also arrived at the second node.
Dumb approach: (data structure is array of stacks). This is basically doing Breadth First Search (BFS) to depth N, except that if loops are allowed (you did not clarify but I assume they are), you don't exclude the visited nodes from further searching.
Push starting node on a stack stored in the array at index 0 (index=depth)
For each level/index "l" 0-N:
For each node on a stack stored at level "l", find all its neighbors, and push them onto a stack stored in level "l+1".
Important: if your task allows finding paths that contain loops, do NOT check if you already visited any node you add. If it does not allow loops, use a hash of visited nodes to not add any node twice**
Stop when you end level "N-1".
Loop over all the nodes you just added to stack at index "N" and find your destination node. If found: success, if not, no such path.
Please note that if by "every node can be connected" you are implying a FULLY CONNECTED graph, then there exists a mathematical answer not involving actually visiting nodes
(however, the formula is too long to write in the text-entry field of StackOverflow)

Resources