0

In networkx, I have a directed draph G = networkx.DiGraph() where each node has an attribute w (always a positive integer, including zero). The graph is acyclic (it represents a poset), and the value increases as one goes from node to node, that is, generically G.nodes[n1]["w"] < G.nodes[n2]["w"] if there is a path between n1 and n2, but it is not a direct function of the position in the graph, i.e. two nodes with edges to the same node can have different values of w, as long as they are bigger than that of their origin.

I need to draw this diagram as a tikz figure in latex. I want the figure to not only represent G, but also that nodes with different values of w are at different heights (and same values of w at the same height.

A toy example I implemented is:

import networkx
import dot2tex


nodes = [
    ["A", {"w": 0}],
    ["B", {"w": 1}],
    ["C", {"w": 2}],
    ["D", {"w": 3}],
        ]

edges = [
    ["A", "B"],
    ["A", "C"],
    ["B", "D"],
    ["C", "D"],
]

G = networkx.DiGraph()
G.add_nodes_from(nodes)
G.add_edges_from(edges)
    
A = networkx.nx_agraph.to_agraph(G)
dot_string = A.string()

latex_string = dot2tex.dot2tex(
    dot_string,
    preproc=True,
    docpreamble=r"\usepackage{amsmath,amssymb,amsthm,bm}",
    format="tikz"
)
latex_string = dot2tex.dot2tex(
    latex_string,
    figonly=False,
    docpreamble=r"\usepackage{amsmath,amssymb,amsthm,bm}",
    autosize=True,
    crop=True,
    valignmode="dot",
    format="tikz"
)

print(latex_string)

with open("test.tex", "w") as f:
    f.write(latex_string)

This gives the picture on the left

enter image description here enter image description here

However I need the node C to be half way between B and D to reflect the fact that its argument w=2 satisfies 1<2<3, as depicted more or less on the right. The actual diagrams I have can have order 50 nodes, so doing it by hand would take ages. Is there a simple way to do it automatically? The precise height is not really important, as long as it's clear that B and C have different w.

1
  • 1
    don't know networkx, but seemingly easy with dot (graphviz), by setting minlen (graphviz.org/docs/attrs/minlen) on each edge to delta of the two W values Commented Sep 30, 2024 at 22:17

1 Answer 1

0

As commented by @sroush, this is achieved by setting the minlen attribute as the difference between each w values for the dot graph. The easiest is to do it directly at the level of the networkx.DiGraph.

Simply adding the following bit lines in the code above will give the desired result

...
G = networkx.DiGraph()
G.add_nodes_from(nodes)
G.add_edges_from(edges)

for e in G.edges:
    G.edges[e]["minlen"] = G.nodes[e[1]]["w"] - G.nodes[e[0]]["w"]
...

resulting figure after adding bit of code

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.