structure.py

2.9 kB · python · 113 lines

1import json2import os3from collections import defaultdict4from fractions import Fraction5from .catalog import load_catalog, _data_dir67MEASURE_KEYS = [8    "sensitivity",9    "block_sensitivity",10    "certificate",11    "certificate_0",12    "certificate_1",13    "decision_tree_depth",14    "real_degree",15    "dnf_size",16    "cnf_size",17]1819def _fp_tuple(row):20    return tuple(row["fill_fingerprint"])2122def invariant_keys(row):23    genus = row["genus"]24    gf2 = row["gf2_degree"]25    pop = row["popcount"]26    fp = _fp_tuple(row)27    return {28        "genus": (genus,),29        "gf2_degree": (gf2,),30        "popcount": (pop,),31        "genus+gf2": (genus, gf2),32        "genus+pop": (genus, pop),33        "gf2+pop": (gf2, pop),34        "genus+gf2+pop": (genus, gf2, pop),35        "fingerprint": fp,36        "genus+fingerprint": (genus,) + fp,37    }3839KEY_ORDER = [40    "genus", "gf2_degree", "popcount",41    "genus+gf2", "genus+pop", "gf2+pop", "genus+gf2+pop",42    "fingerprint", "genus+fingerprint",43]4445def determines(rows, key_name, measure):46    groups = defaultdict(set)47    for row in rows:48        k = invariant_keys(row)[key_name]49        groups[k].add(row[measure])50    bad = {k: sorted(v) for k, v in groups.items() if len(v) > 1}51    return (len(bad) == 0), bad5253def coarsest_determiner(rows, measure):54    for key_name in KEY_ORDER:55        ok, _ = determines(rows, key_name, measure)56        if ok:57            return key_name58    return None5960def determination_report(rows):61    report = {}62    for measure in MEASURE_KEYS:63        det = coarsest_determiner(rows, measure)64        report[measure] = det65    return report6667def collisions(rows, key_name, measure):68    _, bad = determines(rows, key_name, measure)69    out = []70    members = defaultdict(list)71    for row in rows:72        k = invariant_keys(row)[key_name]73        members[k].append(row["name"])74    for k, vals in bad.items():75        out.append((k, vals, members[k]))76    return out7778def measure_gap(rows, big, small):79    out = []80    for row in rows:81        a = row[big]82        b = row[small]83        out.append((row["name"], a, b, a - b))84    return out8586def extremal_on(rows, measure_a, measure_b, ratio=False):87    best = None88    holders = []89    for row in rows:90        a = max(row[measure_a], 0)91        b = max(row[measure_b], 0)92        if ratio:93            if b == 0:94                continue95            val = Fraction(a, b)96        else:97            val = a - b98        if best is None or val > best:99            best = val100            holders = [row["name"]]101        elif val == best:102            holders.append(row["name"])103    return best, holders104105if __name__ == "__main__":106    here = _data_dir()107    for D in (3, 4):108        rows = load_catalog(D, here)109        print(f"=== D={D} ({len(rows)} designs) ===")110        rep = determination_report(rows)111        for measure, det in rep.items():112            print(f"  {measure:22s} determined by: {det}")113        print()