Hypothetical scenario to have a descriptive example: I've a model consisting of 10 parts (vertices) to be put together. Each part can be connected to others (edges) as defined by a connection table.
There's a shortest.paths function in igraph. However here the aim is to find a way to calculate the longest path in the adjacency matrix. Resulting in a path using as many parts as possible, ideally all, so no part of the model is left alone in the end. MWE as follows:
library(igraph)
connections <- read.table(text="A B
1 2
1 7
1 9
1 10
2 7
2 9
2 10
3 1
3 7
3 9
3 10
4 1
4 6
4 7
7 5
7 9
7 10
8 9
8 10
9 10", header=TRUE)
adj <- get.adjacency(graph.edgelist(as.matrix(connections), directed=FALSE))
g1 <- graph_from_adjacency_matrix(adj, weighted=TRUE, mode="undirected")
plot(g1)
Edit:
The result should be something like: for instance if the first part of the model is 8 it could be combined with 9 or 10. Let's say 10 is selected next part can be either 1,2,7 or 9. If 9 is selected as next the follow up could be 1,2,3,7 or 8. If then 8 is selected the model would be finished as part 10 is already in use. The question then would be how to find a way/path to put together as many parts as possible, ideally all of them. The latter would be possible only by starting with 6 or 5.
There are cycles in your graphs, and I don't think you have stated that we cannot use the same vertex (part) more than once: and in this case the longest path might be infinitely long as you can traverse the cycle infinitely many times and then proceed to your destination.
As per your edit, I think this is not allowed. You can use dynamic programming for this I hope. You can start with DFS like algorithm and mark all the vertex except starting as unvisited. Then apply recursion to choose maximum between the longest paths from all the possible vertex we can reach (except which are already visited) from that given vertex.
It is an NP-hard problem, so you would have to check all the possible paths!
You can see: https://en.wikipedia.org/wiki/Longest_path_problem . You will have modify the algorithm to work in graphs with cycle by adding, as stated earlier, a flag to tell which vertices are already visited.
Tell me if i get it right, you are trying to find a path, that touch the maximum number of nodes?
If that so this is basically an instance of the Hamiltonian path problem, I would say an easier version of it if you can pass on a node more than 1 time.
You can try to watch that algorithm.
to respect you edit maybe, you can try to see the graphs search algorithms, you can find something here, however be advise that this type of algorithms are quite heavy on the memory complexity side.
I'm trying to implement movement through four points, while recording which points I visit. Think of it as a square. I can move from corner to corner or diagonally.
If you 'unwrap' the square you get a straight line with four points, which can be thought of as 1-2-3-4- where after 4 it goes back to 1. So if I'm at point 2 I can move to 1 and 3 directly or 4 diagonally. I'd implement that as 2-1 / 2+1 for corner-to-corner or 2+/-2 for diagonally. The problem occurs when I'm at 2 and will try to subtract 2 where I'll end up outside of the list.
The thought I've had is that if I could somehow translate my "out of bounds" numbers to in bounds this would be solved. One solution is hard coding that:
0=4
-1=3
5=1
6=2
but I'm pretty sure there is a better way to do this, however I can't seem to find it.
It seems to me all you want is modular arithmetic (bless the lord for math)
magicFun <- function (x) x %% 4
Here is a simple test run
> magicFun(0:6)
[1] 0 1 2 3 0 1 2
Addendum
It's more about math but the reason it works for negatives is that in Z/nZ ("the world where n is equal to 0") n is "identified" to 0.
This means you can add n as many times as you wish to a given number without changing it's "value".
Also, by convention the numbers in Z/nZ are listed as {0, 1, ..., n-1}.
So suppose n = 4 and x = -6, by the above x = x + 2*4 = 2.
Consider the following problem:
Given N points in plane and M line segments connecting them, find all polygons (convex or concave) that do not contain any other polygons inside.
For instance:
There are 5 polygons founded:
1 - 2 - 5 - 6
2 - 3 - 5
3 - 4 - 5
7 - 8 - 9
10 - 13 - 20 - 12 - 11
How can I identify these polygons and there corresponding vertices and edges? And what is the fastest solution for this?
Build graph with segment ends as vertices and segments as edges, then find cycles using DFS.
Note that the same edges might belong to multiple cycles (polygons) like your 2-5 and there might be many variants to select cycles. To exclude ambiguity, you can build fundamental set of cycles
Edit. As weston noticed in comments, resulted polygons might contains others. So sketch of more geometric approach:
Build lists of adjacency for graph.
Sort edges in ever list by polar angle.
Choose the most bottom vertex A.
If it's degree is 0, remove vertex, if 1, remove vertex and edge.
Otherwise get edge E with the smallest angle from this vertex.
Walk to pair vertex B.
Choose the most left edge F from B.
Move along to F edge into C.
If dead end, remove F and vertex C and return to B.
Repeat moving using left-hand rule until meet vertex A or dead end vertex.
In the walk process remove edges outgoing from vertices of degree 2 or mark them as used.
Say we have a set of 3D (integer) coordinates from (0,0,0) to (100,100,100)
We want to visit each possible coordinate (100^3 possible coordinates to visit) without visiting each coordinate more than once.
The sum of the differences between each coordinate in adjacent steps cannot be more than 2 (I don't know if this is possible. If not, then minimized)
for example, the step from (0,2,1) to (2,0,0) has a total difference of 5 because |x1-x2|+|y1-y2|+|z1-z2| = 5
How do we generate such a sequence of coordinates?
for example, to start:
(0,0,0)
(0,0,1)
(0,1,0)
(1,0,0)
(1,0,1)
(0,0,2)
(0,1,1)
(0,2,0)
(1,1,0)
(2,0,0)
(3,0,0)
(2,0,1)
(1,0,2)
(0,0,3)
etc...
Anyone know an algorithm that will generate such a sequence to an arbitrary coordinate (x,y,z) where x=y=z or can prove that it is impossible for such and algorithm to exist? Thanks
Extra credit: Show how to generate such a sequence with x!=y!=z :D
One of the tricks (there are other approaches) is to do it one line [segment] at a time, one plane [square] at a time. Addressing the last part of the question, this approach works, even if the size of the volume visited is not the same in each dimension (ex: a 100 x 6 x 33 block).
In other words:
Start at (0,0,0),
move only on the Z axis till the end of the segment, i.e.
(0,0,1), (0,0,2), (0,0,3), ... (0,0,100),
Then move to the next line, i.e.
(0,1,100)
and come backward on the line, i.e.
(0,1,99), (0,1,98), (0,1,97), ... (0,1,0),
Next to the next line, going "forward"
And repeat till the whole "panel is painted", i.e ending at
... (0,100,99), (0,100,100),
Then move, finally, by 1, on the X axis, i.e.
(1,100,100)
and repeat on the other panel,but on this panel going "upward"
etc.
Essentially, each move is done on a single dimension, by exactly one. It is a bit as if you were "walking" from room to room in a 101 x 101 x 101 building where each room can lead to any room directly next to it on a given axis (i.e. not going joining diagonally).
Implementing this kind of of logic in a programming language is trivial! The only mildly challenging part is to deal with the "back-and-forth", i.e. the fact that sometimes, some of the changes in a given dimension are positive, and sometimes negative).
Edit: (Sid's question about doing the same diagonally):
Yes! that would be quite possible, since the problem states that we can have a [Manhattan] distance of two, which is what is required to go diagonally.
The path would be similar to the one listed above, i.e. doing lines, back-and-forth (only here lines of variable length), then moving to the next "panel", in the third dimension, and repeating, only going "upward" etc.
(0,0,0) (0,0,1)
(0,1,0) first diagonal, only 1 in lengh.
(0,2,0) "turn around"
(0,1,1) (0,0,2) second diagonal: 2 in length
(0,0,3) "turn around"
(0,1,2) (0,2,1) (0,3,0) third diagonal: 3 in length
(0,4,0) turn around
etc.
It is indeed possible to mix-and-match these approaches, both at the level of complete "panel", for example doing one diagonally and the next one horizontally, as well as within a given panel, for example starting diagonally, but when on the top line, proceeding with the horizontal pattern, simply stopping a bit earlier when looping on the "left" side, since part of that side has been handled with the diagonals.
Effectively this allows a rather big (but obviously finite) number of ways to "paint" the whole space. The key thing is to avoid leaving (too many) non painted adjacent area behind, for getting back to them may either bring us to a dead-end or may require a "jump" of more than 2.
Maybe you can generalize Gray Codes, which seem to solve a special case of the problem.
Seems trivial at first but once started, it is tricky! Especially the steps can be 1 or 2.
This is not an answer but more of a demostration of the first 10+ steps for a particular sequence which hopefully can help others to visualise. Sid, please let me know if the following is wrong:
s = No. of steps from the prev corrdinates
c1 = Condition 1 (x = y = z)
c2 = Condition 2 (x!= y!= z)
(x,y,z) s c1 c2
---------------
(0,0,0) * (start)
(0,0,1) 1
(0,1,0) 2
(1,0,0) 2
(1,0,1) 1
(1,1,0) 2
(1,1,1) 1 *
(2,1,1) 1
(2,0,1) 1 *
(2,0,0) 1
(2,1,0) 1 *
(2,2,0) 1
(2,2,1) 1
(2,2,2) 1 *
(2,3,2) 1
(2,3,3) 1
(3,3,3) 1 *
(3,3,1) 2
(3,2,1) 1 *
(3,2,0) 1 *
.
.
.