"""Draw the six Holton-McKay duals and their witness Even Level Graphs as crossing-free planar drawings (networkx planar_layout, Chrobak-Payne). Two figures: n21_elgs.png -- the six witness Even Level Graphs, parity-coloured, with the edges flipped by the bridge switches dashed red; n21_duals.png -- the six resulting duals, parity-coloured (same fixed parity labelling), with the introduced bridge edges green. Reads experiments/witnesses/dual_*.json. ELG and dual are drawn with independent planar layouts so neither has any edge crossing. """ import sys import os import json sys.path.insert(0, '/Users/didericis/Code/math-research/papers/' 'level_resolutions_of_maximal_planar_graphs/experiments') sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) import networkx as nx import matplotlib matplotlib.use('Agg') import matplotlib.pyplot as plt from matplotlib.lines import Line2D HERE = os.path.dirname(os.path.abspath(__file__)) WDIR = os.path.join(HERE, 'witnesses') FDIR = os.path.join(HERE, '..', 'figures') EVEN_C = '#9ecae1' # even-parity vertices ODD_C = '#fdae6b' # odd-parity vertices def load(i): return json.load(open(os.path.join(WDIR, f'dual_{i}.json'))) def graph_of(edges, labels): G = nx.Graph() G.add_nodes_from(int(v) for v in labels) G.add_edges_from((a, b) for a, b in edges) return G def draw(ax, G, labels, highlight, hcolor, hstyle, title): pos = nx.planar_layout(G) colors = [EVEN_C if labels[str(v)] == 0 else ODD_C for v in G.nodes()] hl = {frozenset(e) for e in highlight} plain = [e for e in G.edges() if frozenset(e) not in hl] nx.draw_networkx_edges(G, pos, edgelist=plain, ax=ax, edge_color='#b0b0b0', width=0.8) if hl: nx.draw_networkx_edges(G, pos, edgelist=[tuple(e) for e in hl], ax=ax, edge_color=hcolor, width=2.4, style=hstyle) nx.draw_networkx_nodes(G, pos, node_color=colors, node_size=200, edgecolors='#444444', linewidths=0.6, ax=ax) nx.draw_networkx_labels(G, pos, font_size=8, ax=ax) ax.set_title(title, fontsize=10) ax.margins(0.12) ax.axis('off') def legend(fig, kind): handles = [ Line2D([0], [0], marker='o', color='w', markerfacecolor=EVEN_C, markeredgecolor='#444', markersize=9, label='even parity'), Line2D([0], [0], marker='o', color='w', markerfacecolor=ODD_C, markeredgecolor='#444', markersize=9, label='odd parity'), ] if kind == 'elg': handles.append(Line2D([0], [0], color='#d62728', lw=2.4, ls='dashed', label='edge flipped by a bridge switch')) else: handles.append(Line2D([0], [0], color='#2ca02c', lw=2.4, label='bridge edge introduced')) fig.legend(handles=handles, loc='lower center', ncol=3, fontsize=9, frameon=False) def main(): os.makedirs(FDIR, exist_ok=True) # Figure 1: the six witness Even Level Graphs (flipped edges red dashed) fig, axes = plt.subplots(2, 3, figsize=(19, 12)) for i, ax in zip(range(6), axes.flat): d = load(i) G = graph_of(d['elg_edges'], d['labels']) removed = [s['remove'] for s in d['bridge_switches']] k = d['num_bridge_switches'] sub = (f"{k} bridge switch" + ("es" if k != 1 else "") if k else "Even Level Graph outright") draw(ax, G, d['labels'], removed, '#d62728', 'dashed', f"dual {i}: ELG (source {d['elg_source']})\n{sub}") legend(fig, 'elg') fig.tight_layout(rect=(0, 0.04, 1, 1)) p1 = os.path.join(FDIR, 'n21_elgs.png') fig.savefig(p1, dpi=160) plt.close(fig) print(f'wrote {p1}') # Figure 2: the six resulting duals (introduced bridge edges green) fig, axes = plt.subplots(2, 3, figsize=(19, 12)) for i, ax in zip(range(6), axes.flat): d = load(i) G = graph_of(d['dual_edges'], d['labels']) added = [s['add'] for s in d['bridge_switches']] draw(ax, G, d['labels'], added, '#2ca02c', 'solid', f"dual {i}") legend(fig, 'dual') fig.tight_layout(rect=(0, 0.04, 1, 1)) p2 = os.path.join(FDIR, 'n21_duals.png') fig.savefig(p2, dpi=160) plt.close(fig) print(f'wrote {p2}') if __name__ == '__main__': main()