catalog.py

3.2 kB · python · 115 lines

1import os2import json3import time4from itertools import product, permutations5from .bang import (6    corners,7    code_to_filled,8    algebraic_degree,9    anf_string,10    genus,11    level_set,12    axis_pins,13)14from .complexity import measures1516# THE COMPLEXITY CATALOG - JOIN GEOMETRY TO COMPLEXITY ON THE FULL FINITE FAMILY1718def _perm_maps(dimension):19    cells = corners(dimension)20    index = {c: i for i, c in enumerate(cells)}21    maps = []22    for perm in permutations(range(dimension)):23        for flips in product((0, 1), repeat=dimension):24            m = [0] * len(cells)25            for i, c in enumerate(cells):26                image = tuple(c[perm[k]] ^ flips[k] for k in range(dimension))27                m[i] = index[image]28            maps.append(tuple(m))29    return maps, cells3031def _orbit(code, maps, ncorners):32    images = set()33    for m in maps:34        v = 035        c = code36        i = 037        while c:38            if c & 1:39                v |= 1 << m[i]40            c >>= 141            i += 142        images.add(v)43    return images4445def canonical_codes(dimension):46    maps, cells = _perm_maps(dimension)47    ncorners = len(cells)48    total = 1 << ncorners49    seen = bytearray(total)50    reps = []51    orbit_sizes = {}52    for code in range(total):53        if seen[code]:54            continue55        orbit = _orbit(code, maps, ncorners)56        rep = min(orbit)57        for v in orbit:58            seen[v] = 159        reps.append(rep)60        orbit_sizes[rep] = len(orbit)61    return sorted(reps), maps, cells, orbit_sizes6263def _width(dimension):64    return len(str((1 << (1 << dimension)) - 1))6566def _design_row(code, cells, dimension, orbit_size):67    filled = code_to_filled(code, cells)68    ls = level_set(filled, cells)69    ax = axis_pins(filled, cells)70    m = measures(filled, cells)71    fp = m.pop("fill_fingerprint")72    row = {73        "name": f"mrly_{code:0{_width(dimension)}d}",74        "i": code,75        "dimension": dimension,76        "genus": genus(filled, cells),77        "gf2_degree": algebraic_degree(filled, cells),78        "level_set_S": list(ls) if ls is not None else None,79        "axis_pins": list(ax) if ax is not None else None,80        "anf": anf_string(filled, cells),81        "orbit_size": orbit_size,82        "fill_fingerprint": [str(x) for x in fp],83    }84    row.update(m)85    return row8687def build(dimension):88    reps, maps, cells, orbit_sizes = canonical_codes(dimension)89    rows = []90    for code in reps:91        rows.append(_design_row(code, cells, dimension, orbit_sizes[code]))92    return rows9394def write_catalog(dimension, directory):95    rows = build(dimension)96    os.makedirs(directory, exist_ok=True)97    path = os.path.join(directory, f"complexity_{dimension}d.json")98    with open(path, "w") as fh:99        json.dump(rows, fh, indent=2)100    return path, rows101102def load_catalog(dimension, directory):103    path = os.path.join(directory, f"complexity_{dimension}d.json")104    with open(path) as fh:105        return json.load(fh)106107def _data_dir():108    return os.path.join(os.path.dirname(__file__), "data")109110if __name__ == "__main__":111    here = _data_dir()112    for D in (3, 4):113        t0 = time.time()114        path, rows = write_catalog(D, here)115        print(f"D={D}: {len(rows)} designs -> {path}  ({round(time.time()-t0,1)}s)")