In Graphviz, nodes have a variety of properties which you might want to set. However, it's quite tedious to have to set them again and again for every node when you actually just want to set a default for all nodes in the current graph. Is it possible to set graph-level default node properties? Or the properties of an abstract "template node"?
This is done by setting properties on "node", within the curly brances of a graph:
graph "mygraph" {
node [ prop1=value, prop2=anothervalue ];
}
apparently you can do the same for edge and graph properties with the graph and edge identifiers instead of node.
Related
I would like to implement a graph in Java. I defined class Node and class Edge, and the graph is represented with a list of Node, and for each node, a list of edges starting from the node is defined as a field of the node. Now I would like to use some Java library to visualize the graph.
Currently I have tried graphviz-java. The result meets my requirement but the edges and nodes are not placed well. See the following graph below:
I created the graph with the API it provided like node(xxx), addLink() through traversing the node list of my graph instead of generating the raw dot file text.
The key code of creating the graph is as follows:
for (LiteralNode litNode : literalNodeArrayList)
{
MutableNode mutableNode = mutNode(litNode.getNodeElement());
for (Edge e : litNode.getEdgeList()) {
MutableNode endNode = mutNode(e.endNode.getNodeElement());
mutableNode.addLink(to(endNode.port(Compass.NORTH)).add(Arrow.VEE));
}
mutableNodes.add(mutableNode);
g.add(mutableNode);
}
It's basically simple traverse with loops. The node and edges are dynamically changed according to different cases.
I would like the node and edges adjust the location to make the graph display better. I have also tried using json file and d3js to visualize the graph but I found those libraries focus too much on displaying huge amount of nodes and their distributions, which I don't need. I like the structure graphviz provided with some stratification. So I would like to get some recommendation.
I mentioned the json file because if no Java library is available, I might as well try some javascript library like d3js and only use java as a backend tool to generate json file I need to input. So the recommendation is not limited to Java.
All graphviz attributes (https://graphviz.gitlab.io/_pages/doc/info/attrs.html) are supported.
Node distances are set with "ranksep" and "nodesep".
To force nodes on the same level, add a subgraph with "rank=same" and the nodes that should be aligned.
Here's a simple example:
Graph g = graph()
.graphAttr().with(attr("ranksep", .1), attr("nodesep", .1))
.with(graph().graphAttr().with(Rank.SAME).with(node("a"), node("c")))
.with(node("a").link("b"), node("b").link("c"));
The graph looks good to me. What do you mean by "I would like the node and edges adjust the location to make the graph display better."?
I have a set of weighted pairwise relations between nodes which are all of the same type, like this:
A-[1]->B
A-[2]->C
B-[3]->C
B-[2]->D
E-[1]->A
I'd like to lay out this graph in such a way that makes the precedence order of the nodes relatively clear (i.e. that "flow" goes roughly from E to A to B/C/D)
I think what I need similar to a Force Layout but with the added notion of edge weight and directionality
I've looked into using neo4j's builtin viz view and d3 but they don't seem to offer what I need out of the box. Is there a standard approach to this kind of problem?
Even with Neo4j's built in viz you should be able to do:
MATCH path = (a:LabelA {id:"A"})-[:FOO*..10]->()
RETURN path
which should show you the tree starting from A
I'm not sure exactly sure what the correct terminology is for my question so I'll just explain what I want to do. I have a directed graph and after I delete a node I want all independently related nodes to be removed as well.
Here's an example:
Say, I delete node '11', I want node '2' to be deleted as well(and in my own example, they'll be nodes under 2 that will now have to be deleted as well) because its not connected to the main graph anymore. Note, that node '9' or '10' should not be deleted because node '8' and '3' connect to them still.
I'm using the python library networkx. I searched the documentation but I'm not sure of the terminology so I'm not sure what this is called. If possible, I would want to use a function provided by the library than create my own recursion through the graph(as my graph is quite large).
Any help or suggestions on how to do this would be great.
Thanks!
I am assuming that the following are true:
The graph is acyclic. You mentioned this in your comment, but I'd like to make explicit that this is a starting assumption.
There is a known set of root nodes. We need to have some way of knowing what nodes are always considered reachable, and I assume that (somehow) this information is known.
The initial graph does not contain any superfluous nodes. That is, if the initial graph contains any nodes that should be deleted, they've already been deleted. This allows the algorithm to work by maintaining the invariant that every node should be there.
If this is the case, then given an initial setup, the only reason that a node is in the graph would be either
The node is in the root reachable set of nodes, or
The node has a parent that is in the root reachable set of nodes.
Consequently, any time you delete a node from the graph, the only nodes that might need to be deleted are that node's descendants. If the node that you remove is in the root set, you may need to prune a lot of the graph, and if the node that you remove is a descendant node with few of its own descendants, then you might need to do very little.
Given this setup, once a node is deleted, you would need to scan all of that node's children to see if any of them have no other parents that would keep them in the graph. Since we assume that the only nodes in the graph are nodes that need to be there, if the child of a deleted node has at least one other parent, then it should still be in the graph. Otherwise, that node needs to be removed. One way to do the deletion step, therefore, would be the following recursive algorithm:
For each of children of the node to delete:
If that node has exactly one parent: (it must be the node that we're about to delete)
Recursively remove that node from the graph.
Delete the specified node from the graph.
This is probably not a good algorithm to implement directly, though, since the recursion involved might get pretty deep if you have a large graph. Thus you might want to implement it using a worklist algorithm like this one:
Create a worklist W.
Add v, the node to delete, to W.
While W is not empty:
Remove the first entry from W; call it w.
For each of w's children:
If that child has just one parent, add it to W.
Remove w from the graph.
This ends up being worst-case O(m) time, where m is the number of edges in the graph, since in theory every edge would have to be scanned. However, it could be much faster, assuming that your graph has some redundancies in it.
Hope this helps!
Let me provide you with the python networkX code that solves your task:
import networkx as nx
import matplotlib.pyplot as plt#for the purpose of drawing the graphs
DG=nx.DiGraph()
DG.add_edges_from([(3,8),(3,10),(5,11),(7,11),(7,8),(11,2),(11,9),(11,10),(8,9)])
DG.remove_node(11)
connected_components method surprisingly doesn't work on the directed graphs, so we turn the graph to undirected, find out not connected nodes and then delete them from the directed graph
UG=DG.to_undirected()
not_connected_nodes=[]
for component in nx.connected_components(UG):
if len(component)==1:#if it's not connected, there's only one node inside
not_connected_nodes.append(component[0])
for node in not_connected_nodes:
DG.remove_node(node)#delete non-connected nodes
If you want to see the result, add to the script the following two lines:
nx.draw(DG)
plt.show()
Does anyone know where I can find an implementation of an algorithm to convert an activity node graph (aka activity-on-node graph) to an event node graph (aka activiy-on-arrow graph)?
If you don't know what I am talking about, take a look here: http://www.brpreiss.com/books/opus7/html/page581.html
Please provide a working algo in your answer.
Thanks in advance.
The easiest thing to do is replace every node v in your original graph with two nodes, v_in and v_out, connected by a single edge with weight equal to the original vertex weight. Then replace all the original edges (u, v) with edges from u_out to v_in of zero weight.
That link states how you do it:
The activity-node graph is a
vertex-weighted graph. However, the
algorithms presented in the preceding
sections all require edge-weighted
graphs. Therefore, we must convert the
vertex-weighted graph into its
edge-weighted dual. In the dual graph
the edges represent the activities,
and the vertices represent the
commencement and termination of
activities. For this reason, the dual
graph is called an event-node graph.
Although I suppose it leaves out some important details. The way they suggest to convert from an activity node to event node graph is to convert every activity node into an event node edge and to add a dummy edge for activities that take multiple inputs.
Another way to construct the event node graph is to replace every activity node with an edge and two nodes, e.g., A->B->C becomes A->A'->B->B'->C-C'. Then, remove every node that has only one input and zero or one output and replace them with an edge of zero cost, as those event nodes don't actually do anything.
foreach node in graph
if count of incoming_arrows != 1
{
Create new node
Assign incoming arrows from old node to new node
Create arrow from new node to old node
Assign cost 0 to new node
}
endif
end foreach
foreach arrow in graph
Assign cost of destination node to cost of arrow
/* if you want ...preceded by "node name:" to get F:5 */
end foreach
Rename the nodes
The data structures needed are something like
struct node
node_name string
node_cost int
struct arrow
arrow_form_node node
arrow_to_node node
arrow_cost int
I have dot (graphviz) file with given graph which consist several nodes and edges.
I would like to create a copy of that graph and cluster cluster (group) few nodes together.
However whenever I am doing that the layout of the graph is changing (adopting to the cluster).
Is there any way I could fix the position of the graph and then add clustering?
If for instance, you want to show a "before and after" (one graph w/out the cluster and one with), it might be easiest to initially create both graphs with the clusters (so that they look identical). Then for the graph that you want "unclustered", set all of the subgraph parameters so that the cluster annotations are invisible--i.e., with no cluster label and with a color that is the same as the background color of your graph. the cluster will appear invisible.
So for instance, in the code below, the cluster will appear invisible:
subgraph cluster_inv {
node [style=filled];
N1 -> N2 -> N3;
label="";
color="#FFFFFF";
}