This is similar to How to trace the path in a Breadth-First Search?, but the method described in the answers in that post doesn't work for my case, it seems.
By path here, I essentially mean a sequence of connected nodes to get from a beginning to end state.
Consider an undirected graph with vertices V={a,b,c} and edges = {{a,b},{a,c}}, and assume that we must traverse the successors alphabetically. We start at node a and the end state is to visit all 3 nodes.
Breadth first search would first visit the edge a->b, and then the edge a->c. So the solution path is a->b->a->c. Since there is no edge between b & c, we must go back through a (so we must traverse the edge b->a). In the answer in the above linked post, the accepted solution would only output a->c.
I can't think of a way to modify the conventional bfs algorithm to do this. I have the same question for dfs, but I'd like to start with bfs for now.
It seems strange to want to do this. It's certainly simpler with depth-first search (DFS), which always either follows an edge or backtracks along that edge. In contrast, breadth-first search (BFS) generally does not visit (or backtrack to) a node adjacent to the previous one visited.
Specifically, this part of your question is wrong, and reveals a misconception:
Since there is no edge between b & c, we must go back through a (so we must traverse the edge b -> a).
BFS will never traverse the edge back from b to a in your example. It finishes visiting b, then polls c from the queue and visits c immediately, without "travelling" there via a.
For an analogy, it makes sense to think of DFS as tracing out a path; if you are in a maze, you could use breadcrumbs to mark places you've "visited", and therefore solve the maze by DFS. In contrast, a human cannot solve a maze by BFS because humans cannot have a queue of places they know how to get to, and "teleport" to the next place in the queue. BFS does not meaningfully trace out a path that you could follow by travelling along edges in the graph.
That said, if you really wanted to, you can construct a path visiting the nodes of the graph, such that each node is visited for the first time in the same order as BFS. The simplest way to do this would be to do a BFS to build a list of the nodes in "BFS order", while also building the "BFS tree". Then for each node in BFS order, you can get to it from the previous node going via their lowest common ancestor in the BFS tree. This path only goes via nodes that have already been visited earlier in BFS order.
Related
I am new to Arango and I am trying to understand the 'right' way to write some queries. I read (https://www.arangodb.com/docs/stable/graphs-traversals-using-traversal-objects.html) and (http://jsteemann.github.io/blog/2015/01/28/using-custom-visitors-in-aql-graph-traversals/), since they always popped up when searching for what I am trying to do. In particular, I have a graph where a given node has a single path (via a certain 'type' of edge) from that node to a leaf. Something like x -a-> y -a-> z. Where a is the edge type, and x,y,z are the nodes. These paths can be of arbitrary length. I would like to write an AQL query that returns the single 'longest' path from the starting node to the leaf node. I find that I always get every sub-path and would then have to do some post-processing. The traversal objects looked like they supplied a solution to this issue, but it seems they are now deprecated. Is there a correct way to do this in AQL? Is there a document that shows how to do what steemann does in his article, but only using AQL? Is there some great AQL documentation on graph queries other than what is on the arangodb site (all of which I have already read, including the graph presentation and the udemy course)? If not, I would be happy to write something to share with the community, but I am not sure yet how to do this myself, so I'd need some pointers to material that can get me started. Long, short, I'd just like to know how to run my query to find the path from node to leaf. However, I'd be happy to contribute once I see how things should be done without traversal-objects. Thank you for your help
Taking a traversal in OUTBOUND direction as example, you can do a second traversal with depth = 1 to check if you reached a leaf node (no more incoming edges).
Based on this information, the “short” paths can be filtered out.
Note that a second condition is required:
it is possible that the last node in a traversal is not a leaf node if the maximum traversal depth is exceeded.
Thus, you need to also let paths through, which contain as many edges as hops you do in the traversal (here: 5).
LET maxDepth = 5
FOR v, e, p IN 1..maxDepth OUTBOUND "verts/s" edges
LET next = (
FOR vv, ee IN OUTBOUND v edges
//FILTER ee != e // needed if traversing edges in ANY direction
LIMIT 1 // optimization, no need to check for more than a single neighbor
RETURN true // using a constant here, which is not actually used
)
FILTER LENGTH(next) == 0 || LENGTH(p.edges) == maxDepth
RETURN CONCAT_SEPARATOR(" -> ", p.vertices[*]._key)
Cross-post from https://groups.google.com/g/arangodb/c/VAo_i_1UHbo/m/ByIUTqIfBAAJ
I'm looking for the right keywords/nomenclature for the following problem, since I cannot find anything on google to this topic:
I have a graph where each edge and each node is assigned to a certain class/color or whatever you call it. Now I want to find a path between a start and a goal node, having some constraints on the path. For example I'd like to have as less "blue" nodes on the path as possible, or max. 2 "red" edges, or a combination of those things. Of course there are also the usual edge costs, which have to be minimized in addition to the fixed path constraints.
How is this kind of problem called, or what do I have to search for?
Best regards
Mark
I do not think that a name for such a general problem exists. However, I'm pretty certain you can re-model your graph and solve this problem via a simple Dijkstra search:
Trying to avoid certain (type of) vertex: Say you have a vertex that is to be avoided, and that has k neighbors. Replace it by a K_k (i.e. a clique with k vertices), and connect each neighbor to one of the k new vertices. Then set the weight of all the clique-edges to something large. Now every path passing over the original vertex will have to pass through the clique and "pay the fee", i.e. it will be avoided, if possible
Trying to avoid certain edges: Just raise their edge weight accordingly
Then, run a simple Dijkstra search. If you have multiple classes that are to be avoided, you can even set the weights as to determine priorities for avoiding each of them..
Hope that helps,
Lukas
I have a 4x4 undirected graph, with links/paths between each node vertically,horizontally and diagonally. In my example I've simplified the contents of these nodes to integers. Given a series of numbers of any length, I want to determine if a path exists on the board that consists of these numbers. No node can be used twice. For example searching 789, 548 and 734 on the graph below would return true, but 111, 7343 and 98989 would return false.
I currently have what is essentially a depth first search, but I realized it is missing some paths. In the above example, 12234 could be missed. If the search starts at 1, moves diagonally to 2, and left to 2, there is nowhere else to go. The search then backtracks, marking the rightmost 2 as visited and blocking the only correct path.
The improvement I've been able to come up with is to add additional state to each node to record the depth at which they were visited. That would eliminate this case, and certainly make it more correct. But this is still a problem for 27979 on the graph above. If the search starts at the left-most 2, goes down and right to 7, up-right to 9, up-left to 7, it will again block the correct path.
It seems like I'm using the wrong kind of search here, but what's the right one?
It seems I've come up with a solution, which I'll share in case someone else comes across this is the future.
On each search I build a tree with bidirectional links, so that at each place the path can go multiple ways it branches, like a breadth-first search. This differs in that each branch of the tree can use the nodes of any other unconnected branch. As each node is added to the tree I follow the links back to root and check the node against each link to eliminate the possibility of cyclical paths and allow reuse of nodes from other paths. Once the a branch has reached the depth desired, I backtrack to root to record the path.
I am not able to figure out the procedure for iterative octree traversal though I have tried approaching it in the way of binary tree traversal. For my problem, I have octree nodes having child and parent pointers and I would like to iterate and only store the leaf nodes in the stack.
Also, is going for iterative traversal faster than recursive traversal?
It is indeed like binary tree traversal, but you need to store a bit of intermediate information. A recursive algorithm will not be slower per se, but use a bit more stack space for O(log8) recursive calls (about 10 levels for 1 billion elements in the octree).
Iterative algorithms will also need the same amount of space to be efficient, but you can place it into the heap it you are afraid that your stack might overflow.
Recursively you would do (pseudocode):
function traverse_rec (octree):
collect value // if there are values in your intermediate nodes
for child in children:
traverse_rec (child)
The easiest way to arrive at an iterative algorithm is to use a stack or queue for depth first or breath first traversal:
function traverse_iter_dfs(octree):
stack = empty
push_stack(root_node)
while not empty (stack):
node = pop(stack)
collect value(node)
for child in children(node):
push_stack(child)
Replace the stack with a queue and you got breath first search. However, we are storing something in the region of O(7*(log8 N)) nodes which we are yet to traverse. If you think about it, that's the lesser evil though, unless you need to traverse really big trees. The only other way is to use the parent pointers, when you are done in a child, and then you need to select the next sibling, somehow.
If you don't store in advance the index of the current node (in respect to it's siblings) though, you can only search all the nodes of the parent in order to find the next sibling, which essentially doubles the amount of work to be done (for each node you don't just loop through the children but also through the siblings). Also, it looks like you at least need to remember which nodes you visited already, for it is in general undecidable whether to descend farther down or return back up the tree otherwise (prove me wrong somebody).
All in all I would recommend against searching for such a solution.
Depends on what your goal is. Are you trying to find whether a node is visible, if a ray will intersect its bounding box, or if a point is contained in the node?
Let's assume that you are doing the last one, checking if a point is/should be contained in the node. I would add a method to the Octnode that takes a point and checks whether or not it lies within the bounding box of the Octnode. If it does return true, else false, pretty simple. From here, call a drill down method that starts at your head node and check each child, simple "for" loop, to see which Octnode it lies in, it can at most be one.
Here is where your iterative vs recursive algorithm comes into play. If you want iterative, just store the pointer to the current node, and swap this pointer from the head node to the one containing your point. Then just keep drilling down till you reach maximal depth or don't find an Octnode containing it. If you want a recursive solution, then you will call this drill down method on the Octnode that you found the point in.
I wouldn't say that iterative versus recursive has much performance difference in terms of speed, but it could have a difference in terms of memory performance. Each time you recurse you add another call depth onto the stack. If you have a large Octree this could result in a large number of calls, possibly blowing your stack.
So I need some help brainstorming, from a theoretical standpoint. Right now I have some code that just draws some objects. The objects lie in the leaves of a quadtree. Now as the objects move I want to keep them placed in the correct leaf of the quadtree.
Right now I am just reconstructing the quadtree on the objects after I change their position. I was trying to figure out a way to correct the tree without rebuilding it completely. All I can think of is having a bunch of pointers to adjacent leaf nodes.
Does anyone have an idea of how to figure out the node into which an object moves without just having a ton of pointers everywhere or a link to articles on this? All I could find was different ways to build the quadtree, nothing about updating it.
If I understand your question. You want some way of mapping between spatial coordinates and leaves on the quadtree.
Here's one possible solution I've been looking at:
For simplicity, let's do the 1D case first. And lets assume we have 32 gridpoints in x. Every grid point then corresponds to some leaf on a quadtree of depth five. (depth 0 = the whole grid, depth 1 = 2 points, depth 2 = 4 points... depth 5 = 32 points).
Each leaf could be represented by the branch indices leading to the leaf. At each level there are two branches we can label A and B. So, a particular leaf might be labeled BBAAB, which would mean, go down the B branch, then the B branch, then the A branch, then the B branch and then the B branch.
So, how do you map e.g. BBABB to an x grid point between 0..31? Just convert it to binary, so that BBABB->11011 = 27. Thus, the mapping from gridpoint to leaf-node is simply a matter of translating the letters A and B into 0s and 1s and then interpreting the result as a binary number.
For the 2D case, it's only slightly more complicated. Now we have four branches from each node, so we can label each branch path using a four-letter alphabet, e.g. starting from the root and taking the 3rd branch and then the fourth branch and then the first branch and then the second branch and then the second branch again we would generate the string CDABB.
Now to convert the string (e.g. 'CDABB') into a pair of gridvalues (x,y).
Let's assume A is lower-left, B is lower right, C is upper left and D is upper right. Then, symbolically, we could write, A.x=0, A.y=0 / B.x=1, B.y=0 / C.x=0, C.y=1 / D.x=1, D.y=1.
Taking the example CDABB, we first look at its x values (CDABB).x = (01011), which gives us the x grid point. And similarly for y.
Finally, if you want to find out e.g. the node immediately to the right of CDABB, then simply convert it to a pair of binary numbers in x and y, add +1 to the x value and convert the new pair of binary numbers back into a string.
I'm sure this has all been discovered, but I haven't yet found this information on the web.
If you have the spatial data necessary to insert an element into the quad-tree in the first place (ex: its point or rectangle), then you have the same data needed to remove it.
An easy way is before you move an element, remove it from the quad-tree using the same data you used to originally insert it, then move it, then re-insert.
Removal from the quad-tree can first remove the element from the leaf node(s), then if the leaf nodes become empty, remove them from their parents. If the parents become empty, remove them from their parents, and so forth.
This simple method is efficient enough for a complex world of objects moving every frame as long as you implement the quad-tree efficiently (ex: use a free list for the nodes). There shouldn't have to be a heap allocation on a per-node basis to insert it, nor a heap deallocation involved in removing every single node. Most node allocations/deallocations should be a simple constant-time operation just involving, say, the manipulation of a couple of integers or pointers.
You can also make this a little more complex if you like. You can start off storing the previous position of an object and then move it. If the new position occupies nodes other than the previous position, then remove the object from the nodes it no longer occupies and insert it to the new ones. Otherwise just keep it in the same node(s).
Update
I usually try to avoid linking my previous answers, but in this case I ended up doing a pretty comprehensive write up on the topic which would be hard to replicate anywhere else. Here it is: https://stackoverflow.com/a/48330314/4842163