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.
Related
I am looking for a solution where I have a set of locations which have some priority.
I want to remove lower priority locations such that no remaining location lies within a particular distance (say 100 meters) to any of the location.
A k-d tree sounds well-suited to this problem.
If you're removing the vast majority of the points, it might make the most sense to start from the point with highest priority, and, for each point, doing something similar to nearest-neighbour search (stopping once we get a point bounded by the given distance) in the tree to check whether to insert the point.
You may want to try to find a self-balancing variant or occasionally rebalance the tree during this process, as unbalanced trees lead to slow operations.
If a significant portion of the points will remain, it might be better to insert all the points into the tree to start and do modified nearest-neighbour search (ignoring the point itself, bounded by distance) starting from the lowest priority and removing relevant points as we go.
Using appropriate construction techniques, you can construct a balanced tree from the start.
Insertion and deletion takes O(log n) in a balanced tree (a simple approach to deletion is to just set a "deleted" flag in the node, but this doesn't ever make the tree smaller) and O(n) in an unbalanced tree. Nearest-neighbour search is similar, although it might take up to O(n) even for balanced trees, but this is a worst case - on average it should be closer to O(log n).
The k-d tree is a binary tree in which every node is a k-dimensional point. Every non-leaf node can be thought of as implicitly generating a splitting hyperplane that divides the space into two parts, known as half-spaces. Points to the left of this hyperplane are represented by the left subtree of that node and points right of the hyperplane are represented by the right subtree. The hyperplane direction is chosen in the following way: every node in the tree is associated with one of the k-dimensions, with the hyperplane perpendicular to that dimension's axis. So, for example, if for a particular split the "x" axis is chosen, all points in the subtree with a smaller "x" value than the node will appear in the left subtree and all points with larger "x" value will be in the right subtree. In such a case, the hyperplane would be set by the x-value of the point, and its normal would be the unit x-axis.
Searching for a nearest neighbour in a k-d tree proceeds as follows:
Starting with the root node, the algorithm moves down the tree recursively, in the same way that it would if the search point were being inserted (i.e. it goes left or right depending on whether the point is lesser than or greater than the current node in the split dimension).
Once the algorithm reaches a leaf node, it saves that node point as the "current best"
The algorithm unwinds the recursion of the tree, performing the following steps at each node:
If the current node is closer than the current best, then it becomes the current best.
The algorithm checks whether there could be any points on the other side of the splitting plane that are closer to the search point than the current best. In concept, this is done by intersecting the splitting hyperplane with a hypersphere around the search point that has a radius equal to the current nearest distance. Since the hyperplanes are all axis-aligned this is implemented as a simple comparison to see whether the distance between the splitting coordinate of the search point and current node is lesser than the distance (overall coordinates) from the search point to the current best.
If the hypersphere crosses the plane, there could be nearer points on the other side of the plane, so the algorithm must move down the other branch of the tree from the current node looking for closer points, following the same recursive process as the entire search.
If the hypersphere doesn't intersect the splitting plane, then the algorithm continues walking up the tree, and the entire branch on the other side of that node is eliminated.
When the algorithm finishes this process for the root node, then the search is complete.
I'm assuming you meant to remove locations, starting with those with lowest priority, within a certain distance to another location.
You could use a quad tree to represent the relative locations. The idea is that you construct a tree where each node has four children. Each child represents a quadrant and as you add each location, you traverse the tree. If you hit a childless node, then you create new child nodes representing once again that same area divided into four regions until each location is in its own region.
Once you've created this tree, you can reduce the sample sizes for each distance check between locations to only those within a certain depth and only locations within the nearby quadrants.
This method however is approximate and doesn't guarantee that you check locations that cross entire major quadrants, however it does efficiently allow you to distance check most locations that are nearby effectively reducing the run time. To get around this, you can create multiple quad trees from the same data with slight offsets, but of course each quad tree is going to be a multiplier factor in the run time since you will build and check each tree individually.
Does this answer your question?
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".
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. :)
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.
Is there any algorithm(s) that can find all the paths, between a source and a sink, in a given connected, undirected, weighted graph / network?
The network consists of multiple source nodes and a single sink node. The path should be free of loops
I would approach this with an A* algorithm with the following differences to basic path finding.
Start from the sink instead of from source, as there is only one sink
Each node is a set of positions instead of a single position. In each iteration add the neighbours of all positions to the queue. Also create branches for all the neighbours such that there will be one more position in the next set. Limit the maximum number of positions to the number of sources as an optimization.
Keep track of which sources you have reached in each path
The traveled cost function should be the total traveled distance with all the branched paths combined
The estimate function should combine all the remaining sources
This should give the optimal paths if the A* algorithm is used correctly.
If you look for all loop-free pathes, a breadth-frist search should do the job. In the iteration, for each current path, do not continue it whenever it hits a point already on the path or the sink.
It looks similar to a Minimum Spanning Tree.