Most solution to this problem propose to do a Depth/Breadth first search.
I however use the following constraints to determine whether a graph is a tree:
All nodes have one parent only, except root which has no parent;
All nodes are connected: they have 1 parent or N children;
It seems this is not sufficient. Why? Can you provide an example respecting my constraints which is not a tree?
In a general undirected graph, you cannot determine who is the child and who is the parent.
Related
I am solving a problem where we are given a BST and three nodes, and we want to determine: "whether
nodeOne or nodeThree is an ancestor of nodeTwo, and the other node is a descendant of nodeTwo."
e.g. if nodeOne is ancestor of nodeTwo, then check if nodeThree is descendant of nodeTwo.
Otherwise if nodeThree is an ancestor of nodeTwo, then check if nodeOne is descendant of nodeTwo.
It is quite a simple few checks, and we will simply search the BST checking the above, i.e. first if nodeOne is ancestor of nodeTwo, and if not then check if nodeThree is ancestor of nodeTwo, then whichever is True, we will check if the other node is a descendant of nodeTwo.
In my mind, this would take O(log(n)) time, where n is number of nodes from fist to last node (first and last are one of the three nodes)- since we know the values of the three nodes, we can eliminate half of the tree each time we traverse down the BST, however in the solution it says that it takes O(h) time, where h is the height of the tree.
Can someone please clarify why it is indeed O(h) time?
I omitted the algorithm as I didnt think it was necessary, but it essentially uses recursion to traverse the tree starting from nodeOne then nodeThree, if nodeOne isn't a descendant of nodeTwo.
The height of the tree is a length of the longest path from the tree's root to a leaf. A search in a BST descends along some path from the root node towards a leaf.
That makes no more steps than a number of nodes on a seek path, which in turn is no more than the tree's height – hence O(h).
ADDED:
You can also find the answer in one pass only. Just seek for nodeThree and record if you encounter nodeOne and nodeTwo along the path.
If so, and in this order, you're done with a positive answer.
If you found only one of them, or both but in wrong order, the answer is negative.
Otherwise, continue seeking from nodeThree, this time aiming at nodeOne.
If you enounter nodeTwo before finding nodeOne the result is positive.
Otherwise, that is you do not find nodeOne, or find it without preceding nodeTwo, the result is negative.
I'm writing a reader for glTF/GLB files in R. Reading through the spec at https://www.khronos.org/registry/glTF/specs/2.0/glTF-2.0.html, the relation between nodes and their children is unclear to me.
A node may have properties defining the transform (matrix, rotation, scale, translation). Do its children inherit this transform? If they specify their own transform, does it replace the parent one, or is it composed with it?
It also may have a camera spec. If the child has one as well, does it replace the parent one, or are they combined somehow?
The child node's transformation is always composed with the parent one. For example, if the parent had a +5 X translation, and the child had a 90deg Y rotation, the resulting child mesh would be positioned at +5 X with the rotated orientation.
Note that matrix is mutually exclusive with the other three (translation, rotation, scale), so a given node must not mix matrix with any of the other forms of transformation. However, a parent could use matrix with children that use the other 3 transforms, or vice versa.
Typically camera appears on a leaf node, although that's not required. If a parent and child both have camera objects, they are considered two separate cameras, although the child's camera will move when the parent is repositioned.
If you get glTF working in R, please let us know with an issue or PR for https://github.com/KhronosGroup/glTF-Project-Explorer, thanks!
We have an Alloy model intended to find possible deadlocks in a system. It is set up such that when a counterexample is found, that implies the system being modeling may have a deadlock, i.e. a circular dependency between nodes in the graph. The problem is the visual model of the graph is so complicated, it's nearly impossible to find the cycle representing the deadlock. If there were a way to highlight the cycle, or at least perhaps highlight arcs in the graph that are directed "up" rather than "down" this would help us visualize things better (since in the model we have, a deadlock-free system has all arcs directed in a downward direction). Is there a way to highlight or selectively plot nodes and arcs that create the counterexample?
The first thing that comes to my mind is that when Alloy shows an instance of a predicate, the various arguments to the predicate can be styled specially. So you might try (1) defining a predicate that is the inverse of your assertion, i.e. one that holds when a deadlock is present and which assigns a named role to the nodes in the cycle, and (2) setting the style to display those nodes in a distinct color or shape. You may be able to hide everything that's not in the cycle, or gray it out.
The following problem comes from geography, but I don't kown of any GIS method to solve it. I think it's solution can be found with graph analysis, but I need some guidance to think in the right direction.
There is a geographical area, say a state. It is subdivided in several quadrants, which are subdivided further, and once again. So its a tree structure with the state as root, and 3 levels of child nodes, each parent having 4 childs. But from the perspective of the underlying process its more like a completed graph, since in theory a node is directly reachable from each other node.
The subdivisions reflect map sheet boundaries at different mapscales. Each mapsheet has to reviewed by a topographer in a time span dependend on the complexity of the map contents.
While reviewing the map, the underlying digital data is locked in the database. And as the objects have topological relationships with objects of neighboring map sheet (eg. roads crossing the map boundaries), all 8 surrounding map sheets are locked also.
The question is, what is the optimal order in which the leafs (on the lowest level) should be visited to satisfy following requirements:
each node has to be visited
we do not deal with travel times but with the timespan a worker spent at each node (map)
the time spent at a node is different
while the worker is at a node, all adjacent nodes cannot be visited; this is true also for other workers too; they cannot work on a map side by side with a map already being processed
if a node has been visited, other nodes having the same parent should be prefered as next node; this is true for all levels of parents
Finally for a given number of nodes/maps and workers we need an ordered series of nodes, each worker visites to minimize the overall time, and the time for each parent also.
After designing the solution the real work begins. We will recognize, that the actual work may need more or less time, than expected. Therefore it is necessary to replay the solution up to a current state, and design a new solution with slightly different conditions, leading to another order of nodes.
Has somebody an idea which data structure and which algorithm to use to find a solution for such kind of problem?
Not havig a ready made algorithm, but may be the following helps devising one:
Your exakt topologie is not cler. I assume from the other remarks,
you are targeting a regular structure. In your case a 4x4 square.
Given the restriction that working on a node blocks any adjacient node can be used to identify a starting condition for the algorithm:
Put a worker to one corner of the total are and then put others
at ditance 2 from this (first in x direction and as soon as the side is "filled" with y direction . This will occupy all (x,y) nodes (x,y in 0,2,..,2n where 2n <= size of grid)
With a 4x4 area this will allow a maximum of 4 workers, and will position a worker per child node of each 2 level grid node)
from this let each worker process (x,y),(x+1),(y+1),(x+1,y). This are the 4 nodes of a small square.
If a worker is done but can not proceed to the next planned node, you may advance it to the next free node from the schedule.
The more workers you will have, the higher the risk for contention will be. If you have any estimates on the expected wokload per node,
then you may prefer starting with the most expensive ones and arrange the processing sequence to continue with the ones that have the highest total expected costs.
I've read A* Pathfinding for Beginners and looked at several source code implementations in C++ and other languages. I understand most of what is happening, with the exception of one possible issue I think I have found, and none of the tutorials/implementations I've found cover this.
When you get to this part:
If an adjacent square is already on the open list [...], if the G cost
of the new path is lower, change the parent of the adjacent square to
the selected square. Finally, recalculate both the F and G scores of
that square.
Changing the G score of a square should also change the G score of every child, right? That is, every square that already has this square as the parent, should get a new G score now also. So, shouldn't you find every child (and child of child) square in the open list and recalculate the G values? That will also change the F value, so if using a sorted list/queue, that also means a bunch of resorting.
Is this just not an actual problem, not worth the extra CPU for the extra calculations, and that is why the implementations I've seen just ignore this issue (do not update children)?
It depends on your heuristic.
For correctness, the basic A* algorithm requires that you have an admissible heuristic, that is, one that never overestimates the minimum cost of moving from a node to the goal. However, a search using an admissible heuristic may not always find the shortest path to intermediate nodes along the way. If that's the case with your heuristic, you might later find a shorter path to a node you've already visited and need to expand that node's children again. In this situation, you shouldn't use a closed list, as you need to be able to revisit nodes multiple times if you keep finding shorter routes.
However, if you use a consistent heuristic (meaning that the estimated cost of a node is never more than the estimated cost to one of its neighbors, plus the cost of moving from the node to that neighbor), you will only ever visit a node by the shortest path to it. That means that you can use a closed list and never revisit a node once you've expanded its children.
All consistent heuristics are admissible, but not all admissible heuristics are consistent. Most admissible heuristics are also consistent though, so you'll often seen descriptions and example code for A* that assumes the heuristic is consistent, even when it doesn't say so explicitly (or only mentions admissibility).
On the page you link to, the algorithm uses a closed list, so it requires a consistent heuristic to be guaranteed of finding an optimal path. However, the heuristic it uses (Manhattan distance) is not consistent (or admissible for that matter) given the way it handles diagonal moves. So while it might find the shortest path, it could also find some other path and incorrectly believe it is the shortest one. A more appropriate heuristic (Euclidean distance, for example) would be both admissible and consistent, and you'd be sure of not running into trouble.
#eselk : As the square, whose parent and G-score are to be updated, is still in OL, so this means that it has Not been expanded yet, and therefore there would be no child of the square in the OL. So updating G-scores of children and then their further children does not arise. Please let me know if this is not clear.