13 Generate all heritable regulatory architectures (HRAs) with n nodes.
14 This version emphasizes correctness while optimizing where possible.
16 start_time = time.time()
17 all_nodes = list(range(1, n + 1))
18 all_edges = list(itertools.permutations(all_nodes, r=2))
21 print(f
"Finding weakly connected heritable topologies for n={n}...")
25 weakly_connected_heritable_non_iso_digraphs = []
37 for k
in range(min_edges, len(all_edges) + 1):
38 if verbose
and k == min_edges:
39 print(f
"Generating edge sets with at least {min_edges} edges...")
40 edge_combinations = itertools.combinations(all_edges, r=k)
41 valid_edge_sets.extend(edge_combinations)
44 print(f
"Checking {len(valid_edge_sets)} potential edge configurations...")
47 for idx, edge_set
in enumerate(valid_edge_sets):
48 if verbose
and idx % 10000 == 0
and idx > 0:
49 print(f
"Processed {idx}/{len(valid_edge_sets)} edge sets...")
52 g.add_nodes_from(all_nodes)
53 g.add_edges_from(edge_set)
56 if not nx.is_weakly_connected(g):
59 heritable = all(g.in_degree(i) > 0
for i
in all_nodes)
64 found_isomorphic =
False
65 for existing
in weakly_connected_heritable_non_iso_digraphs:
66 if nx.is_isomorphic(g, existing):
67 found_isomorphic =
True
70 if not found_isomorphic:
71 weakly_connected_heritable_non_iso_digraphs.append(g)
73 topology_time = time.time()
76 f
"Found {len(weakly_connected_heritable_non_iso_digraphs)} heritable topologies in {topology_time - start_time:.2f} seconds"
80 non_iso_regulatory_architectures = []
83 print(
"Generating regulatory architectures...")
86 for g_idx, g
in enumerate(weakly_connected_heritable_non_iso_digraphs):
87 if verbose
and g_idx % 10 == 0:
89 f
"Processing topology {g_idx+1}/{len(weakly_connected_heritable_non_iso_digraphs)}..."
92 edge_set = list(g.edges())
93 edge_count = len(edge_set)
97 for regulation_pattern
in itertools.product(
98 [
"gray",
"black"], repeat=edge_count
101 regulated_g = nx.DiGraph()
102 regulated_g.add_nodes_from(all_nodes)
105 regulation_to_edges = {}
106 for idx, (u, v)
in enumerate(edge_set):
107 regulated_g.add_edge(u, v)
108 regulation_to_edges[(u, v)] = {
"regulation": regulation_pattern[idx]}
110 nx.set_edge_attributes(regulated_g, regulation_to_edges)
113 found_isomorphic =
False
114 for existing
in non_iso_regulatory_architectures:
115 matcher = isomorphism.DiGraphMatcher(
118 edge_match=
lambda e1, e2: e1.get(
"regulation")
119 == e2.get(
"regulation"),
121 if matcher.is_isomorphic():
122 found_isomorphic =
True
125 if not found_isomorphic:
126 non_iso_regulatory_architectures.append(regulated_g)
128 regulatory_time = time.time()
131 f
"Found {len(non_iso_regulatory_architectures)} non-isomorphic regulatory architectures in {regulatory_time - topology_time:.2f} seconds"
136 heritable_non_iso_regulatory_architectures = []
139 print(
"Filtering for heritable regulatory architectures...")
141 for regulated_g
in non_iso_regulatory_architectures:
143 for node
in all_nodes:
144 has_gray_incoming =
False
145 for pred
in regulated_g.predecessors(node):
146 if regulated_g[pred][node].get(
"regulation") ==
"gray":
147 has_gray_incoming =
True
150 if not has_gray_incoming:
155 heritable_non_iso_regulatory_architectures.append(regulated_g)
157 end_time = time.time()
160 f
"Found {len(heritable_non_iso_regulatory_architectures)} heritable regulatory architectures in {end_time - start_time:.2f} seconds"
162 print(f
"Total time: {end_time - start_time:.2f} seconds")
165 "topologies": weakly_connected_heritable_non_iso_digraphs,
166 "regulatory": non_iso_regulatory_architectures,
167 "heritable": heritable_non_iso_regulatory_architectures,
172 """Plot the HRAs in a grid layout"""
174 print(
"No HRAs to plot")
178 if len(hras) > max_plots:
179 print(f
"Limiting display to first {max_plots} HRAs out of {len(hras)}")
180 hras = hras[:max_plots]
182 rows = (len(hras) + columns - 1) // columns
183 plt.figure(figsize=(columns * 3, rows * 3))
185 for i, g
in enumerate(hras):
186 ax = plt.subplot(rows, columns, i + 1)
188 pos = nx.circular_layout(g)
192 for node
in sorted(g.nodes()):
193 if g.out_degree(node) == 0:
194 node_color_map.append(
"blue")
196 node_color_map.append(
"red")
200 edge_color_map = [g[u][v][
"regulation"]
for u, v
in edges]
202 nx.draw_networkx_nodes(g, pos, node_color=node_color_map, node_size=300, ax=ax)
203 nx.draw_networkx_edges(
206 edge_color=edge_color_map,
208 connectionstyle=
"arc3,rad=0.2",
211 nx.draw_networkx_labels(g, pos, font_color=
"white", ax=ax)
218 """Count HRAs for different entity sizes to verify against expected results"""
221 for n
in range(1, 5):
222 start_time = time.time()
223 print(f
"\nComputing for n={n}...")
227 heritable_topologies = len(data[
"topologies"])
228 regulatory_archs = len(data[
"regulatory"])
229 heritable_archs = len(data[
"heritable"])
231 if heritable_archs > 0:
232 bits = round(math.log2(heritable_archs), 2)
239 "heritable_topologies": heritable_topologies,
240 "regulatory_archs": regulatory_archs,
241 "heritable_archs": heritable_archs,
243 "time": time.time() - start_time,
247 print(f
"\nResults for n={n}:")
248 print(f
"Heritable Topologies: {heritable_topologies}")
249 print(f
"Regulatory Architectures: {regulatory_archs}")
250 print(f
"Heritable Regulatory Architectures: {heritable_archs}")
251 print(f
"Bits: {bits}")
252 print(f
"Time: {results[-1]['time']:.2f} seconds")
255 print(
"\nSummary Table:")
256 print(
"Entities | Heritable Topologies | Regulatory Archs | Heritable Archs | Bits")
257 print(
"---------|---------------------|-----------------|----------------|------")
260 f
"{r['n']} | {r['heritable_topologies']} | {r['regulatory_archs']} | {r['heritable_archs']} | {r['bits']}"