"""Dump candidate invariants for bridge-derived vs non-bridge-derived
triangulations at small n, to spot a separating (necessary) condition."""
import sys
import os
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
from triangulation_gen import enumerate_all_triangulations
from exhaustive_bridge import valid_parity_partitions
from small_n_probe import is_bridge_derived


def per_partition_stats(G):
    """For each valid partition return dict of invariants."""
    rows = []
    for labels in valid_parity_partitions(G):
        ev = [v for v in G.nodes() if labels[v] == 0]
        od = [v for v in G.nodes() if labels[v] == 1]
        SE, SO = G.subgraph(ev), G.subgraph(od)
        ce = nx.number_connected_components(SE)
        co = nx.number_connected_components(SO)
        be = SE.number_of_edges() - len(ev) + ce
        bo = SO.number_of_edges() - len(od) + co
        rows.append(dict(be=be, bo=bo, ee=SE.number_of_edges(),
                         eo=SO.number_of_edges(), ce=ce, co=co,
                         ne=len(ev), no=len(od)))
    return rows


def summarize(G):
    rows = per_partition_stats(G)
    tb = [r['be'] + r['bo'] for r in rows]
    cross = [G.number_of_edges() - r['ee'] - r['eo'] for r in rows]
    # does some partition make BOTH parity subgraphs forests (be=bo=0)?
    forests = any(r['be'] == 0 and r['bo'] == 0 for r in rows)
    return dict(min_tb=min(tb), max_tb=max(tb), nparts=len(rows),
                min_cross=min(cross), max_cross=max(cross),
                both_forest=forests)


def main(n):
    tris = enumerate_all_triangulations(n)
    print(f'n={n}: {len(tris)} triangulations', flush=True)
    bd_stats, nb_stats = [], []
    for G in tris:
        s = summarize(G)
        if is_bridge_derived(G):
            bd_stats.append(s)
        else:
            nb_stats.append(s)

    def col(stats, key):
        return sorted(set(s[key] for s in stats))

    for key in ['min_tb', 'max_tb', 'min_cross', 'max_cross']:
        print(f'  {key:10s}  bridge={col(bd_stats,key)}  '
              f'NONbridge={col(nb_stats,key)}', flush=True)
    print(f'  both_forest exists?  bridge={sorted(set(s["both_forest"] for s in bd_stats))}'
          f'  NONbridge={sorted(set(s["both_forest"] for s in nb_stats))}', flush=True)
    # separator check: any min_tb value unique to one class?
    bd_min = set(s['min_tb'] for s in bd_stats)
    nb_min = set(s['min_tb'] for s in nb_stats)
    print(f'  min_tb only-in-bridge: {bd_min - nb_min}; '
          f'only-in-NONbridge: {nb_min - bd_min}', flush=True)
    print(f'  both_forest: bridge {sum(s["both_forest"] for s in bd_stats)}/{len(bd_stats)}, '
          f'NONbridge {sum(s["both_forest"] for s in nb_stats)}/{len(nb_stats)}', flush=True)


if __name__ == '__main__':
    main(int(sys.argv[1]) if len(sys.argv) > 1 else 9)
