I want to find the path between two vertices of a graph grid (A x B size, with 1x1 cells) (a1, b1) and (a2, b2) but with additional criterion of avoiding some n forbidden nodes (x1, y1), (x2, y2) as far away as possible from any one node to reach the destination. This means for all potential paths, the closest distance to any forbidden node should be the largest. The node positions are integers but the distance away from the nodes can be float numbers.
I would think the shortest path algorithms like Dijkstra's probably wouldn't matter a lot since the shortest path could end up traversing one of the n forbidden nodes. But then how can I factor in the "furthest distance away" from the nodes factor? My thoughts:
I could try to average positions of the forbidden nodes, but I have managed to come up with one counter example that this might end up traversing one of the nodes
The alternative way is to simply compute all possible paths and find the one with the furthest distance from any one forbidden node. This might mean using some dynamic programming approach.
We can also tabulate the min distance from any one forbidden nodes at every node in the graph, and choose the path that gives the greatest distance at each step.
Other thoughts: might have to use disjoint sets and MSTs?
My potential solutions seem to incur very high time complexity and I thought this kind of problem should be quite common (people probably have thought of this before). Is there a standard practice or way to approach this kind of problems optimally?
Pick a distance D and remove from the graph all nodes within distance D of the forbidden nodes. Find out if the source and destination are still connected. Use binary chop to find the largest possible D still leaving the source and destination connected. The path from source to destination on this graph is the path you want.
Related
I have a directed weighted graph, with positive weights, which looks something like this :-
What I am trying to do is:-
Find all possible paths between two nodes.
Arrange the paths in ascending order, based on their path length (as given by the edge weights), say top 5 atleast.
Use an optimal way to do so, so that even in cases of larger number of nodes, the program won't take much time computing.
E.g.:- Say my initial node is d, and final node is c.
So the output should be something like
d to c = 11
d to e to c = 17
d to b to c = 25
d to b to a to c = 31
d to b to a to f to c = 38
How can I achieve this?
The best approach would be to take the Dijkstra’s shortest path algorithm, we can get a shortest path in O(E + VLogV) time.
Take this basic approach to help you find the shortest path possible:
Look at all nodes directly adjacent to the starting node. The values carried by the edges connecting the start and these adjacent nodes are the shortest distances to each respective node.
Record these distances on the node - overwriting infinity - and also cross off the nodes, meaning that their shortest path has been found.
Select one of the nodes which has had its shortest path calculated, we’ll call this our pivot. Look at the nodes adjacent to it (we’ll call these our destination nodes) and the distances separating them.
For every ending (destination node):
If the value in the pivot plus the edge value connecting it totals less than the destination node’s value, then update its value, as a new shorter path has been found.
If all routes to this destination node have been explored, it can be crossed off.
Repeat step 2 until all nodes have been crossed off. We now have a graph where the values held in any node will be the shortest distance to it from the start node.
Find all possible paths between two nodes
You could use bruteforce here, but it is possible, that you get a lot of paths, and it will really take years for bigger graphs (>100 nodes, depending on a lot of facotrs).
Arrange the paths in ascending order, based on their path length (as given by the edge weights), say top 5 atleast.
Simply sort them, and take the 5 first. (You could use a combination of a list of edges and an integer/double for the length of the path).
Use an optimal way to do so, so that even in cases of larger number of nodes, the program won't take much time computing.
Even finding all possible paths between two nodes is NP-Hard (Source, it's for undirected graphs, but is still valid). You will have to use heuristics.
What do you mean with a larger number of nodes? Do you mean 100 or 100 million? It depends on your context.
I have a graph with one origin and multiple destinations. I'm trying to find a way to word the problem to find the correct type of algorithm to solve. The goal is to have as few paths as possible to reach all of the points, yet the paths must follow grid points at all times (ie, right angles).
For example:
Origin: (0, 0)
Point A: (3, 3)
Point B: (3, 0)
Point C: (1, 3)
A path from Origin -> C -> A is great because getting to point A only requires 2 extra segments because it was able to share the path from Origin -> C.
Some things I have thought through:
Exhausting all path options to all points and then exhaustively trying all combinations. This is obviously the brute force and slowest method. Doesn't scale well.
Creating a matrix of 1's from Origin to Point _, then performing matrix addition in order to find the highest traffic points. Then re-performing some type of exhaustive search, having a preference for those paths which follow the high-traffic segments.
What I would love to do is draw the "top" ways to get to each point from the origin, and then compare each path to each other path to see where they could share paths. This feels recursively tricky.
So, my question is less looking for an answer to the specific problem, and more trying to figure out how to approach the problem, ie, which path (pun intended) to go down when trying to solve.
Overall, looking to score paths based on (no particular order yet):
Number of segments shared vs unique segments
Number of turns (preferring straight lines)
Shortest distance
This does not seem similar to minimal spanning tree, but to Steiner tree, https://en.wikipedia.org/wiki/Steiner_tree_problem in particular rectilinear Steiner tree.
https://en.wikipedia.org/wiki/Rectilinear_Steiner_tree
Unfortunately that is NP-hard.
Since you can actually reach all points from any point on 2D-space, then you can represent it as a complete graph with N nodes and N * (N - 1) / 2 edges - from each point to all others.
The weight of every edge can express the distance between two nodes, which is equal to the the distance between this points by x plus distance by y, because you only use right angles:
W[a, b] = = |a.x - b.x| + |a.y - b.y|
Now, you have a normal graph, represented by the set of nodes and edges and you can apply any desired algorithms.
It is pretty unclear what score exactly you want to achieve, but building the minimal spanning tree sounds like the answer to the most optimal paths problem.
For example, you can use Kruskal's algorithm to achieve it.
In a directed graph, find the shortest path from s to t such that the path passes through a certain subset of V, let's call them death nodes. The algorithm is given a number n, while traversing from s to t, the path cannot pass though more than n death nodes. What is the best way to find the shortest path, her? I am thiniing Dijkstra's, but how to make sure we are not passing though more than n nodes? Please help me tweak Dijkstra's to include this condition.
Small n
If n is small you can make n copies of your graph, call them levels 1 to n.
You start at s in level 1. If you are at a normal node, the edges take you to nodes within the same level. If you are at a death node, the edges take you to nodes within the next level. If you are at a death node on level n, the edges are simply omitted.
Also connect the t nodes at all levels to a new single destination T (with zero weight).
Then compute the shortest path from s to T.
The problem with this approach is that the graph size goes up by a factor of n, so it is only appropriate for small n.
Large n
An alternative approach is to increase the weight for each edge leaving a death node by a variable x.
As you increase the variable x, the shortest path will use fewer and fewer death nodes. Adjust the value for x (e.g. with bisection) until the graph only uses n death nodes.
This should take around O(logn) evaluations of the shortest path.
I'd add the number of dead nodes encountered on the way as a new (sparse) dimension to the computed distance -- basically you'd have up to n best distances per node.
Implementing your own BFS would be similar: You'll need to treat "seen with x dead nodes" different from "seen with y dead nodes" for each node, unless the total distance and number of dead nodes on the way are both smaller.
p.s.: If you get stuck with this approach, please post code so far O:)
I have a grid map and I need to find the shortest path between two nodes but that path must include some nodes.
I have thought of trying all permutations, but the map size and the number of must nodes will be variable so I would like to use an optimal algorithm.
The map will be something similar to this:
map
-Dark brown square at Y18 is the start point
-Light brown squares from B20 to S20 are the end point (can make just one end point if needed)
-White squares are walls (you cannot go through them)
-Blue squares means that the point in front of it is a must-pass (for example, the blue square at q5-q6 means must pass zone of p5-p6)
I am going to use Java, and I will make that map a graph with connections between them (for example s10 is connected with s9, o10 and s11).
Thank you very much for your help, and if you have any questions just ask.
To my understanding, this is a combination of two problems; you have the stating point, the destination node and the mandatory intermediate nodes. For determination of the shortest path, you would have to calculate the distance between the starting node and all intermediate nodes, all pairs of intermediate nodes, and the distance from each intermediate node to the destination. If only nonnegative edge weights are involved, this can be done with the algorithm by Dijkstra.
Once all distances are calculated, the optimal Hamiltonian path from the starting node to the destination node, where all intermediate nodes are used, has to be calculated. However, as this problem is NP-hard, it most probably cannot be solved using an efficient algorithm; brute-forcing of all permutations might be feasible.
Asymptotically probably this won't help as you still have to solve Hamilton path, but to calculate distances between every node you can use Floyd-Warshall instead to speed things up a little bit.
So I am working with a "course". The course is full of coordinates. Each coordinate has attributes that allow movement(#left #right #up #down). The course is built upon a coordinate system so left would be x-1, right would be x+1, up would be y-1, and down would be y+1.
My goal is to get the shortest distance of each reachable coordinate.
Distance is defined by the number of moves from the start point (the start coordinate of the course that is provided in the parameters). So the distance from (0,0) to (1,2) would be 3. 1 right and 2 down
I've originally solved this problem using recursion:
Answer: Rather than go through each one as far as as possible in depth, use an array to go through each of the paths within each difference at a time
Think of your problem as a undirected graph with the nodes being the coordinates, where each pair of (distinct) nodes [x0,y0] and [x1,y1] is "adjacent" if:
[x0-x1].abs <= 1 && [y0-y1].abs <= 1
Two nodes are connected by an undirected link if they are adjacent, in which case the length of that link is 1. If two nodes are connected by a path of nodes and links, the distance between them equals the sum of the lengths of the links on the path (i.e., the number of links in the path).
You can find the shortest distance between all pairs of coordinates by employing an algorithm that computes shortest paths between all pairs of nodes in an undirected graph, such as the Floyd-Warshall algorithm (which also works for directed graphs).
Floyd-Warshall treats non-adjacent pairs of nodes as being connected by a link of infinite length (which may be implemented as a suitably large number). If the length of the shortest path between a given pair of nodes is found to be "infinite", you know the nodes are not connected (i.e., there is no path between the coordinates).