matlab — fast matrix multiplication via tensor decomposition over GF(2) (started 2026-10-31)
Idea
A way to multiply matrices with R scalar multiplications = a rank-R decomposition of the matmul
tensor T_
Tools
- search.c : simulated annealing on all bits at FIXED rank R, minimise Hamming(reconstruction, T).
Geometric cooling 2.5*exp(-3 t) finds Strassen <2,2,2>=7 (~1/4000 restarts). Weak method.
- flip.c : FLIP-GRAPH (the method that found real records). Terms are rank-1 u|v|w bitmasks (<=64 bit);
invariant: XOR of all terms == T. A flip rewrites two terms sharing one factor (exact identity,
rank-preserving); a reduction fires when a flip zeroes a term (rank-1) or duplicates another
(cancel mod 2, rank-2). Random walk + opportunistic reduction; `RT` env = steps before
restart-from-best (RT huge = pure long walk, reaches deepest). verify() checks the saved
decomposition against T (full, exact).
- verify.c : standalone check that a hardcoded Strassen reconstructs T exactly (convention sanity). OK.
Validation (exact, verified)
<2,2,2> -> 7 (Strassen) MATCHES best known 7
<3,3,3> -> 23 (Laderman) MATCHES best known 23, found in <1 s
<2,2,3> -> 11 MATCHES best known 11
<2,3,3> -> 15 MATCHES best known 15
Plain flip graph plateaus slightly above best known on medium formats:
<3,3,4> -> 30 (best known 29) one reduction short
<3,4,4> -> 40 (best known 38)
<4,4,4> -> ~49-55 so far (best known GF2 47 = AlphaTensor/KM; Strassen^2 = 49)
Honest standing
The tool is correct and reproduces famous results. Matching the frontier on medium formats needs long walks (running) and, for actual record-BEATING, the symmetry-constrained flip graph (Moosbauer-Poole got <5,5,5>=93) and/or GPU-scale search (Perminov 2026). Beating a world record on this shared CPU box in one session is unlikely; the value is a verified record-search lab + transparent reporting of where each run lands vs. Sedoglavic's catalogue (fmm.univ-lille.fr).
Traps
- Never pipe a timed-out search's stderr to
tail: SIGTERM drops the buffer and you see nothing.
Redirect to a file. (Cost me a false "it's broken".)
- pkill/pgrep -f matching the binary name kills the orchestrating shell (exit 144). Use pkill -x
. - flip2.c (efficiency rewrite) has an index-juggling bug in its local reduction; use flip.c (v1).
Symmetry-constrained flip graph — symflip.c (2026-10-31)
The record-finding trick (Moosbauer-Poole). For SQUARE
a=(i,k)=i*n+k, b=(k,j)=k*n+j, c=(j,i)=j*n+i
the matmul tensor is invariant under the cyclic rotation rho(u,v,w) = (w,u,v) on raw bitmasks. (Verified: build_and_verify builds T in this convention and checks the EXPANDED scheme against it.) We search over rho-INVARIANT schemes, stored as one representative per orbit; the real scheme is the union of expand(rep) = {rep, rho rep, rho^2 rep} (3 terms, or 1 if u==v==w a fixed point). Key fact that makes it correct: a flip on two representatives preserves the expanded sum, because rho is linear (r1+r2 = r1'+r2' => expand(r1)+expand(r2) = expand(r1')+expand(r2')). Reductions remove whole orbits (zero factor, or two reps in the same orbit cancel mod 2). rank = sum(1 if fixed else 3). IMPORTANT fix: partner search must try all 3 rho-rotations of each candidate orbit (else 2/3 of the legal flips are invisible and the walk stalls at ~25 for n=3). Behaviour: symmetry is a CONSTRAINT -> it hurts on tiny formats (n=3 symmetric stalls ~25 vs plain 23) but is the way to search LARGE formats where the unconstrained space is too big. Campaign 2 runs n=4 (target 47), n=5 (target 97/93), n=6 (target 153) symmetric + rectangular plain; logs in sym/.
flip3 — faster + smarter plain flip graph (2026-10-31, "flip3" thread)
flip3.c, usage flip3 n m p seconds seed out.txt [start.txt], env L (plateau length), TGT (stop at rank),
EXC/PMAX (max excursion above best / max plus-transitions before reset). Three changes vs flip.c:
1. targeted partner choice (term i, then a j that SHARES a factor) — v1's random pairs were >95% no-ops;
2. MERGE reduction: two terms sharing two factors -> one term (v1 only cancelled exact duplicates);
3. plateau escape by plus-transition abc+a'b'c' = (a^a')bc + a'(b^b')c + a'b'(c^c') (rank+1) after L
stalled steps; reset to best when the excursion exceeds EXC.
kron.py = Kronecker product of two schemes (v3/strassen2.txt = Strassen⊗Strassen, rank 49, verified). Results (all verify OK):
<3,3,4> 29 = BEST KNOWN, in 1–22 s (flip.c: 30 after 40 min x 6 cores). L=2000 and L=2e6 both hit.
<3,4,4> 39 in ~100 s (best known 38; flip.c 40).
<4,4,4> naive start 52 in 100 s; Strassen² start stays at 49 even with +8 excursions (its factors
are all distinct -> no flips without plus-transitions). KM reached 47 with far more compute.
Running: v3campaign.sh (1 h, 4 workers) -> v3/c/, tgsend summary. Division of labour with the sibling thread: it does symflip (symmetric n=5/6) and ported (2)+(3) there.
Rohdaten
- c3/p334.log (1 KB)
- c3/p344.log (1 KB)
- c3/s444_1.log (1 KB)
- c3/s444_2.log (1 KB)
- c3/s444_3.log (1 KB)
- c3/s444_4.log (1 KB)
- c3/s666_1.log (1 KB)
- c3/s666_2.log (1 KB)
- c3/y444_1.log (1 KB)
- c3/y444_1.txt (1 KB)
- c3/y444_2.log (1 KB)
- c3/y444_2.txt (1 KB)
- c3/y444_3.log (1 KB)
- c3/y444_3.txt (1 KB)
- c3/y555_1.log (1 KB)
- c3/y555_1.txt (1 KB)
- c3/y555_2.log (1 KB)
- c3/y555_2.txt (1 KB)
- c3/y555_3.log (1 KB)
- c3/y555_3.txt (1 KB)
- c3/y666_1.log (1 KB)
- c3sym3.txt (1 KB)
- camp/log_334_1.txt (1 KB)
- camp/log_334_2.txt (1 KB)
- camp/log_334_3.txt (1 KB)
- camp/log_334_4.txt (1 KB)
- camp/log_334_5.txt (1 KB)
- camp/log_334_6.txt (1 KB)
- camp/log_344_1.txt (1 KB)
- camp/log_344_2.txt (1 KB)
- camp/log_344_3.txt (1 KB)
- camp/log_344_4.txt (1 KB)
- camp/log_344_5.txt (1 KB)
- camp/log_344_6.txt (1 KB)
- camp/log_444_1.txt (1 KB)
- camp/log_444_2.txt (1 KB)
- d4.txt (1 KB)
- d5.txt (1 KB)
- dbg.txt (1 KB)
- dbgs.txt (1 KB)
- i3.txt (1 KB)
- log_223.txt (1 KB)
- log_233.txt (1 KB)
- log_334.txt (1 KB)
- log_344.txt (1 KB)
- log_444.txt (1 KB)
- s222.txt (1 KB)
- s333.txt (1 KB)
- sd444.txt (1 KB)
- seed444.txt (1 KB)
- seed666.txt (3 KB)
- sol.txt (1 KB)
- sym/log4_1.txt (1 KB)
- sym/log4_2.txt (1 KB)
- sym/log4_3.txt (1 KB)
- sym/log4_4.txt (1 KB)
- sym/log4_5.txt (1 KB)
- sym/log4_6.txt (1 KB)
- sym/log5_1.txt (1 KB)
- sym/log5_2.txt (1 KB)
- sym/log5_3.txt (1 KB)
- sym/log5_4.txt (1 KB)
- sym/log6_1.txt (1 KB)
- sym/plog334_21.txt (1 KB)
- sym/plog344_21.txt (1 KB)
- sym/plog444_21.txt (1 KB)
- sym/s4_1.txt (1 KB)
- sym/s4_2.txt (1 KB)
- sym/s4_3.txt (1 KB)
- sym/s4_4.txt (1 KB)
- sym/s4_5.txt (1 KB)
- sym/s4_6.txt (1 KB)
- sym/s5_1.txt (1 KB)
- sym/s5_2.txt (1 KB)
- sym/s5_3.txt (1 KB)
- sym/s5_4.txt (1 KB)
- sym/s6_1.txt (1 KB)
- sym3.txt (1 KB)
- sym4.txt (1 KB)
- sym5.txt (1 KB)
- v3/a344_1.txt (1 KB)
- v3/a344_2.txt (1 KB)
- v3/a344_3.txt (1 KB)
- v3/b344_1.txt (1 KB)
- v3/b344_2.txt (1 KB)
- v3/b344_3.txt (1 KB)
- v3/c/l_344a.txt (1 KB)
- v3/c/l_344b.txt (1 KB)
- v3/c/l_444n.txt (1 KB)
- v3/c/l_444s.txt (1 KB)
- v3/e444_10_200_5000_2.txt (1 KB)
- v3/e444_4_40_50000_3.txt (1 KB)
- v3/e444_6_60_2000_1.txt (1 KB)
- v3/e444_6_60_300000_4.txt (1 KB)
- v3/k444_1.txt (1 KB)
- v3/k444_2.txt (1 KB)
- v3/l334_1.txt (1 KB)
- v3/l334_2.txt (1 KB)
- v3/l344_1.txt (1 KB)
- v3/l344_2.txt (1 KB)
- v3/lL20000000_1.txt (1 KB)
- v3/lL20000000_2.txt (1 KB)
- v3/lL2000000_1.txt (1 KB)
- v3/lL2000000_2.txt (1 KB)
- v3/lL20000_1.txt (1 KB)
- v3/lL20000_2.txt (1 KB)
- v3/lL2000_1.txt (1 KB)
- v3/lL2000_2.txt (1 KB)
- v3/la344_1.txt (1 KB)
- v3/la344_2.txt (1 KB)
- v3/la344_3.txt (1 KB)
- v3/lb344_1.txt (1 KB)
- v3/lb344_2.txt (1 KB)
- v3/lb344_3.txt (1 KB)
- v3/le444_10_200_5000_2.txt (1 KB)
- v3/le444_4_40_50000_3.txt (1 KB)
- v3/le444_6_60_2000_1.txt (1 KB)
- v3/le444_6_60_300000_4.txt (1 KB)
- v3/lk444_1.txt (1 KB)
- v3/lk444_2.txt (1 KB)
- v3/ln444_1.txt (1 KB)
- v3/ln444_2.txt (1 KB)
- v3/n444_1.txt (1 KB)
- v3/n444_2.txt (1 KB)
- v3/s222.txt (1 KB)
- v3/s334_1.txt (1 KB)
- v3/s334_2.txt (1 KB)
- v3/s344_1.txt (1 KB)
- v3/s344_2.txt (1 KB)
- v3/sL20000000_1.txt (1 KB)
- v3/sL20000000_2.txt (1 KB)
- v3/sL2000000_1.txt (1 KB)
- v3/sL2000000_2.txt (1 KB)
- v3/sL20000_1.txt (1 KB)
- v3/sL20000_2.txt (1 KB)
- v3/sL2000_1.txt (1 KB)
- v3/sL2000_2.txt (1 KB)
- v3/strassen2.txt (1 KB)
- v3.txt (1 KB)
- vchk.txt (1 KB)
- vchk3.txt (1 KB)
- vchk3b.txt (1 KB)