Shortest route with fewest turns - java

I had a requirement to generate shortest route. The first solution which suited my requirement was Dijkstra's algorithm, and hence I implemented the same (Java). Later, I had to modify the implementation to generate the shortest route "with least number of turns". After some head-scratching, i came up with a solution, although with a lot of conditions added into the existing Dijkstra's algorithm implementation. Now my query is, is there a better approach for this problem(like, any existing algorithm which already does this)? My solution includes storing additional turns information in each of the nodes in the route calculation iteration, and use the same while back-tracking the route.

You shouldn't need any backtracking or substantial tweaks to Dijkstra. Simply keep track (as you do), for each node, of the least number of turns on the currently shortest route to that node. Whenever you relax an edge, if the resulting path is equally short as the currently shortest route, you pick the one with the fewest turns.
Edit: as pointed out in the comments, this approach disregards the fact that the direction of the incoming edge of the chosen route affects the number of turns for the subsequent path. That will be fixed by storing in each node the shortest distance+turns for each incoming edge or for each unique incoming angle (however you measure that).
Alternatively, in order to get by with fewer modifications of Dijkstra, you can modify the graph beforehand: Split each node into one node per incoming edge (so that each resulting node has only one of the original node's incoming edges), but copy all the outgoing edges so that each resulting node has all the outgoing edges of the original node (each of which must be directed to the appropriate copy of the node at the other end of the edge). You might see that some of the resulting nodes have multiple incoming edges, but in that case, the nodes on the other ends of those edges are all copies of the same original node and thus represent the "same" original edge - therefore, each outgoing edge can be unambiguously labeled with whether that edge represented a turn out of that node (relative to the node's incoming edges) or not. Note that the best path in the original graph will still exist in the new graph (and no better paths will have been introduced). Now, Dijkstra just needs to be modified to track the number of turns associated with the shortest path to each node. Whenever an edge from u to v is relaxed and the candidate path is as short as the shortest path you have previously found for v, compare u's turn count plus the edge's turn count (0 or 1 depending on whether the edge constituted a turn) to v's turn count, and use that as a tiebreaker.

Ultimately path finding algorithms are designed to find the lowest cost path. The definition of cost depends on the scenario. In one scenario cost might be distance but in other scenarios it might include terrain, slope, tolls etc. In your case the easiest way to model 'shortest route with least number of turns' is to derive cost from both distance and number of turns. In other words, include a cost for turning.
For example, if you are using the A* algorithm, your cost calculation between two nodes could include a cost for the distance and an additional cost if this move requires a change of direction. If a different path does not require a change of direction then it will be lower cost and the algorithm will choose that path.
The only tricky thing here will be to keep the context of the previous moves to detect the turns. In A* you are generally keeping references back to the previous node so it should be fairly straightforward to decide if the next move requires a turn.

I do not know, why no one else has stated this and why there is an accepted answer.
The problem you are trying to solve (i.e., generate the shortest route with least number of turns) is an example of the weight-constrained shortest path problem.
It is therefore NP-Complete and cannot be solved efficiently.
You can find papers that discuss solving this problem e.g. http://web.stanford.edu/~shushman/math15_report.pdf

Here's a simple heuristic. Like others have pointed out, heuristic is the game in AStar.
if (Cost > CanMaxMove) Heuristic += 1000;
// for cost per grid pt typically 10 to 30
// Cost = PtCost + CostSoFar
// higher is worse (more costly)
You simply find the best path as per usual in AStar, but discount by a large margin moves that would be out of turn. This is a very hard problem as pointed out, but easily solveable given the following condition:
Every turn a new path can and will be searched anyway: this is easily
believable, because until next turn circumstance can easily change. If
not, those are not really turns as we know them.
If that condition is ok with you, just do the above snippet. Heuristic must be discounted by the same value for all "out of this turn" moves and NOT smoothly (e.g. Heuristic += (Cost - CanMove) * 100) i.e. there must be a large difference between "this turn" and "not this turn".

Related

Identifying cheapest path with A* algorithm

So I am writing a Java program that uses the A* search algorithm. The program runs on a 2 dimensional array. It has a start location, a goal and obstacles to move around. Every object on the grid is a node.
SRRRRRRR
RXXRRXXX
RRRXXXRX
RXRRXRRR
XXXRRXRR
RRRRRRRR
XXRXRRXR
XXXXRRRG
S = Start, G = Goal, R = Valid movement tile, X = Illegal movement tile
I have two arraylists:
- openList
- closedList
openList is a list of possible movements sorted from cheapest to most expensive. closedList is a list of nodes that have been visited and will not be visited again. The algorithm will always move into the first node in the openList. This node will then be removed from openList and added to the end of closedList.
My algorithm can successfully navigate from start to goal. The problem that I am having is that I am not sure how to filter out the true path from my list of closed nodes. A* will always look for the cheapest option which means that it may not go directly to the goal. The openList ranks nodes according to the cost of movement so even if the algorithm is sitting one Node away from the goal, if there is a node that is cheaper to move into somewhere earlier on the path then it will take that cheaper node. This means that I am guaranteed to find the cheapest path, but also that at the end my closed list will be full of nodes that are not on the best path to the goal.
At the end my closedList gives me the exact path my algorithm took, not the cheapest path.
My question is: Of all the nodes that my algorithm will explore, how do I differentiate between nodes that are on the cheapest path and nodes that are not?
I would highly, HIGHLY recommend Amit Patel's A* pages, which will go into very good detail about everything you may want to know about Pathfinding.
To solve your specific problem, you need to in some way store the node you came from when you visit a node, so when you reach the goal, you just walk your way backwards along the path. This can be done with a Map<Node, Node>, or, you can make use of references to the parent node by storing something other than a Node: Something that contains the node, and a reference to the node from which you came to visit that node when you add to your lists.
It sounds like your cost function may be broken.
In A*, the cost function is always the sum of the actual cost of the path traversed so far plus a lower bound on the distance remaining. There are rules for admissability of the heuristic - the same as for a metric space IIRC.
Obvious heuristics to use for the lower-bound remaining distance in this case are...
Euclidean distance remaining - sqrt (xdist^2 + ydist^2).
Manhattan distance remaining - xdist + ydist
If the total cost estimate after taking a step along the indirect path isn't greater than after stepping directly to the goal, the only way that can be valid is if the total cost estimate is the same either way. A* won't avoid taking extra steps unless you add a tie-breaker to your cost-comparing tests. But it won't choose a higher-cost route when a direct route is available - unless your cost function is deceiving it (or your code has bugs).
In any case, that same-cost-either-way should never happen in a square grid if a possible move is directly to the goal.
There's a chance you may have implemented Dijkstra rather than A*. The cost function for Dijstra is simply the total distance travelled so far. There's no attempt to estimate distance remaining and therefore nothing to guide the search towards the goal - it explores in all directions equally.
One way to accidentally end up with Dijkstra is to use the obvious "uninformed" (but admissable) lower bound on the remaining distance - zero.
At the end it's still, of course, likely that you will have searched nodes that are off the optimum path - usually fewer than if you've got a good A* heuristic but even that can be wrong for awkward maps. See moveaway00s answer - "you need to in some way store the node you came from when you visit a node". For each node you explore, there's only one possible shortest-possible-distance to get there - if the node is on the shortest path, that backward step is a reverse step along the shortest path.
For Dijkstra, the first time you explore a location is always for the shortest way to get there. For A* that's not necessarily true IIRC (it's true for the goal node, not necessarily for other nodes explored), so you may need to store the shortest distance to the node along with the backward step.

Finding path of zero/Negative weight between Two Nodes on Graph by Utilizing Negative Cycles

I really struggled with describing this in the title but I'll give it a go in a longer format.
I'm really stumped on this problem and I'm not looking for answers, just a little help or some specific topics to read up on.
What I have is a directed Graph with edges of various weights, both negative and positive. What I am attempting to do is to write an algorithm that is provided with two nodes positioned on the graph (and assuming they're connected) finds a path between them that results in the total weight of the path being either zero or negative. The path can include nodes multiple times (hopefully allowing for the path to offset the positive weight of included edges).
I'm currently reading Russel and Norvig's Artificial Intelligence, but am struggling to find a way to apply the logic in the text to my problem due to various problems (The algorithm continuously going round the negative cycle). I'm not fully understanding how to utilize methods such as Backtrack and AStar for this
If anyone could point me in the right direction of something that would help me understand my problem better it would be a great help, I'm fine with dealing with DFS and BFS and many other things in relation to Graphs but having to find a path between two nodes with the weight restrictions is really baffling me.
Thanks
Below I've included a sample graph, I need to be able to find a path from Start to Goal where the total weight of the path doesn't exceed Zero.
Example Graph
http://i144.photobucket.com/albums/r166/ZooropaTV/bu.jpg
Just realised that a lot of the searching/Reading I've been doing has been misguided, since my goal isn't necessarily about finding the shortest path by weight, but by visiting the minimum required number of nodes, I need to have another think about it now, but still would like any advice
I think this is what you want: The Floyd–Warshall algorithm http://en.wikipedia.org/wiki/Floyd%E2%80%93Warshall_algorithm
You'll have to modify it to fit your needs but it will detect negative cycles thus allowing you to find a path of zero or lesser weight.

How to find the best path in graph with weighted nodes and vertices

Let's say I have this graph
always a full graph
one start node - also the finish node
weighted nodes and vertices
I want to find a path short as possible but with the best score (sum of points of nodes) - in other words a path that can't be longer then some defined constant but give me the best amount of points. And I want to start and stop in the same node and don't want to go over already visited nodes.
Are there any algorithms which could help me with this problem or do you have any ideas how to solve it?
Oh, and it's not a homework, I just want to create a special path finder.
EDIT
So far I've been able to construct a working algorithm which can find some path in a few seconds. But I don't get the amount of points I'd like to - I get only about 85% of the desired score. And if I change the algoritm's parameters then time will be in hours and more...
I don't think this is solvable in better than brute force time. You could calculate all paths up to a certain constraint length. However, for an arbitrarily large graph that would be extremely slow. If you're looking for a solid guess, I'd start with a greedy algorithm that picks the step with the highest Points per Length value, until the limit is reached. You can then add things such as reversing in the case of premature filling (say, if you've gone 5, but your limit is 6, and your current node has no paths of length one connected) to find out how that works.
I'm not sure if this would actually work, but these are my initial thoughts:
Perhaps try with the maximum spanning tree (Prim's or Kruskal's). Since you don't want to repeat vertices, your path must end up being the cycle graph. Walk the spanning tree (maybe some sort of greedy algorithm?) and once you hit a leaf, go back to the start vertex (since the original graph was the complete graph). This would only work (maybe) if there were no negative edge weights.
Just some thoughts for now - it's late at night, I'll take a closer look in the morning. :)

How to get the cut-set using the Edmonds–Karp algorithm?

I implemented the Edmonds–Karp algorithm using the Pseudocode that I found in the Edmonds–Karp algorithm wiki page: http://en.wikipedia.org/wiki/Edmonds%E2%80%93Karp_algorithm
It works great, yet the algorithm output is the max flow value(min cut value), I need to the list of edges that this cut contains
I tried to change the algorithm, with no success, can you guys help?
Thank you
If you already have the flow, then compute the residual graph. Then do a depth first search from the source (or breadth first search, I don't think it matters), to compute the vertices in one half of the cut (S). The remaining vertices are in the other half of your cut, T.
This gives you your cut (S, T). If you specifically want the edges between S and T, you could iterate through all the edges, selecting the ones which connect S and T. (Though there may a be a more eleegant way to do this last part.)
Here's some pointers to help clarify how to do this for anyone in the future.
To find the S vertices, do a BFS (or DFS) search from source vertex, only following edges in which some capacity for flow is remaining. (In other words, the non-saturated edges). These ones by definition cannot be in the mincut.
To find the T vertices perform a BFS (or DFS) search from the sink vertex, only connecting to vertices that were not already added to the S set. These can have residual flow, or could be fully saturated, it doesn't matter. Because you are performing BFS from the sink, you'll need to make sure you follow the opposite direction the edge is pointed if the graph is directed. NOTE: It's important to only include vertices that can be reached from the sink in your T set, otherwise you'll end up including edges in your min-cut that do not belong there. (This is what threw me for a long time.)
Once you have these two sets of vertices you can then iterate over all the edges of the graph. Anyone that has a source node in S and a target node in T is part of your min-cut. It's important to note, though, that this is just one of many possible min-cuts. It's much more time intensive to find all the possible S-T min-cuts in a graph.
Hope this helps any future internet people trying to figure this out! Good luck!
If you already know the maximal flow, then the minimal cut is (S, T), where S is the set of vertices reachable from the source in the residual network, T is the complementary set. Edges that connect a vertex from S and a vertex from T belong to the cut.

Why does A* path finding sometimes go in straight lines and sometimes diagonals? (Java)

I'm in the process of developing a simple 2d grid based sim game, and have fully functional path finding.
I used the answer found in my previous question as my basis for implementing A* path finding. (Pathfinding 2D Java game?).
To show you really what I'm asking, I need to show you this video screen capture that I made.
I was just testing to see how the person would move to a location and back again, and this was the result...
http://www.screenjelly.com/watch/Bd7d7pObyFo
Different choice of path depending on the direction, an unexpected result. Any ideas?
If you're looking for a simple-ish solution, may I suggest a bit of randomization?
What I mean is this: in the cokeandcode code example, there is the nested-for-loops that generate the "successor states" (to use the AI term). I refer to the point where it loops over the 3x3 square around the "current" state, adding new locations on the pile to consider.
A relatively simple fix would (should :)) be isolate that code a bit, and have it, say, generated a linkedlist of nodes before the rest of the processing step. Then Containers.Shuffle (or is it Generics.Shuffle?) that linked list, and continue the processing there. Basically, have a routine say,
"createNaiveNeighbors(node)"
that returns a LinkedList = {(node.x-1,node.y), (node.x, node.y-1)... } (please pardon the pidgin Java, I'm trying (and always failing) to be brief.
Once you build the linked list, however, you should just be able to do a "for (Node n : myNewLinkedList)" instead of the
for (int x=-1;x<2;x++) {
for (int y=-1;y<2;y++) {
And still use the exact same body code!
What this would do, ideally, is sort of "shake up" the order of nodes considered, and create paths closer to the diagonal, but without having to change the heuristic. The paths will still be the most efficient, but usually closer to the diagonal.
The downside is, of course, if you go from A to B multiple times, a different path may be taken. If that is unnacceptable, you may need to consider a more drastic modification.
Hope this helps!
-Agor
Both of the paths are of the same length, so the algorithm is doing its job just fine - it's finding a shortest path. However the A* algorithm doesn't specify WHICH shortest path it will take. Implementations normally take the "first" shortest path. Without seeing yours, it's impossible to know exactly why, but if you want the same results each time you're going to have to add priority rules of some sort (so that you're desired path comes up first in the search).
The reason why is actually pretty simple: the path will always try to have the lowest heuristic possible because it searches in a greedy manner. Going closer to the goal is an optimal path.
If you allowed diagonal movement, this wouldn't happen.
The reason is the path you want the algorithm to go.
I don't know the heuristic your A* uses but in the first case it has to go to the end of the tunnel first and then plans the way from the end of the tunnel to the target.
In the second case the simplest moves to the targets are going down till it hits the wall and then it plans the way from the wall to the target.
Most A* I know work with a line of sight heuristic or a Manhattan Distance in the case of a block world. This heuristics give you the shortest way but in case of obstacles that force to go a way that is different from the line of sight the ways depend on your starting point.
The algorithm will go the line of sight as long as possible.
The most likely answer is that going straight south gets it closest to its goal first; going the opposite way, this is not a choice, so it optimizes the sub-path piecewise with the result that alternating up/across moves are seen as best.
If you want it to go along the diagonal going back, you are going to have to identify some points of interest along the path (for example the mouth of the tunnel) and take those into account in your heuristic. Alternatively, you could take them into account in your algorithm by re-computing any sub-path that passes through a point of interest.
Back in the day they used to do a pre-compiled static analysis of maps and placed pathfinding markers at chokepoints. Depending on what your final target is, that might be a good idea here as well.
If you're really interested in learning what's going on, I'd suggest rendering the steps of the A* search. Given your question, it might be very eye-opening for you.
In each case it's preferring the path that takes it closer to its goal node sooner, which is what A* is designed for.
If I saw right, the sphere is moving first to the right in a straigt line, because it cannot got directly toward the goal (path is blocked).
Then, it goes in a straight line toward the goal. It only looks diagonal.
Does your search look in the 'down' direction first? This might explain the algorithm. Try changing it to look 'up' first and I bet you would see the opposite behavior.
Depending on the implementation of your astar you will see different results with the same heuristic, as many people have mentioned. This is because of ties, when two or more paths tie the way you order your open set will determine the way the final path will look. You will always get the optimal path if you have an admissible heuristic, but the nodes visited will increase with the number of ties you have(relative to a heuristic producing not as many ties).
If you dont think visiting more nodes is a problem i would suggest using the randomization (which is your current accepted answer) suggestion. If you think searching more nodes is a problem and want to optimize i would suggest using some sort of tiebreaker. It seems you are using manhattan distance, if you use euclidian distance when two nodes tie as a tiebreaker you will get more straight paths to the goal and you will visit fewer nodes. This is ofcourse given no traps or block of line of sight to the goal.
To avoid visiting nodes with blocking elements in the line of sight path i would suggest finding a heuristic which takes into account these blocking elements. Ofcourse a new heuristic shouldnt do more work than a normal A star search would do.
I would suggest looking at my question as it might produce some ideas and solutions to this problem.

Categories