I am working on a big graph with lots of nodes which is rendered in dot dot -Tsvg graph.gv -o graph.svg.
To keep the overview I "explicitly" define all nodes I use at the begin of the graph.
Now I am searching for a way to make sure that only those "explicitly" defined nodes are used and I don't get "implicitly" created nodes on an edge definition (e.g. typo in the node name).
The rendering of the following graph should not work or warn me on rendering that an "implicit" node is used.
graph main_graph {
// explicit node definition
node1[style=filled, color=grey];
node2[style=filled, color=grey];
node3[style=filled, color=grey];
subgraph graph1 {
edge [color=red,penwidth=2]
node0 -- node2; //node0 implicitly defined
}
subgraph graph2 {
edge [color="blue",penwidth=2]
node2 -- node3;
node1 -- node3;
}
}
Official support does not exist.
I used the tip like the followings.
1. Add mark for implicit node
graph main_graph {
// explicit node definition
node1[style=filled, color=grey];
node2[style=filled, color=grey];
node3[style=filled, color=grey];
// ---- lower boundary of explicit node definition ----
// default node attribute used for the detection of implicit node definition
node[label="IMPLICITLY-DEFINED"]
subgraph graph1 {
edge [color=red,penwidth=2]
node0 -- node2; //node0 implicitly defined
}
subgraph graph2 {
edge [color="blue",penwidth=2]
node2 -- node3;
node1 -- node3;
}
}
2. Find the marks for the implicitly defined node
$ dot -Tplain graph.gv | awk '/IMPLICITLY-DEFINED/{print $2}'
node0
Tested version: graphviz version 2.40.1 (20161225.0304) on macOS
Related
I am doing an AQL traversal with ArangoDB 3.2 in which I retrieve the nodes connected to my vertexCollection like this:
For v, e, p IN 1..10 ANY vertexCollection GRAPH myGraph OPTIONS {uniqueVertices: "global", bfs:true}
RETURN v._id
and now I want to skip the nodes from paths where a particular edge collection is used. I know I can filter for particular attributes in lists, like FILTER p.edges[*].type ALL == 'whatever' but I do not find how to apply this into IS_SAME_COLLECTION() to filter by collection.
I discard the option of specifying exactly the edgeCollection in the traversal instead of the GRAPH because it's just one particular edgeCollection that I want to skip vs. many that I want to go through.
I don't know whether there is already an implementation for 'skip edge collection' or something like that in a graph traversal, so far I could not find it.
Note:
I tried to filter like this
For v, e, p IN 1..10 ANY vertexCollection GRAPH myGraph OPTIONS {uniqueVertices: "global", bfs:true}
FILTER NOT IS_SAME_COLLECTION('edgeToSkip', e._id)
RETURN v._id
But here I simply skip the nodes directly connected with edge 'edgeToSkip' but not all nodes within the path where 'edgeToSkip' is present. So I need, not only to exclude that particular edge, but stop traversing when it is found.
Thanks
UPDATE:
I found a workaround, basically I gather all edges present in a 'path' and then filter out if the edge I want to skip is in the 'path'. Note I change from uniqeVertices: "global" to uniqueVertices: "path".
.
For v, e, p IN 1..10 ANY vertexCollection GRAPH myGraph OPTIONS {uniqueVertices: "path", bfs:true}
# collect edge names (collection name) in the current path
LET ids = (
FOR edge IN p.edges
RETURN PARSE_IDENTIFIER(edge)["collection"]
)
# filter out if edge name (edgeToSkip) is present
FILTER 'edgeToSkip' NOT IN ids
RETURN v._id
This way, once the edgeToSkip is found in the path, no vertex is returned, but vertices before the 'edgeToSkip' yes
If the graph is like this:
vertexA --edge1--> vertexB --edge2--> vertexC --edgeToSkip--> vertexD --edge3--> vertexE
Will return:
vertexA, vertexB and vertexC (but not vertexD and vertexE)
I found a workaround, basically I gather all edges present in a 'path' and then filter out if the edge I want to skip is in the 'path'. Note I change from uniqeVertices: "global" to uniqueVertices: "path".
.
For v, e, p IN 1..10 ANY vertexCollection GRAPH myGraph OPTIONS {uniqueVertices: "path", bfs:true}
# collect edge names (collection name) in the current path
LET ids = (
FOR edge IN p.edges
RETURN PARSE_IDENTIFIER(edge)["collection"]
)
# filter out if edge name (edgeToSkip) is present
FILTER 'edgeToSkip' NOT IN ids
RETURN v._id
This way, once the edgeToSkip is found in the path, no vertex is returned, but vertices before the 'edgeToSkip' yes
If the graph is like this:
vertexA --edge1--> vertexB --edge2--> vertexC --edgeToSkip--> vertexD --edge3--> vertexE
Will return:
vertexA, vertexB and vertexC (but not vertexD and vertexE)
I have an input file with about ~5000 lines and 1 to 9 nodes per line.
Many edges are not unique and I would like to only show the unique ones.
A more simple example.
graph {
a -- b
a -- b
a -- b
}
Yields
Is there a way to make the above graph yield something like
I know I could change the sample input to
graph {
a -- b
}
But it would not be easy to do that for my real input.
There actually is a way: Use the strict keyword:
strict graph G {
a -- b [label="First"];
a -- b [label="Second"];
a -- b [label="Third"];
}
Result:
Without strict, all three edges would be shown. Note that it only takes the first edge's attributes, contrary to what the documentation suggests.
Try strict:
strict graph {
a -- b
a -- b
a -- b
}
This yields
and should work for any size of graph.
In case you want to get a clean file, which doesn't contain any of the duplicate edges, you can use the graph processing tool gvpr.
Here is a snippet, which does just that:
BEG_G { graph_t g = graph($G.name,"U") }
E {
node_t h = clone(g,$.head);
node_t t = clone(g,$.tail);
if(isEdge(t,h,"")==NULL){
edge_t e = clone(g,$);
}
}
END_G { $O = g; }
save this as something like gvpr_rm_dupl_edges and run $ gvpr -f gvpr_rm_dupl_edges input.dot -o output.dot. gvpr comes preinstalled with graphviz.
In case of directed graphs, change the "U" in the beginning of the code snippet to "D"
I wrote this snippet for a simple graph, without sub-graphs. It might not work on something more sophisticated.
Is it possible to alter the following code to put Child_4 at the same horizontal level as Grandchild_0 (thereby pushing Grandchild_4 to its own level)?
import networkx as nx
import matplotlib.pyplot as plt
G = nx.DiGraph()
G.add_node("ROOT")
for i in xrange(5):
G.add_node("Child_%i" % i)
G.add_node("Grandchild_%i" % i)
G.add_edge("ROOT", "Child_%i" % i)
G.add_edge("Child_%i" % i, "Grandchild_%i" % i)
pos=nx.graphviz_layout(G,prog='dot')
nx.draw(G,pos,arrows=False)
plt.show()
The above code produces the following layout, which I'd like to alter by shifting a child down one level to be horizontally aligned with the grandchildren:
Within the Python network library networkx, I'm using graphviz's dot engine to render a tree (following this recommendation). I would like to control the y-position of the nodes by specifying which nodes should have the same height. The nodes might be at different depths in the tree.
I know I could control the node height if I wrote my own graphviz code through using the rank=same command (e.g., {rank=same; n4 -> p2;} [ex.]). However, I am relying on networkx.graphviz_layout() [doc | source] to generate the node positions, and graphviz_layout can send only command line arguments to pygraphviz. My attempts to use variants of nx.graphviz_layout(G, prog='dot', args="-Grank=same; n4 -> p2;") have failed. Is it possible to describe the desired node heights within the NetworkX wrapper for pygraphviz, or do I need to write my own wrapper around pygraphviz? Edit: The answer provides a new wrapper around pygraphviz. It would significantly simplify things to send the rank information within the existing NetworkX wrapper for pygraphviz. I'll change my accepted answer if someone can tell me how that might be possible.
I can't find a way to achieve this through the original networkx wrapper.
Instead, I've written a new wrapper for pygraphviz, with most lines copied from the source code. It adds a parameter sameRank = [] for a list of nodes-of-the-same-rank lists and a for loop around an invocation of pygraphviz.add_subgraph(listOfNodes,rank="same").
def graphviz_layout_with_rank(G, prog = "neato", root = None, sameRank = [], args = ""):
## See original import of pygraphviz in try-except block
## See original identification of root through command line
A = nx.to_agraph(G)
for sameNodeHeight in sameRank:
if type(sameNodeHeight) == str:
print("node \"%s\" has no peers in its rank group" %sameNodeHeight)
A.add_subgraph(sameNodeHeight, rank="same")
A.layout(prog=prog, args=args)
## See original saving of each node location to node_pos
return node_pos
In the question example, Child_4 can be pushed to the same horizontal level as Grandchild_0 through the line:
pos=graphviz_layout_with_rank(G, prog='dot',sameRank=[["Child_4","Grandchild_0"]])
I have to make a method for making a list with all the paths in a graph.My graph has only one start node and one finish node. Each node has a list whith its children and other list whith its parents. I have to make another list containing all the paths (each of them in another list)
Any suggestion??
It depends on whether it is acyclic or not. Clearly a cycle will result in infinity paths (once round the loop, twice round, 3 times round... etc etc). If the graph is acyclic then you should be able to do a depth-first seach (DFS) (http://en.wikipedia.org/wiki/Depth-first_search) and simply count the number of times you encounter the destination node.
First familiarize yourself with basic graph algorithms (try a textbook, or google). Figure out which one best suits the problem you are solving, and implement it. You may need to adapt the algorithm a little, but in general there are widely known algorithms for all basic graph problems.
If you have a GraphNode class that looks something like this:
public class GraphNode
{
public IEnumerable<GraphNode> Children { get; set; }
// ...
}
Then this sould do the work:
public static class GraphPathFinder
{
public static IEnumerable<IEnumerable<GraphNode>> FindAllPathsTo(this GraphNode startNode, GraphNode endNode)
{
List<IEnumerable<GraphNode>> results = new List<IEnumerable<GraphNode>>();
Stack<GraphNode> currentPath = new Stack<GraphNode>();
currentPath.Push(startNode);
FindAllPathsRecursive(endNode, currentPath, results);
return results;
}
private static void FindAllPathsRecursive(GraphNode endNode, Stack<GraphNode> currentPath, List<IEnumerable<GraphNode>> results)
{
if (currentPath.Peek() == endNode) results.Add(currentPath.ToList());
else
{
foreach (GraphNode node in currentPath.Peek().Children.Where(p => !currentPath.Contains(p)))
{
currentPath.Push(node);
FindAllPathsRecursive(endNode, currentPath, new List<IEnumerable<GraphNode>>());
currentPath.Pop();
}
}
}
}
It's a simple implementation of the DFS algorithm. No error checking, optimizations, thread-safety etc...
Also if you are sure that your graph does not cycles, you may remove the where clause in the foreach statement in the last method.
Hope this helped.
You could generate every possible combination of vertices (using combinatorics) and filter out the paths that don't exist (where the vertices aren't joined by an edge or the edge has the wrong direction on it).
You can improve on this basic idea by having the code that generates the combinations check what remaining vertices are available from the current vertex.
This is all assuming you have acyclic graphs and wish to visit each vertex exactly once.
I'm having a hell of a time trying to figure this one out. Everywhere I look, I seem to be only running into explanations on how to actually traverse through the list non-recursively (the part I actually understand). Can anyone out there hammer in how exactly I can go through the list initially and find the actual predecessor/successor nodes so I can flag them in the node class? I need to be able to create a simple Binary Search Tree and go through the list and reroute the null links to the predecessor/successor. I've had some luck with a solution somewhat like the following:
thread(node n, node p) {
if (n.left !=null)
thread (n.left, n);
if (n.right !=null) {
thread (n.right, p);
}
n.right = p;
}
From your description, I'll assume you have a node with a structure looking something like:
Node {
left
right
}
... and that you have a binary tree of these set up using the left and right, and that you want to re-assign values to left and right such that it creates a doublely-linked-list from a depth first traversal of the tree.
The root (no pun intended) problem with what you've got so far is that the "node p" (short for previous?) that is passed during the traversal needs to be independent of where in the tree you currently are - it always needs to contain the previously visited node. To do that, each time thread is run it needs to reference the same "previous" variable. I've done some Python-ish pseudo code with one C-ism - if you're not familiar, '&' means "reference to" (or "ref" in C#), and '*' means "dereference and give me the object it is pointing to".
Node lastVisited
thread(root, &lastVisisted)
function thread(node, lastVisitedRef)
if (node.left)
thread(node.left, lastVisitedRef)
if (node.right)
thread(node.right, lastVisitedRef)
// visit this node, reassigning left and right
if (*lastVisitedRef)
node.right = *lastVisitedRef
(*lastVisitedRef).left = node
// update reference lastVisited
lastVisitedRef = &node
If you were going to implement this in C, you'd actually need a double pointer to hold the reference, but the idea is the same - you need to persist the location of the "last visited node" during the entire traversal.