How to find a path between two points connected by lines - algorithm

I try to get this code developed for a potential project at work and I think Dijkstra can help but no idea how to get started.[![enter image description here][1]][1]
I have a list of Line objects called myList and each line has EndPoint1 and EndPoint2 as Point2Dcordinates (x,y) and Name as string. So the list has L1, L2, L3, L4, L5, L6, L7, and L8 as shown in the example image. Points A, B, C, D, and E are points of these lines and they are always not connected points between two lines.
I would like to write a method that gives me a list of the lines (or names of the lines) that connected two points for example:
List<string> FindPath(Point2D P1, Point2D P2): (A, E): L1, L3, L6, L7, L8
List<string> FindPath(Point2D P1, Point2D P2): (B, D): L2, L3, L5
Edit:
I would like to find all possible paths, although 99.9% of the time there is only 1 path possible.

You are talking about a data structure called a graph, a collection of nodes (points), connected by edges (line segments).
Graphs comes in several flavours. They can be directed or undirected, and they can by cyclic, or acyclic.
Directed graphs have one-way edges: the edge a→b can only be used to travel from a to b, it can't be used to get from b to a. Undirected graphs, on the other hand, have 2-way edges: as long as two nodes are connected, you can get from either one to the other.
Cyclic graphs allow cycles, where traversing the graph can return you to a node you have already visited (a → b → c → a is a cycle); acyclic graphs do not allow such cycles. If your graph is cyclic, when you traverse it, you'll need to track what nodes you've visited, so you can detect and deal with cycles. If you don't you'll wind up in an endless loop.
In addition, both nodes and edges may carry additional information, such as "cost", making them a weighted graph. Google's and Apple's maps are modeled as such weighted graphs. Each intersection is a node, and each street segment between intersections is an edge. The additional information (weigths) carried by edges are information such as average speed, starting/ending addresses, etc.
If you need to find the shortest path between two nodes in your graph, you may need a weighted graph (where the edges carry a distance. Or not: perhaps "shortest path" is defined as the least number of intermediate nodes between A and B.
So, you need the correct model:
a set of nodes, and
a set of edges, defined by the 2 nodes it connects.
One can (and it is sometimes useful to dispense with the set of nodes completely, and define the graph solely in terms of its edges:
Once you have that, finding a path from any two points in the graph is actually pretty easy. The algorithm is this:
You can get from node A to node B if an edge AB exists. Otherwise...
You can get from node A to node B if
an edge AX exists, and
you have not yet visited node X, and
you can [recursively] get from node X to node B.
That's about all there is to it.

I am assuming you need to find the shortest path from one point to another. Hence you need to do a BFS *).
First convert the points into a graph. The graph could be of the format
// The key is the point and the it contains the list of all
// the neighbours
Map<Point2D, List<Point2D>> graph = new HashMap<>();
Then use a Queue and a visited matrix to keep track of the visited points. When looping through the Points make sure you add them to an answer list.
For more details on BFS look here: https://www.geeksforgeeks.org/print-paths-given-source-destination-using-bfs/
*) Breadth First Search Algorithm

You can solve this by treating it as a graph. Each x is a vertex, and your lines are the edges. Then to find the path between P1 and P2, run BFS from P1.

Related

In a DAG, how to find vertices where paths converge?

I have a type of directed acyclic graph, with some constraints.
There is only one "entry" vertex
There can be multiple leaf vertices
Once a path splits, anything under that path cannot reach into the other path (this will become clearer with some examples below)
There can be any number of "split" vertices. They can be nested.
A "split" vertex can split into any number of paths. The examples below only show 2 paths for each, but it could be more.
My challenge is the following: for each "split" vertex (any vertex that has at least 2 outgoing edges), find the vertices where its paths reconnect - if such a vertex exists. The solution should be as efficient as possible.
Example A:
example a
In this example, vertex A is a "split" vertex, and its "reconnect vertex" is F.
Example B:
example b
Here, there are two split vertices: A and E. For both of them vertex G is the reconnect vertex.
Example C:
example c
Now there are three split vertices: A, D and E. The corresponding reconnect vertices are:
A -> K
D -> K
E -> J
Example D:
example d
Here we have three split vertices again: A, D and E. But this time, vertex E doesn't have a reconnect vertex because one of the paths terminates early.
Sounds like what you want is:
Connect each vertex with out-degree 0 to a single terminal vertex
Construct the dominator tree of the edge-reversed graph. The linked wikipedia article points to a couple algorithms for doing this.
The "reconnect vertex" for a split vertex is its immediate dominator in the edge-reversed graph, i.e., its parent in that dominator tree. This is called its "postdominator" in your original graph. If it's the terminal vertex that you added, then it doesn't have a reconnect vertex in your original graph.
This is the problem of identifying post-dominators in compilers and program analysis. This is often used in the context of calculating control dependences in control flow graphs. "Advanced Compiler Design and Implementation" is a good reference on these topics.
If the graph does not have cycles, then the solution (a) suggested by #matt-timmermans will work.
If the graph has cycles, then solution (a) can report spurious post-dominators. In such cases, a network-flow based approach works better. The algorithm to calculate non-termination sensitive control dependence in this paper using this approach. The basic idea is
at every split node, inject a unique token into the graph along each outgoing edge and
propagate the tokens thru the graph subject to this constraint: if node n is reachable from split node m, then tokens arriving at node m pass thru node n only if all tokens of node m have arrived at node n.
At the end, node n post-dominates node m if all tokens of node m have arrived at node n.

How to traverse a Graph based on the angle between two edges

I am stuck in a problem regarding Graph traversal based on the angle between two edges. I would like to summarize the problem as follows, given 5 vertices a,b,c,d,e and the edges (a, b), (b, c), (c, d), (d, e).
If I want to traverse the graph based on calculating the angle between two edges like for example angle((a, b), (b, c)). If my angle is greater than 10 degree I should stop at b and start the process again.
What steps do I need to consider to approach this problem having concrete programming structures.
If I understand correctly, when angle((a,b),(b,c)) returns a value of over some threshold (10, in your example), you should stop traversing the graph.
This means that effectively, this node (b) is not helping by connecting the two edges ((a,b) and (b,c)). It might be useful for some other set of edges, but that specific connection is not available.
What I suggest is swapping the role of edges and nodes. Every edge in G becomes a node in G' and every node in G becomes and edge in G' only if the value of angle() returns a value lower than your threshold.
On G' you can now run BFS, DFS or any other algorithm of your liking. When you are done, use the reverse transformation to "translate" your answer back into the original graph in question.

Find paths that cover all edges between two nodes

we hope you are able to help us with the following problem:
A directed graph that may contain cycles is given. One has to find a set of paths that fulfill the following criterion:
all edges that can be passed on the way from node A to node B must be covered by the paths within the set (one edge can be part of more than one paths from the set)
the solution does not have to be necessarily the one with the lowest number of paths and the paths does not have to be necessarily the shortest ones. However, the solution should be efficiently implementable using a programming language just as java. We need the solution to generate a few test cases and it is important to cover all edges between a node A and a node B.
does everyone know a suitable algorithm? or does no efficient solution exist?
thanks a lot in advance for your advise! (we have already searched for a solution, but the one we found was focused on shortest paths and were extremely inefficient)
Here is a graphical representation of our problem:
http://i.stack.imgur.com/wIY34.jpg
Consider all edges R(A) reachable from A. They can be found by adding a node on each edge (i.e. turning each edge U->V to U->X->V) and then perform a Breadth First Search starting from A.
Edges outside of R(A) clearly cannot be be on a path from A to B, since then they'd be reachable from A. So all paths to B must go through edges of R(A).
So the set of edges, U, we want to "cover" are all edges of R(A) that B is reachable from.
Now we are looking for a set of paths S from A to B, which contains all edges of U.
A straightforward method is the following:
Color all edges of R(A) black and set S={ }
While there are black edges remaining:
Take a black edge UV.
If B is reachable from V:
Construct a path P = A -> ... -> U -> V -> ... -> B
Color all edges of P as gray
Add P to S
Else:
Color UV as gray.
Then return S
As #user189 pointed out, if we consider reachable edges from A that go through B, we are allowing paths that go twice through B. (I.e. a->b->c->g->f->e in the example image).
His suggested solution (removing the node B before computing R(A) ) fixes this.
Regarding complexity:
R(A) can be computed in O(|E|) time and the paths from A to an edge UV in R(A) can be directly read from the BFS tree. To check for reachability to B from V and to find the path, we can use a BFS tree starting from B and following edges backwards, computed in O(|E|) time.
If we reference the paths implicitly through the edge UV that connects the two BFS trees, and use a O(1) read/update structure to maintain the set of black edges and to look up edges in the BFS trees, I think we can do this in O(|E|) time.

Cycle detection in a Multigraph

I would like to list all the cycles in an undirected multigraph.
Tarjan's strongly connected components algorithm was written for a directed graph. Will it work for multigraphs? If not, is there an cycle listing algorithm for undirected multigraphs?
There are a few ways to reduce your problem to Tarjan, depending on how you want to count cycles.
First, apply two transformations to your graph:
Convert to a directed graph by replacing each undirected edge with a pair of opposing directed edges.
For each pair of nodes, collapse edges pointing the same direction into a single edge.
You'll be left with a directed graph. Apply Tarjan's algorithm.
Now, depending on what you consider a cycle, you may or may not be done. If a cycle is set of nodes (that happen to posses the required edges), then you can read the cycles directly off the transformed graph.
If a cycle is a set of edges (sharing the required nodes), then you need to "uncollapse" the edges introduced in step 2 above. For each collapsed edge, enumerate along the set of real edges it replaced. Doing so for each edge in each collapsed cycle will yield all actual cycles in a combinatorial explosion. Note that this will generate spurious two-cycles which you'll need to prune.
To illustrate, suppose the original graph has three nodes A, B and C, with two edges between A and B, one between B and C and one between A and C. The collapsed graph will be a triangle, with one cycle.
Having found a cycle between the three nodes, walk each combination of edges to recover the full set of cycles. Here, there are two cycles: both include the A to C and B to C edges. They differ in which A to B edge they choose.
If the original graph also had two edges between B and C, then there would be four expanded graphs. The total number of expanded cycles is the product of the edge counts: 4 == 2 * 2 * 1.

How do I partition a bipartite graph by color?

For instance, suppose I have a graph G = (V, E) where
V = {A, B, C, D}
E = {(A, B), (A,D), (C, D)}
This graph is bipartite, and thus can be split into two disjoint sets {A, C} and {B, D}. My first guess is that I can simply walk the graph and assign alternating colors to each vertex. Is this the case, or is it more complicated/simpler than this? Are there any known algorithms for this?
Your first guess is correct - traverse the graph and alternate.
The algorithm should be simple. I'd keep two queues of nodes to visit, one for each colour. Pop nodes off the queues alternately, mark its colour, and push any non-visited adjacent nodes into the queue for the opposite colour. Terminate when the number of visited nodes + the length of both queues = number of nodes in the graph.
From Wikipedia (http://en.wikipedia.org/wiki/Bipartite_graph)
If a bipartite graph is connected, its bipartition can be defined by the parity of the distances from any arbitrarily chosen vertex v: one subset consists of the vertices at even distance to v and the other subset consists of the vertices at odd distance to v.
Thus, one may efficiently test whether a graph is bipartite by using this parity technique to assign vertices to the two subsets U and V, separately within each connected component of the graph, and then examine each edge to verify that it has endpoints assigned to different subsets.
Traverse the graph and alternate, if it doesn't succeded it means that your graph is not bipartite.
If you are sure that the graph is biparte, then you can just assign colors alternating them for traversing each vertex, as it holds that:
A graph is bipartite if and only if it is 2-colorable.
I implemented it in my graph drawing tool, you can see my code in JavaScript.
I just marked first vertex as left partity, then recursively marked it's neighbours as right partity, recursively mark their neighbours as left partity... If you find correctly marked node, stop recursion of this branch. If you find uncorrectly marked node, graph is not bipartite.
Maybe it can be done simpler, but during last few months I had some hard Prolog - Haskell coding days, maybe it had affected my brain and now I see recursion in everything :-D
Just in case anyone's curious, here's the code I came up with:
def dfs(root, colorings):
to_visit1 = deque()
to_visit2 = deque()
to_visit1.append(root)
while len(to_visit1) != 0 or len(to_visit2) != 0:
dfs_color(to_visit1, to_visit2, True, colorings)
dfs_color(to_visit2, to_visit1, False, colorings)
def dfs_color(queue, opposite_queue, color, colorings):
while len(queue) != 0:
v = queue.pop()
if v in adjacency_list:
colorings[v] = color
neighbors = adjacency_list[v]
del adjacency_list[v]
for neighbor in neighbors:
opposite_queue.append(neighbor)
Admittedly, this isn't my best code. I'm using True/False as the color because when I used recursion, it made it easy to just say not color. Of course, I had to change it because I blew my stack on bigger graphs. Also to give credit where due, this code is based on the wikipedia code for DFS.
Although as has been pointed out, I think this may just be a disguised BFS.

Resources