Supplement to "Existence of directed strongly regular graphs with parameters (87,30,14,9,11) and (87,56,40,36,36) ..." (teichmuller_lift, Nov 2026).

data/
  dsrg87_30_c29.jsonl          the three graphs A, B (= converse of A), C (self-converse): blocks D[i][j] in Z_29, vertex (i,x) -> (j, x+g), g in D[i][j]
  dsrg87_30_c29_matrices.txt   full 87 x 87 0/1 matrices of A, B, C ('# name' then 87 rows)
  dsrg87_30_c29.all.hits.jsonl all 968 realisations found by the numerical C_29 three-orbit search (each integer-checked)
  dsrg87_30_c29.triples.jsonl  the 29 diagonal triples that pass the pair stage
  q87_30.json                  the 10 block-size classes
verify/  (proof of Theorem 1). Tested from a clean unzip:
    cd verify; cp ../data/dsrg87_30_c29.jsonl ../data/dsrg87_30_c29_matrices.txt .; cp dsrg87_30_c29_matrices.txt shipped.txt
    python3 verify87_30.py        # checks the shipped matrices (run this before grpring_check.py, which overwrites them)
    python3 grpring_check.py; cmp shipped.txt dsrg87_30_c29_matrices.txt   # regenerated matrices are byte-identical
  grpring_check.py   pure Python: the nine identities in Z[Z_29] for each graph and for its complement
                     (87,56,40,36,36), no matrices; regenerates the matrices file
  verify87_30.py     numpy: A^2 = 14 I + 9 A + 11 (J - I - A), complement, spectrum, stored matrices = blocks; pynauty: non-isomorphism, converses, |Aut| = 58
  verify_dsrg.py     numpy check of any hits file: python3 verify_dsrg.py 87 30 14 9 11 29 ../data/dsrg87_30_c29.all.hits.jsonl
search/  (the numerical search of Section 6; sources as run, for inspection, not a portable pipeline)
  Several exclusion steps use floating point without an error bound (paper, Section 6, "Arithmetic"), so this search is
  not a proof of completeness. The scripts contain absolute paths of the original working directories (.tmp/m55, .tmp/m56,
  .tmp/m57); all files of those directories that the run used are here. Python modules: numpy, cypari (import name
  cypari, version 2.5.7), pynauty. The C programs were compiled with gcc 13.3.0 and -lm; the exact flags were not recorded.
  Order of the original run:
  1. build29.sh       norm tables for p = 29: normset, canonset (off-diagonal sizes), normdiag + mkfac.py (diagonal sizes)
  2. D00 representatives up to multipliers: pairc3 with DUMPREPS=<file> in place of REPSFILE, one file per block-size
     class (reps_87_30_c<class>.bin; 3,510 / 3,510 / 13,468 / 13,468 / 42,288 / 42,288 / 111,041 x 4 representatives)
  3. front87_30.sh    front end: run_pairc3.py -> pairc3.c (L1 bound + norm-pair tests), 10 classes x 12 shards
  4. par_exact.sh     pair stage with PP=29 SIG=1 (exact_probe.py; norm_probe.py / cypari); 29 triples pass
  5. run_compc.py 87 30 14 9 11 29 <29 triples> NPROC cm87_30 with STAGE1=mitm (ideal_s2.py: meet-in-the-middle in Z[zeta]/I)
  6. run_compc.py on the 8 unit-ideal triples (default stage = compc.c)
  7. cls87_30.py      isomorphism classes, converses, |Aut| (pynauty)
  stage_summaries.txt  final log line of every front-end class, the pair-stage totals, per-triple completion counts
                       (both completions) and the indices of the 8 unit-ideal triples, copied from the original logs
  exact_pairs.py, r11_sample.py, r11_cmp.py   the 1% cross-check (pair test without early stop vs ideal_s2, two labellings)
  ctl29.py, pairc2.c  front-end cross-check (pairc3 vs pairc2 + PARI norms on sample shards)
  fixcheck.py        trace congruences: an automorphism of order 29 has 0 or 29 fixed points.
                     python3 fixcheck.py 87 30 14 9 11 29   (no arguments: the default rows, starting with this one)
structure/
  norm87.py          shift to symmetric coordinates (norm87_{A,B,C}.json)
  antiaut.py, affaut.py   maps (i,x) -> (pi(i), u x + c_i) that preserve or reverse a graph
  wl2.py, orbrank.py coherent closure rank vs orbital rank of Aut (135 for all three)
family/
  sym3b.py           symmetric three-orbit model over Z_n (numerical search: float tolerances 1e-7 / 1e-6; outputs are
                     integer-checked, empty cases are not certified) for dsrg(3n, n+1, (n+13)/3, (n-2)/3, (n+4)/3): python3 sym3b.py n shard nshard out.jsonl
  cls.py             classes of its output
  classes_n{5,17,20,29}.json   one block array per isomorphism class found
  run_summaries.txt  final summary line of every shard of the sharded runs (n = 20 and 26 with sym3b.py; n = 29 with sym3.py,
                     the prime-n version without the zero-safe pair test; sym3b.py at n = 29 gives the same 4 hits). Other n: python3 sym3b.py n 0 1 out.jsonl
