Neo4j - Dijkstra algorithm with full path evaluation - java

I have a neo4j database with weighted paths, where the total weight calculation depends on the path as a whole. For example, some nodes may provide "credit" which offsets future weight but not weight earlier in the path (so it can't just be summed).
The Dijkstra algorithm seems like the right starting point. If the entire path required to get to each node is stored, then that path plus the new segment can be evaluated to get a cost to reach a new node. Unfortunately, the CostEvaluator only wants to work for a segment at a time. Is there a reasonable way to repurpose the code in this manner?

Related

Shortest route with fewest turns

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".

Path beween tree nodes, cost between edges differs in direction of traversal

I have a shortest-path problem and not sure what the right approach would be.
Given a tree, I would like to find the path and the path cost between two nodes, where the cost differs depending on the direction of traversal.
For example if A is a child node of B, A->B could have a cost of 3 and B->A has a cost of 4.
Is there a Java library where I can model this problem by setting up a graph with nodes and path costs in different directions as defined above, and have a way to get the path and path cost between two nodes?
There is a single path between each pair of nodes in a tree. Thus it doesn't really matter if prizes differ in the two directions - find the single path and then compute its prize in the two directions. Note that what you have is not a shortest path problem - you have a single path.

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.

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. :)

best path for sewer design

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.

Categories