How to plot the same graph repeatedly?

I am using Python NetworkX pygraphviz_layout to plot a graph. I have the same set of nodes and edges, but everytime I run the code, the graph layout is different. I would like to get the same graph everytime.

I tried to search if there are any random seed that can be set but could not find any.

Here is my example code, and example of different graph layout being generated.

import matplotlib.pyplot as plt
import networkx as nx
import random

G = nx.DiGraph()
for i in range(100):
	G.add_node(i)

random.seed(1)
for i in range(100):
	a = random.randint(0,99)
	b = random.randint(0,99)
	G.add_edge(a,b)

pos = nx.nx_agraph.pygraphviz_layout(G, prog='fdp')
nx.draw(G, pos=pos, with_labels=True)

plt.savefig("plot_graph_folder/temp.png")

temp - Copy
temp

Unfortunately the algorithms we use are nondeterministic. We would like to fix this, there is an issue in the repo, but haven’t gotten the time. It’s probably a big job.

Thank you! Appreciate your reply.

To give some background as to what’s going on in the Graphviz code itself, there are two main sources of non-determinism I’m aware of:

  1. Intended random layout. Calls to rand and friends. Most of this is controllable with explicit seeds.
  2. The use of pointers as IDs, implying ordering. This was a reasonable thing to do when the code was written, but in the modern era of ASLR this causes unintended variation.

The second has proved extremely challenging to fix because attempts to alter this uncovered that some tools in the Graphviz suite are tightly coupled to the underlying library implementation and rely on being able to reverse IDs into pointers. More details in Repeated file read gives different results with libcgraph (#1767) · Issues · graphviz / graphviz · GitLab.

There is a graph attribute, “start”, that I believe fdp considers.

fdp -Gstart=2 file.gv -Tpdf -o file.pdf

where start=2 is supposed to give results deterministically.

That being said, I thought start=1 was the default, except maybe not on Windows? From lib/fdpgen/tlayout.c · main · graphviz / graphviz · GitLab


    /* Set seed value */
    if (T_smode == INIT_RANDOM)
        local_seed = T_seed;
    else {
#if defined(_WIN32)
        local_seed = time(NULL);
#else
        local_seed = getpid() ^ time(NULL);
#endif
    }
    srand48(local_seed);

Doesn’t that indicate Windows and everything else differ in how they generate a random seed, not what the default is?

Having said that, I don’t know why this needs OS-specific code here, nor why using your PID as a seed component is sensible, nor even why someone would want a randomized layout. But perhaps I am insufficiently creative.

Everything you say is reasonable. When we did this, we thought it would be cool if you could see a different layout every time you ran it. We never thought repeatability could be that important. Not defending it.