From b123ff44a211b9fc96b9f8fd1538e9965a95b34e Mon Sep 17 00:00:00 2001 From: Joel Pulikkan Date: Sat, 24 Oct 2026 19:27:10 -0400 Subject: [PATCH] Lever ceilings on the #4610 productive-helper word: re-ranking, reorder and re-frame (no kappa claim) Co-Authored-By: Claude Opus 5.5 --- .../frontier-word-reorder-ceilings/README.md | 52 +++++ .../r12-levers/DIGEST.md | 76 ++++++++ .../r12-levers/README.md | 95 ++++++++++ .../r12-levers/tools/consolidate.py | 18 ++ .../r12-levers/tools/dimlp.py | 66 +++++++ .../r12-levers/tools/dimmilp.py | 69 +++++++ .../r12-levers/tools/marg.py | 15 ++ .../r12-levers/tools/moment.py | 26 +++ .../r12-levers/tools/regdp.py | 35 ++++ .../r12-levers/tools/stab.py | 33 ++++ .../r13-reorder/README.md | 130 +++++++++++++ .../data/cons-backward-medium.json.gz | Bin 0 -> 51499 bytes .../data/cons-forward-True.json.gz | Bin 0 -> 51551 bytes .../data/cons-forward-medium.json.gz | Bin 0 -> 51498 bytes .../data/cons-forward-wide.json.gz | Bin 0 -> 53888 bytes .../r13-reorder/data/cons-forward.json.gz | Bin 0 -> 51480 bytes .../data/mip-backward-pinw.json.gz | Bin 0 -> 44811 bytes .../r13-reorder/data/mip-backward.json.gz | Bin 0 -> 44806 bytes .../r13-reorder/data/mip-forward-pinw.json.gz | Bin 0 -> 44816 bytes .../r13-reorder/data/mip-forward.json.gz | Bin 0 -> 44811 bytes .../r13-reorder/logs/ceil-lp-backward.txt | 95 ++++++++++ .../r13-reorder/logs/ceil-lp-forward.txt | 93 +++++++++ .../r13-reorder/logs/ceil-mip-backward.txt | 67 +++++++ .../r13-reorder/logs/ceil-mip-forward.txt | 67 +++++++ .../r13-reorder/logs/ceil-mipw-backward.txt | 66 +++++++ .../r13-reorder/logs/ceil-mipw-forward.txt | 66 +++++++ .../r13-reorder/logs/cons-backward-medium.txt | 77 ++++++++ .../r13-reorder/logs/cons-forward-medium.txt | 77 ++++++++ .../r13-reorder/logs/cons-forward-wide-lp.txt | 177 ++++++++++++++++++ .../r13-reorder/logs/cons-forward-wide.txt | 35 ++++ .../r13-reorder/logs/cons-forward.txt | 68 +++++++ .../r13-reorder/logs/me-f-0.txt | 38 ++++ .../r13-reorder/logs/me-f-1.txt | 39 ++++ .../r13-reorder/logs/me-f-2.txt | 38 ++++ .../r13-reorder/logs/me-f-3.txt | 37 ++++ .../r13-reorder/logs/me-f-4.txt | 37 ++++ .../r13-reorder/logs/rw-b.txt | 52 +++++ .../r13-reorder/logs/rw-f-0.txt | 12 ++ .../r13-reorder/logs/rw-f-1.txt | 12 ++ .../r13-reorder/logs/rw-f-2.txt | 12 ++ .../r13-reorder/logs/rw-f-3.txt | 12 ++ .../r13-reorder/logs/rw-f-4.txt | 12 ++ .../r13-reorder/logs/rw-main.txt | 75 ++++++++ .../r13-reorder/tools/backbone.py | 28 +++ .../r13-reorder/tools/ceil.py | 173 +++++++++++++++++ .../r13-reorder/tools/checkcur.py | 31 +++ .../r13-reorder/tools/construct.py | 125 +++++++++++++ .../r13-reorder/tools/lift.py | 109 +++++++++++ .../r13-reorder/tools/load.py | 23 +++ .../r13-reorder/tools/mipeval.py | 29 +++ .../r13-reorder/tools/poset.py | 145 ++++++++++++++ .../r13-reorder/tools/price.py | 21 +++ .../r13-reorder/tools/realize.py | 97 ++++++++++ .../r13-reorder/tools/rewrite.py | 150 +++++++++++++++ .../r13-reorder/tools/sdom.py | 72 +++++++ 55 files changed, 2882 insertions(+) create mode 100644 research/frontier-word-reorder-ceilings/README.md create mode 100644 research/frontier-word-reorder-ceilings/r12-levers/DIGEST.md create mode 100644 research/frontier-word-reorder-ceilings/r12-levers/README.md create mode 100644 research/frontier-word-reorder-ceilings/r12-levers/tools/consolidate.py create mode 100644 research/frontier-word-reorder-ceilings/r12-levers/tools/dimlp.py create mode 100644 research/frontier-word-reorder-ceilings/r12-levers/tools/dimmilp.py create mode 100644 research/frontier-word-reorder-ceilings/r12-levers/tools/marg.py create mode 100644 research/frontier-word-reorder-ceilings/r12-levers/tools/moment.py create mode 100644 research/frontier-word-reorder-ceilings/r12-levers/tools/regdp.py create mode 100644 research/frontier-word-reorder-ceilings/r12-levers/tools/stab.py create mode 100644 research/frontier-word-reorder-ceilings/r13-reorder/README.md create mode 100644 research/frontier-word-reorder-ceilings/r13-reorder/data/cons-backward-medium.json.gz create mode 100644 research/frontier-word-reorder-ceilings/r13-reorder/data/cons-forward-True.json.gz create mode 100644 research/frontier-word-reorder-ceilings/r13-reorder/data/cons-forward-medium.json.gz create mode 100644 research/frontier-word-reorder-ceilings/r13-reorder/data/cons-forward-wide.json.gz create mode 100644 research/frontier-word-reorder-ceilings/r13-reorder/data/cons-forward.json.gz create mode 100644 research/frontier-word-reorder-ceilings/r13-reorder/data/mip-backward-pinw.json.gz create mode 100644 research/frontier-word-reorder-ceilings/r13-reorder/data/mip-backward.json.gz create mode 100644 research/frontier-word-reorder-ceilings/r13-reorder/data/mip-forward-pinw.json.gz create mode 100644 research/frontier-word-reorder-ceilings/r13-reorder/data/mip-forward.json.gz create mode 100644 research/frontier-word-reorder-ceilings/r13-reorder/logs/ceil-lp-backward.txt create mode 100644 research/frontier-word-reorder-ceilings/r13-reorder/logs/ceil-lp-forward.txt create mode 100644 research/frontier-word-reorder-ceilings/r13-reorder/logs/ceil-mip-backward.txt create mode 100644 research/frontier-word-reorder-ceilings/r13-reorder/logs/ceil-mip-forward.txt create mode 100644 research/frontier-word-reorder-ceilings/r13-reorder/logs/ceil-mipw-backward.txt create mode 100644 research/frontier-word-reorder-ceilings/r13-reorder/logs/ceil-mipw-forward.txt create mode 100644 research/frontier-word-reorder-ceilings/r13-reorder/logs/cons-backward-medium.txt create mode 100644 research/frontier-word-reorder-ceilings/r13-reorder/logs/cons-forward-medium.txt create mode 100644 research/frontier-word-reorder-ceilings/r13-reorder/logs/cons-forward-wide-lp.txt create mode 100644 research/frontier-word-reorder-ceilings/r13-reorder/logs/cons-forward-wide.txt create mode 100644 research/frontier-word-reorder-ceilings/r13-reorder/logs/cons-forward.txt create mode 100644 research/frontier-word-reorder-ceilings/r13-reorder/logs/me-f-0.txt create mode 100644 research/frontier-word-reorder-ceilings/r13-reorder/logs/me-f-1.txt create mode 100644 research/frontier-word-reorder-ceilings/r13-reorder/logs/me-f-2.txt create mode 100644 research/frontier-word-reorder-ceilings/r13-reorder/logs/me-f-3.txt create mode 100644 research/frontier-word-reorder-ceilings/r13-reorder/logs/me-f-4.txt create mode 100644 research/frontier-word-reorder-ceilings/r13-reorder/logs/rw-b.txt create mode 100644 research/frontier-word-reorder-ceilings/r13-reorder/logs/rw-f-0.txt create mode 100644 research/frontier-word-reorder-ceilings/r13-reorder/logs/rw-f-1.txt create mode 100644 research/frontier-word-reorder-ceilings/r13-reorder/logs/rw-f-2.txt create mode 100644 research/frontier-word-reorder-ceilings/r13-reorder/logs/rw-f-3.txt create mode 100644 research/frontier-word-reorder-ceilings/r13-reorder/logs/rw-f-4.txt create mode 100644 research/frontier-word-reorder-ceilings/r13-reorder/logs/rw-main.txt create mode 100644 research/frontier-word-reorder-ceilings/r13-reorder/tools/backbone.py create mode 100644 research/frontier-word-reorder-ceilings/r13-reorder/tools/ceil.py create mode 100644 research/frontier-word-reorder-ceilings/r13-reorder/tools/checkcur.py create mode 100644 research/frontier-word-reorder-ceilings/r13-reorder/tools/construct.py create mode 100644 research/frontier-word-reorder-ceilings/r13-reorder/tools/lift.py create mode 100644 research/frontier-word-reorder-ceilings/r13-reorder/tools/load.py create mode 100644 research/frontier-word-reorder-ceilings/r13-reorder/tools/mipeval.py create mode 100644 research/frontier-word-reorder-ceilings/r13-reorder/tools/poset.py create mode 100644 research/frontier-word-reorder-ceilings/r13-reorder/tools/price.py create mode 100644 research/frontier-word-reorder-ceilings/r13-reorder/tools/realize.py create mode 100644 research/frontier-word-reorder-ceilings/r13-reorder/tools/rewrite.py create mode 100644 research/frontier-word-reorder-ceilings/r13-reorder/tools/sdom.py diff --git a/research/frontier-word-reorder-ceilings/README.md b/research/frontier-word-reorder-ceilings/README.md new file mode 100644 index 0000000000..0caef8f662 --- /dev/null +++ b/research/frontier-word-reorder-ceilings/README.md @@ -0,0 +1,52 @@ +# Lever ceilings on the #4610 round-three productive-helper word (no κ claim) + +Two screening rounds on Cao Yifan's #4610 word (`research/kappa-round3-warp-20261022/ACTUAL-WORD.json.gz`, +κ 0.0030217758). The word is unchanged in the current #5413 caller, so these bounds still describe it. +They say where the remaining headroom is *not*, so that effort goes elsewhere. Unless a line says +"exact", every bound is a floating-point screen and not a certificate. + +## Summary + +| Lever | Result | Where | +|---|---|---| +| Productive re-ranking (finish rank-4/7/8 helpers as rank 9) | loses for every k by strict subadditivity of x^(1−C): dM = f(9) − f(k) − f(9−k) < 0 (4→9: dC ≈ −1.35e-6) | `r12-levers/` §1 | +| Longer controllers, query thinning | already closed by #4658/#4659 and #4664/#4666/#4674 | `r12-levers/` §2–3 | +| Centre merging; query/local climb fusion | worth ≈ +4.1e-5 and +2.8e-5 if legal, but not legal (#4698/#4700; the query temporary shares no frame) | `r12-levers/` | +| One climb per register (fragmentation fully removed, same masses) | ceiling 0.0071457 | `r12-levers/` | +| Reorder freely + re-frame, keeping the ADD graph | ceiling 0.0071108 | `r13-reorder/` §2 | +| **Reorder within the exact commutation poset + re-frame** (dimension-only MIP, HiGHS optimal) | 0.0033076 (free warps) / 0.0032280 (pinned warps); **does not lift to real subspaces** (332 clashes) | `r13-reorder/` §2 | +| **Same, exact subspace LP over full frame domains (3.03M variables)** | local cost ≥ 5251.946 vs current 5253.117, i.e. ≤ 1.17 units per local, **κ ≤ ≈ 0.003107** | `r13-reorder/` §4 | +| Exact subspace MIP on restricted and medium frame domains (forward and backward) | **optimum equals the current word (gap 0)** | `r13-reorder/` §2 | +| One-step non-commuting swaps with exact correction ADDs | 0 gains (1005 + 1466 greedy sites; 36 MIP-reframed feasible rewrites all at exactly the current cost; 153 infeasible) | `r13-reorder/` §4 | + +**Takeaway.** Each of the 632 registers climbs in 3–9 steps, because a scalar ADD needs both operands +at the identical frame. That fragmentation is the whole concave loss. Reordering within the true +dependencies and re-choosing frames can remove at most about 1.17 cost units per local. The helper +frames forced in *every* valid reordering already cost 3458.82 of the helpers' 3464.74. What remains +needs a redesigned helper factorization, not reordering or local rewrites. Our #5462 shows the +owned-relation lever is also at its optimum. + +## Contents +- `r12-levers/` + - `README.md`: notes. + - `DIGEST.md`: a working digest of the productive-helper accounting, with commands. + - `tools/`: `moment.py` reproduces #4610's raw crossing; `marg.py`, `consolidate.py`, `stab.py`, + `regdp.py`, `dimmilp.py`, `dimlp.py`. +- `r13-reorder/` + - `README.md`: model, ceilings, why the fragmentation is forced, and probes. + - `tools/`: `poset.py`, `ceil.py`, `sdom.py`, `backbone.py`, `construct.py`, `realize.py`, `rewrite.py`, + `mipeval.py`, `lift.py`, `price.py`, and others. + - `logs/`: solver logs, renamed `.txt`. + - `data/`: gzipped MIP/LP solutions. + +`realize.py` rebuilds the current word exactly from the poset model and passes both native +interpreters on all 632 arbitrary-input columns. That is the positive control for the model. + +**Running the tools.** They expect a checkout of #4610 (head 9fd59d9b) as the working directory, and a +few contain absolute paths from the machine that produced them; adjust those paths before running. +Python 3.12+ with numpy, scipy and highspy. + +**Credits.** Cao Yifan (#4610 word and native semantics), zxv (#4359 productive-helper paradigm, native +and compiler machinery), Cinna Davis and 1337isnot1337 (#4440/#4441/#4447 controllers; #4658/#4659), +#4664/#4666/#4674/#4698/#4700, Dugongue (#4713), aliromman and Clear1nsight (#5383/#5413). Prepared by +Joel Pulikkan (GamingPuzzled) with Claude Opus 5.5 (Anthropic) via Claude Code. Apache-2.0. diff --git a/research/frontier-word-reorder-ceilings/r12-levers/DIGEST.md b/research/frontier-word-reorder-ceilings/r12-levers/DIGEST.md new file mode 100644 index 0000000000..92425a8a5f --- /dev/null +++ b/research/frontier-word-reorder-ceilings/r12-levers/DIGEST.md @@ -0,0 +1,76 @@ +# Productive-helper paradigm digest (R12, 2026-10-22) + +Base for all numbers: PR4610 head 9fd59d9b08ec (worktree ~/imb-r12, branch pr4610). +Frontier: #4610 kappa 0.0030217758 (round6 compiler tightening of the round-three word); +raw crossing (0.00302177587077, 0.00302177587078). #4635 (Word RAM) 0.0030217754 is lower. +Selected main still 0.00302015 (#4470 / joint-helper-lattice). + +## 1. Accounting (how kappa is computed) +- Saving C solves M(C) = sum_k T_k k^(1-C) - sum_r P_r r^(1-C) = 0 (T = productive targets, P = paid + recursive jobs, ranks = Gaussian ranks / axis counts). kappa = slightly below the raw root after the + strict compiler (paid tensor completion #4416, splitting at c^v, higher-moment tails #4433, + v=1024, c=20, b=21, u=1/5, contraction reserve now 1e-11; finite integer threshold j, H, N=2^H). +- Code: research/kappa-round6-compiler-tightening-20261022/arithmetic.py + `assemble(local)` builds (T,P) from the p16 controller: for each physical event + LOCAL -> T += helper census H, P += local paid profile N; QUERY_SHEAR -> P[1] += 112; + IDLE(stages) -> P[8*len] += 224; diagonal term -> T[1+8*sum] += 112. + Exact intervals: research/higher-moment-strictification/verify.py (E.moment), + second engine research/kappa-rebuild/architecture/mixed_target_probe.py. +- Quick float pricer: ~/imb-harness/r12/tools/moment.py (run from ~/imb-r12 with python3.14 -B); + marginals: ~/imb-harness/r12/tools/marg.py. +- Current invoice (PR4610 round3): local paid N={1:2201,2:412,3:510,4:127,5:40,8:8} (3298 jobs, + mass 5327); helpers H={4:28,7:7,8:47,9:326} (408, mass 3471). Controller p16, a=7 prefix pairs, + 18 LOCAL (full native), 15 QUERY_SHEAR, 15 IDLE, 90 ADD, 16 SIGNED_SWAP; ambient rank 145. + T={4:504,7:126,8:846,9:5868, 17..65 step 8: 448 each, 73:224, 145:224}; + P={1:41298,2:7416,3:9180,4:2286,5:720,8:144, 16..64 step 8: 448 each, 72:224}. + 10,928 productive fields, 64,404 paid calls. +- Rank-mass ledger (KEY INVARIANT): surplus sum T k - sum P r = 752 = + 35840 (diagonal 177408 - idle 141568) - 18*1856 (local deficit) - 1680 (queries). + Local deficit 1856 = 224*8 (main D_s transverse work) + 64 (eight paid rank-8 owned-centre jobs, + no productive credit). Helper/native MILPs (#4470,#4610,#4672) move helper and paid mass + TOGETHER (deficit unchanged); gains are purely concave redistribution. +- Linearization: M ~ 752 - C*S, S = sum T k ln k - sum P r ln r; dM/dC = -247222 at root. + Marginal dC per local-type change (x18 copies): remove one paid rank-1: +7.28e-5; + free helper rank +1 (8->9): +7.2e-5 (but violates mass invariant); paid 4+4->3+5: +5.5e-8; + merge paid 1+1->2: +3.05e-7; split helper 9->4+5: +1.35e-6; drop the 64 centre charge: C~0.00806 (#4659). + +## 2. Structure +- Native local word: research/kappa-round3-warp-20261022/ACTUAL-WORD.json.gz + (canonical: v=112 ports, h=9, 632 start/final columns, 4429 frames, 72 warps, 180 warp edges; + programs forward/backward 21449 ops). 408 helpers arbitrary independent inputs; 1 owned centre + reused sequentially (8 centre calls, rank 8 each). +- Controller (#4440 query-thinned): paired path, 2p+1 stages, full native at {0,2p} u odd, other + stages replaced by rank-one query shears S_y(Q^-1)/S_x(-Q) (1 paid rank-1 per port); idles drop + thin-stage multipliers. Code: research/query-thinned-controllers/controller.py (keep_mask, + thick_stages, inventories, replay_events); p16 pinned in research/joint-helper-lattice/ + {CONTROLLER.json, verify.py:controller16}. +- Boundaries: exact rational L A R = diagonal check over Laurent coefficients (32x32), verify.py. +- LP column generation / controller discovery (#4359): research/kappa-rebuild/architecture/ + {controller_menu_search.py, mixed_forest_search.py, mixed_target_probe.py, controller_tariff.py}; + DP over native/thin stages: research/kappa-hybrid-controller/search/direct_stage_dp.py. +- Helper/native MILPs (#4610): research/kappa-round3-warp-20261022/{line_free_milp.py, + helper_line_milp.py, both_boundary_milp.py} (HiGHS, 1.6-2.0M vars, --operator all --seconds 180). +- Hyperplane-retiming min-cut search (#4672): pr4672 research/hyperplane-retiming/search/*.py. + +## 3. Admission checks (what a new supplier must pass) +all-632-column arbitrary-input replay both orientations (two interpreters); exact Clifford +admission of changed native G maps with absolute phase on 512 columns; warp classes; helper +boundaries; controller Laurent factorization; two rational moment engines; strict compiler + +54 outer predicates; mutation controls. Registered replay: +`python3.12 -B scripts/research_package.py --package research/ [--check-only]` +(PR4610 packages themselves were run with python3.14; joint-helper-lattice is registered). + +## 4. Levers already used / closed +Used: productive helper jobs + mixed balance (#4359), paid target padding (#4416), native tensor +strictification (#4412), p6 native controller (#4414), query thinning p17->p16 (#4440), helper +retiming (#4441), contact span (#4447), joint helper entrance/exit lattice MILP (#4470), +joint helper entrances + native maps (#4610 round3), compiler reserve 1e-9 -> 1e-11 (#4610 round6), +helper621 chart (#4626, does not combine), hyperplane retiming (#4672, round-two only; its +round-three screen found nothing). +Closed (proved no gain): any pair count / split / full-vs-thin mask with fixed profile (#4658 p<=64 +exact, #4659 all p: root < 0.0030217759); independent idle factors (#4664); idle-free binary +controllers (#4666); paid symmetric phase changes on 4610 word (#4696); typed A/B quotient (#4654 +-> #4660, #4674 surcharge >= 8*7^-C); ambient quotients (#4596/#4629/#4633 closed, #4655); +centre rank floor 64 under monotone chart retiming (#4700); scalar trace compression no moment +change (#4692). Active (1337isnot1337, today): centre interface (#4694 640-field, #4698 helper +normal form) -- the 64-per-local centre charge is the dominant waste. diff --git a/research/frontier-word-reorder-ceilings/r12-levers/README.md b/research/frontier-word-reorder-ceilings/r12-levers/README.md new file mode 100644 index 0000000000..4c5a9f0887 --- /dev/null +++ b/research/frontier-word-reorder-ceilings/r12-levers/README.md @@ -0,0 +1,95 @@ +# R12 notes: lever screens on the PR4610 round-three productive-helper supplier (no new kappa) + +Base: PR4610 head 9fd59d9b08ec (Cao Yifan), word `research/kappa-round3-warp-20261022/ACTUAL-WORD.json.gz`, +p16 query-thinned controller (`research/joint-helper-lattice/CONTROLLER.json`), pricer +`research/kappa-round6-compiler-tightening-20261022/arithmetic.py::assemble`. +Frontier: kappa 0.0030217758; raw crossing 0.00302177587078 (reproduced in floating point by +`tools/moment.py`). Tools are in `~/imb-harness/r12/tools/` and run from `~/imb-r12`. +All bounds below are floating-point screens. None is an exact certificate unless stated. + +## 0. Accounting facts used by every screen +- M(C) = sum T_k k^(1-C) - sum P_r r^(1-C); dM/dC = -247,222 at the root, so a moment change + dM gives dC = dM/247,222. +- Rank-mass surplus is 752 = 112*(2 + 30 windows - 15 thin) - 18*64. The local deficit is + 1856 = 224*8 (main transverse) + 64 (eight paid rank-8 owned-centre transports). In every + admitted chain step (#4470, #4610, #4672) the helper and paid masses move together. All gains + since #4470 are concave redistribution at fixed mass. +- Native semantics (from `kappa-rebuild/complex/native_extensions.py::literal_replay`): + - Every paid job is a `climb` of one register to a strictly larger F2^9 chart. Its rank is + the dimension jump. + - A scalar ADD needs both registers at the identical frame. + - Warps are free G-map transports. + - Helper credit is final dim minus start dim. + - Every one of the 632 registers climbs in 3-9 steps; this fragmentation is the entire + concave loss. + +## 1. Productive re-ranking (lever 1): dead +Finishing a rank-k helper as rank 9 adds 9-k rank mass to the targets. The mass invariant +means it must add at least 9-k paid mass. With #4416 padding semantics (one paid job on the +missing axes), the change is dM = f(9) - f(k) - f(9-k) < 0 by strict subadditivity of +x^(1-C). +- Per local type (x18): 4->9 costs -0.334 (dC -1.35e-6); 7->9 and 8->9 also lose. +- Paying with rank-one jobs loses more. 8->9 with one rank-one job gives dM = 17.83 - 18 < 0. +- The opposite move, splitting rank-9 helpers, wins (+1.35e-6 for 9->4+5). That would need + a helper whose output is a product of independent fields, which no native form currently + provides. +- A re-ranking gains only if completion costs less paid mass than the rank it adds. That + would be a new circuit, not a completion. + +## 2. Controller length scaling (lever 2): dead with the fixed local profile +- #4658 (Cinna Davis): exact, p <= 64, all splits, all native/thin subsets: C < 0.003022. +- #4659: all p, all binary full/query masks: best raw crossing is in + (0.0030217758, 0.0030217759), attained by the existing p16. +- In closed form (my derivation), surplus(p) = 112(p+1) - 64(p+2) = 48p - 16. The growth of + S = sum T k ln k - sum P r ln r outruns it beyond p16. + +## 3. Query-thinning of idles and adapters (lever 3): dead or covered +- Idles are already maximally merged paid jobs of rank 8*len. Replacing an idle of rank 8s by + rank-one queries costs 8s*f(1) - f(8s) > 0. +- Independent idle factors: #4664. Idle-free binary controllers: #4666. Typed A/B quotient + query interfaces: #4660 and #4674 (surcharge >= 8*7^-C). +- Thin stages are already priced by #4659. + +## 4. New screens: chart/order ceilings for the redistribution lever +All of these keep the helper census, endpoint dims and the eight centre jobs. + +| relaxation | what is freed | ceiling (raw root) | tool | +|---|---|---:|---| +| single climb per register | everything except register masses | 0.0071457 | consolidate.py | +| keep ADD graph, free order + frames (dims only) | scalar order, warps | 0.0071108 | stab.py | +| fixed per-register order, decoupled registers | frames, warps, coupling of ADD levels | 0.0063826 | regdp.py | +| fixed global order, coupled, dims only (free warps) | frames/warps only | LP: local paid cost >= 5297.54 vs 5316.72 current (saving <= 19.18/local, linearized root <= ~0.0044) | dimlp.py | +| current admitted word | (none) | 0.0030217759 | moment.py | + +How to read the table: +- The first three rows show that the add graph and per-register order constrain little. +- The binding constraint is the coupling: both ends of an ADD share one frame, under + monotone climbing in a common time order. +- Row 4 is the right relaxation for "new warp gauges / native maps at fixed scalar order". + The gap between rows 4 and 5 is what exact-frame rigidity (available G maps) costs. +- A full MILP on row 4's model (170k binaries, 516k rows; LP via HiGHS IPM without crossover, 624 s; primal objective, so not a certified dual bound) did not beat the current word's + cost in 900 s with HiGHS single-thread. Its incumbent local cost was 5318.99, against + 5316.72 for the current word. + +## 5. Other levers considered +- Centre amortization: merge the 18 sequential centre transports per centre index into one + rank-144 job. The fixed-mass ceiling is dM = 1152(8^-C - 144^-C) ~ 10.1, about +4.1e-5. + It is illegal: each centre call reads and writes main data inside its local (#4698 shows + z_out = z_in + h + R_X X), so the transports neither commute nor sit idle. #4700 proves the + 64-per-local floor under monotone chart retiming. The centre is the dominant waste: 1152 of + surplus against 752 actual, and removing it gives 0.00806 (#4659). It is under active attack + by 1337isnot1337 (#4694, #4698, #4700). +- Query/local fusion: fuse each rank-one query with an adjacent rank-one local climb on the + same register, on disjoint axes. The ceiling is 1680(2 - 2^(1-C)) ~ 7.0, about +2.8e-5. + Query copies live in an owned temporary Z that is erased, with no common frame with the + local's climbs. Not realizable without a new native interface. +- Compiler-only: the raw crossing is 7.1e-11 above the claimed 0.0030217758, so a further + reserve tightening could state about 0.00302177586. This is not a lever, and #4610 round6 + already marks it as numerical-only. + +## Conclusion +No lever beats 0.0030217758. The quantified headroom is in climb fragmentation (rows 1-4), and +only a changed scalar circuit or order can reach it, because frame-equal ADD coupling forces +the fragmentation. The next concrete step is a coupled-relaxation solve restricted to one +connected block of the add graph, with exact G-map availability, to locate which registers' +fragmentation is forced by order rather than by available warps. diff --git a/research/frontier-word-reorder-ceilings/r12-levers/tools/consolidate.py b/research/frontier-word-reorder-ceilings/r12-levers/tools/consolidate.py new file mode 100644 index 0000000000..4cd432f32f --- /dev/null +++ b/research/frontier-word-reorder-ceilings/r12-levers/tools/consolidate.py @@ -0,0 +1,18 @@ +"""Ceiling for any chart/retiming lever that keeps per-register climb mass: +replace each register's climb chain by one climb of the same total rank.""" +import sys,gzip,json; sys.path.insert(0,str(__import__('pathlib').Path.home()/'imb-harness/r12/tools')) +from moment import * +from collections import Counter,defaultdict +w=json.loads(gzip.decompress(open(ROOT/'research/kappa-round3-warp-20261022/ACTUAL-WORD.json.gz','rb').read())) +c=w['canonical'];fr=c['frames'];dim=lambda i:len(fr[i]) +helpers={4:28,7:7,8:47,9:326} +for side in ['forward','backward']: + steps=defaultdict(list) + for op in w['programs'][side]: + if op[0]=='climb': steps[op[2]].append(op[5]) + nsteps=Counter(len(v) for v in steps.values()) + one=Counter(sum(v) for v in steps.values()); one[8]+=8 # centres + print(side,'chain lengths',dict(sorted(nsteps.items())),'consolidated paid',dict(one)) + for name,N in [('current',LOCAL['paid']),('consolidated',dict(one))]: + H,_,T,P,_=invoice({'helpers':helpers,'paid':N}); print(f' {name:13s} root {root(T,P):.10f}') + # helper-only consolidation (main chains kept) : classify main as registers with total 8 and start dim>=0 not helper — ambiguous; report split diff --git a/research/frontier-word-reorder-ceilings/r12-levers/tools/dimlp.py b/research/frontier-word-reorder-ceilings/r12-levers/tools/dimlp.py new file mode 100644 index 0000000000..8fb6153581 --- /dev/null +++ b/research/frontier-word-reorder-ceilings/r12-levers/tools/dimlp.py @@ -0,0 +1,66 @@ +"""Free-warp relaxation of the chart problem with FIXED scalar order. +Keep every L-L ADD and its time order on each register, endpoints' dims; +let every frame be any subspace of the right dim (free warps). Minimize paid +concave cost. Gives a ceiling for chart/warp-gauge levers at fixed order.""" +import sys,gzip,json,time; sys.path.insert(0,str(__import__('pathlib').Path.home()/'imb-harness/r12/tools')) +from moment import * +from collections import Counter,defaultdict +import numpy as np, scipy.sparse as sp +from scipy.optimize import milp,LinearConstraint,Bounds +side=sys.argv[1] if len(sys.argv)>1 else 'forward' +Cc=float(sys.argv[2]) if len(sys.argv)>2 else 0.00302 +w=json.loads(gzip.decompress(open(ROOT/'research/kappa-round3-warp-20261022/ACTUAL-WORD.json.gz','rb').read())) +c=w['canonical'];fr=c['frames'];dim=lambda i:len(fr[i]) +s={i:dim(c['start'][i]) for i in range(632)}; fn={i:dim(c['final'][i]) for i in range(632)} +seq=defaultdict(list); edges=[] +for op in w['programs'][side]: + if op[0]=='scalar' and op[1][0]=='add': + a,b=tuple(op[1][1]),tuple(op[1][2]) + if a[0]=='L' and b[0]=='L': + A,B=a[1],b[1]; e=len(edges); edges.append((A,B,max(s[A],s[B]),min(fn[A],fn[B]))); seq[A].append(e); seq[B].append(e) +nv=0; W={} +for e,(A,B,lo,hi) in enumerate(edges): + for l in range(lo,hi+1): W[e,l]=nv; nv+=1 +U={}; cost=[] +for r in range(632): + for a in range(s[r],fn[r]+1): + for b in range(a+1,fn[r]+1): U[r,a,b]=nv; nv+=1 +obj=np.zeros(nv) +for (r,a,b),j in U.items(): obj[j]=(b-a)**(1-Cc) +rows=[];cols=[];vals=[];lb=[];ub=[];m=0 +def row(entries,l,u): + global m + for j,v in entries: rows.append(m);cols.append(j);vals.append(v) + lb.append(l);ub.append(u);m+=1 +for e,(A,B,lo,hi) in enumerate(edges): row([(W[e,l],1) for l in range(lo,hi+1)],1,1) +for r in range(632): + S,F=s[r],fn[r] + if S==F: continue + for l in range(S,F+1): + out=[(U[r,l,b],1) for b in range(l+1,F+1)]; inn=[(U[r,a,l],-1) for a in range(S,l)] + rhs=1 if l==S else (-1 if l==F else 0) + row(out+inn,rhs,rhs) + for e in set(seq[r]): + lo,hi=edges[e][2],edges[e][3] + for l in range(max(lo,S+1),min(hi,F-1)+1): + row([(W[e,l],1)]+[(U[r,a,l],-1) for a in range(S,l)],-np.inf,0) + q=seq[r] + for e1,e2 in zip(q,q[1:]): + if e1==e2: continue + L1,H1=edges[e1][2],edges[e1][3];L2,H2=edges[e2][2],edges[e2][3] + for l in range(min(L1,L2),max(H1,H2)): + ent=[(W[e1,x],1) for x in range(L1,min(H1,l)+1)]+[(W[e2,x],-1) for x in range(L2,min(H2,l)+1)] + row(ent,0,np.inf) +A=sp.csr_matrix((vals,(rows,cols)),shape=(m,nv)) +print('vars',nv,'rows',m,flush=True) +t=time.time() +import highspy +h=highspy.Highs(); h.setOptionValue('output_flag',False); h.setOptionValue('threads',1); h.setOptionValue('solver','ipm'); h.setOptionValue('run_crossover','off'); h.setOptionValue('time_limit',float(sys.argv[3])) +Acsc=A.tocsc() +lp=highspy.HighsLp(); lp.num_col_=nv; lp.num_row_=m; lp.col_cost_=obj; lp.col_lower_=np.zeros(nv); lp.col_upper_=np.ones(nv) +lp.row_lower_=np.array([x if x!=-np.inf else -highspy.kHighsInf for x in lb]); lp.row_upper_=np.array([x if x!=np.inf else highspy.kHighsInf for x in ub]) +lp.a_matrix_.format_=highspy.MatrixFormat.kColwise; lp.a_matrix_.start_=Acsc.indptr; lp.a_matrix_.index_=Acsc.indices; lp.a_matrix_.value_=Acsc.data +h.passModel(lp); h.run(); info=h.getInfo() +print('status',h.modelStatusToString(h.getModelStatus()),'primal obj',info.objective_function_value,'dual obj',getattr(info,'dual_objective_value',None),'t',time.time()-t,flush=True) +cur=sum(n*r**(1-Cc) for r,n in LOCAL['paid'].items()); lbcost=info.objective_function_value+8*8**(1-Cc) +print('LP local cost (approx lower bound)',lbcost,'current',cur,'saving/local',cur-lbcost,'dC~',18*(cur-lbcost)/247222) diff --git a/research/frontier-word-reorder-ceilings/r12-levers/tools/dimmilp.py b/research/frontier-word-reorder-ceilings/r12-levers/tools/dimmilp.py new file mode 100644 index 0000000000..744c08196b --- /dev/null +++ b/research/frontier-word-reorder-ceilings/r12-levers/tools/dimmilp.py @@ -0,0 +1,69 @@ +"""Free-warp relaxation of the chart problem with FIXED scalar order. +Keep every L-L ADD and its time order on each register, endpoints' dims; +let every frame be any subspace of the right dim (free warps). Minimize paid +concave cost. Gives a ceiling for chart/warp-gauge levers at fixed order.""" +import sys,gzip,json,time; sys.path.insert(0,str(__import__('pathlib').Path.home()/'imb-harness/r12/tools')) +from moment import * +from collections import Counter,defaultdict +import numpy as np, scipy.sparse as sp +from scipy.optimize import milp,LinearConstraint,Bounds +side=sys.argv[1] if len(sys.argv)>1 else 'forward' +Cc=float(sys.argv[2]) if len(sys.argv)>2 else 0.00302 +w=json.loads(gzip.decompress(open(ROOT/'research/kappa-round3-warp-20261022/ACTUAL-WORD.json.gz','rb').read())) +c=w['canonical'];fr=c['frames'];dim=lambda i:len(fr[i]) +s={i:dim(c['start'][i]) for i in range(632)}; fn={i:dim(c['final'][i]) for i in range(632)} +seq=defaultdict(list); edges=[] +for op in w['programs'][side]: + if op[0]=='scalar' and op[1][0]=='add': + a,b=tuple(op[1][1]),tuple(op[1][2]) + if a[0]=='L' and b[0]=='L': + A,B=a[1],b[1]; e=len(edges); edges.append((A,B,max(s[A],s[B]),min(fn[A],fn[B]))); seq[A].append(e); seq[B].append(e) +nv=0; W={} +for e,(A,B,lo,hi) in enumerate(edges): + for l in range(lo,hi+1): W[e,l]=nv; nv+=1 +U={}; cost=[] +for r in range(632): + for a in range(s[r],fn[r]+1): + for b in range(a+1,fn[r]+1): U[r,a,b]=nv; nv+=1 +obj=np.zeros(nv) +for (r,a,b),j in U.items(): obj[j]=(b-a)**(1-Cc) +rows=[];cols=[];vals=[];lb=[];ub=[];m=0 +def row(entries,l,u): + global m + for j,v in entries: rows.append(m);cols.append(j);vals.append(v) + lb.append(l);ub.append(u);m+=1 +for e,(A,B,lo,hi) in enumerate(edges): row([(W[e,l],1) for l in range(lo,hi+1)],1,1) +for r in range(632): + S,F=s[r],fn[r] + if S==F: continue + for l in range(S,F+1): + out=[(U[r,l,b],1) for b in range(l+1,F+1)]; inn=[(U[r,a,l],-1) for a in range(S,l)] + rhs=1 if l==S else (-1 if l==F else 0) + row(out+inn,rhs,rhs) + for e in set(seq[r]): + lo,hi=edges[e][2],edges[e][3] + for l in range(max(lo,S+1),min(hi,F-1)+1): + row([(W[e,l],1)]+[(U[r,a,l],-1) for a in range(S,l)],-np.inf,0) + q=seq[r] + for e1,e2 in zip(q,q[1:]): + if e1==e2: continue + L1,H1=edges[e1][2],edges[e1][3];L2,H2=edges[e2][2],edges[e2][3] + for l in range(min(L1,L2),max(H1,H2)): + ent=[(W[e1,x],1) for x in range(L1,min(H1,l)+1)]+[(W[e2,x],-1) for x in range(L2,min(H2,l)+1)] + row(ent,0,np.inf) +A=sp.csr_matrix((vals,(rows,cols)),shape=(m,nv)) +print('vars',nv,'rows',m,flush=True) +t=time.time() +LPMODE=len(sys.argv)>4 and sys.argv[4]=="lp" +res=milp(obj,constraints=LinearConstraint(A,lb,ub),integrality=np.zeros(nv) if LPMODE else np.ones(nv),bounds=Bounds(0,1),options={"time_limit":float(sys.argv[3]) if len(sys.argv)>3 else 600,"disp":False,"mip_rel_gap":1e-6}) +print("dual bound",getattr(res,"mip_dual_bound",None),"fun",res.fun,"(+centres",8*8**(1-Cc),")",flush=True) +if LPMODE: + lbcost=res.fun+8*8**(1-Cc); cur=sum(n*r**(1-Cc) for r,n in LOCAL["paid"].items()); print("LP local cost lower bound",lbcost,"current",cur,"saving per local",cur-lbcost); sys.exit() +print(res.status,res.message,'obj',res.fun,'t',time.time()-t,flush=True) +x=res.x; P=Counter() +for (r,a,b),j in U.items(): + if x[j]>0.5: P[b-a]+=1 +P[8]+=8 +print('paid',dict(sorted(P.items())),'mass',sum(k*v for k,v in P.items())) +H,_,T,PP,_=invoice({'helpers':{4:28,7:7,8:47,9:326},'paid':dict(P)}); print('ceiling root (fixed order, free warps)',root(T,PP)) +cur=sum(n*r**(1-Cc) for r,n in LOCAL['paid'].items()); print('current local cost',cur,'relaxed',sum(n*r**(1-Cc) for r,n in P.items())) diff --git a/research/frontier-word-reorder-ceilings/r12-levers/tools/marg.py b/research/frontier-word-reorder-ceilings/r12-levers/tools/marg.py new file mode 100644 index 0000000000..df9ec56790 --- /dev/null +++ b/research/frontier-word-reorder-ceilings/r12-levers/tools/marg.py @@ -0,0 +1,15 @@ +import sys; sys.path.insert(0,str(__import__('pathlib').Path.home()/'imb-harness/r12/tools')) +from moment import * +import math +H,N,T,P,word=invoice() +C=root(T,P) +f=lambda x:x**(1-C) +print('surplus',sum(k*n for k,n in T.items())-sum(r*n for r,n in P.items())) +dM=sum(-n*k**(1-C)*math.log(k) for k,n in T.items())+sum(n*r**(1-C)*math.log(r) for r,n in P.items()) +print('C*',C,'dM/dC',dM) +def dC(dm): return -dm/dM +# per-local (x18) moves +for name,dm in [('helper 4->9 alone',18*(f(9)-f(4))),('one paid rank1 removed',18*f(1)), + ('helper+1 rank 9',18*f(9)),('paid 4+4->3+5',18*(2*f(4)-f(3)-f(5))),('paid 2->1+1',18*(f(2)-2*f(1))),('helper 8->9',18*(f(9)-f(8))),('helper 9 -> 4+5', 18*(f(4)+f(5)-f(9)))]: + print(f'{name:30s} dM={dm:.6g} dC={dC(dm):.4e}') +print('frontier gap to beat (0.0030217758):', 0.0030217758-C) diff --git a/research/frontier-word-reorder-ceilings/r12-levers/tools/moment.py b/research/frontier-word-reorder-ceilings/r12-levers/tools/moment.py new file mode 100644 index 0000000000..4eda8ead34 --- /dev/null +++ b/research/frontier-word-reorder-ceilings/r12-levers/tools/moment.py @@ -0,0 +1,26 @@ +"""Reproduce PR4610 p16 moment invoice; float root finder for screening.""" +import sys, json, importlib.util +from pathlib import Path +from collections import Counter +ROOT=Path.home()/'imb-r12' +A=ROOT/'research/kappa-round6-compiler-tightening-20261022' +def load(path,name): + spec=importlib.util.spec_from_file_location(name,path); m=importlib.util.module_from_spec(spec); sys.modules[name]=m; spec.loader.exec_module(m); return m +sys.path.insert(0,str(A)) +ar=load(A/'arithmetic.py','ar') +LOCAL={'helpers':{4:28,7:7,8:47,9:326},'paid':{1:2201,2:412,3:510,4:127,5:40,8:8}} +def invoice(local=LOCAL): + H,N,T,P,word=ar.assemble(local); return H,N,T,P,word +def margin(T,P,C): + return sum(n*k**(1-C) for k,n in T.items())-sum(n*r**(1-C) for r,n in P.items()) +def root(T,P,lo=0.0,hi=0.5): + for _ in range(200): + m=(lo+hi)/2 + if margin(T,P,m)>0: lo=m + else: hi=m + return lo +if __name__=='__main__': + H,N,T,P,word=invoice() + print('T',dict(sorted(T.items())));print('P',dict(sorted(P.items()))) + print('events',Counter(e[0] for e in word['physical_events'])) + print('root',root(T,P)) diff --git a/research/frontier-word-reorder-ceilings/r12-levers/tools/regdp.py b/research/frontier-word-reorder-ceilings/r12-levers/tools/regdp.py new file mode 100644 index 0000000000..0d1aefdbb6 --- /dev/null +++ b/research/frontier-word-reorder-ceilings/r12-levers/tools/regdp.py @@ -0,0 +1,35 @@ +"""Exact decoupled ceiling (valid upper bound on root) for any chart/warp lever with FIXED +per-register scalar order and fixed endpoint dims: each register independently picks a +nondecreasing level sequence through its ADD intervals; cost = sum f(climb sizes).""" +import sys,gzip,json; sys.path.insert(0,str(__import__('pathlib').Path.home()/'imb-harness/r12/tools')) +from moment import * +from collections import Counter,defaultdict +side=sys.argv[1] if len(sys.argv)>1 else 'forward'; Cc=0.00302 +w=json.loads(gzip.decompress(open(ROOT/'research/kappa-round3-warp-20261022/ACTUAL-WORD.json.gz','rb').read())) +c=w['canonical'];fr=c['frames'];dim=lambda i:len(fr[i]) +s={i:dim(c['start'][i]) for i in range(632)}; fn={i:dim(c['final'][i]) for i in range(632)} +seq=defaultdict(list); actual=defaultdict(list) +for op in w['programs'][side]: + if op[0]=='scalar' and op[1][0]=='add': + a,b=tuple(op[1][1]),tuple(op[1][2]) + if a[0]=='L' and b[0]=='L': + A,B=a[1],b[1]; I=(max(s[A],s[B]),min(fn[A],fn[B])) + seq[A].append(I); seq[B].append(I) +f=lambda x:x**(1-Cc); INF=float('inf') +def dp(r): + S,F=s[r],fn[r] + best={S:(0.0,())} + for lo,hi in seq[r]: + new={} + for l,(cst,pr) in best.items(): + for m in range(max(l,lo),hi+1): + v=(cst+(f(m-l) if m>l else 0), pr+((m-l,) if m>l else ())) + if m not in new or v[0]l else 0),pr+((F-l,) if F>l else ())) for l,(cst,pr) in best.items()),key=lambda t:t[0]) + return pr +P=Counter() +for r in range(632): P.update(dp(r)) +P[8]+=8 +print('decoupled ceiling paid',dict(sorted(P.items())),'mass',sum(k*v for k,v in P.items())) +_,_,T,PP,_=invoice({'helpers':{4:28,7:7,8:47,9:326},'paid':dict(P)}); print('root ceiling',root(T,PP)) diff --git a/research/frontier-word-reorder-ceilings/r12-levers/tools/stab.py b/research/frontier-word-reorder-ceilings/r12-levers/tools/stab.py new file mode 100644 index 0000000000..19389269cc --- /dev/null +++ b/research/frontier-word-reorder-ceilings/r12-levers/tools/stab.py @@ -0,0 +1,33 @@ +"""Exact per-register ceiling for any lever keeping the scalar ADD graph and all +endpoints but freeing scalar order and frames (free warps, any dims). +Each add (A,B) needs A,B at a common frame of some dim d in [max(sA,sB),min(fA,fB)]. +Register cost >= min over stabbing chains of sum f(gaps). Sum + centres -> root ceiling.""" +import sys,gzip,json,itertools; sys.path.insert(0,str(__import__('pathlib').Path.home()/'imb-harness/r12/tools')) +from moment import * +from collections import Counter,defaultdict +w=json.loads(gzip.decompress(open(ROOT/'research/kappa-round3-warp-20261022/ACTUAL-WORD.json.gz','rb').read())) +c=w['canonical'];fr=c['frames'];dim=lambda i:len(fr[i]) +s={i:dim(c['start'][i]) for i in range(632)}; fn={i:dim(c['final'][i]) for i in range(632)} +iv=defaultdict(set) +for op in w['programs']['forward']: + if op[0]=='scalar' and op[1][0]=='add': + a,b=tuple(op[1][1]),tuple(op[1][2]) + if a[0]=='L' and b[0]=='L': + A,B=a[1],b[1]; I=(max(s[A],s[B]),min(fn[A],fn[B])) + assert I[0]<=I[1]; iv[A].add(I); iv[B].add(I) +def best(A): + lo,hi=s[A],fn[A]; need=[I for I in iv[A] if not (I[0]<=lo<=I[1] or I[0]<=hi<=I[1])] + pts=list(range(lo+1,hi)); bestc=None + for k in range(len(pts)+1): + for X in itertools.combinations(pts,k): + if all(any(I[0]<=x<=I[1] for x in X) for I in need): + ch=[lo,*X,hi]; prof=[ch[i+1]-ch[i] for i in range(len(ch)-1)] + cost=sum(p**(1-0.003) for p in prof) + if bestc is None or cost2 merge worth +3.05e-7 kappa (both orientations). +- Pure commutation cannot move them, because these ops are rigid in EVERY linear extension. + Stage 3 would need non-commuting rewrites with correction terms. Examples: + - `A+=cB ; B+=dE == B+=dE ; A+=cB ; A+=-cd E` + - `A+=cB ; D+=eA == D+=eA ; D+=ec B ; A+=cB` + + Each one adds an ADD with its own co-frame requirement. In the h300 case, the correction + `h300 += -c h301` can sit at frame 0, but `h300 += x19` then needs a common later frame of h300 + and x19. That cascades through h300's readers (h295, h490, ...), which need x19's contribution + co-framed. Section 4 tests one-step versions of these rewrites; none gains. + +## 4. Wide LP and stage-3 probes +- Full-domain exact subspace LP, forward, fixed warps: optimum 5251.9459 against 5253.1170 current. + This is a valid bound: any reorder plus re-framing of the existing ADD program saves at most + 1.171 cost units per local (linearized dC <= 8.5e-5, so kappa <= ~0.003107). + - The integer MIP (3.0M vars) does not get through HiGHS presolve probing. + - On both restricted families it equals current, with gap 0. + - The LP slack is presumably fractional path mixing. That is not proven. +- Greedy correction-rewrite screen (`tools/rewrite.py`). Each candidate is a one-step + non-commuting swap with an exact correction ADD: + - x is re-framed on A's visited frames; + - the correction is placed on common visited frames ∪ {empty, full}; + - each candidate is scored by local chain cost, then by full `synthesize`. + + Results: 0 gains on all 1005 single-op helper intermediate visits (forward and backward), and + 0 on all 1466 single-op visits including main x/y registers (forward). +- MIP-reframed correction rewrites (`tools/mipeval.py`, medium-domain exact MIP over the whole + rewritten program), on a sample of the first helper sites. Each feasible rewrite re-optimizes + to exactly the current cost (gain 0). The majority are INFEASIBLE: the correction ADD forces an + empty frame interval (lows ⊄ ups), because it couples two registers with no common admissible + frame (e.g. `h224+=x0; x0+=x27` gives the correction `h224+=-x27` across two port lines). + Counts: 36 feasible (all gain 0), 1 MIP-infeasible, 152 interval-infeasible (sample of 30 sites per worker x 5 workers, stopped early). + +## Next steps +1. Multi-step correction rewrites. One-step swaps are either infeasible or neutral. A gain needs + a coordinated rewrite of a whole helper thread, e.g. re-associating the sum carried by one + helper so that it reads its port lines in nested order. Evaluate with `construct.py` medium + (~20 s per program) and `realize.py`. +2. Close the LP gap of the full-domain model (1.17 units/local) with a decomposition. Per-register + gap paths link only through shared op frames, so Lagrangian relaxation of the shared-frame + rows is natural. This would either prove that the current word is the exact optimum of + reorder+frame, or locate the fractional slack. +3. Resynthesis of the helper network, which is what the stage-3 brief describes. Fragmentation is + forced by the order in which each helper's accumulated span grows (port lines in, + hyperplanes out). A new design must choose helper factorizations whose spans grow in large, + shared steps. + - Any accepted single 1+1->2 merge on both orientations is about +3e-7 kappa. + - Packaging: `realize.py` replay, phase check of new paid pairs + (`warp-interface-20261022/verify_candidate.phases`), round6 strict compiler. +4. Free warps jointly with reorder: the dims ceiling rises only 0.00323 -> 0.00331. diff --git a/research/frontier-word-reorder-ceilings/r13-reorder/data/cons-backward-medium.json.gz b/research/frontier-word-reorder-ceilings/r13-reorder/data/cons-backward-medium.json.gz new file mode 100644 index 0000000000000000000000000000000000000000..dd85cd676484c7ec0d47985a7fb7f65a552da895 GIT binary patch literal 51499 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�>lc|DGB60)L4)*o=SA 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 RtXQmdjH*lWJS`jk^FPt9OOF5m literal 0 HcmV?d00001 diff --git a/research/frontier-word-reorder-ceilings/r13-reorder/data/cons-forward-medium.json.gz b/research/frontier-word-reorder-ceilings/r13-reorder/data/cons-forward-medium.json.gz new file mode 100644 index 0000000000000000000000000000000000000000..9d11bf5f7ac727ecfd38a367417fcee687f20102 GIT binary patch literal 51498 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 literal 0 HcmV?d00001 diff --git a/research/frontier-word-reorder-ceilings/r13-reorder/data/cons-forward-wide.json.gz b/research/frontier-word-reorder-ceilings/r13-reorder/data/cons-forward-wide.json.gz new file mode 100644 index 0000000000000000000000000000000000000000..cf90a49cfe704eac282988dfdb1399242590acca GIT binary patch literal 53888 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 literal 0 HcmV?d00001 diff --git a/research/frontier-word-reorder-ceilings/r13-reorder/data/cons-forward.json.gz b/research/frontier-word-reorder-ceilings/r13-reorder/data/cons-forward.json.gz new file mode 100644 index 0000000000000000000000000000000000000000..3ca1746b60a805a2cd66b35f796450672fa74dc8 GIT binary patch literal 51480 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 literal 0 HcmV?d00001 diff --git a/research/frontier-word-reorder-ceilings/r13-reorder/data/mip-backward.json.gz b/research/frontier-word-reorder-ceilings/r13-reorder/data/mip-backward.json.gz new file mode 100644 index 0000000000000000000000000000000000000000..a58290315c66d651c97fe9984634941f6258ab41 GIT binary patch literal 44806 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 literal 0 HcmV?d00001 diff --git a/research/frontier-word-reorder-ceilings/r13-reorder/data/mip-forward-pinw.json.gz b/research/frontier-word-reorder-ceilings/r13-reorder/data/mip-forward-pinw.json.gz new file mode 100644 index 0000000000000000000000000000000000000000..6da817e9aed1072dce5442ea50fcf7c2ec2d9e77 GIT binary patch literal 44816 zcmeHw30zah_J1v{)IMwcxi1*BE!bMYC1sN=R_j7hQ7fXdX zfIuR3!GanUS)wEnsVoH&1p@++fP{oK0Rmh?Nb;W>5K#2BeXp-?`SZD#nKNg$Gv}Uj z<~xHQG!1?4J@tl4ueXi7_aCy@NAL^S<+sP;(0-o)OD`h9=dE?mFgF%*qpZt*evf5w zaR%S{d<2^Gw)ESMNxfNdp&Lwp3OkkCsyP%LoARMfqVJ+F^Q%<&@U<|Uj-GZphqg`i3)nEg2XDQ zMg>WG$bMqItDb2>a|-9r&yz&gDGS;S>^_X0o*7Sb5@<|wB+)8mff|zbk^OW7>>K>~ z<&x-TWx-+nWF6U0i{a>)ZZxNUwnkZ?g`|M3$8eN-m5wQvhaN4Y@<9EO@yvdx`^RlUjU@;|s~jAk5Y^3rl zeSLiu9Rba{+PiiUajMJ_NnJ$UbzdUVM*dQw)Abtl^}Wlp>ieL3%~Q`^v=iDn-Si$A z+DA|)Lzl4Bt{^keuOz>2e-2jg+L?~*1p0!zk4SdMp9Jc9jc{?QZEM(Xnu;d~$jB`w ziR1G|Bz-0yCVZ$|(jh|=1ga59#Kk7CWTuUrG$N@*Qx1sZ<;A4x!DN}Qy`Mc1M_0J! z+^XVKWmgqcJ=P44nHt|h0HSBv2}dLc%jvM_uah8ePCd}l$Sz=*!~b^|XlbO-V3_9g z!>$p zJ{31AgcwcPq0%FwBjrabcy{bK)!l*QNG!0>*Gh08Yf0vts<`LgRMp)4EbnCzhUCXB z+LpD8!`|j2(8#g~Ba*-{B2X1nOp?5s1O&SHzo{x{9<1Qk_98V8uOg?&(#}I(9@j{z z-B~;CS!KDYjubbi#i@99%AurPrvP7h7-OiaE2`~HRcxEn@Fy7|I1o#prRe0Tcx_pB ztT+{CL{fJdwri}7oH!z>EpB~NRbvkC>xb|1E7vZr9>LaqcST-KZQU`Za zmfy3Ythi?+DL7b+Flo8uZDrp5I2EXdWPN0!j%%l{j;9d>d>c6! zOWB^?4ov7J*07c**ymw+UfZ)+Z9`qg1^zfN(uijDnilYJU!CwpGjG#laL9X;TsEvt$GT%|_0T zQ%Q=|N?Bh3QFqTy|14hbBcSEU_3+5US;JaRKa~wHX|VOMD$v6*vKH25|3EKSfgV#W ze8Gy~IYv~09o=s`>~6Q=~vV> zpPMpeMo%a|oJVX{{hVj}^J)?0=6QsRYRm!bo?_$c>YG-knX;ATl-_yH$z!ZdAIL(U zQf9;<_NWpMVq=Qwsp_NFEYdp+uWQA|>FP(;reax673F9g!dLZ$54NZnZ@T!(tRt#g zA8buAJxhJT#`GR#tCA}OMne5m@O3dw|evWy!r zE0ptsA|8_?t1osUuRyk3<0i~zWnxf-hM7eGx+PpdPMq8|FLZJW50@d7|WE4>A|B%U2|?KBdNx%_6H@$G!vc$wDEGFIro(lgN@tm+n)xJ z$JGZc=I5yAJW@sm8+X~a$5b14@seHA^184$q0?MMEA^l@yLB`%R}h1&`)b>$0BS4^Rq)H zAdj@&51}K`JvFt)h~7SxE)+WA>*czDmz-Sti68vdf-FFt9!8GYt?_7p@?;PQtn7a+H^-#lr&72VaR5PCfL47sy?VyN+UbkXx;(-3Ka zHy`F$AP==ih8nx0Tb>`Aj^GBiJ1uw+Dx_t{(bM!(=x?RFK0=s~8uCNdAh8{9 zMbRVCKS+0djQE)JNkNDMazn?_DEb-nRp~A>#6r@y1tE?|kB+yZ=`rYh=`M4`=cHb> zbDb(RR~`^1M9gM+TJvz;TUyn=b*koExjd|U($S8IXN(ik=db{A0d@@7ZmS>x;IgZ0NgL%5UL ze$8<~-tU-r&iEGkRQ<7qh`pr6g*n@ik2)gH8KNTF-s6X zk~S9Qe1n{!dK6=vhepfBEJd6qMHc1kL4Kmz7;6mg2V+o(Skj}SoP9`J)uUKrA(|o^ z^Eo1sG_e>ZBwS{hI^y`}f`cu!eIC8)>`qPSei2i$4u?CR&Zs$0FGt^(&9g?_CdCvR zc_Y14JLBk8=o;BP8^m4G(_$k6GDuYuN0*@AlFze6JRr>w82KVks&>ZH>(F!M^Xw46 zlC}wqh{*G*ns~Y#y<9$T8KQ&~BQQFQOjhkopf{s;%IDc5DoIZTsZR9CN6)F$e`IP-sL!K3C0U(becj@axXXiy2Jhc&EuHlKz%cdZM;5r_K7Cjjj71?p$xkGH z^j>L53^KQK`4#$7OiW|#I>fg@YfD4UBg;DPU!hxLG8=2xBMt@qP#O}ClyxpoqA$Zd zZLHmZ2n@EYEkb1@Z{MOZ&WN9bHi~kRk=wc+B^$e7vYN(hMcfLC6y;n)e%rM% z#n=@iZW`l)-~>Gq<=j99c0Ecl_QdoxjoF6C4w_h&a})VP*T!qcyD=usW40p-f;N`r z+(yQ9J-TL$$Do_X>_9vYiY&{ygS^_c@w)K=j9c>&65OrFo1S zqBdw^c}^xWziZlRTf4E^ca^(RJrkP|#}3 z`ismPn+R1`lL%*WH#y0#CLMlKYTvXU+2tP*RJjJDy~rH9dD&WDb~bk`G)sKo&=Ap1 z3bOMue>j3avgLn1$Cv5jPq1GmVxI7KT5~ta>{)5FV*gi=|7CJzNrj`Jbfz^^5s+Nr zm|0%q5kmezVf7zQge9@+OCNPKeyhH7hZ3{{yWWCz6?{~QtgjY`xj6u z_h6|@S*v56l8Ta?Wu>2~_McPx7g8$sVzo=BhtfSgr zK;0q7a)}ZdCmGX9Wa&6gM$eK$6s0T5Js$k`I>i%|QOE2COG+s zm^Z{uu8O2ZP-#rnZ+3nui2NSi|7+T4*8$)?ES&xBS+xFYT4f)Os$;FzJ0_WO zCA@=s$wmLHH4l!XS@&_!>PZ;XkIcj`gC8W#*CYb@t@k1g=T|fYd+YNP~KP6OpTo{qo?V+W&+dH(1#D z3!d^Eg=?RAp=aGj%IZ(Bs41*@CxufU2Aq11TJw1BLwwY8)K~4XmwU#4O}X+Zwr&cG zbW*r{)#Rz1a;Zl&dA-8wH;G~)s$3ki>UXsKJ)`|qZO}shvH*07m+)vAenm6tr>@w? zz2o;&uiU}z-q8voj~}~$YYv_NpCtC7Q7l%XQ27KeVseDS8acj0h3ZwuYWv31(t%g} z$F5vmbdq-BA+Gc}%eP&a)q~&JhgzbWIa6PBigqFw_jMiXR=ZH#gFn=VveV6+qb~}l zoyfzL*0I{#g?&BvqkX6^bTjAaiy~RCT_2-lLx1*k2$*aiAiXKAuuaUu1rf)3%gYJ7Sh%1sw*sXxV_$qI2sGS)bi z@CP+Mw-2>P7rRt{DwZZI!iC6K4l3bQHNLD5bx;>;tv?kVTwW#lPu`Bea5^1tW zxR3^xL#ObQUi>sI>Xa^awf@va`S0}CzskdYZ~PdQXY|AU<|Z?0B%?<17a2(?*+P+) zS^nH(lo(aQs3nYg!KfFEdcmj{jC#R;ofpKBy%lMka+${{F{*@7OBnTnQ7;(vf>AFR z^@9I8FQAj>C=O?q*LwT~gq%gj=+E)*^|828e*LZSg?APfrkfO|ZMp6|TeLcDllPWk znX|XEt7vQ5P^L-lc5Y3nbV*}-d5U<+RA&PtsnRKp<%JUkCu_H8e(wIdHK|g$RU`M% zyCMs3t}DEKu<({!A^Wn|nzW0Rn_90P*33)lV^sCRUVzs8J5_5APC za{^7#)#sYL5BxKLKkym$D?K=WT;_ys#o7PS2!W^M&6N1&2E^ZDoKo7>*$aBYQM|fC z>>Ta{XqmWqlo(aQe}N@fLU+Z@e(XZ-UqIXlW~WG+o1nYB-2YDc6FNJUPY- z{QG85sP`D))_XuKveu;-{447>>QW=*%J_SGCFl0KhS%>1w$KM3xWlh<@up?4D|J4e zY1(HzFU>uws5?ND+^Xz$u9CE-q#GKnN!w_#$MDIyuZspUUXdENa!anCUIbI}WJt73wP-b*@Oq zaXl>VC7ng#ZHqiV3;wYC5yzox4*1^Vm1_?8-h7MbQ(rm$!6b>FtG8ehY!}etxm8fx8?~?9)C}>xgW`>`g;_(XWZrvsO4Sz2oIxJ&c`d23f;9F}m`kq}TI{ZCZ z{=TI48+0!&ClmI!U$-xP?iz6AVTNK|D1lRV#(u+ZCjuY_VdilE74vQN;$~W*W;(c5 z)e=YxbCy~Zc9>siG26T7Q?f&aje1y6}%&vfj0 zr}XfFBk||wB<;)lxx&|LBpEB`R*$HTzjOYj=e0dwKb|_XoR;TcAAQ8UbzNob9n}7S z5(Pwvk05IUPT9#!4uoU!PdA}UH>PPfIB{Q|okZ^=!MriSMW>s4ABjiV z4|Pbbi?8q%wAkWb&o+g6mA3oICEpA_&owrJJg&}Occn`nC{K}uHPw0O=aid3CcDEW zxH0&<(shjZ#we7#-xWuJe?hFJU8&ih!u)$;;$=}NVnHlNTIA-p&(aRXh>vv?6qyaO z1#W(LOAd-5j&)QNnFYwA?1=>l9O<9PPOTGH_$pd#1CGSo+Y1ur$OYj-cyun&}Y zfhWlD9~DmA(=l`mUsr%-zpEs<{{w%9T4 zs_laH?_@Pb*|>LHajf<)h_fV>ni1|w*E9YU=Ds{qYF$=^Z*_|;;YhrVy&!Imyf|Fd z&yIDhE;1v?qHKr-aU5x}TgN_25{i-aPq6oho9945dE9DWcEE3u(4ZWz6HhWnuB8OT zL#k)K)xv;067J0m)cyk{WtXlyxWfLlzViGXD+8m|L8Gu$%J0=>v6SJeV4l4|qkbbJ z=FY26{GAt1pJuk4DsJZ2#nvU%X^_qM@B`uGa2oCH>dbN*MOPS^TIV5oiG)g{%Z5FJ z!4+R3xRmfB+9tee9x#JYQhkZ*K#uMDEyeU`cAWXJmCH zI9B%x%m`F@RK|;H)~o9uP>53{^9}~YjP6UV4pq_V^SxoltBZxp{mTWaDg)|n25Rd9 zs_#|U5~u<389;lk;0s(Is7^7zKKz+~eZ(`coxm%8P5;*oKg?BLEPa?R`h7=lQ2mm; z_}#^~>p$v*|1~yvwjD7DvQj>vM3C( zfXUe-bi0kWtUxhZVja8xVYaw=Hq@KT<@vG+ze&=-hv3@_s#5EIX|Y{mzo966@*gH| z^&7yDMOgoVaZX2{8+f)x8y*SY7pv%!+>$*dqKR3=KApDPm#v3)o>yIBda2nG_oa%i zhyD)h7{B~8$-vU1Q|qKHws!U#1mQ!ZTNH{REi$tsItcz*vfw3;e!ZW+;Cc?1VVF37 zfMmW13$X)Xq4*DU4yHNvh#=^DPwF7?fi{JmNb9odWb;nwsNw^Z@PP1vujO0pD_kOr z0bgs}j5pby*WF839RI0gBz7G_pq4+!I(o^X&T}s9`)5h8ETOH@oQk~Nc7kbamz1>hCN-Ex?TgcC3kw2J)Vp{`x|x&yId1uxK$q0u!?wzyI54m?z>FbyIYjxDjC^2(H2i5& z+5|`j!S8Qi**8Gkem18cFuhnR*8#wmen>rH)Yl<9t&Z7tPa>Hd4B>|(gI)vv(ud<= zUkGaoW*zTTK-2fVOfEy}B{VWB=vEr4Ac~BI&fGhRzTf||A9TjG9kt)UdnQ|h;YZMw?8%gi|iDN}4&1;T4oWE?(97SMeU2XWF$U`eI zhja<2A<-iA%maOWp z-t=hIX{kBKALQ-Y3k^^aH8%7+&L>eCbLcYTJCBpkc@L?LmoG4W3S@;soczm-pEv}f z#GK)AQpPI=HQ)NhxdnYXfm5_rHBl@v%WsrQ#HXt;XeH;EX=ccf2a z7*V{hdKWaNTw?zo!cQo4R=nh4OdQ|A(~Nqy)49ZDX1^6W!sVh31ubV_CdgWR4NZzR z6_^;>fvjlLFqUXWou1V%!Yq6rSw_9WJ~2zrBmv&zTs^MTr7nynl$N-x3^!yBo*&rj zFwrBtiu+B24rKdqXoaZLS8{D%Ty4ml9|M-G#*`0 z#xG!;0~6$hu`i;XI|zl*nzO6#|F>w-< zM4}Aw2^R7>a-xpS)(H-Hs60Kj)CBQ!d2$bDfnTU*8b{ydOcUt4L<8YZpvS=lj-9E1 zq3T?1S}o7fPy$&92qT6LNph$Igp&4cBQXC(5LXQOdG;nZrbJxSkw3t>FvM#tsiID2 zTrjgSC0GpkO7f_t5LJa`85S&t>XP*!%m->IGz9ff=cVn;{!@#4PkKc)8&ow2!YOCg*8=>^Dna}s6=*Pj%7tIbafN_*SeMU z8nRjkb_wV*8|$V~7Ew*P*%WwT6}kXVSxQ8uPO}Urqy!(1Wm~F5+E}G>FYj)V3xjtT zXRw?k8%1v|8q&^H@QH_*{OOid&=MP^QCczBPEH=ZO(k&KPSItyLdJ{JEcJW_Gy)km zJ%+l;uzeI#4mYOE297q+5Sy=2_CfY1`EuDh1;p46yf2uR&;?}yi_(UbNl+Xxzq)Cu zr@Ji0RcZ}+D;z!D;fcVesL*J&parDWooLnz>EawJpD*ntn?srdH-IeyyLXeNkn_1& zLWbBLqrO!`!|P0*JulL%^L*y0sHg7Z^~SXEQA(6bL={8r#I8(b9j{Y_o=nmftvpQ= zM%zcM(qW7}op>JcapfkwV7ur-xeMWRA*E{?=QBH@B*b)~E&zBMn+2&KyF~DUKK7>-cS!p{5sKxV&ohUEPKY=rSU0hQuj*78pVlYHmB$eu>Ftg2 z)p%J-9;K@xB@b)sv`MFra)|1I3)T4eL6A_{+oJ-8vOypfP||{}Ii)Vm_-Ftll*B`l8Xn5?I#5j4 zWN9#KVh0Gw6a4syacT^kN4^1q;Ok04V^=-+@!9MZNoh z13(#SowY-4T0%jB&_E@~76u>?=}$CRxL@Db4Ut@Z1G<1>Nq@Q(*rZY;Z-Qq8kg zi9DoBJ-uZqT+SkDT4M@^<$1lBk`~JbHT!s#MJ{n_FkBq3Ql+6D0OJPp35E&cc<1Ho z^kuEDZjggG_cGfW9&dfWJYaxMkx#X}ef$9%r7G}5S{~{ehPkU1lq2xl$mpEPx|wBI zDRN-t^Pot_VI8mZk3|Jg7^~30&K#i`BK+jgX_q49N9-8M8jmIXh^%jdO-T>?upKAW zRO!@CQC@~V0qmKa-k$COl&mI&JNM&cA?xB(IKYD45^QRFc_$6P9!A71A=%g&oz9Cr z-=$9NbbjQLO_^E*Cx&otE|Ewz_QR)=8aA`w8z%>$K7;pu?}CPu3+(TB@5@ql!ij+% zWR4(Cf=@iWSMP!t_IGM8Buz_}$<^(uz8+F=pIy+fch;i2vM-(vhx8mmiOV3S0))z0 zpqjk(_xubVY;5xP^1hO#>@i(84BN%BqtpvVB!0oBcre9Mc%Fe|FNmUNi(ZnUAK(>W zV<^FA2j7+uQl_$&N7o<~uvaTpz#2Q+u%6X&VBAAz9!t3MZG^dI=TI`RLX|Qk3$p>A0I0xV$>cx5Ty@C-GeM{`}3UZBF#D4Kq(0dGSODb6Djm8}A7QD0cH zGNyx<>fGu4*kzUHRH`#2`1S9L23Ckh9fl}@V;j7E4?E|9FoppZuI@|j>3d(o!}7Gs z=HhY^SUZa4Nu_Ai0Uq%-@|yT~xhm|rs(bJal6H_Zz=)}so@E?LwXVIDhWArvY3r(R za+xY6f}q#*8lq4;-r%!tL_6`6AJ28-5#Jo2BCFusNgOzlqW789An3F zvZ*2B8r~N^ha_`tG6|7|e8iC`kXY-nPx~}Gf#yslx&R%PybDMwDK99tVSfq^w3S&W zfWe*b-<%koKes!wE}5^{Qg3U2DlzgPQr@3bkv&&j*5~j>K~ID z$O2zXCNb8uVM|@sdv?_W_}1_v<@boaaKhJB*1N*!c^{`C6 zrTLKyowp2(2e3{KAHf7uEbG(M)JnkLS7&+6=>=*Q7>K4vE_kL>8bEbDP&UvQ`2!d# z@wAcy03;Fg_Vd}b03ZO(a8H1}9n7V)>J%lyEtFOOYQdqS{E#Prh*dD&12E5_8s7^B zoezL+e+Ot5*k*xl_~ldjhaTDS3J9^V%3qo*2^awAAgHD0qD*?5OaRseD1#WtY99}l z#(-kgU>bP`wr(a6-V%m1iEKd~H5dkf5ug@cVjVy{K&DuEK$&M2f0B)|naMGsMK=$y+i z=rkmIVNKHTV1yUS?oh)uFx<3c!B7wkfq(!w?G$0a3PJXw*3d*H;))reE z0Ad6y1j85*E#&J7&!>RlUS0;oSBW8j-_%WpWQix2q>~2$7wXB<7OQaO26)wwvc?kw zTS{AN^8nTx#)o^t@b8VR&nTLpqF38s`9VNMhLHzwAD9D6puKsV7#QjGi!yRbbWRQm z-3#-nZA*Z#FeR*Ne}lY)UN3zSC5?84-3=g~E|ymbPQe;H;I8v*1;|W`($wex@Ea^r zUuv6*PyloY!CkixoPD5Y;sDV7pyD1!3FChsaK^F8RJMd@z^AOlfzY8D3w>Z<_8)nu z(cm^BL0APj8BRc;I1RE;xKe1~um=cxFyqNV>O34K6;*v`8;Jxy|KNF*J>A7Bk&Vzr zf&=>lI5PDg{M1=g6$RW|iXdS<4}cPR3W3Sy(JUpBLI?&${U^bJ!`|Sj4-lU4=bcV{ z*gs|{??DFKk;LouKzX(T+$B>tfx(nktPJqu={;EIP0@J3V6Cjkg=|1`aG|Yrh<*jd zy#RK=CUU_PX<*K@C?x@$O}z%YgDxjQ!~oE+Q?vkt36f%{(#%0vEge<}J?1B*0tM7cVg5D}(`w7F>n_;Rx*a zdpN)Et_|L!`p+}{*K+-3A8@{b%Ww>baZNua>qm;PT=w(fbIZW-r9bOGxV+R7T*(aw zm%|77XR8L_)e9Ik1i1cJI557kf^Vh%M+tyS077Xx#7i)%VuKtaY0pp87xbWgO>VKE@ zCRFnGF~};ACOG#mo1|II_hOn2AD4{u3m#vUT*)V$oXbvjSm09Y(_OPs)<)a$*4_?+QeUM z6HXNJ^Qy@bW>5Do8S{CV_SPQ>qpVR)jM~JgD~tw((O5XTD~#@sqp;w&0n#E0xwh(W z5|5tl2N~0O+_u)^gi+S0CPr;y)D=d9!e}fU-4#an$5B}D+W?6`A=g#SmQ?q2=VsXO zxb3ZBgi+S0CPr;y)D=d9!e}h~PuUgp?6i9or%mz%iz%PI%RVsg$LG*jZ4KC zs3!hXY~mwHIK{rBH9upN7*)ckC5(E(s27ZS!ALJqDXR3nRkXfxoLKGkd=UGqn>YWE)Mvxt<g`FN1mk!Psz{NP>sJgJ-+Lwz2)4e+TK-m zIl0X^U8`r)L#fKix-Q5gtuV)SyR3!1+hQm3AWNo(gjg_moyIL_OGC8nAnUup`*iN6h@k!Ch)Ilk44PO+53VZ;;2eB)ODA-XO?$k?pycAdX`R<5~lmY1Eq8pR#6bBq;g>4%xShy;oI# zta-A%083hXv(xL$z6jHE6)O7P?zg_NQ!>Y|N3Oco{BWCx1QBsg;#_O7OS86TQ_1d9 z+Q(wtr0}nrOvja(PA_Yo^flKiVjQ2>m}Q1u?Hsr+a9WNkc&)$tb4_DplkI|Al}lYy z&SknZKTXLHT>WL!*yO{Q&}4V3OzjUFr;W-GYw19pa-%(VPdqQ`;}jYQN}Y z-M#7AdefqF6gSM4v{iz=eyeR$?llopwkF<9!2&AP(?6AXWX++i`0J^6>Gq+iqV$Dn z9(ODbc&|NJxRrZ2I9`CW^L&pOjD?Z^n-e!w+6<(=tDRMif*#~FtcW`9|A*V)m> z8cgu>f;~#n~#r|!^-b}B=rtSCBue+FeM<1?A-o5)Cg*|g__;nZ5geSR2 z>x^)({*kgL|KQlB53&fN1-N|&ox;V98q-NjDP6+Ybxf43XZ(D#q0afs?hVt@Gf?}DPA2dUTbzuAUpQ7H07%IjLGv$ zU1ZuEt?IlrHN;<>5E_1u__)0#xH12kJ;Q}hZzr4B+WeT2(AySCDhqMCKW^`^8%9ebR-3PXc7yQbq0lqkaF>0rK#IG?yftRbt84AkK$@o?@!dtu8`N_-e<{Jj(&f0wDOQQhIu`kL==15 z2xBX|lkMw)pci=gzlF3lH`;}x)$AKzkS+sZ57B=2_?fz6Kqo#t=#JEWMwP9{yY`4 z7ssOH>JB23Ss2{DEYgH0L5HU{2?a~IcNcWwp(Wg98Db34M_ZtZI~OOnv2bEa?o1I9 zc4!x>cdgGPpA&bqm_&=YD4RTYA5gW$#cZD>?COmbMT%`d3#Nj!F?FUQ{c|DsFW0t& z9IC$dyuD>XN6SotJ@XmMjin7=T8+WkC8rcF(FllJT%vb(Q>0e~W8^I+hXl-s_yFM= z0bb%RXyUBZwsh^nEMq-$iWdrI%2Vx2n^6_n84fpudyGw8IM`5aevc+uStwnQ>dE46 zRb~mRIs7I;EEknJGrVHFT&z#cVi$&fcWYX4HBZoeCe7KA**fk3D{QMzcxp4M+$#o8 z{-taCfp$TawCN6kecpAS&<(m?yf3EJ&XrXh>GJNys~E^TJ?Y>o{q2kj<|A`%VKB99 zS#Rdkl&xpeC2l9HQnoVA-Lnc5xs`@j?2B`!Hqlglr+1~#Z><8;y0|3vN>D>< z-9IE$ETF0jtMcB#@kLA4wvkpZ`|760*_-ZXAKm!sDf_Di7qcn4D{98tfPE;F)R}^U z@!R*IuBFaQuNd!bozuoHGo9RB5%skNDSa<-izCx})46X7iqb!J*&Tl5Y>lHM)ve*; z-)6e+^iQ0%UGU9=i?bf@zHZ*9_P&}Y3`u`{e3LYM@b!|0dr1X`7mK@O-SCav*%Zz1 zJKmgk9D6tN@w=<1C!a=#o^C1Jygqa5?tzv01> zyBou5b{O6s`<)Tvs`gyP;XcCkv?wZR;7^S#o1vxd^{<`bZfiU}eXswnIqpwaPp@ov zz#y^HKT=jPo>k%Nvdr=?lm`bBwe1f+SyA=L3hyb2)+aa4UUfC>!zbO3VQJ!)X!}m8 z=U!1NzvrvnI!TWSIEfmWtCrt;R(IUnKQYWw-1;>c_RU`c6#LMt*LR(+$@;cX==1|F z_$Trl_Zewlnx=gzSu=h0XKVPg3xaK;JSEx5Glg+8^OSo`#|5XZ;F^Ipt1V7%a@_M| z(#-3%{Vz*tig>Q1J-KWRt?V^74SN zymzWT!QcB;jruTRdatv9b(+&d`c4=SnezP_tJ>}Bdej>>n}oBJ=A!Xc2TxeX?P3)_ z!lU+B8>P++4*xM_to?y;Dz&#f<$DlQ_c-p`pE|RKm@bZF`Ns&hLRt$$d(FUpY-5K~rml7~LnkF^nvI^7Hd` rT9;W>ye$31-S+8_=Snw5s}?^6s?#zil=F4Hw9FEl&zFC1^w$3adHRbj literal 0 HcmV?d00001 diff --git a/research/frontier-word-reorder-ceilings/r13-reorder/data/mip-forward.json.gz b/research/frontier-word-reorder-ceilings/r13-reorder/data/mip-forward.json.gz new file mode 100644 index 0000000000000000000000000000000000000000..e7c21cec637cacff6ac29108d887bbc2ed666b8c GIT binary patch literal 44811 zcmeHw30zah_J1v{)IMwcxi1*BE!bMYC1sN=R_j7hQ7fXdX zfIuR3!GanUS)wEnsVoH&1p@++fPsWH0Rmh?Nb;W>5K#2BeXp-?`SZD#nKNg$Gv}Uj z<~xHQG!1?4z03`jUT+(D?>}U*kKh-u%WsdR7m?ue*1Bhy8w;*YLyZtO|R22iKac!FDfWs1r@2FM=I!v3VN!7#44yp1=aPC z{lt1#J=28d6waTYCyACS3)&6rK8&578BcQ(XiRe?(JEzu8mj9f`{@SQH~90*CDF~w zg2VdBI`(7$=_1-!| zC7(ZEuVeOU$Q?>$!OMl&Qye&()Z%LtpKVwh3)XCgu((h@Rz{qx;+$5CXE~V=J~(z} z?ddZPiD$mLmBm5Z#LVBLE6c1v+r-PSsKkNHI3dv}$Y+HxtbsEVvwt_o%4eOhxRLV( z#^z`F>Mrp$=Ikyh8ZU=P0x3go`A%i z%-Is6itKY#xW0|^e^{Fw`H7xW)Sj|TJFHE<+*~dGgcVm$%%S+47lx@gBBvdq`s&z^{*D_nDKRdK4a zs|u|GNvcG*W0VOmq6-SA}~a zrtqvFLE+KlBWRXojZ89at7qBB4--8`BvXBoU>!b-FCURy{;UmXX;>GIJ9eDv?m%)R7Fg(OB{-0^B=b#G+;eZLYHog(_p%5>^5Yh5%i6_Z zZ}SmoWLbm}NnjWes0u13NnT9?0$u#yR24K2R`6?kk(!5BkyB)8=OHhTYoyfftR45P zvfNZhiks8oR6IN7P|~hbfUi7^F;vwR)%K<;w#{kylZ+4?h^5a`bn;ZZwk$hVoQg9d zkzR)F8fzmbj!0^YTi;aG*ad&**Y>KP)A^>V)>Y78RrN*kX~p`xE{)Zf$+5bu^?a)= zCuoIMM)48IhbLv9X@En#$~83N@%|t$0&ax^Tmrs=^7b{Z;Hmcx;0Dh)f#G#$#FP;BLzDdsdVc z_v|EbD(=gPw)d+5U~eM@2a6FVEtkBl%)1|_0@aYLk4)5Y?ex|0G=hL{BL`zC+q2t& z3BAM`*75}VJS@*^dlsv0sLQy(9|uMn(X3w60zU4m6TWEXZF&q2d2f=drvwh6Lvp_8 z)-Qg!yam`mU$ZMGqMmn7kA<2?%C;|#p`_pv^=>U9(g!xSj*|Bvf(8SwjNdmdN@Yb!n*7q=;bQVW2%KOSP?wO zh$_%yRskHpURwp&IaJuLUn?+RA9sZJy^(9_@4)~YX2T5hiHI?K-kbU5iPOjSd=g79 zKyMg(hIFZDO0{c0c5yNNin``=Q>M)5 z3FU|Lh|Q{>^K5@!Eu!2!k8n|qIe^_$YEX%2)9F0Txs=n~S78T=77hjomL{;m9ttqBw zsV~@=cFT+;l!iD&uu6@^uD5zy9#TV@5s&y@m3Rm{LqN|_AGI}|Bv+Ab#nRfNw&a2w z1u_7-e{W4Src-e%0Kp@7Ju6ghA-`4qQ5*6*XhxQCE#`gYuE6dn-LP#Fe!!>The5ag8iKrz{lw9mV=0dhS;|@%eGLaHdPhKp!s74B)K%Q|Y z<|pMmYD6P>qvT>QvMjG_&P`<`)wtFEpyZfl!n1%jUJf+pzH(x)al3u{(;)J=`hdm! z9QB+>%E(~jF8lVFYU3_mvP)WC7xpG}nu}qTg{$IYIPHO0`mDGx;fp-`!u@F zzDH84pYT@Td-p@$LXK@)ew6+;dPYs{TZs1p*WM3#8#%4*{!#i^v~5l87{tWDAMS^| zgEVhjevJM;dRtBH+lU!~`S(M{BCXr*AEQq|2iDXYA?60YmmTsRa&_DC@92}zF*UXC zAU+9Pn;r5#a%lquh6v zqR-T3k4NAGm*=dUg?!R>^MtWA`c7^32M9vo(VUeg$hx-0bmL{{C$-rV5CMVrb5 zPa1DVpLw1=1(6iE{Nc(4$Sv(RPa1DUcl9ZR9uGc4?rfhJYP=m?^!(T~L|Wj@hdCC= zL+z2F#_s5r=f|caxPfgCa~2_wwog1|ybC>EdTa*bVc_E2uZ7A8rs-S^e|b>wcb&Si z4ry|iwL)PeQ!)>O`|>tpZWw((dZRRP7NRULGuOx(dAt2W7~LCvNSZhsQ61QmYh;Uj z&^|Yu?u(9;CYm5*fwp-@%aA4Q7sBa>(Kn@ua}bKaz&s-~@_GB*2s#P8H@&*6sQTVM1!i4_Sl6cDxluk3|1a zx9elX$D~gRLL87AI*vxs&!Df??J`3wBz;>D;)wLITKlT~Ioz(VgjtlaB z$Ha5Sx6r5Rk1a&(B`q$@*^YeF5qZuy4SlWtm<7U{bf_@L6wmF zEJQguy-glRB0Vb1@j&);JYpF0(S7w}79)<4CKl!FM82om7-O7+Hj#~4g7}fNu_)&o z15s9RU z#V8@+GRxEv$3GVwY^m+@=v8NTYC`vmn38ok-1&4y&3Sq``o3(QHR3iYrr5|E>808k zN3TNH$mZD~?vkDs8xfE}s+u^u1pStLo-N`5X@2maP`MhO_5>kx7=rA%_wKIX86r@0*5e4~NHJ3$KqaVo=v50O`rqC!D*`d0? zqHED@@u)x;?ti#*(Xo|?IYDiYa_GqAofCgD{y)sA zhGSnM%z_p_&iN6!u`}`~bAg^>Tzf50%+16P56=GXZeo4qVWP0cQ%XCXjU}LQ#VrS5Mr6DoM z+|K1!=u0s%jkW6#-v+HM4LOf2>%4!3ZjH%otX+>d6!b%BNIX*3xjc!!4D+iR|vYpG3!EdK%SOsyj2+(h1KGxvn-aGOm5sc8i^e!3eh%6w%1K6U>w1)I?1IT^8nYE~D=1Qwa}D`z*TxiMSB$u6 zj0=Jj^hlI*0~y%$D8<+l)7La+8zMVsVp+~jsjwlG)SeA1e8PoOX znlT=OZXUA(@i-{5EawjLYS+f=#s@HN&0|~<6+w^6a?+8RU5~CC6EKwKF>Z+3po!%< znaKREjW>*mnE2)~?uf>qjpaFakx#q&m_D1F?p;mtd{Vl&sc}Zvol`+Ut1;^@GH+}m zR9#IXoXOqfB)^(;_(`dK(|%-^e?(B_8jSWLbL{42Ykk?-+_BIs@qt4_L^~!^H|M?tWrjI|tewm1Q!ry7l-6XSTrO}H0UqSwt$(1D)j)Kye)=Wh}a)o1Nd5uR1 z`2&U3e>f4A#HufS)Y15@`pz9n&<^Z+3)YQuPOgPX?E2ED9gPRochV_AuGnG=mg1Zf zxiE=eUs}`Acu0LGlR|dGuD6s}GLkV=OV( zFsZ)2RMoLRNbS$1RC-{ki&(h~CwXB~SAD6bV}G#PpHHdu#A+9@#>O}q7bU$bD>YK> z|4!|nO{v_8r7mWzj&Yh_lr&XV`Zv}76Kek)O64xBb}{QjjMJK;Br{p*WYzwYYX66n z%5SjLC9K>SCwx(om8^8OYJa%eKaWzm8>?Ny8XN0GFG^Y^EB#2dKT7RiK&jk=r7mTy zj&({ZN^+K!ex}-gPVHYvsoaazE@hpFb;>JB+H3xbA^#rpJnd8tVCk@qYJUNBhaAf# zN@Sd5Oe>M4<2V^TOA1kxt|<3-@ZakcPf$iVzbSuLr!;t$A8rnZbxurh@)0p_h@D&& zNsFM;n5y6G{8AA4J-Ywbw9&2uz{nfO}J{(oYTCI0V(r1YHUQVg{q$+)> zLh>KD_*}G#(_;2#DP2`Gfpmh7E?voNpC{~##2?MK|KiIu{E2+jm%sd*7k^852ltYT z{#k1t97nV6U{oRxOfVyBC&hYU%dzQV2J|e z7kJ^NRQ!_)RCCMBBi-xl$+-z!l>h*#f5edn_4+0vR~h@|!9}(I2|I4Eu=5u@WcZh5ls$=oByE(K7ssX4Fqzv5$Ml@26h5 zgWbKO6+|9Cb^+HMI{!aO>_ekitVE&m30}nH2!%Cre1{6vtB%$7ji;ppulSE$xw_~i z?ZiV|>2sEEyD+NB;Ed{7 zKXwS$lE?+9ExOnR`cr3VvR`o_^{j#p;kRmhdLPP77i+0M#h}RwaYi!MIF;}RH9ofw zwMQ4bRDUX#CM&{)$XE_4;Z-%htPgci7i+CQ6-Sd5&^rsSOvPZa(29`so z@RMHrG%f0sE_Sv4)J6I4^w+=2!+vl47?o%A!~NzaGioHGM)DUKNhsMuk(OEh++&m& zRl=wxjC#SS7mRwrs27ZS!GE0>#F4!fX`FJI$0#wXgi%Wv^@33^81;ftFBtWL|2i+A zljkT7XO`D``~`%ZMaJmQ@$dDqxOM#cTjLAwEG$enDNNgP-FdcXb=oHHEyFTrZ)aE0 z*0iBalicmxno{YK#`f|Q@sg>|21Zh)QyR+)Ckjs1ZqfYQ{dH?nrE;rA?xA-@7T#P} zc>7@CEw@7UWv?}97b`clUOlqKK6#EP94?;ce*YJ){V!1O=oEjA8IS7u->2sUnxd=E zHF+QSX8?cTGwfG-aQ?W=3Ehgb|DzECPsy7p@y!j0zr{GEw3XTmdcsjW=^=IwcLKCb z+&oH*D&fDt5-g#+;$}Z~A@?sJZUnPaB+X6G-Cpj0G5HrLYIKUf#vn)a{Qr%fLDc!f zaSjBlewAk`D(TZW2qiA#577OQL+2&SScT`Wt;2lQa4xOR{ zu=MAW)4ZRZh87UdlW)b|SY6^=Srq~o|A7Wb0Q zqVTpwo}UGO*!_s(&@~5q@A1kt2Ym0r=X*)OiD>v`O5cv;VV4{)?mUirCGNO7EqPd$ zd@lL2*UvkKva?>7cl^9Hc~~~Ih=C;;)^bF{4elaqo1k8ivI~S67k)WAnC+?c;P?J{ z6~GYs2ELnaEJe>L*PqK4exl)R>+L!06w3TEA#1q8!0vp8~`E0n_V7sqc>z3&X9s~0!Z3N_QgwW^jtT9~uc zqOimKLW|knMW2!#Dja|H*xVg;n{kGF=^ti^eSe*k)M8d2{Rs`Xz@61!47Tr@fW&@m%Cv-TYfVQ@`jUL(m^Ik$R5b^M+4FFmjA`TFtHndP)R2m9zF=B?{0WAC8$2b3rvLVN^S z8*s`_W^y1LlZVQ)&r?rc?7q3w%<44>#=WG}>>p23rJXId82b&v@X`?^(Lv}|f?{+Q znPL7~a-=v#Di0-E*(G>g*8R!?1hI4EMd8GKd3F-Lj|B6^1Q(rd?tLU4Wk1v*RT^L6 zD`>IBzn*Oh^(t-mlS{rCe4cA;1bJMYz3xhvJW!q@32Tyi=;xH1KqkAxCAcy8yLIar z@r_X^cfTu+0{?4v4`F1(ldv9(MRUDZm87g!c@L&t(`*cRkTFDjo4zxw5zrY*1wb0 z7-i$$amBIPzaY+%RBA@JTeqI^r!e>Bky52u6~5IiwuB?`Hui$JIr8FgRX;n{vAW2N zAd9jg7Q}JtirqT)S&~qUtbc;NN8CII3d-YF`?3Rmi-ZQ{c%68XIdUx}ARbaZ^Q{&J zyGKJj;6 zJbjwka;mtQFO8KZNHxf2eE5NIayX6lc6DaCjiM`zOqF^_ULv8==(1tYU~t8k2rebO zh_(r@ng`4vlvH2hI*_Bg&0E)3#@(?23?8w-Rl=#eu5{}t3$P?L+cUDd5*(|01!e@Q zJSyWwHS5*&4=BW`l6eOMVn+9+R)?zS^!eT}iF|Ui|LjTk;<5 z|1ewJJR9oG!H8HI>s;m zOfs;mg20{1`=@x}z)D@Z85gi2oELrf9N59_BUvNE#%P>rwKR_~HgoW6F zuu%L5ItSC7dPETPy(e{$_&}S&PNa2Nb+UOUbX4&HN_ar{z}NCE_7yIX#elChZpNEz z&+G1`D~|tEG7`HEAyCVoV;#L@QRg|A_WiRY*l~Wh1F`XWjTOE@N8*`tlKw#wy7cg+ zr}#CnbtHQ1hq&dJM8lr0OI@!4+LAlH${tTfpZyIxgVurGu)1+$KK zDxmFal?KAUAi4>R&D{Dx%(-hOdn^9)0#?`_c8dkP2wy>p3#Xlp9@s^?jD#_~G1 z_&8N9#V-0K$sr9(*n{EQ(ey^MURq?Vc)d^L?7Fd>FNS62oC0!OR))jYsIz;_wu8)h z&(wg0if!UsLu(im9<1RqV;c9)gzfZeE6e6JM;^{!wr7qaFjHC^J}C0g3JfA&4xQ$H z2f01s+M2SsYg$##(3;hUc<}|VsQhv$b~U8ZQ6d$R*oD3LQe2#_qEmQf}eh?!_csX#a#}yCO+P0S@}Dr8tQ5IE|%_hVvk#=ZhVCM zLjR6-a;MX86Gbbs7fvZ!@x}Ca-KY3JZm5=kKe`;hNNyunu30(o!Rks@^;d6twCZ%7 zImaL5?b-_sP!TmY^gGTcQ5tjTGUGdslh1h%sg0K}Fn$VTg+iSC%Z#5m1fs;8;c-&N zD+V>+`o*~geL8_tv{p4yEI~n+FMbz(-ndrBEP$!^mn~?xdf_*T7{+&`Ph%KSysvr} zG^Si){~p3mD0Ei5K9=azK<-UUSXe@rDu`=?{TgkSLz}SqY3LuTvmn~G6&BO>~)yv5njc8 z)vK_6lDaY>;W%fzlg5KnYl%M`QLj7VmEMn2iFB`TCwFysv!22OMbPyvT=srzY z4111Vx3^6%S1tqMbVkh0&U`tNC~k0}VkB(nvfsn1RR#2f|llUw(h=Be6gPgfua65|l)u4DksT z@;P#%j?LBy4tS_MJ+;&X@pE}{4`+d2sAd{R-{njb=(|J%;ZLB)!3B<;seqyCTy0t{ z&(TldvPG?*&voR%D z4Eaj(sHPBAg=HBQEQX}XdJyIVwGv2ip2;Bq8{!o}Hfmjoi)n}!I$uZ%W`Y^Lf|*Xf60rVE!c@Jh!j;ZeVW&gzmH@kG zoRXl@dh_^z(pWNx-qdY>OvsYnF73BQO>eWxa;1)`49D zy3EG9X_Q4&Q*Jf|URZ@Lz*CkIQK{1`!wD(Dhhy26Dv>r;socxETjavv-NhL!C&@<9 zTZ@LYa}|8zAtryiB^9*9Mro8*47QV#M{iRJ+_qD6nXQoV;xtP=p8<_PhE0#5ZZd2i zg_OgMDYJp24K&2&Ym|ME{Yk!DwoU;twgc}ArX_SiS-_&SVPz5&2h6W-TI%U8OL48U zhP)Myp6>8OU{h3Rv|7*t(&|n$>xFc24wcWZ>m{2*ngch0EdslDlckXJxmiMn*dC+4 zRYSw;OrAY2(ya4*=BTKr?&I~wwDD0&luASuL+!+_Or@09DMC*sX^U2#rU|3%BUb4! z#-2_*kNCK96JD@gbfMgZaJrDvHI4I`olp{Dx=vctN1^XKG+;jVUCz z4rQ#S#6|T>9UON^`#=$j<(VXT@`1nDPP}$p~0*10dP$!_I1zU4UU7GRH07fW@ha@#Tl;?Gzn6Aln!K{fL zARtfh<0HnYF>I2Pp8;LT6czCZILg2~RVXV(8C?`C6b}HT04#q8PNf$0?gtJ4WvF%5 z63GBgGKV6`h9Hn7q(h|c>@H%Dj+s-gCSeHz2BePacLAl!46-%^KBe*_s9g&ifYyMS zAUFjv0*BKJLfHgCww>K{eU+@4&h``ll-HP&Hh}gzMLU2UtFq)0y=nmO#j?xte$s0R z1qng}l^~a^cRvQ>z|k|B=<6deY+q4vU}tvliE{L`==FN+63W}*;B(rwZW?Em&*>pv zr|2j4G-_Hy%BsO;KxbAe(T-xFs>tQQoPo#=$j2_tk>q?3_WUFR@DGl4l0prI#9A~Q z1R5}*Tdx<&)4SKJ)P;;Cc)~xXY+ZnlfUa+?Uk4nY3517#Jiu~e+1-?Cp0!HkQMc67 zTb9D*ETX10reIi}*NZ7>v20MYk5^gb5~l{k#qlat8tMTsZZMx`aKUcOFW*81uO zIf!#Fv#sIr*7wT;2Iv&|RLk4PAFxrX0#Bsnp{`+=yIMgx0>6!n&Z(5nEW_3z2Ub20 zigX;-@k;+#Q~-ss3JvVc5t<>wPY#`SDN=sKj*+bKSi+CU`X<;Ka)ueFeew-|1U3>}$Sg>1yO>HmlqygB&h`1#r8#|-Zd9mla)Ty1$ zk6f}TQ;Xol5YEjdk~)q3@Tuwyn_2LUlY>y7!F#`VK|{&~_IJGZWhp!1#6S-+M-V5$ zCm!CbcR>vMJGB>*rX|bd>ULFM4=K3ME@;?0YtdcV7f**ndJdt)We`&VLgg$_P2T!@ zeg+RVHu-ybU&&JTn64X!?PA$c>IEYbzhF~5m|`hB&p@&lMA5TFFUimk@CvXol;E?2 zZ%YU%Q(4QSYmf@qtCcEXjU8=R&uTd^?x8b}CEWQo!d$a+C>dCxN*R*!3hGJ*@yeM} z?E&6UH!ObvmaquCvXpOlh8obLSz4tRsIWAOrXOp-+t5Rb^N2)cs{mWn7nZDy>ENY0 zcRD|IS>-vE>P!iK{rjSU6{1mxAxhxb25;ZP&Uqk=VSt6J`;vS5-k0#OJgu_1xSRym zj$(OIDH?TvN4$-^CO%%S3VW{V9(;r9I!GE|#8gbrG7hC$*WOCQ`>C_E(kh%>rb>w* z=rz5DDAdmP<^}ik0#|2cK!)S0`#{%(f_hcA2Plw1XdN6XxC;#BiHirv*s+{!YKXXo z_l3_P$y}RELS!KyaU=>P)_UyIKFv;`Ia7%)K!+vo0+LF~3yN*npMnEzW!4E`@F&X; zNj`)$J=I`4BSu#p@F*2$6tvb^fiyvWe<4K!T#qIvVMSg#>P-YkMM)O*k4X(=fiEVL z7;D%V1g-@^=WEqCE)L?v%Kc?0yPT^MAIV|Jku!+pt>F?8)%ID0SuLRTFC(b zk_dYH`RrN%5P)X5C&1ng=2BX9iW1=#N-F@h;LuTi$P+-sDj4qpnCDQ9?*)U-2SB&K z12hY4vp_fe@+tj8kL-8_gjiVRFU^$%3;=Wx)KYU%CcRB20P6yjK@4QIj|WR*K(T5t zjl2UZoe6}ugdt5LTOg$d!vHV>)WS=Y0>lGkij_BB55;G8iV^@}z+?8pQda=7N?Zb% zNf}@R0Qe2xeS9&L$Vjv zBn=Nnc%keLHCzM3O-mLG1;G#q2!PX05eBRfWG`wBO;jSTm?5lM#LAEq0xb<7MzBIK zi~-R?zMk-W3K;I?Wk7tD7y|fB-DF6XcydWPc@S`+o-A##3RiA`R}Cp^JTb7Pw6!)5 zV7*~{xF-z%-pKllq6sQ`wGEaZ1XN@gc>wo;Ij{uUo5zWPkzT(jBd0{?KFrV7C z1PBXL!m9Q+$V=$;(ic(EXjjng$53LfUpNMo*bmk!(mcU)rYo`NZ|7io>$q^U91w>2wfyNus?t! zQ~$wFokdkqz`dmi64vtoD3PZSm~0-+QX(mYU{KV55*#?}4W9Y{;R%1<>C}h)V}|k` zWWXIsyj~BKXDh&6GIbLeOlif+06(7IgLU2%jRy?Y%8Fdb1~dm3+FFO`S5VvwU z7fg``=1hxH62RHiYp^@$auP%g01Z1u3qZ&)0L2tF>52go8hR>MdA5tYxP$nxr#p-w zF?1NjjkQ%aJnABN*ul!FJgT$`f?FIXNPq%SPeGxrbvC?mfHg7Tqr(75W|eJ6TJP)Q zLA3SsKtazsMR3Fgt!(kSh=j^v*PZYMh9n+7+QIl0L||yvAQ*%%L5D+Na3N~?D)=S%;XvTYvhBz9 z;Qu(YHK6)ocem~;`6nKdD1|(W=83u$Su;1_D{Jy(3 zc#rBo&-7o*^_P9X`35e-F&xG<{g|vDDZ+Bu&xg+~1IL&CtpDKhQcG|pHym6JALO5{ z8h}?XVAK%c`d{I|_{IvpmHHng04@Otr6I*|FZKw=WiW#JUu7Ats)hi{5EdE4EdNWa zH=-W{c7ox^-^ED(O|5LGQvqCRNBx~lwX*-0fiM4}%J9p;{%vL8cY`ngS`99}9AH7o za5FS;LDZi`SJhc_*82=)!|p`DO_1S=4=V*~_+TvKHvLH2atf5D1?MScGz)@xe*DXcY*3|Qp&pcwst zWNN=`5&hRuFN-q3d~tF08l3WS`#(j_H!Ev&_!nj~s)QjcQ`lCPrOhG$@S5!qHt}bblO$1-}iD7E#ExRezIs^mISS zn9k$2wH_yovPLyAY7?WbFd7s_W8vtoFuFgE!h+uhNCXO5S~Xiz-P4_$VZ-CLw}uf$ zS)-a5wTV$z7!3-evG6}-SJ1Q5?p2&N$rCK5eD*H;z`P%yLtmAbG#sC9eenL#531}h zDxZBF9eb9rYJwyEw$Xm)5C64Kc+dBtuCmx zR6;)0Y#&|oN3v@79_q7*l+84Y)_6yrr3g>S&)86nzc)R;>!-ct+^5>!RdzYK%{X1F zXVb$vm6NqJ$Rn*V$9B7{iGMvU)4R%zn_(Rr%rDocdt9TLHxrl4%GiC|-8^r%t9hv; z-leKrBR_b3hXUurN*5Lm(^PR%WwOJhJZNU;#O^`1&1>?luhS1byHfuS))r;iibj|u3aa6x&Ez!~? zHV`gWtl#4|r?_s}dFoPaUC%n7+#fmZ3~6;wp<3hnMZ4AU=e!@D2VO1?TVq+(zS~2W z*M22)(T5NHqorprZd26hy0mn%SSSW^5!V`UDQyw~M`3Re!8`vb_LH zT6?q8>&(6g({mLn`rhuhzOhp>$FE1Oy4L(~n}-AuaZch~Yq3kSwr5kx?o!&vV%((g zubNE9m6=X2Yo7Eq*D7KhpVydWhFsc z$q-!qWz*Q?!Fel za&9dRY@%9h-6c8cD|WT2#k!VzSlFeSeI52-llKqA+pO-2bIr}GY+6Lqnp1ZtD<6K+ ziFNf$Hgj>k23}$Mw&do`H+C$j+EbM@)pUWTWuOHb1kgiwS$MJs!{5k#tq? zT~Yd!)^7@PJ*YnfJ8w=~RkOe(&-uI58Eol-j=UY>qe#)52fkC=FV1Se=w#i!>DhYI zqH`2C%$BrOg1vsLZByV7vKUi-*rT(=YAF2;F|bH9X~==}J`94!6e{hZAOhS#{Uh(Z}WRLZ0y8 zfwXtaim>A!dMw5MZN}bAuf(S9_tUStn0ZGZu1em$`yPcob8h%`7u19&xku~@sUPp@ z-e4rWJx65ETy%H0>&bwF2drwhu77%Ck}e2)H%;q|aIgN6vM2xG*yJy+rU%;3zj&B> zWXXeV&7lvn2%-hJeFvSw#m%XaDaknd05?{wo9O7hYpiA^Y_2(? z=)M{M(D&C=%nubDd2fr?_n}px=a1oC?0QqYI$FHe?3zG!>}hGrRqq*-=a;(3v^iSU zd24Ejzc?W@{2uXfdrNR*{xf@q3!mOjHnGW5wkJC)DMtj$Jky#Is#2}?KfFPzZrz3F z$F=(imw9$=r6EN%>xAn~X^T4cIC&L@25ojt#~&zBgvryz==olbG*K$vXJy&B=gH;g zcBj{+ZtJ+a?p)T5)R{htt5v-}Q8&9nUW}?~At?W*= z!&jN#tJ~^!y)s>RPMl&U6il5B`tpcrE(sPH=~F@;m&G-EkdLJ8cVd2?o{n=32_}lu z;^eEYJG&%wx5Squr##ZN=q~&1)1GUqK&DD48D5%T8)>w1tGAPtt@!%$RLou+i;}B5 zh)8B(aQm`I6P^Sep4uc7EaBc=(1nMVaF=C>F+?A2fhz7?oZQC3i7B}=MM&78U8vr* zK9hV-+|gnZE#{(Z^4xtu)fN}CeUh-NH&zrWw*4%a3ev{ZnTqt!h2Xzj+Y)l9`r7mM zmIWOxGYR(0XDm0CHhgI{24|O?Qn*ATAZ~Gq-rY^9yDAtXZ!tL}U`E6T2-gVk5_drp zXRWrSYZqo2>zPx$P%u-TYG2xns>sf8xFOtQZ0f?nhHCSBG|9@sx&^78Ebdlimav+` zZxY0EQK>V-E5^&k`qV6TVd!_arWIH71l?!SoE@31;|{RGw)%vpHlxbDV({c&y0#x^ z7gW_X-662gyY3UZLD!4-#kAVFvWg>J-o1Dg19_(>9bBcqol(JjWX>%Nrj{-1&3u}& z^=!Jt?POKTR>rw|R)He7((sCXaqiS6nyT;guJrk>RbW~dm&9JlYTBL#QIxX#hlGj+ zRCQrh-a9zHXvx|((&}Yj-Sjwn)BWtD8(%$Tf7Re(Hbr+u%~%_-4`q@%Q&2E|`##jQ z)S2lO5q?ZstX@{z3Rff>I8-ti@Rjq@QvKr6wU8D-kf(F zdpGj&yQ`-spGJqCZYkWnK6C5j;2-OhxM$^zFC;B2$vkq_;vc^CTzdC@!-FMvH-^>h zFuXnXJ0r$b?YWA>eT3_2QB=~vpBh;Y2ub>`%bFoUQsH) z=d0a1NskFQi5i)!mfw3OJ?`zF7-lJM{hAE><}U$?edyKeyH3|+eOoAW`T-aG6M2sN zjI=LJ)4r6fnZEk7HT>BH!8TEzlI-M}!nm1v$~~szf>T#;%|M&g7N<8k?s+n4=JneC zm!-5tOrKFa_S8P3)lPzjf|(e*i}UfFb*GqpD%2Bx@aCUT@d(Lelft?3@_?|scd9X8ud{%4n$tu2P8blG^8FgC+U@Il)EhRNgtL_9qVZJ+Pguw8ViiBaqxM)E zrOpfv|1o8({ef{RwYNOwdk|CiIPTk@If!NcFJ-ZD3R0bK>yR+ZV?-A3Wi0 zy)v%&rV#7TDqdVw(tOa7{cuTK+OmBaO)<}scXzAiKRAi#QqSHc8lP&xDNe7`+}l5I zp6L6W!~SP#;C~YZ;1f_ literal 0 HcmV?d00001 diff --git a/research/frontier-word-reorder-ceilings/r13-reorder/logs/ceil-lp-backward.txt b/research/frontier-word-reorder-ceilings/r13-reorder/logs/ceil-lp-backward.txt new file mode 100644 index 0000000000..9b2cadc833 --- /dev/null +++ b/research/frontier-word-reorder-ceilings/r13-reorder/logs/ceil-lp-backward.txt @@ -0,0 +1,95 @@ +model vars 54296 rows 91837 hubs 1948 t 9.68522024154663 +Running HiGHS 1.15.1 (git hash: 04024d7): Copyright (c) 2026 under MIT licence terms +Includes third-party software components, see THIRD_PARTY_NOTICES.md for full details +LP has 91837 rows; 54296 cols; 281273 nonzeros +Coefficient ranges: + Matrix [1e+00, 1e+00] + Cost [1e+00, 9e+00] + Bound [1e+00, 1e+00] + RHS [1e+00, 1e+00] +Presolving model +33829 rows, 28511 cols, 146676 nonzeros 0s +26236 rows, 25671 cols, 120879 nonzeros 0s +Dependent equations search running on 4785 equations with time limit of 12.00s +Dependent equations search removed 604 rows and 7783 nonzeros in 0.00s (limit = 12.00s) +23154 rows, 24415 cols, 104875 nonzeros 0s +Presolve reductions: rows 23154(-68683); columns 24415(-29881); nonzeros 104875(-176398) +Solving the presolved LP +IPX model has 23154 rows, 24415 columns and 104875 nonzeros +Input + Number of variables: 24415 + Number of free variables: 0 + Number of constraints: 23154 + Number of equality constraints: 4131 + Number of matrix entries: 104875 + Matrix range: [1e+00, 1e+00] + RHS range: [1e+00, 1e+00] + Objective range: [4e-03, 9e+00] + Bounds range: [1e+00, 1e+00] +Preprocessing + Dualized model: no + Number of dense columns: 0 + Range of scaling factors: [1.00e+00, 1.00e+00] + Scaled cost norm: 8.94992 + Scaled bounds norm: 1 +IPX version 1.0 +Interior point solve + Iter primal obj dual obj pinf dinf gap time + 0 4.94960652e+03 -2.04666642e+05 1.68e+00 8.79e-01 2.10e+00 0.2 + 1 9.36724581e+03 -1.77801731e+05 6.33e-01 3.45e-02 2.22e+00 0.2 + 2 7.42036113e+03 -8.52047394e+04 1.83e-01 3.45e-08 2.38e+00 0.2 + 3 5.82141385e+03 -2.53919921e+04 4.89e-02 2.76e-09 3.19e+00 0.2 + 4 5.36489910e+03 -4.11548713e+03 1.38e-02 2.50e-10 1.52e+01 0.3 + 5 5.26724998e+03 2.12323464e+03 2.85e-03 4.74e-11 8.51e-01 0.4 + Constructing starting basis... + Iter primal obj dual obj pinf dinf gap time + 6 5.25718554e+03 4.98333926e+03 3.33e-04 3.67e-12 5.35e-02 0.6 + 7 5.25536549e+03 5.19652305e+03 1.37e-05 7.61e-13 1.13e-02 0.7 + 8 5.25391180e+03 5.22983732e+03 5.01e-06 1.42e-13 4.59e-03 0.7 + 9 5.25225798e+03 5.23650962e+03 3.03e-06 3.28e-14 3.00e-03 0.8 + 10 5.25040039e+03 5.24259046e+03 1.40e-06 7.14e-15 1.49e-03 0.9 + 11 5.24987793e+03 5.24398289e+03 9.50e-07 4.03e-15 1.12e-03 1.1 + 12 5.24883992e+03 5.24605140e+03 3.40e-07 5.06e-15 5.31e-04 1.1 + 13 5.24857960e+03 5.24697121e+03 2.01e-07 7.29e-15 3.06e-04 1.3 + 14 5.24815364e+03 5.24748167e+03 5.91e-08 9.47e-15 1.28e-04 1.3 + 15 5.24801373e+03 5.24762901e+03 1.19e-08 8.55e-15 7.33e-05 1.4 + 16 5.24795889e+03 5.24779818e+03 5.11e-09 9.76e-15 3.06e-05 1.5 + 17 5.24792972e+03 5.24787560e+03 1.06e-09 1.43e-14 1.03e-05 1.5 + 18 5.24791001e+03 5.24790331e+03 9.26e-11 1.79e-14 1.28e-06 1.6 + 19 5.24790829e+03 5.24790727e+03 1.32e-11 1.96e-14 1.94e-07 1.6 + 20 5.24790792e+03 5.24790769e+03 1.60e-13 2.53e-14 4.32e-08 1.7 + 21 5.24790791e+03 5.24790785e+03 3.57e-14 3.06e-14 1.28e-08 1.7 + 22* 5.24790791e+03 5.24790790e+03 1.94e-16 1.88e-14 2.22e-09 1.8 + 23* 5.24790791e+03 5.24790791e+03 2.07e-16 1.87e-14 3.80e-10 2.0 + 24* 5.24790791e+03 5.24790791e+03 2.67e-16 2.33e-14 6.82e-11 2.0 + 25* 5.24790791e+03 5.24790791e+03 3.21e-16 1.18e-14 6.50e-12 2.0 + 26* 5.24790791e+03 5.24790791e+03 1.78e-16 1.43e-14 4.97e-14 2.1 +Running crossover as requested + Primal residual before push phase: 7.50e-11 + Dual residual before push phase: 1.42e-13 + Number of dual pushes required: 8064 + Number of primal pushes required: 2363 +Summary + Runtime: 2.11s + Status interior point solve: optimal + Status crossover: optimal + objective value: 5.24790791e+03 + interior solution primal residual (abs/rel): 2.95e-13 / 1.48e-13 + interior solution dual residual (abs/rel): 9.24e-14 / 9.28e-15 + interior solution objective gap (abs/rel): -2.74e-10 / -5.22e-14 + basic solution primal infeasibility: 5.55e-16 + basic solution dual infeasibility: 1.11e-15 +Ipx: IPM optimal +Ipx: Crossover optimal + +Performed postsolve +Solving the original LP from the solution after postsolve + +Model status : Optimal +IPM iterations: 26 +Crossover iterations: 1595 +Objective value : 5.2479079123e+03 +P-D objective error : 5.3719787459e-15 +HiGHS run time : 2.15 +status Optimal obj 5247.907912304778 mip_dual_bound 0.0 +current non-centre local cost 5253.116991559385 LB 5247.907912304778 headroom/local 5.209079254606877 linearized dC 0.0003792681338348682 diff --git a/research/frontier-word-reorder-ceilings/r13-reorder/logs/ceil-lp-forward.txt b/research/frontier-word-reorder-ceilings/r13-reorder/logs/ceil-lp-forward.txt new file mode 100644 index 0000000000..6bcac72335 --- /dev/null +++ b/research/frontier-word-reorder-ceilings/r13-reorder/logs/ceil-lp-forward.txt @@ -0,0 +1,93 @@ +model vars 54296 rows 91837 hubs 1948 t 9.52112603187561 +Running HiGHS 1.15.1 (git hash: 04024d7): Copyright (c) 2026 under MIT licence terms +Includes third-party software components, see THIRD_PARTY_NOTICES.md for full details +LP has 91837 rows; 54296 cols; 281273 nonzeros +Coefficient ranges: + Matrix [1e+00, 1e+00] + Cost [1e+00, 9e+00] + Bound [1e+00, 1e+00] + RHS [1e+00, 1e+00] +Presolving model +33829 rows, 28511 cols, 146676 nonzeros 0s +26236 rows, 25671 cols, 120879 nonzeros 0s +Dependent equations search running on 4785 equations with time limit of 12.00s +Dependent equations search removed 604 rows and 7783 nonzeros in 0.00s (limit = 12.00s) +23154 rows, 24415 cols, 104875 nonzeros 0s +Presolve reductions: rows 23154(-68683); columns 24415(-29881); nonzeros 104875(-176398) +Solving the presolved LP +IPX model has 23154 rows, 24415 columns and 104875 nonzeros +Input + Number of variables: 24415 + Number of free variables: 0 + Number of constraints: 23154 + Number of equality constraints: 4131 + Number of matrix entries: 104875 + Matrix range: [1e+00, 1e+00] + RHS range: [1e+00, 1e+00] + Objective range: [4e-03, 9e+00] + Bounds range: [1e+00, 1e+00] +Preprocessing + Dualized model: no + Number of dense columns: 0 + Range of scaling factors: [1.00e+00, 1.00e+00] + Scaled cost norm: 8.94992 + Scaled bounds norm: 1 +IPX version 1.0 +Interior point solve + Iter primal obj dual obj pinf dinf gap time + 0 4.94960652e+03 -2.04666642e+05 1.68e+00 8.79e-01 2.10e+00 0.2 + 1 9.36724581e+03 -1.77801731e+05 6.33e-01 3.45e-02 2.22e+00 0.2 + 2 7.42036113e+03 -8.52047394e+04 1.83e-01 3.45e-08 2.38e+00 0.2 + 3 5.82141385e+03 -2.53919921e+04 4.89e-02 2.76e-09 3.19e+00 0.2 + 4 5.36489910e+03 -4.11548713e+03 1.38e-02 2.50e-10 1.52e+01 0.3 + 5 5.26725001e+03 2.12323424e+03 2.85e-03 4.74e-11 8.51e-01 0.4 + Constructing starting basis... + Iter primal obj dual obj pinf dinf gap time + 6 5.25717895e+03 4.89680464e+03 3.32e-04 5.04e-12 7.10e-02 0.6 + 7 5.25552612e+03 5.19678333e+03 1.90e-05 8.04e-13 1.12e-02 0.7 + 8 5.25395561e+03 5.22956658e+03 6.28e-06 1.24e-13 4.65e-03 0.7 + 9 5.25237184e+03 5.23622747e+03 3.94e-06 2.43e-14 3.08e-03 0.8 + 10 5.25037160e+03 5.24269441e+03 1.71e-06 5.71e-15 1.46e-03 0.9 + 11 5.24981006e+03 5.24423128e+03 1.11e-06 4.24e-15 1.06e-03 1.0 + 12 5.24879258e+03 5.24620986e+03 4.00e-07 8.99e-15 4.92e-04 1.1 + 13 5.24851352e+03 5.24697180e+03 2.14e-07 7.52e-15 2.94e-04 1.2 + 14 5.24814090e+03 5.24750375e+03 6.73e-08 4.90e-15 1.21e-04 1.3 + 15 5.24800993e+03 5.24765145e+03 1.13e-08 8.86e-15 6.83e-05 1.3 + 16 5.24795192e+03 5.24780031e+03 4.35e-09 9.20e-15 2.89e-05 1.4 + 17 5.24792471e+03 5.24787509e+03 5.59e-10 1.27e-14 9.45e-06 1.4 + 18 5.24791084e+03 5.24790337e+03 9.23e-11 1.18e-14 1.42e-06 1.4 + 19 5.24790855e+03 5.24790731e+03 1.80e-11 1.38e-14 2.37e-07 1.5 + 20 5.24790802e+03 5.24790774e+03 2.87e-12 2.00e-14 5.30e-08 1.5 + 21 5.24790794e+03 5.24790788e+03 6.79e-13 1.22e-14 1.18e-08 1.6 + 22* 5.24790791e+03 5.24790791e+03 2.71e-14 1.50e-14 1.24e-09 1.6 + 23* 5.24790791e+03 5.24790791e+03 2.62e-16 1.24e-14 1.79e-10 1.7 + 24* 5.24790791e+03 5.24790791e+03 2.65e-16 1.29e-14 8.86e-12 1.7 +Running crossover as requested + Primal residual before push phase: 6.86e-09 + Dual residual before push phase: 2.54e-10 + Number of dual pushes required: 8064 + Number of primal pushes required: 2363 +Summary + Runtime: 1.75s + Status interior point solve: optimal + Status crossover: optimal + objective value: 5.24790791e+03 + interior solution primal residual (abs/rel): 8.45e-11 / 4.23e-11 + interior solution dual residual (abs/rel): 1.72e-10 / 1.73e-11 + interior solution objective gap (abs/rel): 3.22e-08 / 6.14e-12 + basic solution primal infeasibility: 4.44e-16 + basic solution dual infeasibility: 4.44e-16 +Ipx: IPM optimal +Ipx: Crossover optimal + +Performed postsolve +Solving the original LP from the solution after postsolve + +Model status : Optimal +IPM iterations: 24 +Crossover iterations: 1529 +Objective value : 5.2479079123e+03 +P-D objective error : 5.4586235644e-15 +HiGHS run time : 1.79 +status Optimal obj 5247.907912304779 mip_dual_bound 0.0 +current non-centre local cost 5253.116991559385 LB 5247.907912304779 headroom/local 5.209079254605967 linearized dC 0.00037926813383480195 diff --git a/research/frontier-word-reorder-ceilings/r13-reorder/logs/ceil-mip-backward.txt b/research/frontier-word-reorder-ceilings/r13-reorder/logs/ceil-mip-backward.txt new file mode 100644 index 0000000000..33db68851e --- /dev/null +++ b/research/frontier-word-reorder-ceilings/r13-reorder/logs/ceil-mip-backward.txt @@ -0,0 +1,67 @@ +model vars 54296 rows 91837 hubs 1948 t 9.473834037780762 +Running HiGHS 1.15.1 (git hash: 04024d7): Copyright (c) 2026 under MIT licence terms +Includes third-party software components, see THIRD_PARTY_NOTICES.md for full details +MIP has 91837 rows; 54296 cols; 281273 nonzeros; 48416 integer variables (48416 binary) +Coefficient ranges: + Matrix [1e+00, 1e+00] + Cost [1e+00, 9e+00] + Bound [1e+00, 1e+00] + RHS [1e+00, 1e+00] +Presolving model +33857 rows, 30141 cols, 162026 nonzeros 0s +28203 rows, 25606 cols, 133502 nonzeros 0s +20516 rows, 21230 cols, 97780 nonzeros 0s +19132 rows, 17731 cols, 83210 nonzeros 1s +Presolve reductions: rows 19132(-72705); columns 17731(-36565); nonzeros 83210(-198063) + +Solving MIP model with: + 19132 rows + 17731 cols (17349 binary, 0 integer, 382 implied int., 0 continuous, 0 domain fixed) + 83210 nonzeros + Thread count 1 (of 10 threads). Using 1 max workers. Parallel search off + +Src: B => Branching; C => Central rounding; F => Feasibility pump; H => Heuristic; + I => Shifting; J => Feasibility jump; L => Sub-MIP; P => Empty MIP; R => Randomized rounding; + S => Solve LP; T => Evaluate node; U => Unbounded; X => User solution; Y => HiGHS solution; + Z => ZI Round; l => Trivial lower; p => Trivial point; u => Trivial upper; z => Trivial zero + + Nodes | B&B Tree | Objective Bounds | Dynamic Constraints | Work +Src Proc. InQueue | Leaves Expl. | BestBound BestSol Gap | Cuts InLp Confl. | LpIters Time + + J 0 0 0 0.00% -inf 5254.249442 Large 0 0 0 0 1.6s + 0 0 0 0.00% 5248.83022 5254.249442 0.10% 0 0 4 10710 1.9s + L 0 0 0 0.00% 5249.506806 5249.528193 0.00% 3944 122 133 14534 6.4s + 1 0 1 100.00% 5249.506806 5249.528193 0.00% 3920 122 133 16143 6.4s + +Solving report + Status Optimal + Primal bound 5249.52819301 + Dual bound 5249.50680627 + Gap 0.000407% (tolerance: 0.01%) + P-D integral 0.184042288811 + Solution status feasible + 5249.52819301 (objective) + 0 (bound viol.) + 4.46309655899e-14 (int. viol.) + 0 (row viol.) + Timing 6.43 + 2.07 (Presolve) + MIP time [calls] = 1.39 [1] + subMIP time [calls] = 0.68 [3] + 4.36 (Solve) + MIP time [calls] = 2.93 [1] + subMIP time [calls] = 1.43 [3] + 0.00 (Postsolve) + MIP time [calls] = 0.00 [1] + subMIP time [calls] = 0.00 [3] + Max sub-MIP depth 6 + Nodes 1 + Repair LPs 0 + LP iterations 16143 + 0 (strong br.) + 3824 (separation) + 1609 (heuristics) +status Optimal obj 5249.528193012387 mip_dual_bound 5249.506806268134 +current non-centre local cost 5253.116991559385 LB 5249.528193012387 headroom/local 3.588798546997168 linearized dC 0.0002612970279584706 +profile {1: 1514, 2: 513, 3: 396, 4: 159, 5: 44, 6: 112, 7: 1} +profile {1: 1514, 2: 513, 3: 396, 4: 159, 5: 44, 6: 112, 7: 1} diff --git a/research/frontier-word-reorder-ceilings/r13-reorder/logs/ceil-mip-forward.txt b/research/frontier-word-reorder-ceilings/r13-reorder/logs/ceil-mip-forward.txt new file mode 100644 index 0000000000..98e4dce62d --- /dev/null +++ b/research/frontier-word-reorder-ceilings/r13-reorder/logs/ceil-mip-forward.txt @@ -0,0 +1,67 @@ +model vars 54296 rows 91837 hubs 1948 t 9.313153982162476 +Running HiGHS 1.15.1 (git hash: 04024d7): Copyright (c) 2026 under MIT licence terms +Includes third-party software components, see THIRD_PARTY_NOTICES.md for full details +MIP has 91837 rows; 54296 cols; 281273 nonzeros; 48416 integer variables (48416 binary) +Coefficient ranges: + Matrix [1e+00, 1e+00] + Cost [1e+00, 9e+00] + Bound [1e+00, 1e+00] + RHS [1e+00, 1e+00] +Presolving model +33857 rows, 30141 cols, 162026 nonzeros 0s +28203 rows, 25606 cols, 133502 nonzeros 0s +20529 rows, 21236 cols, 97821 nonzeros 0s +19129 rows, 17751 cols, 83308 nonzeros 1s +Presolve reductions: rows 19129(-72708); columns 17751(-36545); nonzeros 83308(-197965) + +Solving MIP model with: + 19129 rows + 17751 cols (17369 binary, 0 integer, 382 implied int., 0 continuous, 0 domain fixed) + 83308 nonzeros + Thread count 1 (of 10 threads). Using 1 max workers. Parallel search off + +Src: B => Branching; C => Central rounding; F => Feasibility pump; H => Heuristic; + I => Shifting; J => Feasibility jump; L => Sub-MIP; P => Empty MIP; R => Randomized rounding; + S => Solve LP; T => Evaluate node; U => Unbounded; X => User solution; Y => HiGHS solution; + Z => ZI Round; l => Trivial lower; p => Trivial point; u => Trivial upper; z => Trivial zero + + Nodes | B&B Tree | Objective Bounds | Dynamic Constraints | Work +Src Proc. InQueue | Leaves Expl. | BestBound BestSol Gap | Cuts InLp Confl. | LpIters Time + + J 0 0 0 0.00% -inf 5254.313954 Large 0 0 0 0 1.6s + 0 0 0 0.00% 5248.828204 5254.313954 0.10% 0 0 2 10806 1.9s + L 0 0 0 0.00% 5249.508367 5249.533948 0.00% 4052 113 126 14752 7.8s + 1 0 1 100.00% 5249.508367 5249.533948 0.00% 4037 113 126 17773 7.8s + +Solving report + Status Optimal + Primal bound 5249.53394772 + Dual bound 5249.50836682 + Gap 0.000487% (tolerance: 0.01%) + P-D integral 0.187436934146 + Solution status feasible + 5249.53394772 (objective) + 0 (bound viol.) + 1.59872115546e-14 (int. viol.) + 0 (row viol.) + Timing 7.84 + 1.91 (Presolve) + MIP time [calls] = 1.39 [1] + subMIP time [calls] = 0.52 [2] + 5.93 (Solve) + MIP time [calls] = 3.01 [1] + subMIP time [calls] = 2.92 [2] + 0.00 (Postsolve) + MIP time [calls] = 0.00 [1] + subMIP time [calls] = 0.00 [2] + Max sub-MIP depth 4 + Nodes 1 + Repair LPs 0 + LP iterations 17773 + 0 (strong br.) + 3946 (separation) + 3021 (heuristics) +status Optimal obj 5249.533947716081 mip_dual_bound 5249.508366817607 +current non-centre local cost 5253.116991559385 LB 5249.533947716081 headroom/local 3.58304384330404 linearized dC 0.00026087803342531295 +profile {1: 1515, 2: 514, 3: 395, 4: 159, 5: 44, 6: 112, 7: 1} +profile {1: 1515, 2: 514, 3: 395, 4: 159, 5: 44, 6: 112, 7: 1} diff --git a/research/frontier-word-reorder-ceilings/r13-reorder/logs/ceil-mipw-backward.txt b/research/frontier-word-reorder-ceilings/r13-reorder/logs/ceil-mipw-backward.txt new file mode 100644 index 0000000000..6178bd34a4 --- /dev/null +++ b/research/frontier-word-reorder-ceilings/r13-reorder/logs/ceil-mipw-backward.txt @@ -0,0 +1,66 @@ +model vars 50972 rows 74279 hubs 1171 t 8.594899892807007 +Running HiGHS 1.15.1 (git hash: 04024d7): Copyright (c) 2026 under MIT licence terms +Includes third-party software components, see THIRD_PARTY_NOTICES.md for full details +MIP has 74279 rows; 50972 cols; 232083 nonzeros; 47029 integer variables (47029 binary) +Coefficient ranges: + Matrix [1e+00, 1e+00] + Cost [1e+00, 9e+00] + Bound [1e+00, 1e+00] + RHS [1e+00, 1e+00] +Presolving model +26496 rows, 27583 cols, 133156 nonzeros 0s +20796 rows, 22169 cols, 103679 nonzeros 0s +14969 rows, 18049 cols, 75112 nonzeros 0s +12958 rows, 13328 cols, 56714 nonzeros 1s +Presolve reductions: rows 12958(-61321); columns 13328(-37644); nonzeros 56714(-175369) + +Solving MIP model with: + 12958 rows + 13328 cols (13124 binary, 0 integer, 204 implied int., 0 continuous, 0 domain fixed) + 56714 nonzeros + Thread count 1 (of 10 threads). Using 1 max workers. Parallel search off + +Src: B => Branching; C => Central rounding; F => Feasibility pump; H => Heuristic; + I => Shifting; J => Feasibility jump; L => Sub-MIP; P => Empty MIP; R => Randomized rounding; + S => Solve LP; T => Evaluate node; U => Unbounded; X => User solution; Y => HiGHS solution; + Z => ZI Round; l => Trivial lower; p => Trivial point; u => Trivial upper; z => Trivial zero + + Nodes | B&B Tree | Objective Bounds | Dynamic Constraints | Work +Src Proc. InQueue | Leaves Expl. | BestBound BestSol Gap | Cuts InLp Confl. | LpIters Time + + J 0 0 0 0.00% -inf 5254.062926 Large 0 0 0 0 1.2s + 0 0 0 0.00% 5250.252933 5254.062926 0.07% 0 0 2 7048 1.4s + L 0 0 0 0.00% 5250.456461 5250.467249 0.00% 5125 98 134 8548 5.1s + 1 0 1 100.00% 5250.456461 5250.467249 0.00% 5125 98 134 10782 5.1s + +Solving report + Status Optimal + Primal bound 5250.46724884 + Dual bound 5250.45646089 + Gap 0.000205% (tolerance: 0.01%) + P-D integral 0.0880955484903 + Solution status feasible + 5250.46724884 (objective) + 0 (bound viol.) + 2.56461518688e-14 (int. viol.) + 0 (row viol.) + Timing 5.13 + 1.35 (Presolve) + MIP time [calls] = 1.05 [1] + subMIP time [calls] = 0.29 [3] + 3.78 (Solve) + MIP time [calls] = 1.83 [1] + subMIP time [calls] = 1.95 [3] + 0.00 (Postsolve) + MIP time [calls] = 0.00 [1] + subMIP time [calls] = 0.00 [3] + Max sub-MIP depth 6 + Nodes 1 + Repair LPs 0 + LP iterations 10782 + 0 (strong br.) + 1500 (separation) + 2234 (heuristics) +status Optimal obj 5250.467248835251 mip_dual_bound 5250.456460888703 +current non-centre local cost 5253.116991559385 LB 5250.467248835251 headroom/local 2.64974272413383 linearized dC 0.0001929252616450354 +profile {1: 1906, 2: 340, 3: 382, 4: 168, 5: 48, 6: 102, 7: 1} diff --git a/research/frontier-word-reorder-ceilings/r13-reorder/logs/ceil-mipw-forward.txt b/research/frontier-word-reorder-ceilings/r13-reorder/logs/ceil-mipw-forward.txt new file mode 100644 index 0000000000..db9f20cfb4 --- /dev/null +++ b/research/frontier-word-reorder-ceilings/r13-reorder/logs/ceil-mipw-forward.txt @@ -0,0 +1,66 @@ +model vars 50972 rows 74279 hubs 1171 t 8.595556020736694 +Running HiGHS 1.15.1 (git hash: 04024d7): Copyright (c) 2026 under MIT licence terms +Includes third-party software components, see THIRD_PARTY_NOTICES.md for full details +MIP has 74279 rows; 50972 cols; 232083 nonzeros; 47029 integer variables (47029 binary) +Coefficient ranges: + Matrix [1e+00, 1e+00] + Cost [1e+00, 9e+00] + Bound [1e+00, 1e+00] + RHS [1e+00, 1e+00] +Presolving model +26496 rows, 27583 cols, 133156 nonzeros 0s +20796 rows, 22169 cols, 103679 nonzeros 0s +14969 rows, 18049 cols, 75112 nonzeros 0s +12958 rows, 13328 cols, 56714 nonzeros 1s +Presolve reductions: rows 12958(-61321); columns 13328(-37644); nonzeros 56714(-175369) + +Solving MIP model with: + 12958 rows + 13328 cols (13124 binary, 0 integer, 204 implied int., 0 continuous, 0 domain fixed) + 56714 nonzeros + Thread count 1 (of 10 threads). Using 1 max workers. Parallel search off + +Src: B => Branching; C => Central rounding; F => Feasibility pump; H => Heuristic; + I => Shifting; J => Feasibility jump; L => Sub-MIP; P => Empty MIP; R => Randomized rounding; + S => Solve LP; T => Evaluate node; U => Unbounded; X => User solution; Y => HiGHS solution; + Z => ZI Round; l => Trivial lower; p => Trivial point; u => Trivial upper; z => Trivial zero + + Nodes | B&B Tree | Objective Bounds | Dynamic Constraints | Work +Src Proc. InQueue | Leaves Expl. | BestBound BestSol Gap | Cuts InLp Confl. | LpIters Time + + J 0 0 0 0.00% -inf 5254.062926 Large 0 0 0 0 1.2s + 0 0 0 0.00% 5250.252933 5254.062926 0.07% 0 0 2 7048 1.4s + L 0 0 0 0.00% 5250.456461 5250.467249 0.00% 5125 98 149 8548 5.1s + 1 0 1 100.00% 5250.456461 5250.467249 0.00% 5125 98 149 10782 5.1s + +Solving report + Status Optimal + Primal bound 5250.46724884 + Dual bound 5250.45646089 + Gap 0.000205% (tolerance: 0.01%) + P-D integral 0.0900543950578 + Solution status feasible + 5250.46724884 (objective) + 0 (bound viol.) + 2.56461518688e-14 (int. viol.) + 0 (row viol.) + Timing 5.12 + 1.35 (Presolve) + MIP time [calls] = 1.05 [1] + subMIP time [calls] = 0.29 [3] + 3.77 (Solve) + MIP time [calls] = 1.83 [1] + subMIP time [calls] = 1.95 [3] + 0.00 (Postsolve) + MIP time [calls] = 0.00 [1] + subMIP time [calls] = 0.00 [3] + Max sub-MIP depth 6 + Nodes 1 + Repair LPs 0 + LP iterations 10782 + 0 (strong br.) + 1500 (separation) + 2234 (heuristics) +status Optimal obj 5250.467248835251 mip_dual_bound 5250.456460888703 +current non-centre local cost 5253.116991559385 LB 5250.467248835251 headroom/local 2.64974272413383 linearized dC 0.0001929252616450354 +profile {1: 1906, 2: 340, 3: 382, 4: 168, 5: 48, 6: 102, 7: 1} diff --git a/research/frontier-word-reorder-ceilings/r13-reorder/logs/cons-backward-medium.txt b/research/frontier-word-reorder-ceilings/r13-reorder/logs/cons-backward-medium.txt new file mode 100644 index 0000000000..1b954a3f52 --- /dev/null +++ b/research/frontier-word-reorder-ceilings/r13-reorder/logs/cons-backward-medium.txt @@ -0,0 +1,77 @@ +vars 18205 rows 25542 V 4676 arcs 12397 hubs 339 const 2264.1356200372484 t 17.329953908920288 +Running HiGHS 1.15.1 (git hash: 04024d7): Copyright (c) 2026 under MIT licence terms +Includes third-party software components, see THIRD_PARTY_NOTICES.md for full details +MIP has 25542 rows; 18205 cols; 72487 nonzeros; 17073 integer variables (17073 binary) +Coefficient ranges: + Matrix [1e+00, 1e+00] + Cost [1e+00, 9e+00] + Bound [1e+00, 1e+00] + RHS [1e+00, 1e+00] +Assessing feasibility of MIP using primal feasibility and integrality tolerance of 1e-06 +WARNING: Row 2132 has infeasibility of 1 from [lower, value, upper] = [ 1; 0; 1] +Solution has num max sum +Col infeasibilities 0 0 0 +Integer infeasibilities 0 0 0 +Row infeasibilities 2835 1 2835 +Row residuals 0 0 0 +Attempting to find feasible solution by solving LP for user-supplied values of discrete variables +Presolving model +Problem status detected on presolve: Infeasible +Model status : Infeasible +Objective value : 0.0000000000e+00 +HiGHS run time : 0.01 +Presolving model +7654 rows, 11624 cols, 38546 nonzeros 0s +5394 rows, 9120 cols, 30414 nonzeros 0s +4279 rows, 8043 cols, 28948 nonzeros 0s +2370 rows, 4320 cols, 12712 nonzeros 0s +1600 rows, 3974 cols, 11394 nonzeros 0s +1532 rows, 2769 cols, 7876 nonzeros 0s +1156 rows, 2499 cols, 6773 nonzeros 0s +1154 rows, 1432 cols, 3763 nonzeros 0s +706 rows, 1349 cols, 3467 nonzeros 0s +604 rows, 455 cols, 748 nonzeros 0s +138 rows, 433 cols, 667 nonzeros 0s +20 rows, 37 cols, 82 nonzeros 0s +Presolve reductions: rows 20(-25522); columns 37(-18168); nonzeros 82(-72405) + +Solving MIP model with: + 20 rows + 37 cols (37 binary, 0 integer, 0 implied int., 0 continuous, 0 domain fixed) + 82 nonzeros + Thread count 1 (of 10 threads). Using 1 max workers. Parallel search off + +Src: B => Branching; C => Central rounding; F => Feasibility pump; H => Heuristic; + I => Shifting; J => Feasibility jump; L => Sub-MIP; P => Empty MIP; R => Randomized rounding; + S => Solve LP; T => Evaluate node; U => Unbounded; X => User solution; Y => HiGHS solution; + Z => ZI Round; l => Trivial lower; p => Trivial point; u => Trivial upper; z => Trivial zero + + Nodes | B&B Tree | Objective Bounds | Dynamic Constraints | Work +Src Proc. InQueue | Leaves Expl. | BestBound BestSol Gap | Cuts InLp Confl. | LpIters Time + + J 0 0 0 0.00% -inf 2988.981372 Large 0 0 0 0 0.2s + 1 0 1 100.00% 2988.981372 2988.981372 0.00% 0 0 0 5 0.2s + +Solving report + Status Optimal + Primal bound 2988.98137152 + Dual bound 2988.98137152 + Gap 0% (tolerance: 1e-05%) + P-D integral 2.42022547951e-06 + Solution status feasible + 2988.98137152 (objective) + 0 (bound viol.) + 0 (int. viol.) + 0 (row viol.) + Timing 0.19 + 0.18 (Presolve) + 0.01 (Solve) + 0.00 (Postsolve) + Max sub-MIP depth 0 + Nodes 1 + Repair LPs 0 + LP iterations 5 + 0 (strong br.) + 0 (separation) + 0 (heuristics) +status Optimal cost 5253.116991559382 bound 5253.116991559382 current 5253.116991559385 diff --git a/research/frontier-word-reorder-ceilings/r13-reorder/logs/cons-forward-medium.txt b/research/frontier-word-reorder-ceilings/r13-reorder/logs/cons-forward-medium.txt new file mode 100644 index 0000000000..5d31e5da98 --- /dev/null +++ b/research/frontier-word-reorder-ceilings/r13-reorder/logs/cons-forward-medium.txt @@ -0,0 +1,77 @@ +vars 18205 rows 25542 V 4676 arcs 12397 hubs 339 const 2264.1356200372484 t 18.416934967041016 +Running HiGHS 1.15.1 (git hash: 04024d7): Copyright (c) 2026 under MIT licence terms +Includes third-party software components, see THIRD_PARTY_NOTICES.md for full details +MIP has 25542 rows; 18205 cols; 72487 nonzeros; 17073 integer variables (17073 binary) +Coefficient ranges: + Matrix [1e+00, 1e+00] + Cost [1e+00, 9e+00] + Bound [1e+00, 1e+00] + RHS [1e+00, 1e+00] +Assessing feasibility of MIP using primal feasibility and integrality tolerance of 1e-06 +WARNING: Row 2132 has infeasibility of 1 from [lower, value, upper] = [ 1; 0; 1] +Solution has num max sum +Col infeasibilities 0 0 0 +Integer infeasibilities 0 0 0 +Row infeasibilities 2835 1 2835 +Row residuals 0 0 0 +Attempting to find feasible solution by solving LP for user-supplied values of discrete variables +Presolving model +Problem status detected on presolve: Infeasible +Model status : Infeasible +Objective value : 0.0000000000e+00 +HiGHS run time : 0.01 +Presolving model +7653 rows, 11624 cols, 38539 nonzeros 0s +5394 rows, 9120 cols, 30414 nonzeros 0s +4279 rows, 8043 cols, 28948 nonzeros 0s +2370 rows, 4320 cols, 12712 nonzeros 0s +1600 rows, 3974 cols, 11394 nonzeros 0s +1532 rows, 2769 cols, 7876 nonzeros 0s +1156 rows, 2499 cols, 6773 nonzeros 0s +1154 rows, 1432 cols, 3763 nonzeros 0s +706 rows, 1349 cols, 3467 nonzeros 0s +604 rows, 455 cols, 748 nonzeros 0s +138 rows, 433 cols, 667 nonzeros 0s +20 rows, 37 cols, 82 nonzeros 0s +Presolve reductions: rows 20(-25522); columns 37(-18168); nonzeros 82(-72405) + +Solving MIP model with: + 20 rows + 37 cols (37 binary, 0 integer, 0 implied int., 0 continuous, 0 domain fixed) + 82 nonzeros + Thread count 1 (of 10 threads). Using 1 max workers. Parallel search off + +Src: B => Branching; C => Central rounding; F => Feasibility pump; H => Heuristic; + I => Shifting; J => Feasibility jump; L => Sub-MIP; P => Empty MIP; R => Randomized rounding; + S => Solve LP; T => Evaluate node; U => Unbounded; X => User solution; Y => HiGHS solution; + Z => ZI Round; l => Trivial lower; p => Trivial point; u => Trivial upper; z => Trivial zero + + Nodes | B&B Tree | Objective Bounds | Dynamic Constraints | Work +Src Proc. InQueue | Leaves Expl. | BestBound BestSol Gap | Cuts InLp Confl. | LpIters Time + + J 0 0 0 0.00% -inf 2988.981372 Large 0 0 0 0 0.2s + 1 0 1 100.00% 2988.981372 2988.981372 0.00% 0 0 0 5 0.2s + +Solving report + Status Optimal + Primal bound 2988.98137152 + Dual bound 2988.98137152 + Gap 0% (tolerance: 1e-05%) + P-D integral 1.03736777178e-05 + Solution status feasible + 2988.98137152 (objective) + 0 (bound viol.) + 0 (int. viol.) + 0 (row viol.) + Timing 0.20 + 0.18 (Presolve) + 0.01 (Solve) + 0.00 (Postsolve) + Max sub-MIP depth 0 + Nodes 1 + Repair LPs 0 + LP iterations 5 + 0 (strong br.) + 0 (separation) + 0 (heuristics) +status Optimal cost 5253.116991559382 bound 5253.116991559382 current 5253.116991559385 diff --git a/research/frontier-word-reorder-ceilings/r13-reorder/logs/cons-forward-wide-lp.txt b/research/frontier-word-reorder-ceilings/r13-reorder/logs/cons-forward-wide-lp.txt new file mode 100644 index 0000000000..1106a20830 --- /dev/null +++ b/research/frontier-word-reorder-ceilings/r13-reorder/logs/cons-forward-wide-lp.txt @@ -0,0 +1,177 @@ +vars 3027094 rows 340588 V 91690 arcs 2931555 hubs 1140 const 1870.5582598933547 t 32.4970281124115 +Running HiGHS 1.15.1 (git hash: 04024d7): Copyright (c) 2026 under MIT licence terms +Includes third-party software components, see THIRD_PARTY_NOTICES.md for full details +LP has 340588 rows; 3027094 cols; 10649569 nonzeros +Coefficient ranges: + Matrix [1e+00, 1e+00] + Cost [1e+00, 9e+00] + Bound [1e+00, 1e+00] + RHS [1e+00, 1e+00] +Presolving model +310361 rows, 3016558 cols, 10578398 nonzeros 2s +208343 rows, 2608001 cols, 6715518 nonzeros 18s +Dependent equations search running on 119343 equations with time limit of 24.00s +Dependent equations search removed 460 rows and 341372 nonzeros in 5.74s (limit = 24.00s) +207547 rows, 2492782 cols, 6145005 nonzeros 35s +Presolve reductions: rows 207547(-133041); columns 2492782(-534312); nonzeros 6145005(-4504564) +Solving the presolved LP +IPX model has 207547 rows, 2492782 columns and 6145005 nonzeros +Input + Number of variables: 2492782 + Number of free variables: 0 + Number of constraints: 207547 + Number of equality constraints: 118891 + Number of matrix entries: 6145005 + Matrix range: [1e+00, 1e+00] + RHS range: [1e+00, 1e+00] + Objective range: [3e-03, 9e+00] + Bounds range: [1e+00, 4e+01] +Preprocessing + Dualized model: no + Number of dense columns: 0 + Range of scaling factors: [1.00e+00, 1.00e+00] + Scaled cost norm: 8.96582 + Scaled bounds norm: 35 +IPX version 1.0 +Interior point solve + Iter primal obj dual obj pinf dinf gap time + 0 3.09771596e+03 -2.95916207e+07 7.93e-02 1.05e+00 2.00e+00 39.6 + 1 8.22987084e+04 -2.03286929e+07 2.94e-02 2.39e-01 2.02e+00 42.3 + 2 4.86701211e+04 -1.41281121e+07 6.68e-03 1.04e-01 2.01e+00 44.4 + 3 1.81614948e+04 -6.06898477e+06 2.15e-03 3.94e-02 2.01e+00 46.3 + 4 9.83535321e+03 -3.56699193e+06 9.82e-04 1.90e-02 2.01e+00 48.2 + 5 6.70717480e+03 -1.91478993e+06 5.09e-04 8.27e-03 2.01e+00 50.4 + 6 5.23288629e+03 -1.11475932e+06 2.85e-04 3.84e-03 2.02e+00 53.8 + 7 4.51660537e+03 -7.89874343e+05 1.76e-04 2.20e-03 2.02e+00 62.9 + 8 4.18106585e+03 -6.03753482e+05 1.25e-04 1.35e-03 2.03e+00 70.5 + 9 3.84265718e+03 -4.59250157e+05 7.29e-05 8.62e-04 2.03e+00 80.7 + Constructing starting basis... + Iter primal obj dual obj pinf dinf gap time + 10 3.67351202e+03 -3.70504792e+05 4.58e-05 5.93e-04 2.04e+00 108.5 + 11 3.58539904e+03 -2.89321557e+05 3.17e-05 3.44e-04 2.05e+00 122.3 + 12 3.55658318e+03 -2.43693960e+05 2.71e-05 2.33e-04 2.06e+00 138.7 + 13 3.52797564e+03 -1.86879431e+05 2.25e-05 1.09e-04 2.08e+00 155.0 + 14 3.43217076e+03 -1.01600568e+05 7.22e-06 3.62e-05 2.14e+00 171.8 + 15 3.41783643e+03 -9.17211149e+04 4.92e-06 2.88e-05 2.15e+00 204.2 + 16 3.40082815e+03 -6.81418276e+04 2.20e-06 1.36e-05 2.21e+00 225.5 + 17 3.39009523e+03 -4.33413057e+04 4.83e-07 6.59e-06 2.34e+00 245.8 + 18 3.38961534e+03 -3.89813190e+04 4.06e-07 4.85e-06 2.38e+00 305.3 + 19 3.38867733e+03 -3.15972151e+04 2.57e-07 2.95e-06 2.48e+00 329.2 + 20 3.38773546e+03 -2.29872424e+04 1.08e-07 1.36e-06 2.69e+00 347.9 + 21 3.38702060e+03 8.27473286e+01 2.34e-09 1.06e-07 1.90e+00 369.1 + 22 3.38682119e+03 2.09457968e+03 1.27e-09 2.14e-08 4.71e-01 395.0 + 23 3.38649436e+03 2.66818382e+03 6.41e-10 2.21e-09 2.37e-01 413.7 + 24 3.38630327e+03 2.89510825e+03 4.49e-10 3.59e-13 1.56e-01 429.9 + 25 3.38577511e+03 3.11165676e+03 6.53e-11 3.65e-13 8.44e-02 443.8 + 26 3.38570008e+03 3.12881417e+03 5.47e-11 3.90e-13 7.88e-02 461.6 + 27 3.38543445e+03 3.23660732e+03 2.83e-11 5.15e-13 4.49e-02 475.6 + 28 3.38537859e+03 3.25761043e+03 2.50e-11 7.30e-13 3.85e-02 492.6 + 29 3.38504621e+03 3.30270509e+03 1.08e-11 7.47e-13 2.46e-02 509.1 + 30 3.38500435e+03 3.30455126e+03 1.02e-11 7.59e-13 2.40e-02 535.3 + 31 3.38475197e+03 3.32011264e+03 6.32e-12 7.30e-13 1.93e-02 552.0 + 32 3.38462732e+03 3.33045312e+03 5.15e-12 5.20e-13 1.61e-02 575.1 + 33 3.38457971e+03 3.33190929e+03 4.75e-12 7.30e-13 1.57e-02 592.7 + 34 3.38447284e+03 3.33504404e+03 3.76e-12 7.30e-13 1.47e-02 607.7 + 35 3.38435068e+03 3.33796497e+03 2.62e-12 8.65e-13 1.38e-02 628.7 + 36 3.38429345e+03 3.33990291e+03 2.38e-12 8.91e-13 1.32e-02 645.8 + 37 3.38424487e+03 3.34306461e+03 2.07e-12 7.30e-13 1.22e-02 661.5 + 38 3.38416193e+03 3.34665411e+03 1.62e-12 1.10e-12 1.11e-02 674.7 + 39 3.38408365e+03 3.34855505e+03 1.26e-12 7.30e-13 1.06e-02 689.5 + 40 3.38397589e+03 3.35539803e+03 1.05e-12 7.30e-13 8.48e-03 703.8 + 41 3.38387639e+03 3.35719241e+03 8.17e-13 4.50e-13 7.91e-03 723.0 + 42 3.38381371e+03 3.35957623e+03 7.32e-13 7.67e-13 7.19e-03 739.9 + 43 3.38369756e+03 3.36124890e+03 5.32e-13 7.30e-13 6.65e-03 759.0 + 44 3.38362608e+03 3.36207913e+03 4.37e-13 7.97e-13 6.39e-03 776.4 + 45 3.38360478e+03 3.36359380e+03 3.91e-13 7.49e-13 5.93e-03 791.4 + 46 3.38343131e+03 3.36653235e+03 2.65e-13 7.30e-13 5.01e-03 810.0 + 47 3.38337974e+03 3.36876239e+03 2.20e-13 5.45e-13 4.33e-03 835.2 + 48 3.38334544e+03 3.36929016e+03 1.91e-13 5.97e-13 4.16e-03 856.1 + 49 3.38325138e+03 3.36971364e+03 1.54e-13 7.30e-13 4.01e-03 872.6 + 50 3.38319581e+03 3.37002745e+03 1.29e-13 8.33e-13 3.90e-03 895.9 + 51 3.38314580e+03 3.37129577e+03 1.15e-13 7.30e-13 3.51e-03 912.2 + 52 3.38310983e+03 3.37169594e+03 1.04e-13 9.80e-13 3.38e-03 930.9 + 53 3.38308288e+03 3.37223596e+03 9.17e-14 1.10e-12 3.21e-03 949.7 + 54 3.38300728e+03 3.37430227e+03 7.87e-14 8.94e-13 2.58e-03 970.2 + 55 3.38294445e+03 3.37489077e+03 6.81e-14 7.30e-13 2.38e-03 1030.9 + 56 3.38290864e+03 3.37506205e+03 6.19e-14 7.72e-13 2.32e-03 1063.7 + 57 3.38289745e+03 3.37508462e+03 5.83e-14 1.10e-12 2.31e-03 1083.2 + 58 3.38287093e+03 3.37597204e+03 5.55e-14 1.10e-12 2.04e-03 1099.1 + 59 3.38286437e+03 3.37598184e+03 5.39e-14 1.10e-12 2.04e-03 1114.8 + 60 3.38284886e+03 3.37671379e+03 5.20e-14 9.26e-13 1.81e-03 1128.0 + 61 3.38283642e+03 3.37672463e+03 4.97e-14 7.30e-13 1.81e-03 1139.1 + 62 3.38277878e+03 3.37721789e+03 4.38e-14 6.36e-13 1.64e-03 1149.4 + 63 3.38277317e+03 3.37723714e+03 4.22e-14 7.30e-13 1.64e-03 1163.5 + 64 3.38274389e+03 3.37730584e+03 3.73e-14 7.30e-13 1.61e-03 1173.5 + 65 3.38268221e+03 3.37768774e+03 3.18e-14 5.42e-13 1.48e-03 1182.7 + 66 3.38266509e+03 3.37778296e+03 2.96e-14 6.41e-13 1.44e-03 1193.7 + 67 3.38258470e+03 3.37813110e+03 2.25e-14 7.30e-13 1.32e-03 1202.8 + 68 3.38257510e+03 3.37823538e+03 2.17e-14 7.30e-13 1.28e-03 1212.8 + 69 3.38246831e+03 3.37842454e+03 1.67e-14 7.51e-13 1.20e-03 1221.8 + 70 3.38246385e+03 3.37843095e+03 1.62e-14 7.30e-13 1.19e-03 1239.1 + 71 3.38243183e+03 3.37872039e+03 1.45e-14 7.30e-13 1.10e-03 1249.7 + 72 3.38241183e+03 3.37896038e+03 1.32e-14 7.30e-13 1.02e-03 1263.6 + 73 3.38235887e+03 3.37910967e+03 1.11e-14 7.30e-13 9.61e-04 1275.1 + 74 3.38233749e+03 3.37916178e+03 1.03e-14 7.30e-13 9.39e-04 1283.9 + 75 3.38233207e+03 3.37917522e+03 9.67e-15 7.30e-13 9.33e-04 1291.9 + 76 3.38229852e+03 3.37939059e+03 8.68e-15 1.10e-12 8.60e-04 1299.4 + 77 3.38226688e+03 3.37955516e+03 7.89e-15 9.25e-13 8.02e-04 1309.0 + 78 3.38225992e+03 3.37959417e+03 7.50e-15 1.12e-12 7.88e-04 1317.5 + 79 3.38224609e+03 3.37965876e+03 6.91e-15 1.07e-12 7.65e-04 1323.0 + 80 3.38224483e+03 3.37966208e+03 7.11e-15 1.17e-12 7.64e-04 1328.3 + 81 3.38220488e+03 3.37981937e+03 5.92e-15 1.46e-12 7.05e-04 1333.2 + 82 3.38218447e+03 3.37987020e+03 5.53e-15 9.89e-13 6.84e-04 1339.0 + 83 3.38212854e+03 3.38004527e+03 4.54e-15 1.10e-12 6.16e-04 1344.1 + 84 3.38210091e+03 3.38012622e+03 4.14e-15 1.20e-12 5.84e-04 1350.6 + 85 3.38208509e+03 3.38021271e+03 3.75e-15 1.16e-12 5.54e-04 1356.8 + 86 3.38207046e+03 3.38024701e+03 3.16e-15 9.36e-13 5.39e-04 1361.8 + 87 3.38206275e+03 3.38025895e+03 3.16e-15 7.30e-13 5.33e-04 1366.3 + 88 3.38203473e+03 3.38045688e+03 2.76e-15 7.30e-13 4.67e-04 1370.7 + 89 3.38202988e+03 3.38047013e+03 2.76e-15 7.30e-13 4.61e-04 1375.2 + 90 3.38200772e+03 3.38051663e+03 2.57e-15 6.30e-13 4.41e-04 1379.1 + 91 3.38198393e+03 3.38061006e+03 2.37e-15 7.30e-13 4.06e-04 1383.5 + 92 3.38198098e+03 3.38061661e+03 2.17e-15 7.30e-13 4.03e-04 1387.6 + 93 3.38196072e+03 3.38069174e+03 1.97e-15 7.91e-13 3.75e-04 1391.5 + 94 3.38191877e+03 3.38076039e+03 1.78e-15 5.64e-13 3.42e-04 1396.1 + 95 3.38189535e+03 3.38078118e+03 1.58e-15 5.38e-13 3.29e-04 1401.9 + 96 3.38186696e+03 3.38080911e+03 1.38e-15 1.10e-12 3.13e-04 1409.5 + 97 3.38183281e+03 3.38085943e+03 1.18e-15 8.97e-13 2.88e-04 1414.9 + 98 3.38182266e+03 3.38086111e+03 1.18e-15 7.43e-13 2.84e-04 1420.2 + 99 3.38178315e+03 3.38086518e+03 9.87e-16 7.30e-13 2.71e-04 1424.2 + 100 3.38172643e+03 3.38092405e+03 6.91e-16 1.10e-12 2.37e-04 1427.9 + 101 3.38169948e+03 3.38097833e+03 5.92e-16 7.30e-13 2.13e-04 1433.6 + 102 3.38168710e+03 3.38101612e+03 5.92e-16 7.30e-13 1.98e-04 1440.3 + 103 3.38166830e+03 3.38106983e+03 4.93e-16 8.12e-13 1.77e-04 1444.8 + 104 3.38160042e+03 3.38110400e+03 3.95e-16 8.57e-13 1.47e-04 1449.8 + 105 3.38152283e+03 3.38116551e+03 1.97e-16 6.05e-13 1.06e-04 1454.5 + 106 3.38151668e+03 3.38120437e+03 1.97e-16 7.50e-13 9.23e-05 1458.9 + 107 3.38151082e+03 3.38121197e+03 1.97e-16 8.71e-13 8.84e-05 1466.3 + 108 3.38148765e+03 3.38122038e+03 1.97e-16 9.38e-13 7.90e-05 1471.4 + 109 3.38144579e+03 3.38123000e+03 1.17e-16 8.53e-13 6.38e-05 1475.8 + 110 3.38143073e+03 3.38127761e+03 1.97e-16 8.88e-13 4.53e-05 1481.0 + 111 3.38141823e+03 3.38133190e+03 1.97e-16 6.45e-13 2.55e-05 1485.6 + 112 3.38141369e+03 3.38134024e+03 1.97e-16 7.64e-13 2.17e-05 1491.1 + 113 3.38140119e+03 3.38136378e+03 1.97e-16 6.51e-13 1.11e-05 1496.5 + 114 3.38138944e+03 3.38138200e+03 1.97e-16 7.77e-13 2.20e-06 1500.9 + 115 3.38138789e+03 3.38138604e+03 9.87e-17 5.99e-13 5.48e-07 1504.9 + 116 3.38138790e+03 3.38138625e+03 1.97e-16 7.94e-13 4.90e-07 1509.6 + 117 3.38138792e+03 3.38138671e+03 1.97e-16 7.44e-13 3.57e-07 1514.1 + 118 3.38138777e+03 3.38138761e+03 1.11e-16 7.75e-13 4.52e-08 1519.2 + 119* 3.38138767e+03 3.38138766e+03 1.97e-16 7.87e-13 4.00e-09 1523.4 +Summary + Runtime: 1523.50s + Status interior point solve: optimal + Status crossover: not run + objective value: 3.38138767e+03 + interior solution primal residual (abs/rel): 7.11e-15 / 1.97e-16 + interior solution dual residual (abs/rel): 1.90e-10 / 1.90e-11 + interior solution objective gap (abs/rel): 1.35e-05 / 4.00e-09 +Ipx: IPM optimal + +Performed postsolve + +Model status : Optimal +IPM iterations: 119 +Objective value : 3.3813876722e+03 +P-D objective error : 1.3082204811e-09 +HiGHS run time : 1524.10 +status Optimal cost 5251.9459321091235 bound nan current 5253.116991559385 diff --git a/research/frontier-word-reorder-ceilings/r13-reorder/logs/cons-forward-wide.txt b/research/frontier-word-reorder-ceilings/r13-reorder/logs/cons-forward-wide.txt new file mode 100644 index 0000000000..faebd2a74e --- /dev/null +++ b/research/frontier-word-reorder-ceilings/r13-reorder/logs/cons-forward-wide.txt @@ -0,0 +1,35 @@ +vars 3027094 rows 340588 V 91690 arcs 2931555 hubs 1140 const 1870.5582598933547 t 34.53424620628357 +Running HiGHS 1.15.1 (git hash: 04024d7): Copyright (c) 2026 under MIT licence terms +Includes third-party software components, see THIRD_PARTY_NOTICES.md for full details +MIP has 340588 rows; 3027094 cols; 10649569 nonzeros; 3023245 integer variables (3023245 binary) +Coefficient ranges: + Matrix [1e+00, 1e+00] + Cost [1e+00, 9e+00] + Bound [1e+00, 1e+00] + RHS [1e+00, 1e+00] +Assessing feasibility of MIP using primal feasibility and integrality tolerance of 1e-06 +WARNING: Row 2132 has infeasibility of 1 from [lower, value, upper] = [ 1; 0; 1] +Solution has num max sum +Col infeasibilities 0 0 0 +Integer infeasibilities 0 0 0 +Row infeasibilities 4434 1 4434 +Row residuals 0 0 0 +Attempting to find feasible solution by solving LP for user-supplied values of discrete variables +Presolving model +Problem status detected on presolve: Infeasible +Model status : Infeasible +Objective value : 0.0000000000e+00 +HiGHS run time : 0.95 +Presolving model +310372 rows, 3021858 cols, 10604028 nonzeros 3s + Considered 1276 / 2972857 binaries; 1276 probed (rate 3/ms => expected probing finish time 11706s) 58s + Considered 2461 / 2972857 binaries; 2461 probed (rate 4/ms => expected probing finish time 12646s) 63s + Considered 1337 / 2633690 binaries; 1337 probed (rate 3/ms => expected probing finish time 9947s) 97s +238793 rows, 2515271 cols, 7734767 nonzeros 99s + Considered 2155 / 2514177 binaries; 2155 probed (rate 2/ms => expected probing finish time 5963s) 123s + Considered 1982 / 2512430 binaries; 1982 probed (rate 2/ms => expected probing finish time 6484s) 143s + Considered 2320 / 2510653 binaries; 2320 probed (rate 2/ms => expected probing finish time 5571s) 163s + Considered 2069 / 2509062 binaries; 2069 probed (rate 2/ms => expected probing finish time 6243s) 184s + Considered 2347 / 2507470 binaries; 2347 probed (rate 2/ms => expected probing finish time 5547s) 208s + Considered 2055 / 2506031 binaries; 2055 probed (rate 2/ms => expected probing finish time 6335s) 232s + Considered 2093 / 2504337 binaries; 2093 probed (rate 2/ms => expected probing finish time 6245s) 258s diff --git a/research/frontier-word-reorder-ceilings/r13-reorder/logs/cons-forward.txt b/research/frontier-word-reorder-ceilings/r13-reorder/logs/cons-forward.txt new file mode 100644 index 0000000000..11b3b367ae --- /dev/null +++ b/research/frontier-word-reorder-ceilings/r13-reorder/logs/cons-forward.txt @@ -0,0 +1,68 @@ +vars 6440 rows 6922 V 2643 arcs 3560 hubs 56 const 2409.628225694342 t 17.56764268875122 +Running HiGHS 1.15.1 (git hash: 04024d7): Copyright (c) 2026 under MIT licence terms +Includes third-party software components, see THIRD_PARTY_NOTICES.md for full details +MIP has 6922 rows; 6440 cols; 16172 nonzeros; 6203 integer variables (6203 binary) +Coefficient ranges: + Matrix [1e+00, 1e+00] + Cost [1e+00, 9e+00] + Bound [1e+00, 1e+00] + RHS [1e+00, 1e+00] +Assessing feasibility of MIP using primal feasibility and integrality tolerance of 1e-06 +WARNING: Row 2132 has infeasibility of 1 from [lower, value, upper] = [ 1; 0; 1] +Solution has num max sum +Col infeasibilities 0 0 0 +Integer infeasibilities 0 0 0 +Row infeasibilities 2352 1 2352 +Row residuals 0 0 0 +Attempting to find feasible solution by solving LP for user-supplied values of discrete variables +Presolving model +Problem status detected on presolve: Infeasible +Model status : Infeasible +Objective value : 0.0000000000e+00 +HiGHS run time : 0.00 +Presolving model +1076 rows, 1270 cols, 3228 nonzeros 0s +248 rows, 462 cols, 1247 nonzeros 0s +175 rows, 378 cols, 1031 nonzeros 0s +129 rows, 307 cols, 859 nonzeros 0s +127 rows, 224 cols, 625 nonzeros 0s +92 rows, 188 cols, 466 nonzeros 0s +68 rows, 119 cols, 345 nonzeros 0s +57 rows, 95 cols, 270 nonzeros 0s +32 rows, 55 cols, 156 nonzeros 0s +26 rows, 46 cols, 129 nonzeros 0s +20 rows, 0 cols, 0 nonzeros 0s +0 rows, 0 cols, 0 nonzeros 0s +Presolve reductions: rows 0(-6922); columns 0(-6440); nonzeros 0(-16172) - Reduced to empty +Presolve: Optimal + +Src: B => Branching; C => Central rounding; F => Feasibility pump; H => Heuristic; + I => Shifting; J => Feasibility jump; L => Sub-MIP; P => Empty MIP; R => Randomized rounding; + S => Solve LP; T => Evaluate node; U => Unbounded; X => User solution; Y => HiGHS solution; + Z => ZI Round; l => Trivial lower; p => Trivial point; u => Trivial upper; z => Trivial zero + + Nodes | B&B Tree | Objective Bounds | Dynamic Constraints | Work +Src Proc. InQueue | Leaves Expl. | BestBound BestSol Gap | Cuts InLp Confl. | LpIters Time + + 0 0 0 0.00% 2843.488766 2843.488766 0.00% 0 0 0 0 0.0s + +Solving report + Status Optimal + Primal bound 2843.48876587 + Dual bound 2843.48876587 + Gap 0% (tolerance: 1e-05%) + P-D integral 0 + Solution status feasible + 2843.48876587 (objective) + 0 (bound viol.) + 0 (int. viol.) + 0 (row viol.) + Timing 0.01 + 0.01 (Presolve) + 0.00 (Solve) + 0.00 (Postsolve) + Max sub-MIP depth 0 + Nodes 0 + Repair LPs 0 + LP iterations 0 +status Optimal cost 5253.116991559382 bound 5253.1169915593855 current 5253.116991559385 diff --git a/research/frontier-word-reorder-ceilings/r13-reorder/logs/me-f-0.txt b/research/frontier-word-reorder-ceilings/r13-reorder/logs/me-f-0.txt new file mode 100644 index 0000000000..d1bbce30b3 --- /dev/null +++ b/research/frontier-word-reorder-ceilings/r13-reorder/logs/me-f-0.txt @@ -0,0 +1,38 @@ +INFEASIBLE (224, 2, 8136) next ValueError('min() iterable argument is empty') +INFEASIBLE (224, 2, 8136) prev ValueError('min() iterable argument is empty') +INFEASIBLE (229, 89, 8141) next ValueError('min() iterable argument is empty') +INFEASIBLE (229, 89, 8141) prev AssertionError(('empty', 11619)) +EVAL (236, 9, 8148) next Optimal 5253.116991559382 gain 2.7284841053187847e-12 (8148, 8160, 'next', ['add', ['L', 236], ['L', 7], 1, 1], ['add', ['L', 7], ['L', 237], 1, 1], ['add', ['L', 236], ['L', 237], -1, 1]) 39.0 +INFEASIBLE (236, 9, 8148) prev AssertionError(('empty', 10423)) +INFEASIBLE (225, 354, 8195) next AssertionError(((231, 0), 9, 29)) +INFEASIBLE (225, 354, 8195) prev ValueError('min() iterable argument is empty') +INFEASIBLE (245, 92, 8295) next ValueError('min() iterable argument is empty') +INFEASIBLE (245, 92, 8295) prev ValueError('min() iterable argument is empty') +EVAL (252, 12, 8302) next Optimal 5253.116991559382 gain 2.7284841053187847e-12 (8302, 8314, 'next', ['add', ['L', 252], ['L', 10], 1, 1], ['add', ['L', 10], ['L', 253], 1, 1], ['add', ['L', 252], ['L', 253], -1, 1]) 37.6 +INFEASIBLE (252, 12, 8302) prev ValueError('min() iterable argument is empty') +INFEASIBLE (241, 374, 8349) next AssertionError(((247, 0), 12, 93)) +INFEASIBLE (241, 374, 8349) prev ValueError('min() iterable argument is empty') +INFEASIBLE (261, 27, 8449) next ValueError('min() iterable argument is empty') +INFEASIBLE (261, 27, 8449) prev ValueError('min() iterable argument is empty') +EVAL (268, 81, 8456) next Optimal 5253.116991559382 gain 2.7284841053187847e-12 (8456, 8468, 'next', ['add', ['L', 268], ['L', 79], 1, 1], ['add', ['L', 79], ['L', 269], 1, 1], ['add', ['L', 268], ['L', 269], -1, 1]) 32.1 +INFEASIBLE (268, 81, 8456) prev ValueError('min() iterable argument is empty') +INFEASIBLE (257, 394, 8503) next AssertionError(((263, 0), 81, 91)) +INFEASIBLE (257, 394, 8503) prev ValueError('min() iterable argument is empty') +INFEASIBLE (277, 58, 8603) next ValueError('min() iterable argument is empty') +INFEASIBLE (277, 58, 8603) prev ValueError('min() iterable argument is empty') +EVAL (284, 40, 8610) next Optimal 5253.116991559382 gain 2.7284841053187847e-12 (8610, 8622, 'next', ['add', ['L', 284], ['L', 38], 1, 1], ['add', ['L', 38], ['L', 285], 1, 1], ['add', ['L', 284], ['L', 285], -1, 1]) 38.9 +INFEASIBLE (284, 40, 8610) prev ValueError('min() iterable argument is empty') +INFEASIBLE (273, 414, 8657) next AssertionError(((279, 0), 33, 40)) +INFEASIBLE (273, 414, 8657) prev ValueError('min() iterable argument is empty') +INFEASIBLE (293, 104, 8757) next ValueError('min() iterable argument is empty') +INFEASIBLE (293, 104, 8757) prev ValueError('min() iterable argument is empty') +EVAL (300, 21, 8764) next Optimal 5253.116991559382 gain 2.7284841053187847e-12 (8764, 8776, 'next', ['add', ['L', 300], ['L', 19], 1, 1], ['add', ['L', 19], ['L', 301], 1, 1], ['add', ['L', 300], ['L', 301], -1, 1]) 33.0 +INFEASIBLE (300, 21, 8764) prev AssertionError(('empty', 11094)) +INFEASIBLE (289, 434, 8811) next AssertionError(((295, 0), 21, 57)) +INFEASIBLE (289, 434, 8811) prev ValueError('min() iterable argument is empty') +INFEASIBLE (309, 34, 8911) next ValueError('min() iterable argument is empty') +INFEASIBLE (309, 34, 8911) prev ValueError('min() iterable argument is empty') +EVAL (316, 26, 8918) next Optimal 5253.116991559382 gain 2.7284841053187847e-12 (8918, 8930, 'next', ['add', ['L', 316], ['L', 24], 1, 1], ['add', ['L', 24], ['L', 317], 1, 1], ['add', ['L', 316], ['L', 317], -1, 1]) 23.4 +INFEASIBLE (316, 26, 8918) prev ValueError('min() iterable argument is empty') +INFEASIBLE (307, 453, 8965) next AssertionError(((309, 0), 34, 37)) +INFEASIBLE (307, 453, 8965) prev ValueError('min() iterable argument is empty') diff --git a/research/frontier-word-reorder-ceilings/r13-reorder/logs/me-f-1.txt b/research/frontier-word-reorder-ceilings/r13-reorder/logs/me-f-1.txt new file mode 100644 index 0000000000..e7f54e8f1e --- /dev/null +++ b/research/frontier-word-reorder-ceilings/r13-reorder/logs/me-f-1.txt @@ -0,0 +1,39 @@ +INFEASIBLE (225, 2, 8137) next ValueError('min() iterable argument is empty') +INFEASIBLE (225, 2, 8137) prev ValueError('min() iterable argument is empty') +INFEASIBLE (230, 29, 8142) next ValueError('min() iterable argument is empty') +INFEASIBLE (230, 29, 8142) prev AssertionError(('empty', 11619)) +EVAL (238, 83, 8150) next Optimal 5253.116991559382 gain 2.7284841053187847e-12 (8150, 8164, 'next', ['add', ['L', 238], ['L', 81], 1, 1], ['add', ['L', 81], ['L', 239], 1, 1], ['add', ['L', 238], ['L', 239], -1, 1]) 40.1 +INFEASIBLE (238, 83, 8150) prev ValueError('min() iterable argument is empty') +INFEASIBLE (234, 355, 8196) next ValueError('min() iterable argument is empty') +INFEASIBLE (234, 355, 8196) prev ValueError('min() iterable argument is empty') +INFEASIBLE (246, 93, 8296) next ValueError('min() iterable argument is empty') +INFEASIBLE (246, 93, 8296) prev ValueError('min() iterable argument is empty') +EVAL (254, 13, 8304) next Optimal 5253.116991559382 gain 2.7284841053187847e-12 (8304, 8318, 'next', ['add', ['L', 254], ['L', 11], 1, 1], ['add', ['L', 11], ['L', 255], 1, 1], ['add', ['L', 254], ['L', 255], -1, 1]) 32.3 +INFEASIBLE (254, 13, 8304) prev ValueError('min() iterable argument is empty') +INFEASIBLE (250, 375, 8350) next ValueError('min() iterable argument is empty') +INFEASIBLE (250, 375, 8350) prev ValueError('min() iterable argument is empty') +INFEASIBLE (262, 91, 8450) next ValueError('min() iterable argument is empty') +INFEASIBLE (262, 91, 8450) prev ValueError('min() iterable argument is empty') +EVAL (270, 11, 8458) next Optimal 5253.116991559382 gain 2.7284841053187847e-12 (8458, 8472, 'next', ['add', ['L', 270], ['L', 9], 1, 1], ['add', ['L', 9], ['L', 271], 1, 1], ['add', ['L', 270], ['L', 271], -1, 1]) 32.6 +INFEASIBLE (270, 11, 8458) prev ValueError('min() iterable argument is empty') +INFEASIBLE (266, 395, 8504) next ValueError('min() iterable argument is empty') +INFEASIBLE (266, 395, 8504) prev ValueError('min() iterable argument is empty') +INFEASIBLE (278, 33, 8604) next ValueError('min() iterable argument is empty') +INFEASIBLE (278, 33, 8604) prev ValueError('min() iterable argument is empty') +EVAL (286, 79, 8612) next Optimal 5253.116991559382 gain 2.7284841053187847e-12 (8612, 8626, 'next', ['add', ['L', 286], ['L', 77], 1, 1], ['add', ['L', 77], ['L', 287], 1, 1], ['add', ['L', 286], ['L', 287], -1, 1]) 35.0 +INFEASIBLE (286, 79, 8612) prev ValueError('min() iterable argument is empty') +INFEASIBLE (282, 415, 8658) next ValueError('min() iterable argument is empty') +INFEASIBLE (282, 415, 8658) prev ValueError('min() iterable argument is empty') +INFEASIBLE (294, 57, 8758) next ValueError('min() iterable argument is empty') +INFEASIBLE (294, 57, 8758) prev ValueError('min() iterable argument is empty') +EVAL (302, 41, 8766) next Optimal 5253.116991559382 gain 2.7284841053187847e-12 (8766, 8780, 'next', ['add', ['L', 302], ['L', 39], 1, 1], ['add', ['L', 39], ['L', 303], 1, 1], ['add', ['L', 302], ['L', 303], -1, 1]) 34.5 +INFEASIBLE (302, 41, 8766) prev ValueError('min() iterable argument is empty') +INFEASIBLE (298, 435, 8812) next ValueError('min() iterable argument is empty') +INFEASIBLE (298, 435, 8812) prev ValueError('min() iterable argument is empty') +INFEASIBLE (310, 87, 8912) next ValueError('min() iterable argument is empty') +INFEASIBLE (310, 87, 8912) prev ValueError('min() iterable argument is empty') +EVAL (318, 37, 8920) next Optimal 5253.116991559382 gain 2.7284841053187847e-12 (8920, 8934, 'next', ['add', ['L', 318], ['L', 35], 1, 1], ['add', ['L', 35], ['L', 319], 1, 1], ['add', ['L', 318], ['L', 319], -1, 1]) 23.8 +INFEASIBLE (318, 37, 8920) prev ValueError('min() iterable argument is empty') +INFEASIBLE (305, 454, 8966) next AssertionError(((311, 0), 87, 26)) +INFEASIBLE (305, 454, 8966) prev ValueError('min() iterable argument is empty') +INFEASIBLE (323, 36, 9064) next ValueError('min() iterable argument is empty') diff --git a/research/frontier-word-reorder-ceilings/r13-reorder/logs/me-f-2.txt b/research/frontier-word-reorder-ceilings/r13-reorder/logs/me-f-2.txt new file mode 100644 index 0000000000..937ab2bb78 --- /dev/null +++ b/research/frontier-word-reorder-ceilings/r13-reorder/logs/me-f-2.txt @@ -0,0 +1,38 @@ +INFEASIBLE (226, 78, 8138) next ValueError('min() iterable argument is empty') +INFEASIBLE (226, 78, 8138) prev AssertionError(('empty', 11635)) +INFEASIBLE (231, 29, 8143) next ValueError('min() iterable argument is empty') +INFEASIBLE (231, 29, 8143) prev AssertionError(('empty', 11619)) +INFEASIBLE (229, 351, 8192) next AssertionError(((225, 0), 2, 9)) +INFEASIBLE (229, 351, 8192) prev ValueError('min() iterable argument is empty') +INFEASIBLE (241, 72, 8291) next ValueError('min() iterable argument is empty') +EVAL (241, 72, 8291) prev Optimal 5253.116991559382 gain 2.7284841053187847e-12 (8291, 8290, 'prev', ['add', ['L', 241], ['L', 240], 1, 1], ['add', ['L', 240], ['L', 70], 1, 1], ['add', ['L', 241], ['L', 70], 1, 1]) 29.3 +INFEASIBLE (247, 93, 8297) next ValueError('min() iterable argument is empty') +INFEASIBLE (247, 93, 8297) prev ValueError('min() iterable argument is empty') +INFEASIBLE (245, 371, 8346) next ValueError('min() iterable argument is empty') +INFEASIBLE (245, 371, 8346) prev ValueError('min() iterable argument is empty') +INFEASIBLE (257, 74, 8445) next ValueError('min() iterable argument is empty') +EVAL (257, 74, 8445) prev Optimal 5253.116991559382 gain 2.7284841053187847e-12 (8445, 8444, 'prev', ['add', ['L', 257], ['L', 256], 1, 1], ['add', ['L', 256], ['L', 72], 1, 1], ['add', ['L', 257], ['L', 72], 1, 1]) 32.8 +INFEASIBLE (263, 91, 8451) next ValueError('min() iterable argument is empty') +INFEASIBLE (263, 91, 8451) prev ValueError('min() iterable argument is empty') +INFEASIBLE (261, 391, 8500) next ValueError('min() iterable argument is empty') +INFEASIBLE (261, 391, 8500) prev ValueError('min() iterable argument is empty') +INFEASIBLE (273, 14, 8599) next ValueError('min() iterable argument is empty') +EVAL (273, 14, 8599) prev Optimal 5253.116991559382 gain 2.7284841053187847e-12 (8599, 8598, 'prev', ['add', ['L', 273], ['L', 272], 1, 1], ['add', ['L', 272], ['L', 12], 1, 1], ['add', ['L', 273], ['L', 12], 1, 1]) 36.0 +INFEASIBLE (279, 33, 8605) next ValueError('min() iterable argument is empty') +INFEASIBLE (279, 33, 8605) prev ValueError('min() iterable argument is empty') +INFEASIBLE (277, 411, 8654) next ValueError('min() iterable argument is empty') +INFEASIBLE (277, 411, 8654) prev ValueError('min() iterable argument is empty') +INFEASIBLE (289, 103, 8753) next ValueError('min() iterable argument is empty') +EVAL (289, 103, 8753) prev Optimal 5253.116991559382 gain 2.7284841053187847e-12 (8753, 8752, 'prev', ['add', ['L', 289], ['L', 288], 1, 1], ['add', ['L', 288], ['L', 101], 1, 1], ['add', ['L', 289], ['L', 101], 1, 1]) 36.9 +INFEASIBLE (295, 57, 8759) next ValueError('min() iterable argument is empty') +INFEASIBLE (295, 57, 8759) prev ValueError('min() iterable argument is empty') +INFEASIBLE (293, 431, 8808) next ValueError('min() iterable argument is empty') +INFEASIBLE (293, 431, 8808) prev ValueError('min() iterable argument is empty') +INFEASIBLE (305, 100, 8907) next ValueError('min() iterable argument is empty') +EVAL (305, 100, 8907) prev Optimal 5253.116991559382 gain 2.7284841053187847e-12 (8907, 8906, 'prev', ['add', ['L', 305], ['L', 304], 1, 1], ['add', ['L', 304], ['L', 98], 1, 1], ['add', ['L', 305], ['L', 98], 1, 1]) 25.6 +INFEASIBLE (311, 87, 8913) next ValueError('min() iterable argument is empty') +INFEASIBLE (311, 87, 8913) prev ValueError('min() iterable argument is empty') +INFEASIBLE (309, 451, 8962) next ValueError('min() iterable argument is empty') +INFEASIBLE (309, 451, 8962) prev ValueError('min() iterable argument is empty') +INFEASIBLE (314, 455, 8967) next ValueError('min() iterable argument is empty') +INFEASIBLE (314, 455, 8967) prev ValueError('min() iterable argument is empty') diff --git a/research/frontier-word-reorder-ceilings/r13-reorder/logs/me-f-3.txt b/research/frontier-word-reorder-ceilings/r13-reorder/logs/me-f-3.txt new file mode 100644 index 0000000000..3fa18be5ec --- /dev/null +++ b/research/frontier-word-reorder-ceilings/r13-reorder/logs/me-f-3.txt @@ -0,0 +1,37 @@ +INFEASIBLE (227, 78, 8139) next ValueError('min() iterable argument is empty') +INFEASIBLE (227, 78, 8139) prev AssertionError(('empty', 11635)) +EVAL (232, 94, 8144) next Optimal 5253.116991559382 gain 2.7284841053187847e-12 (8144, 8152, 'next', ['add', ['L', 232], ['L', 92], 1, 1], ['add', ['L', 92], ['L', 233], 1, 1], ['add', ['L', 232], ['L', 233], -1, 1]) 32.8 +INFEASIBLE (232, 94, 8144) prev AssertionError(('empty', 11619)) +INFEASIBLE (224, 352, 8193) next ValueError('min() iterable argument is empty') +INFEASIBLE (224, 352, 8193) prev ValueError('min() iterable argument is empty') +INFEASIBLE (243, 73, 8293) next ValueError('min() iterable argument is empty') +EVAL (243, 73, 8293) prev Optimal 5253.116991559382 gain 2.7284841053187847e-12 (8293, 8292, 'prev', ['add', ['L', 243], ['L', 242], 1, 1], ['add', ['L', 242], ['L', 71], 1, 1], ['add', ['L', 243], ['L', 71], 1, 1]) 31.4 +EVAL (248, 65, 8298) next Optimal 5253.116991559382 gain 2.7284841053187847e-12 (8298, 8306, 'next', ['add', ['L', 248], ['L', 63], 1, 1], ['add', ['L', 63], ['L', 249], 1, 1], ['add', ['L', 248], ['L', 249], -1, 1]) 34.5 +INFEASIBLE (248, 65, 8298) prev ValueError('min() iterable argument is empty') +INFEASIBLE (240, 372, 8347) next ValueError('min() iterable argument is empty') +INFEASIBLE (240, 372, 8347) prev ValueError('min() iterable argument is empty') +INFEASIBLE (259, 4, 8447) next ValueError('min() iterable argument is empty') +EVAL (259, 4, 8447) prev Optimal 5253.116991559382 gain 2.7284841053187847e-12 (8447, 8446, 'prev', ['add', ['L', 259], ['L', 258], 1, 1], ['add', ['L', 258], ['L', 2], 1, 1], ['add', ['L', 259], ['L', 2], 1, 1]) 35.8 +EVAL (264, 63, 8452) next Optimal 5253.116991559382 gain 2.7284841053187847e-12 (8452, 8460, 'next', ['add', ['L', 264], ['L', 61], 1, 1], ['add', ['L', 61], ['L', 265], 1, 1], ['add', ['L', 264], ['L', 265], -1, 1]) 33.3 +INFEASIBLE (264, 63, 8452) prev ValueError('min() iterable argument is empty') +INFEASIBLE (256, 392, 8501) next ValueError('min() iterable argument is empty') +INFEASIBLE (256, 392, 8501) prev ValueError('min() iterable argument is empty') +INFEASIBLE (275, 102, 8601) next ValueError('min() iterable argument is empty') +EVAL (275, 102, 8601) prev Optimal 5253.116991559382 gain 2.7284841053187847e-12 (8601, 8600, 'prev', ['add', ['L', 275], ['L', 274], 1, 1], ['add', ['L', 274], ['L', 100], 1, 1], ['add', ['L', 275], ['L', 100], 1, 1]) 35.5 +EVAL (280, 105, 8606) next Optimal 5253.116991559382 gain 2.7284841053187847e-12 (8606, 8614, 'next', ['add', ['L', 280], ['L', 103], 1, 1], ['add', ['L', 103], ['L', 281], 1, 1], ['add', ['L', 280], ['L', 281], -1, 1]) 35.2 +INFEASIBLE (280, 105, 8606) prev ValueError('min() iterable argument is empty') +INFEASIBLE (272, 412, 8655) next ValueError('min() iterable argument is empty') +INFEASIBLE (272, 412, 8655) prev ValueError('min() iterable argument is empty') +INFEASIBLE (291, 56, 8755) next ValueError('min() iterable argument is empty') +EVAL (291, 56, 8755) prev Optimal 5253.116991559382 gain 2.7284841053187847e-12 (8755, 8754, 'prev', ['add', ['L', 291], ['L', 290], 1, 1], ['add', ['L', 290], ['L', 54], 1, 1], ['add', ['L', 291], ['L', 54], 1, 1]) 31.3 +EVAL (296, 20, 8760) next Optimal 5253.116991559382 gain 2.7284841053187847e-12 (8760, 8768, 'next', ['add', ['L', 296], ['L', 18], 1, 1], ['add', ['L', 18], ['L', 297], 1, 1], ['add', ['L', 296], ['L', 297], -1, 1]) 32.3 +INFEASIBLE (296, 20, 8760) prev ValueError('min() iterable argument is empty') +INFEASIBLE (288, 432, 8809) next ValueError('min() iterable argument is empty') +INFEASIBLE (288, 432, 8809) prev ValueError('min() iterable argument is empty') +INFEASIBLE (307, 50, 8909) next ValueError('min() iterable argument is empty') +EVAL (307, 50, 8909) prev Optimal 5253.116991559382 gain 2.7284841053187847e-12 (8909, 8908, 'prev', ['add', ['L', 307], ['L', 306], 1, 1], ['add', ['L', 306], ['L', 48], 1, 1], ['add', ['L', 307], ['L', 48], 1, 1]) 27.7 +EVAL (312, 47, 8914) next Optimal 5253.116991559382 gain 2.7284841053187847e-12 (8914, 8922, 'next', ['add', ['L', 312], ['L', 45], 1, 1], ['add', ['L', 45], ['L', 313], 1, 1], ['add', ['L', 312], ['L', 313], -1, 1]) 29.2 +INFEASIBLE (312, 47, 8914) prev ValueError('min() iterable argument is empty') +EVAL (304, 452, 8963) next Optimal 5253.116991559382 gain 2.7284841053187847e-12 (8963, 8964, 'next', ['add', ['L', 306], ['L', 304], 1, 1], ['add', ['L', 495], ['L', 306], 1, 1], ['add', ['L', 495], ['L', 304], 1, 1]) 22.9 +INFEASIBLE (304, 452, 8963) prev ValueError('min() iterable argument is empty') +INFEASIBLE (320, 51, 9061) next ValueError('min() iterable argument is empty') diff --git a/research/frontier-word-reorder-ceilings/r13-reorder/logs/me-f-4.txt b/research/frontier-word-reorder-ceilings/r13-reorder/logs/me-f-4.txt new file mode 100644 index 0000000000..a5775c13ec --- /dev/null +++ b/research/frontier-word-reorder-ceilings/r13-reorder/logs/me-f-4.txt @@ -0,0 +1,37 @@ +INFEASIBLE (228, 89, 8140) next ValueError('min() iterable argument is empty') +INFEASIBLE (228, 89, 8140) prev AssertionError(('empty', 11619)) +EVAL (234, 59, 8146) next Optimal 5253.116991559382 gain 2.7284841053187847e-12 (8146, 8156, 'next', ['add', ['L', 234], ['L', 57], 1, 1], ['add', ['L', 57], ['L', 235], 1, 1], ['add', ['L', 234], ['L', 235], -1, 1]) 32.9 +INFEASIBLE (234, 59, 8146) prev AssertionError(('empty', 11619)) +INFEASIBLE (227, 353, 8194) next AssertionError(((229, 0), 83, 89)) +INFEASIBLE (227, 353, 8194) prev ValueError('min() iterable argument is empty') +INFEASIBLE (244, 92, 8294) next ValueError('min() iterable argument is empty') +INFEASIBLE (244, 92, 8294) prev ValueError('min() iterable argument is empty') +EVAL (250, 64, 8300) next Optimal 5253.116991559382 gain 2.7284841053187847e-12 (8300, 8310, 'next', ['add', ['L', 250], ['L', 62], 1, 1], ['add', ['L', 62], ['L', 251], 1, 1], ['add', ['L', 250], ['L', 251], -1, 1]) 34.5 +INFEASIBLE (250, 64, 8300) prev ValueError('min() iterable argument is empty') +INFEASIBLE (243, 373, 8348) next AssertionError(((245, 0), 92, 13)) +INFEASIBLE (243, 373, 8348) prev ValueError('min() iterable argument is empty') +INFEASIBLE (260, 27, 8448) next ValueError('min() iterable argument is empty') +INFEASIBLE (260, 27, 8448) prev ValueError('min() iterable argument is empty') +EVAL (266, 96, 8454) next Optimal 5253.116991559382 gain 2.7284841053187847e-12 (8454, 8464, 'next', ['add', ['L', 266], ['L', 94], 1, 1], ['add', ['L', 94], ['L', 267], 1, 1], ['add', ['L', 266], ['L', 267], -1, 1]) 33.3 +INFEASIBLE (266, 96, 8454) prev ValueError('min() iterable argument is empty') +INFEASIBLE (259, 393, 8502) next AssertionError(((261, 0), 27, 11)) +INFEASIBLE (259, 393, 8502) prev ValueError('min() iterable argument is empty') +INFEASIBLE (276, 58, 8602) next ValueError('min() iterable argument is empty') +INFEASIBLE (276, 58, 8602) prev ValueError('min() iterable argument is empty') +EVAL (282, 19, 8608) next Optimal 5253.116991559382 gain 2.7284841053187847e-12 (8608, 8618, 'next', ['add', ['L', 282], ['L', 17], 1, 1], ['add', ['L', 17], ['L', 283], 1, 1], ['add', ['L', 282], ['L', 283], -1, 1]) 32.9 +INFEASIBLE (282, 19, 8608) prev ValueError('min() iterable argument is empty') +INFEASIBLE (275, 413, 8656) next AssertionError(((277, 0), 58, 79)) +INFEASIBLE (275, 413, 8656) prev ValueError('min() iterable argument is empty') +INFEASIBLE (292, 104, 8756) next ValueError('min() iterable argument is empty') +INFEASIBLE (292, 104, 8756) prev ValueError('min() iterable argument is empty') +EVAL (298, 42, 8762) next Optimal 5253.116991559382 gain 2.7284841053187847e-12 (8762, 8772, 'next', ['add', ['L', 298], ['L', 40], 1, 1], ['add', ['L', 40], ['L', 299], 1, 1], ['add', ['L', 298], ['L', 299], -1, 1]) 34.9 +INFEASIBLE (298, 42, 8762) prev AssertionError(('empty', 11094)) +INFEASIBLE (291, 433, 8810) next AssertionError(((293, 0), 104, 41)) +INFEASIBLE (291, 433, 8810) prev ValueError('min() iterable argument is empty') +INFEASIBLE (308, 34, 8910) next ValueError('min() iterable argument is empty') +INFEASIBLE (308, 34, 8910) prev ValueError('min() iterable argument is empty') +EVAL (314, 109, 8916) next Optimal 5253.116991559382 gain 2.7284841053187847e-12 (8916, 8926, 'next', ['add', ['L', 314], ['L', 107], 1, 1], ['add', ['L', 107], ['L', 315], 1, 1], ['add', ['L', 314], ['L', 315], -1, 1]) 29.3 +INFEASIBLE (314, 109, 8916) prev ValueError('min() iterable argument is empty') +EVAL (495, 452, 8964) next Infeasible inf gain -inf (8964, 11381, 'next', ['add', ['L', 495], ['L', 306], 1, 1], ['add', ['L', 242], ['L', 495], 1, 1], ['add', ['L', 242], ['L', 306], 1, 1]) 22.9 +EVAL (495, 452, 8964) prev Optimal 5253.116991559382 gain 2.7284841053187847e-12 (8964, 8963, 'prev', ['add', ['L', 495], ['L', 306], 1, 1], ['add', ['L', 306], ['L', 304], 1, 1], ['add', ['L', 495], ['L', 304], 1, 1]) 23.9 +INFEASIBLE (321, 51, 9062) next ValueError('min() iterable argument is empty') diff --git a/research/frontier-word-reorder-ceilings/r13-reorder/logs/rw-b.txt b/research/frontier-word-reorder-ceilings/r13-reorder/logs/rw-b.txt new file mode 100644 index 0000000000..515721bcd1 --- /dev/null +++ b/research/frontier-word-reorder-ceilings/r13-reorder/logs/rw-b.txt @@ -0,0 +1,52 @@ +base 5253.116991559385 {1: 2201, 3: 510, 2: 412, 4: 127, 5: 40} +progress 0 1005 0.5192229747772217 +progress 20 1005 11.334260940551758 +progress 40 1005 24.643244981765747 +progress 60 1005 38.388993978500366 +progress 80 1005 49.193082094192505 +progress 100 1005 63.038671016693115 +progress 120 1005 75.42782211303711 +progress 140 1005 86.5616979598999 +progress 160 1005 101.83211183547974 +progress 180 1005 116.17642903327942 +progress 200 1005 134.07788801193237 +progress 220 1005 146.93708491325378 +progress 240 1005 157.33074188232422 +progress 260 1005 171.0831847190857 +progress 280 1005 181.79714393615723 +progress 300 1005 194.7508008480072 +progress 320 1005 211.5713448524475 +progress 340 1005 226.06753087043762 +progress 360 1005 239.9384469985962 +progress 380 1005 252.6707239151001 +progress 400 1005 266.9719319343567 +progress 420 1005 279.9858748912811 +progress 440 1005 294.4333701133728 +progress 460 1005 307.730703830719 +progress 480 1005 322.9955561161041 +progress 500 1005 337.2598457336426 +progress 520 1005 351.74688482284546 +progress 540 1005 366.74834394454956 +progress 560 1005 380.1847469806671 +progress 580 1005 392.5245199203491 +progress 600 1005 404.4221348762512 +progress 620 1005 413.36533188819885 +progress 640 1005 422.5647029876709 +progress 660 1005 435.6310908794403 +progress 680 1005 451.4355938434601 +progress 700 1005 470.09354996681213 +progress 720 1005 486.0798840522766 +progress 740 1005 501.41382694244385 +progress 760 1005 516.134458065033 +progress 780 1005 527.2243340015411 +progress 800 1005 543.0559637546539 +progress 820 1005 559.6745269298553 +progress 840 1005 576.9543280601501 +progress 860 1005 593.1921100616455 +progress 880 1005 607.8476459980011 +progress 900 1005 624.8673658370972 +progress 920 1005 641.9235367774963 +progress 940 1005 658.8859488964081 +progress 960 1005 675.0571939945221 +progress 980 1005 692.7022387981415 +progress 1000 1005 711.596498966217 diff --git a/research/frontier-word-reorder-ceilings/r13-reorder/logs/rw-f-0.txt b/research/frontier-word-reorder-ceilings/r13-reorder/logs/rw-f-0.txt new file mode 100644 index 0000000000..970c434487 --- /dev/null +++ b/research/frontier-word-reorder-ceilings/r13-reorder/logs/rw-f-0.txt @@ -0,0 +1,12 @@ +base 5253.116991559385 {1: 2201, 3: 510, 2: 412, 4: 127, 5: 40} +progress 0 201 0.6913650035858154 +progress 20 201 13.671886920928955 +progress 40 201 24.279155731201172 +progress 60 201 35.184913873672485 +progress 80 201 45.729660749435425 +progress 100 201 56.33304786682129 +progress 120 201 69.77192282676697 +progress 140 201 83.51839876174927 +progress 160 201 103.36594486236572 +progress 180 201 114.93960285186768 +progress 200 201 127.39115786552429 diff --git a/research/frontier-word-reorder-ceilings/r13-reorder/logs/rw-f-1.txt b/research/frontier-word-reorder-ceilings/r13-reorder/logs/rw-f-1.txt new file mode 100644 index 0000000000..80b0e59809 --- /dev/null +++ b/research/frontier-word-reorder-ceilings/r13-reorder/logs/rw-f-1.txt @@ -0,0 +1,12 @@ +base 5253.116991559385 {1: 2201, 3: 510, 2: 412, 4: 127, 5: 40} +progress 0 201 0.8783509731292725 +progress 20 201 14.4479341506958 +progress 40 201 25.117834091186523 +progress 60 201 37.63045406341553 +progress 80 201 48.86953902244568 +progress 100 201 60.38821506500244 +progress 120 201 73.77492690086365 +progress 140 201 93.14671206474304 +progress 160 201 107.88471293449402 +progress 180 201 119.02444291114807 +progress 200 201 130.76395082473755 diff --git a/research/frontier-word-reorder-ceilings/r13-reorder/logs/rw-f-2.txt b/research/frontier-word-reorder-ceilings/r13-reorder/logs/rw-f-2.txt new file mode 100644 index 0000000000..d462b3b17a --- /dev/null +++ b/research/frontier-word-reorder-ceilings/r13-reorder/logs/rw-f-2.txt @@ -0,0 +1,12 @@ +base 5253.116991559385 {1: 2201, 3: 510, 2: 412, 4: 127, 5: 40} +progress 0 201 0.32804107666015625 +progress 20 201 10.008479118347168 +progress 40 201 19.96697998046875 +progress 60 201 31.525847911834717 +progress 80 201 41.165717124938965 +progress 100 201 51.733497858047485 +progress 120 201 65.35350108146667 +progress 140 201 80.36490988731384 +progress 160 201 100.18773198127747 +progress 180 201 112.79806590080261 +progress 200 201 124.7567970752716 diff --git a/research/frontier-word-reorder-ceilings/r13-reorder/logs/rw-f-3.txt b/research/frontier-word-reorder-ceilings/r13-reorder/logs/rw-f-3.txt new file mode 100644 index 0000000000..d78dd9648c --- /dev/null +++ b/research/frontier-word-reorder-ceilings/r13-reorder/logs/rw-f-3.txt @@ -0,0 +1,12 @@ +base 5253.116991559385 {1: 2201, 3: 510, 2: 412, 4: 127, 5: 40} +progress 0 201 0.9240820407867432 +progress 20 201 15.481535911560059 +progress 40 201 26.836770057678223 +progress 60 201 37.96262216567993 +progress 80 201 48.79980993270874 +progress 100 201 60.10064387321472 +progress 120 201 74.4070029258728 +progress 140 201 94.33353590965271 +progress 160 201 109.69495391845703 +progress 180 201 119.92797708511353 +progress 200 201 131.08415818214417 diff --git a/research/frontier-word-reorder-ceilings/r13-reorder/logs/rw-f-4.txt b/research/frontier-word-reorder-ceilings/r13-reorder/logs/rw-f-4.txt new file mode 100644 index 0000000000..ef8feb7f63 --- /dev/null +++ b/research/frontier-word-reorder-ceilings/r13-reorder/logs/rw-f-4.txt @@ -0,0 +1,12 @@ +base 5253.116991559385 {1: 2201, 3: 510, 2: 412, 4: 127, 5: 40} +progress 0 201 0.706294059753418 +progress 20 201 13.233187913894653 +progress 40 201 23.250657081604004 +progress 60 201 34.45551300048828 +progress 80 201 45.06859993934631 +progress 100 201 55.21320605278015 +progress 120 201 69.58285403251648 +progress 140 201 89.62983298301697 +progress 160 201 104.12325501441956 +progress 180 201 116.08802914619446 +progress 200 201 128.50711107254028 diff --git a/research/frontier-word-reorder-ceilings/r13-reorder/logs/rw-main.txt b/research/frontier-word-reorder-ceilings/r13-reorder/logs/rw-main.txt new file mode 100644 index 0000000000..fd504db0af --- /dev/null +++ b/research/frontier-word-reorder-ceilings/r13-reorder/logs/rw-main.txt @@ -0,0 +1,75 @@ +base 5253.116991559385 {1: 2201, 3: 510, 2: 412, 4: 127, 5: 40} +progress 0 1466 0.8444459438323975 +progress 20 1466 15.373609781265259 +progress 40 1466 32.2211389541626 +progress 60 1466 48.765575885772705 +progress 80 1466 60.750154972076416 +progress 100 1466 72.08704876899719 +progress 120 1466 82.90082287788391 +progress 140 1466 95.211256980896 +progress 160 1466 109.1370108127594 +progress 180 1466 128.0849678516388 +progress 200 1466 138.13508796691895 +progress 220 1466 150.0571448802948 +progress 240 1466 160.344468832016 +progress 260 1466 173.99254894256592 +progress 280 1466 182.95334792137146 +progress 300 1466 188.20003390312195 +progress 320 1466 194.8326859474182 +progress 340 1466 204.0410599708557 +progress 360 1466 212.2589590549469 +progress 380 1466 219.7335958480835 +progress 400 1466 230.69247484207153 +progress 420 1466 242.24879693984985 +progress 440 1466 254.17916202545166 +progress 460 1466 266.75916385650635 +progress 480 1466 278.4749927520752 +progress 500 1466 291.02600383758545 +progress 520 1466 305.22447395324707 +progress 540 1466 317.9266109466553 +progress 560 1466 334.62884402275085 +progress 580 1466 348.41386103630066 +progress 600 1466 359.8711168766022 +progress 620 1466 370.8390760421753 +progress 640 1466 383.304319858551 +progress 660 1466 394.5833959579468 +progress 680 1466 406.95889687538147 +progress 700 1466 419.9493079185486 +progress 720 1466 429.72242879867554 +progress 740 1466 441.2155120372772 +progress 760 1466 451.08610701560974 +progress 780 1466 460.7346239089966 +progress 800 1466 471.298947095871 +progress 820 1466 482.3960118293762 +progress 840 1466 492.4330668449402 +progress 860 1466 506.3340787887573 +progress 880 1466 517.4278378486633 +progress 900 1466 528.4102220535278 +progress 920 1466 540.1632759571075 +progress 940 1466 549.8875460624695 +progress 960 1466 565.3603250980377 +progress 980 1466 583.1503260135651 +progress 1000 1466 597.7818038463593 +progress 1020 1466 615.6226499080658 +progress 1040 1466 628.3308379650116 +progress 1060 1466 641.6844148635864 +progress 1080 1466 658.4958028793335 +progress 1100 1466 676.4646897315979 +progress 1120 1466 693.2582240104675 +progress 1140 1466 708.0915999412537 +progress 1160 1466 724.3624658584595 +progress 1180 1466 736.0387797355652 +progress 1200 1466 747.6977698802948 +progress 1220 1466 762.2084038257599 +progress 1240 1466 772.2892849445343 +progress 1260 1466 785.2792618274689 +progress 1280 1466 797.8391189575195 +progress 1300 1466 808.1130418777466 +progress 1320 1466 817.6264879703522 +progress 1340 1466 830.1104691028595 +progress 1360 1466 841.3097338676453 +progress 1380 1466 852.7023048400879 +progress 1400 1466 864.3408718109131 +progress 1420 1466 875.2367758750916 +progress 1440 1466 890.3961730003357 +progress 1460 1466 904.6720349788666 diff --git a/research/frontier-word-reorder-ceilings/r13-reorder/tools/backbone.py b/research/frontier-word-reorder-ceilings/r13-reorder/tools/backbone.py new file mode 100644 index 0000000000..70a8ff30e2 --- /dev/null +++ b/research/frontier-word-reorder-ceilings/r13-reorder/tools/backbone.py @@ -0,0 +1,28 @@ +"""Exact backbone ceiling: frames forced in EVERY linear extension of the conflict poset +(fixed warps, pinned C0 ops) form a chain per register segment; any valid chain contains +them and, by subadditivity of x^(1-C), costs at least the backbone chain. Valid lower bound +on the local paid cost of any reorder+frame lever (same ADD program, same warps/interfaces).""" +import sys, json +sys.path.insert(0, str(__import__('pathlib').Path(__file__).resolve().parent)) +from sdom import * +from price import root + +def backbone(S): + dom, Fm = S['dom'], S['Fm']; prof = Counter(); chains = {} + for key in set(S['members']) | set(S['ends']): + fs = set(S['ends'][key]) + for i in S['members'].get(key, []): + if len(dom[i]) == 1: fs |= dom[i] + ch = sorted(fs, key=lambda X: Fm.dims[X]) + for a, b in zip(ch, ch[1:]): + assert Fm.dims[a] < Fm.dims[b] and Fm.spans[a] < Fm.spans[b], (key, a, b) + prof[Fm.dims[b]-Fm.dims[a]] += 1 + chains[key] = ch + return prof, chains + +if __name__ == '__main__': + w = load() + for side, rw in (('forward', False), ('forward', True), ('backward', True)): + S = domains(w, side, relax_warps=rw); prof, _ = backbone(S); C = 0.00302 + cost = sum(n*r**(1-C) for r, n in prof.items()) + print(side, 'relax_warps', rw, 'backbone profile', dict(sorted(prof.items())), 'mass', sum(k*v for k, v in prof.items()), 'cost', cost, 'root(if mass-padded)', root(prof) if sum(k*v for k,v in prof.items())==5263 else None, flush=True) diff --git a/research/frontier-word-reorder-ceilings/r13-reorder/tools/ceil.py b/research/frontier-word-reorder-ceilings/r13-reorder/tools/ceil.py new file mode 100644 index 0000000000..2d08e4878d --- /dev/null +++ b/research/frontier-word-reorder-ceilings/r13-reorder/tools/ceil.py @@ -0,0 +1,173 @@ +"""Stage-1 dependency-respecting ceiling (dims relaxation, coupled). + +Valid relaxation of: any linear extension of the exact conflict poset + any frame +assignment (subspaces; warps' frames free, dims preserved; C0 ops pinned). +Variables: level of every op (one-hot), per register a level path s->f (flow). +Constraints: ops sharing a register in consecutive conflict groups are level-monotone +(hub variables); an op's level must be on every one of its registers' paths; domains +pruned by subspace bounds and forced frames. Objective: sum (b-a)^(1-C) over climbs. +Usage: python ceil.py SIDE C TIME [mip]""" +import sys, time +sys.path.insert(0, str(__import__('pathlib').Path(__file__).resolve().parent)) +from poset import * +import numpy as np, scipy.sparse as sp, highspy + +def domains(w, p, groups): + c = w['canonical']; fr = c['frames'] + import os + PINW = os.environ.get('PINW') == '1' + lows, lowd, ups, upd, pinned = bounds(w, p, groups, relax_warps=not PINW) + pos = preds_succs(p, groups) + dom = {} + for i, e in enumerate(p): + if e[0] == 'center': + continue + dom[i] = set(range(lowd[i], upd[i]+1)) + if PINW and e[0] == 'warp': dom[i] = {len(fr[e[3]])} + # forced frames per L register + seg = defaultdict(dict) + for r, gl in groups.items(): + if r[0] != 'L': continue + sg = 0 + for t, ops in gl: + if p[ops[0]][0] == 'warp': + for j in ops: seg[j][r] = None + sg += 1; continue + for j in ops: seg[j][r] = sg + def regs(i): + return [(r[1], seg[i][r]) for r, k in pos[i].items() if r[0] == 'L' and seg[i][r] is not None] + changed = True; it = 0 + while changed: + it += 1; changed = False + forced = defaultdict(dict) + for i, D in dom.items(): + if len(D) == 1: + d = next(iter(D)) + if p[i][0] != 'warp' and len(lows[i]) == d: + for r in regs(i): + forced[r][d] = span(lows[i]) + for i, D in dom.items(): + if p[i][0] == 'warp': + continue + lo, hi = span(lows[i]), span(ups[i]); new = set() + for l in D: + ok = True + for r in regs(i): + for d, Y in forced[r].items(): + if d == l and not (lo <= Y <= hi): ok = False + if d < l and not (Y <= hi): ok = False + if d > l and not (lo <= Y): ok = False + if ok: new.add(l) + if new != D: + assert new, ('empty domain', i) + dom[i] = new; changed = True + # dims propagation through conflict groups + for r, gl in groups.items(): + if r[0] != 'L': continue + for (t0, a), (t1, b) in zip(gl, gl[1:]): + m = min(min(dom[j]) for j in a if j in dom) + for j in b: + if j in dom: + nd = {l for l in dom[j] if l >= m} + if nd != dom[j]: dom[j] = nd; changed = True + for (t0, a), (t1, b) in reversed(list(zip(gl, gl[1:]))): + M = max(max(dom[j]) for j in b if j in dom) + for j in a: + if j in dom: + nd = {l for l in dom[j] if l <= M} + if nd != dom[j]: dom[j] = nd; changed = True + return dom, pos, lows, ups + +def model(w, side, C): + c = w['canonical']; fr = c['frames'] + p, groups = build(w, side) + dom, pos, lows, ups = domains(w, p, groups) + s = {i: len(fr[c['start'][i]]) for i in range(632)}; f = {i: len(fr[c['final'][i]]) for i in range(632)} + nv = 0; cost = []; W = {} + def var(cst=0.0): + nonlocal nv; cost.append(cst); nv += 1; return nv-1 + for i, D in dom.items(): + for l in sorted(D): W[i, l] = var() + U = {} + for r in range(632): + for a in range(s[r], f[r]+1): + for b in range(a+1, f[r]+1): + U[r, a, b] = var((b-a)**(1-C)) + rows, cols, vals, lb, ub = [], [], [], [], [] + def row(ent, lo, hi): + k = len(lb) + for j, v in ent: rows.append(k); cols.append(j); vals.append(v) + lb.append(lo); ub.append(hi) + for i, D in dom.items(): row([(W[i, l], 1) for l in D], 1, 1) + for r in range(632): + S, F = s[r], f[r] + for l in range(S, F+1): + out = [(U[r, l, b], 1) for b in range(l+1, F+1)]; inn = [(U[r, a, l], -1) for a in range(S, l)] + rhs = 1 if l == S else (-1 if l == F else 0) + if S < F: row(out+inn, rhs, rhs) + # op level must be on path of each register + for i, D in dom.items(): + for r, k in pos[i].items(): + if r[0] != 'L': continue + R = r[1] + for l in D: + if l == s[R] or l == f[R]: continue + assert s[R] < l < f[R], (i, R, l) + row([(W[i, l], 1)]+[(U[R, a, l], -1) for a in range(s[R], l)], -np.inf, 0) + # monotonicity via hubs + nh = 0 + for r, gl in groups.items(): + if r[0] != 'L': continue + for (t0, a), (t1, b) in zip(gl, gl[1:]): + a = [j for j in a if j in dom]; b = [j for j in b if j in dom] + levels = sorted(set().union(*(dom[j] for j in a+b))) + lo, hi = levels[0], levels[-1] + if all(max(dom[j]) <= min(dom[k]) for j in a for k in b): continue + H = {l: var() for l in range(lo, hi)}; nh += 1 + for l in range(lo, hi): + for j in a: # cum_j(l) >= H(l) + row([(W[j, x], 1) for x in dom[j] if x <= l]+[(H[l], -1)], 0, np.inf) + for k in b: # H(l) >= cum_k(l) + row([(H[l], 1)]+[(W[k, x], -1) for x in dom[k] if x <= l], 0, np.inf) + A = sp.csc_matrix((vals, (rows, cols)), shape=(len(lb), nv)) + return dict(p=p, groups=groups, dom=dom, W=W, U=U, A=A, lb=lb, ub=ub, cost=np.array(cost), nv=nv, nh=nh, s=s, f=f) + +def solve(M, mip, tl): + h = highspy.Highs(); h.setOptionValue('output_flag', True); h.setOptionValue('threads', 1) + h.setOptionValue('time_limit', float(tl)) + if not mip: + h.setOptionValue('solver', 'ipm'); h.setOptionValue('run_crossover', 'on') + lp = highspy.HighsLp(); nv = M['nv']; A = M['A'] + lp.num_col_ = nv; lp.num_row_ = A.shape[0]; lp.col_cost_ = M['cost'] + lp.col_lower_ = np.zeros(nv); lp.col_upper_ = np.ones(nv) + inf = highspy.kHighsInf + lp.row_lower_ = np.array([x if x != -np.inf else -inf for x in M['lb']]); lp.row_upper_ = np.array([x if x != np.inf else inf for x in M['ub']]) + lp.a_matrix_.format_ = highspy.MatrixFormat.kColwise; lp.a_matrix_.start_ = A.indptr; lp.a_matrix_.index_ = A.indices; lp.a_matrix_.value_ = A.data + if mip: + integ = [highspy.HighsVarType.kContinuous]*nv + for j in list(M['W'].values())+list(M['U'].values()): integ[j] = highspy.HighsVarType.kInteger + lp.integrality_ = integ + h.passModel(lp); h.run() + return h + +def dump(M, h, path): + import json + x = h.getSolution().col_value + lev = {i: max(D, key=lambda l: x[M['W'][i, l]]) for i, D in M['dom'].items()} + paths = {} + prof = Counter() + for (r, a, b), j in M['U'].items(): + if x[j] > 0.5: prof[b-a] += 1; paths.setdefault(r, []).append((a, b)) + json.dump(dict(levels=lev, paths={r: sorted(v) for r, v in paths.items()}, profile=dict(prof)), open(path, 'w')) + return lev, paths, prof + +if __name__ == '__main__': + side = sys.argv[1]; C = float(sys.argv[2]); tl = float(sys.argv[3]); mip = len(sys.argv) > 4 + t = time.time(); w = load(); M = model(w, side, C) + print('model vars', M['nv'], 'rows', M['A'].shape[0], 'hubs', M['nh'], 't', time.time()-t, flush=True) + h = solve(M, mip, tl); info = h.getInfo() + cur = sum(n*r**(1-C) for r, n in {1:2201,2:412,3:510,4:127,5:40}.items()) + obj = info.objective_function_value + print('status', h.modelStatusToString(h.getModelStatus()), 'obj', obj, 'mip_dual_bound', getattr(info, 'mip_dual_bound', None), flush=True) + print('current non-centre local cost', cur, 'LB', obj, 'headroom/local', cur-obj, 'linearized dC', 18*(cur-obj)/247222) + if mip: print("profile", dict(sorted(dump(M, h, f"/Users/joelpulikkan/imb-harness/r13/mip-{side}"+("-pinw" if __import__("os").environ.get("PINW")=="1" else "")+".json")[2].items()))) diff --git a/research/frontier-word-reorder-ceilings/r13-reorder/tools/checkcur.py b/research/frontier-word-reorder-ceilings/r13-reorder/tools/checkcur.py new file mode 100644 index 0000000000..bde3ba1bfa --- /dev/null +++ b/research/frontier-word-reorder-ceilings/r13-reorder/tools/checkcur.py @@ -0,0 +1,31 @@ +import sys; sys.path.insert(0,'/Users/joelpulikkan/imb-harness/r13/tools') +from construct import * +w=load(); M=build_mip(w,'forward',0.00302, wide='wide' in sys.argv) +Fm=M['S']['Fm']; nv=M['nv']; x=np.zeros(nv) +for (i,X),v in M['V'].items(): x[v]=1.0 if M['cur'][i]==X else 0.0 +# used nodes per key +used=defaultdict(set) +seg=M['S']['seg'] +for (i,X),v in M['V'].items(): + if M['cur'][i]==X: + for R,k in seg[i].items(): + if isinstance(k,int): used[R,k].add(X) +gaps=defaultdict(set) +for (key,u,v_) in M['arcs']: gaps[key].add(u); gaps[key].add(v_) +for key,ch in M['chains'].items(): + for a,b in zip(ch,ch[1:]): + if (key,a,b) not in M['arcs'] and not any(k==key and u==a for (k,u,_) in []): pass + nodes=[a]+sorted([X for X in used[key] if X not in ch and Fm.le(a,X) and Fm.le(X,b)],key=lambda X:Fm.dims[X])+[b] + for u,v_ in zip(nodes,nodes[1:]): + j=M['arcs'].get((key,u,v_)) + if j is None: + if len(nodes)>2 or any((key,a,t) in M['arcs'] for t in [b]): print('missing arc',key,u,v_,Fm.dims[u],Fm.dims[v_],Fm.le(u,v_)) + else: x[j]=1 +A=M['A'].tocsr(); r=A@x +bad=[(k,r[k],M['lb'][k],M['ub'][k]) for k in range(len(M['lb'])) if r[k]M['ub'][k]+1e-9] +print('violations',len(bad),bad[:10]) +k0=bad[0][0] +cols=A[k0].indices +inv={v:k for k,v in M['arcs'].items()} +print([inv.get(c_,('V?',c_)) for c_ in cols][:10]) +key=inv[cols[0]][0]; print('chain',[(X,Fm.dims[X]) for X in M['chains'][key]], 'used',[(X,Fm.dims[X]) for X in used[key]]) diff --git a/research/frontier-word-reorder-ceilings/r13-reorder/tools/construct.py b/research/frontier-word-reorder-ceilings/r13-reorder/tools/construct.py new file mode 100644 index 0000000000..52ddf9498a --- /dev/null +++ b/research/frontier-word-reorder-ceilings/r13-reorder/tools/construct.py @@ -0,0 +1,125 @@ +"""Stage-2 construction MIP: exact chain cost with subspace frames on restricted domains. +Free ops choose a frame from D'(x) = dom(x) ∩ (backbone frames of its registers ∪ {current frame}); +per register-segment backbone gap a path over used candidates; conflict-group dims monotonicity. +Usage: python construct.py SIDE C TIME [wide]""" +import sys, time, json, os +sys.path.insert(0, str(__import__('pathlib').Path(__file__).resolve().parent)) +from backbone import * +import numpy as np, scipy.sparse as sp, highspy + +def build_mip(w, side, C, wide=False): + S = domains(w, side); prof, chains = backbone(S) + p, groups, dom, seg, Fm = S['p'], S['groups'], S['dom'], S['seg'], S['Fm'] + cur = {i: Fm.lab(w['canonical']['frames'][p[i][2]]) for i in dom} + for i in dom: + if cur[i] not in dom[i]: cur[i] = min(dom[i], key=lambda X: Fm.dims[X]) + bb = {key: set(ch) for key, ch in chains.items()} + keys_of = {i: [(R, k) for R, k in seg[i].items() if isinstance(k, int)] for i in dom} + GLOBAL = set().union(*bb.values()) | set(cur.values()) + D = {} + for i, d in dom.items(): + if len(d) == 1: D[i] = set(d); continue + allowed = set().union(*(bb[key] for key in keys_of[i])) | {cur[i]} + if wide == 'medium': allowed = GLOBAL + D[i] = (d & allowed) if wide != True else set(d) + D[i].add(cur[i]) + # gaps + def gap_of(key, X): + ch = chains[key] + if X in bb[key]: return None + for a, b in zip(ch, ch[1:]): + if Fm.le(a, X) and Fm.le(X, b): return (a, b) + raise AssertionError((key, X)) + nv = 0; cost = []; integ = [] + def var(c=0.0, it=True): + nonlocal nv; cost.append(c); integ.append(it); nv += 1; return nv-1 + free = {i for i in D if len(dom[i]) > 1} + V = {(i, X): var() for i in free for X in sorted(D[i])} + gapc = defaultdict(set); need = [] # (V var, key, gap, X) + for (i, X), v in V.items(): + for key in keys_of[i]: + g = gap_of(key, X) + if g is not None: gapc[key, g].add(X); need.append((v, key, g, X)) + rows, cols, vals, lb, ub = [], [], [], [], [] + def row(ent, lo, hi): + k = len(lb) + for j, a in ent: rows.append(k); cols.append(j); vals.append(a) + lb.append(lo); ub.append(hi) + for i in free: row([(V[i, X], 1) for X in D[i]], 1, 1) + arcs = {}; inflow = defaultdict(list); f = lambda x: x**(1-C) + for (key, (a, b)), K in gapc.items(): + nodes = [a] + sorted(K, key=lambda X: Fm.dims[X]) + [b] + out = defaultdict(list); inl = defaultdict(list) + for u in nodes: + for v_ in nodes: + if u != v_ and Fm.dims[u] < Fm.dims[v_] and Fm.spans[u] < Fm.spans[v_]: + j = var(f(Fm.dims[v_]-Fm.dims[u])); arcs[key, u, v_] = j + out[u].append(j); inl[v_].append(j) + if v_ in K: inflow[key, v_].append(j) + for u in nodes: + ent = [(j, 1) for j in out[u]] + [(j, -1) for j in inl[u]] + rhs = 1 if u == a else (-1 if u == b else 0) + row(ent, rhs, rhs) + const = 0.0 + for key, ch in chains.items(): + segs = [(a, b) for a, b in zip(ch, ch[1:])] + for a, b in segs: + if (key, (a, b)) not in gapc: const += f(Fm.dims[b]-Fm.dims[a]) + for v, key, g, X in need: + row([(v, 1)] + [(j, -1) for j in inflow[key, X]], -np.inf, 0) + # monotonicity over conflict groups (dims cumulative), hubs + def cum(i, l): # list of (var, coef) and constant for P(dim f(i) <= l) + d = D[i] + if i not in free: return [], 1.0 if Fm.dims[next(iter(d))] <= l else 0.0 + return [(V[i, X], 1) for X in d if Fm.dims[X] <= l], 0.0 + nh = 0 + for r, gl in groups.items(): + if r[0] != 'L': continue + for (t0, A), (t1, B) in zip(gl, gl[1:]): + A = [j for j in A if j in D]; B = [j for j in B if j in D] + if not A or not B: continue + if max(Fm.dims[X] for j in A for X in D[j]) <= min(Fm.dims[X] for j in B for X in D[j]): continue + lo = min(Fm.dims[X] for j in A+B for X in D[j]); hi = max(Fm.dims[X] for j in A+B for X in D[j]) + nh += 1 + for l in range(lo, hi): + H = var(0.0, False) + for j in A: + e, c0 = cum(j, l); row(e+[(H, -1)], -c0, np.inf) + for k in B: + e, c0 = cum(k, l); row([(H, 1)]+[(x, -a) for x, a in e], c0, np.inf) + M = dict(free=free, S=S, chains=chains, D=D, V=V, arcs=arcs, cur=cur, nv=nv, cost=np.array(cost), integ=integ, const=const, + A=sp.csc_matrix((vals, (rows, cols)), shape=(len(lb), nv)), lb=lb, ub=ub, nh=nh) + return M + +def run(M, tl, start=True): + h = highspy.Highs(); h.setOptionValue('output_flag', bool(os.environ.get('HVERB'))); h.setOptionValue('threads', 1); h.setOptionValue('time_limit', float(tl)) + h.setOptionValue('mip_rel_gap', 1e-7) + lp = highspy.HighsLp(); nv = M['nv']; A = M['A']; inf = highspy.kHighsInf + lp.num_col_ = nv; lp.num_row_ = A.shape[0]; lp.col_cost_ = M['cost']; lp.col_lower_ = np.zeros(nv); lp.col_upper_ = np.ones(nv) + lp.row_lower_ = np.array([x if x != -np.inf else -inf for x in M['lb']]); lp.row_upper_ = np.array([x if x != np.inf else inf for x in M['ub']]) + lp.a_matrix_.format_ = highspy.MatrixFormat.kColwise; lp.a_matrix_.start_ = A.indptr; lp.a_matrix_.index_ = A.indices; lp.a_matrix_.value_ = A.data + if not os.environ.get('LPONLY'): + lp.integrality_ = [highspy.HighsVarType.kInteger if t else highspy.HighsVarType.kContinuous for t in M['integ']] + else: + h.setOptionValue('solver', 'ipm'); h.setOptionValue('run_crossover', 'off'); start = False + h.passModel(lp) + if start: + sol = highspy.HighsSolution(); x = np.zeros(nv) + for (i, X), v in M['V'].items(): x[v] = 1.0 if M['cur'][i] == X else 0.0 + sol.col_value = list(x) + # only V given; HiGHS completes? provide partial via setSolution + try: h.setSolution(sol) + except Exception as ex: print('setSolution failed', ex) + h.run(); return h + +if __name__ == '__main__': + side, C, tl = sys.argv[1], float(sys.argv[2]), float(sys.argv[3]); wide = True if 'wide' in sys.argv else ('medium' if 'medium' in sys.argv else False) + t = time.time(); w = load(); M = build_mip(w, side, C, wide) + print('vars', M['nv'], 'rows', M['A'].shape[0], 'V', len(M['V']), 'arcs', len(M['arcs']), 'hubs', M['nh'], 'const', M['const'], 't', time.time()-t, flush=True) + h = run(M, tl); info = h.getInfo(); x = h.getSolution().col_value + obj = info.objective_function_value + M['const'] + curc = sum(n*r**(1-C) for r, n in {1:2201,2:412,3:510,4:127,5:40}.items()) + print('status', h.modelStatusToString(h.getModelStatus()), 'cost', obj, 'bound', (info.mip_dual_bound if not os.environ.get('LPONLY') else float('nan')) + M['const'], 'current', curc, flush=True) + frames = {i: (max(d, key=lambda X: x[M['V'][i, X]]) if (i, next(iter(d))) in M['V'] else next(iter(d))) for i, d in M['D'].items()} + Fm = M['S']['Fm'] + json.dump(dict(frames={i: Fm.fb[X] for i, X in frames.items()}, cost=obj), open(f'/Users/joelpulikkan/imb-harness/r13/cons-{side}{"-"+str(wide) if wide else ""}.json', 'w')) diff --git a/research/frontier-word-reorder-ceilings/r13-reorder/tools/lift.py b/research/frontier-word-reorder-ceilings/r13-reorder/tools/lift.py new file mode 100644 index 0000000000..57631d2e3a --- /dev/null +++ b/research/frontier-word-reorder-ceilings/r13-reorder/tools/lift.py @@ -0,0 +1,109 @@ +"""Lift a dims-level solution (levels per op) to subspace frames. +Nodes (R, seg, level) merged by ops; chain order within each (R, seg).""" +import sys, json, os +sys.path.insert(0, str(__import__('pathlib').Path(__file__).resolve().parent)) +from poset import * + +class UF: + def __init__(s): s.p = {} + def f(s, x): + s.p.setdefault(x, x) + while s.p[x] != x: + s.p[x] = s.p[s.p[x]]; x = s.p[x] + return x + def u(s, a, b): + a, b = s.f(a), s.f(b) + if a != b: s.p[a] = b + +def segments(p, groups): + seg = defaultdict(dict); nseg = {} + for r, gl in groups.items(): + if r[0] != 'L': continue + sg = 0 + for t, ops in gl: + if p[ops[0]][0] == 'warp': + for j in ops: seg[j][r[1]] = ('W', sg) + sg += 1; continue + for j in ops: seg[j][r[1]] = sg + nseg[r[1]] = sg + return seg, nseg + +def setup(w, side, levels): + c = w['canonical']; fr = c['frames'] + p, groups = build(w, side) + lows, lowd, ups, upd, pinned = bounds(w, p, groups, relax_warps=False) + seg, nseg = segments(p, groups) + uf = UF(); fixed = {}; lo = defaultdict(list); hi = defaultdict(list) + lev = {} + for r in range(632): + uf.f((r, 0, len(fr[c['start'][r]]))) + fixed[(r, 0, len(fr[c['start'][r]]))] = tuple(fr[c['start'][r]]) + k = nseg.get(r, 0); fixed[(r, k, len(fr[c['final'][r]]))] = tuple(fr[c['final'][r]]); uf.f((r, k, len(fr[c['final'][r]]))) + for i, e in enumerate(p): + if e[0] == 'center': continue + l = levels[i] + if e[0] == 'warp': + R = e[1][1]; k = seg[i][R][1] + assert len(fr[e[3]]) == l + fixed[(R, k, l)] = tuple(fr[e[3]]); fixed[(R, k+1, l)] = tuple(fr[e[4]]); uf.f((R, k, l)); uf.f((R, k+1, l)) + continue + nodes = [(R, seg[i][R], l) for R in seg[i]] + for a in nodes[1:]: uf.u(nodes[0], a) + if not nodes: continue + lo[nodes[0]].append(lows[i]); hi[nodes[0]].append(ups[i]) + if i in pinned: fixed[nodes[0]] = pinned[i] + return p, groups, uf, fixed, lo, hi, nseg + +def lift(w, side, levels): + p, groups, uf, fixed, lo, hi, nseg = setup(w, side, levels) + comp = defaultdict(set) + for x in list(uf.p): comp[uf.f(x)].add(x) + L = defaultdict(list); H = defaultdict(list); F = {} + for x, b in lo.items(): L[uf.f(x)] += b + for x, b in hi.items(): H[uf.f(x)] += b + clashes = [] + for x, b in fixed.items(): + k = uf.f(x) + if k in F and span(F[k]) != span(b): clashes.append(('fixed clash', x)); continue + F[k] = b + # chain neighbours + chains = defaultdict(set) + for (r, k, l) in uf.p: chains[r, k].add(l) + below = defaultdict(set); above = defaultdict(set) + for (r, k), ls in chains.items(): + ls = sorted(ls) + for a, b in zip(ls, ls[1:]): + A, B = uf.f((r, k, a)), uf.f((r, k, b)); below[B].add(A); above[A].add(B) + lvl = {k: next(iter(v))[2] for k, v in comp.items()} + assert all(all(x[2] == lvl[k] for x in v) for k, v in comp.items()) + order = sorted(comp, key=lambda k: lvl[k]) + X = {}; fails = list(clashes) + # static upper bound per component: meet of his, fixed, and fixed uppers above (transitively later) + for k in order: + need = join(*(L[k]), *(X[b] for b in below[k] if b in X), *( [F[k]] if k in F else [])) + up = tuple(1 << i for i in range(9)) + for b in H[k]: up = meet(up, b) + if not span(need) <= span(up) or len(need) > lvl[k]: + fails.append((k, lvl[k], len(need), len(up))); X[k] = need; continue + if len(need) < lvl[k]: + if k in F: fails.append((k, 'fixed dim')); X[k] = need; continue + # extend preferring vectors needed by components above + cand = [] + for a in above[k]: + for b in L[a]: cand += list(b) + if a in F: cand += list(F[a]) + cur = list(need); su = span(up) + for v in cand + list(up): + if len(cur) >= lvl[k]: break + if v in su and len(join(cur, [v])) > len(cur): cur = list(join(cur, [v])) + need = tuple(cur) + if len(need) < lvl[k]: fails.append((k, 'cannot extend')); + X[k] = need + return X, fails, comp, lvl + +if __name__ == '__main__': + side = sys.argv[1]; sol = json.load(open(sys.argv[2])) + levels = {int(k): v for k, v in sol['levels'].items()} + w = load(); X, fails, comp, lvl = lift(w, side, levels) + print('components', len(comp), 'fails', len(fails)) + for f in fails[:20]: print(f) diff --git a/research/frontier-word-reorder-ceilings/r13-reorder/tools/load.py b/research/frontier-word-reorder-ceilings/r13-reorder/tools/load.py new file mode 100644 index 0000000000..d736761233 --- /dev/null +++ b/research/frontier-word-reorder-ceilings/r13-reorder/tools/load.py @@ -0,0 +1,23 @@ +"""Shared loader for the PR4610 round-three native word (run from ~/imb-r13).""" +import gzip, json +from pathlib import Path +from collections import Counter, defaultdict +ROOT = Path.home()/'imb-r13' +WORD = ROOT/'research/kappa-round3-warp-20261022/ACTUAL-WORD.json.gz' + +def load(): + w = json.loads(gzip.decompress(WORD.read_bytes())) + return w + +def span(basis): + s = {0} + for v in basis: + if v not in s: + s |= {x ^ v for x in tuple(s)} + return frozenset(s) + +def roles(e): + if e[0] == 'scalar': + g = e[1] + return [r[1] for r in (g[1:3] if g[0] in ('add', 'copy') else g[1:2]) if r[0] == 'L'] + return [e[1][1]] if e[0] == 'warp' else [] diff --git a/research/frontier-word-reorder-ceilings/r13-reorder/tools/mipeval.py b/research/frontier-word-reorder-ceilings/r13-reorder/tools/mipeval.py new file mode 100644 index 0000000000..2804ed1fac --- /dev/null +++ b/research/frontier-word-reorder-ceilings/r13-reorder/tools/mipeval.py @@ -0,0 +1,29 @@ +"""MIP re-framing (construct.py medium domains) of one-step correction rewrites. +Usage: mipeval.py SIDE PART NPARTS [MAXSITES]""" +import sys, time, json +sys.path.insert(0, str(__import__('pathlib').Path(__file__).resolve().parent)) +from rewrite import * +import construct as K +from copy import deepcopy + +def evaluate(w, side, site, d, C=0.00302): + res = swap(w['programs'][side], site[2], d) + if res is None: return None + new, info = res + w2 = dict(w); w2['programs'] = dict(w['programs']); w2['programs'][side] = new + import io, contextlib + M = K.build_mip(w2, side, C, 'medium') + h = K.run(M, 120, start=False); info2 = h.getInfo() + st = h.modelStatusToString(h.getModelStatus()) + return st, info2.objective_function_value + M['const'], info + +if __name__ == '__main__': + side, part, nparts = sys.argv[1], int(sys.argv[2]), int(sys.argv[3]); mx = int(sys.argv[4]) if len(sys.argv) > 4 else 10**9 + w = load(); sites = thin_sites(w, side)[part::nparts][:mx] + for s in sites: + for d in ('next', 'prev'): + t = time.time() + try: r = evaluate(w, side, s, d) + except (ValueError, AssertionError) as ex: print('INFEASIBLE', s, d, repr(ex)[:80], flush=True); continue + if r is None: continue + print('EVAL', s, d, r[0], r[1], 'gain', 5253.116991559385 - r[1], r[2], round(time.time()-t, 1), flush=True) diff --git a/research/frontier-word-reorder-ceilings/r13-reorder/tools/poset.py b/research/frontier-word-reorder-ceilings/r13-reorder/tools/poset.py new file mode 100644 index 0000000000..30bcbf527a --- /dev/null +++ b/research/frontier-word-reorder-ceilings/r13-reorder/tools/poset.py @@ -0,0 +1,145 @@ +"""Exact dependency poset of the PR4610 round-three local scalar program. + +Ops = every non-climb, non-marker event (scalar add/scale/copy/clear, warp, centre). +Per register R each op touching R is typed: + T : ADD with target R (T,T commute: a+=cb, a+=de) + S : ADD/copy with source R (S,S commute) + X : anything else on R (scale, warp, clear, copy target, centre, C-frame ops) - exclusive. +Two ops conflict iff they share a register with types not in {(T,T),(S,S)}. +This is exactly the commutation relation of the ops as linear maps on generic data +(warps/scales assumed generic) -- ADD a+=cb vs d+=ef commute iff a!=f and d!=b. +Group structure: per register consecutive maximal runs of one commuting type; +every op of group k depends on every op of group k-1 (stored via hub nodes). +""" +import sys +sys.path.insert(0, str(__import__('pathlib').Path(__file__).resolve().parent)) +from load import * + +def reg_types(e): + """[(reg, type)] with reg = ('L',i) / ('C',i).""" + k = e[0] + if k == 'scalar': + g = e[1] + if g[0] == 'add': + return [(tuple(g[1]), 'T'), (tuple(g[2]), 'S')] + if g[0] == 'copy': + return [(tuple(g[1]), 'X'), (tuple(g[2]), 'S')] + return [(tuple(g[1]), 'X')] + if k == 'warp': + return [(tuple(e[1]), 'X')] + if k == 'center': + return [(('C', e[1]), 'X')] + return [] + +def build(w, side='forward'): + p = [e for e in w['programs'][side] if e[0] not in ('climb', 'phase', 'adapter', 'residual_adapter')] + groups = defaultdict(list) # reg -> list of [type, [op ids]] + for i, e in enumerate(p): + for r, t in reg_types(e): + g = groups[r] + if g and g[-1][0] == t and t != 'X': + g[-1][1].append(i) + else: + g.append([t, [i]]) + return p, groups + +def preds_succs(p, groups): + """Immediate-group dependency lists: for op i, list of (reg, group index).""" + pos = defaultdict(dict) # op -> reg -> group index + for r, gl in groups.items(): + for k, (t, ops) in enumerate(gl): + for i in ops: + pos[i][r] = k + return pos + +def basis_of(vecs): + piv = {} + for v in vecs: + while v: + h = v.bit_length() - 1 + if h in piv: + v ^= piv[h] + else: + piv[h] = v + break + return piv + +def join(*bases): + piv = {} + for b in bases: + for v in b: + while v: + h = v.bit_length() - 1 + if h in piv: + v ^= piv[h] + else: + piv[h] = v + break + return tuple(sorted(piv.values())) + +def meet(a, b): + sa, sb = span(a), span(b) + return join(sa & sb) + +def bounds(w, p, groups, relax_warps=True): + """Subspace lower/upper bound for every op frame valid for EVERY linear extension. + Warps: if relax_warps, warp output/input frames are free of the same dim (dims only + propagate through them). Ops touching C are pinned to their current frames.""" + c = w['canonical']; fr = c['frames'] + pos = preds_succs(p, groups) + FULL = tuple(1 << i for i in range(9)) + n = len(p) + pinned = {} + for i, e in enumerate(p): + if e[0] == 'center' or (e[0] == 'scalar' and any(r[0] == 'C' for r, _ in reg_types(e))): + f = e[2] if e[0] == 'scalar' else None + if f is not None: + pinned[i] = tuple(fr[f]) + lows = [None]*n; lowd = [0]*n # for warps lows = input frame bound + for i, e in enumerate(p): + parts = []; d = 0 + for r, k in pos[i].items(): + if r[0] == 'C': + continue + if k == 0: + parts.append(tuple(fr[c['start'][r[1]]])) + else: + for j in groups[r][k-1][1]: + if p[j][0] == 'warp' and relax_warps: + d = max(d, lowd[j]) + elif p[j][0] == 'warp': + parts.append(tuple(fr[p[j][4]])) + else: + parts.append(lows[j]) + if i in pinned: + parts.append(pinned[i]) + lows[i] = join(*parts); lowd[i] = max(d, len(lows[i])) + ups = [None]*n; upd = [9]*n + for i in range(n-1, -1, -1): + e = p[i]; cur = FULL; d = 9 + for r, k in pos[i].items(): + if r[0] == 'C': + continue + gl = groups[r] + if k == len(gl)-1: + cur = meet(cur, tuple(fr[c['final'][r[1]]])) + else: + for j in gl[k+1][1]: + if p[j][0] == 'warp' and relax_warps: + d = min(d, upd[j]) + elif p[j][0] == 'warp': + cur = meet(cur, tuple(fr[p[j][3]])) + else: + cur = meet(cur, ups[j]) + if i in pinned: + cur = meet(cur, pinned[i]) + ups[i] = cur; upd[i] = min(d, len(cur)) + return lows, lowd, ups, upd, pinned + +def cur_frame_dim(w, e): + fr = w['canonical']['frames'] + if e[0] == 'scalar': + return len(fr[e[2]]) + if e[0] == 'warp': + return len(fr[e[3]]) + return None diff --git a/research/frontier-word-reorder-ceilings/r13-reorder/tools/price.py b/research/frontier-word-reorder-ceilings/r13-reorder/tools/price.py new file mode 100644 index 0000000000..913bd6de70 --- /dev/null +++ b/research/frontier-word-reorder-ceilings/r13-reorder/tools/price.py @@ -0,0 +1,21 @@ +"""Float root for a local paid profile (centre 8x rank-8 appended), via PR4610 arithmetic.assemble.""" +import sys, json, importlib.util +from pathlib import Path +ROOT = Path.home()/'imb-r13' +A = ROOT/'research/kappa-round6-compiler-tightening-20261022' +sys.path.insert(0, str(A)) +spec = importlib.util.spec_from_file_location('ar', A/'arithmetic.py'); ar = importlib.util.module_from_spec(spec); sys.modules['ar'] = ar; spec.loader.exec_module(ar) +HEL = {4:28,7:7,8:47,9:326} +def margin(T, P, C): return sum(n*k**(1-C) for k, n in T.items())-sum(n*r**(1-C) for r, n in P.items()) +def root(paid, helpers=HEL): + paid = dict(paid); paid[8] = paid.get(8, 0)+8 if 8 not in paid or paid.get('_c') is None else paid[8] + H, N, T, P, word = ar.assemble({'helpers': helpers, 'paid': paid}) + lo, hi = 0.0, 0.5 + for _ in range(200): + m = (lo+hi)/2 + if margin(T, P, m) > 0: lo = m + else: hi = m + return lo +if __name__ == '__main__': + prof = {int(k): v for k, v in json.loads(sys.argv[1]).items()} + print(prof, 'mass', sum(k*v for k, v in prof.items()), 'root', root(prof)) diff --git a/research/frontier-word-reorder-ceilings/r13-reorder/tools/realize.py b/research/frontier-word-reorder-ceilings/r13-reorder/tools/realize.py new file mode 100644 index 0000000000..5d55d3fdbc --- /dev/null +++ b/research/frontier-word-reorder-ceilings/r13-reorder/tools/realize.py @@ -0,0 +1,97 @@ +"""Realize a frame assignment as an actual native program and replay it exactly. +Order = stable topological sort (priority = original position) of conflict edges plus +per-register-segment frame-order edges; climbs synthesized (warp_merge.synthesize).""" +import sys, json, heapq, gzip, time +from copy import deepcopy +sys.path.insert(0, str(__import__('pathlib').Path(__file__).resolve().parent)) +from lift import * +ROOTP = __import__('pathlib').Path.home()/'imb-r13' +sys.path.insert(0, str(ROOTP/'research/warp-interface-20261022')) +from warp_merge import J, F, synthesize + +def realize(w, side, frames): + """frames: {op index in poset list p: basis list}. Returns new program (with climbs) and new canonical.""" + c = deepcopy(w['canonical']); orig = w['programs'][side] + labels = {span(b): i for i, b in enumerate(c['frames'])} + def lab(b): + s = span(b) + if s not in labels: + labels[s] = len(c['frames']); c['frames'].append(sorted(join(b), reverse=True)) + return labels[s] + events = [e for e in orig if e[0] != 'climb'] + pidx = [k for k, e in enumerate(events) if e[0] not in ('phase', 'adapter', 'residual_adapter')] + p, groups = build(w, side) + assert len(p) == len(pidx) + seg, nseg = segments(p, groups) + newev = [deepcopy(e) for e in events] + fdim = {} + for i, e in enumerate(p): + k = pidx[i] + if i in frames: + assert newev[k][0] == 'scalar' + newev[k][2] = lab(frames[i]) + if newev[k][0] == 'scalar': fdim[i] = len(c['frames'][newev[k][2]]) + # graph over poset ops + succ = defaultdict(set); indeg = [0]*len(p) + def edge(a, b): + if b not in succ[a]: succ[a].add(b); indeg[b] += 1 + hub = len(p); extra = 0 + nodes = list(range(len(p))) + for r, gl in groups.items(): + for (t0, A), (t1, B) in zip(gl, gl[1:]): + for a in A: + for b in B: edge(a, b) + # frame-order edges within register segments + members = defaultdict(list) + for i in range(len(p)): + for R, k in seg[i].items(): + if isinstance(k, int) and i in fdim: members[R, k].append(i) + for key, m in members.items(): + bylev = defaultdict(list) + for i in m: bylev[fdim[i]].append(i) + ls = sorted(bylev) + for l1, l2 in zip(ls, ls[1:]): + for a in bylev[l1]: + for b in bylev[l2]: edge(a, b) + heap = [(pidx[i], i) for i in range(len(p)) if indeg[i] == 0]; heapq.heapify(heap); order = [] + while heap: + _, i = heapq.heappop(heap); order.append(i) + for j in succ[i]: + indeg[j] -= 1 + if indeg[j] == 0: heapq.heappush(heap, (pidx[j], j)) + assert len(order) == len(p), 'cycle' + # place markers: keep each marker before the first op that originally followed it + pos_of = {pidx[i]: n for n, i in enumerate(order)} + out = []; markers = defaultdict(list); nxt = None + for k in range(len(events)-1, -1, -1): + if k in pos_of: nxt = pos_of[k] + else: markers[nxt if nxt is not None else len(order)].append(events[k]) + for n, i in enumerate(order): + out += list(reversed(markers.get(n, []))); out.append(newev[pidx[i]]) + out += list(reversed(markers.get(len(order), []))) + prog = synthesize(c, out) + return c, prog + +def replay(c, prog, backward): + V = F.load(ROOTP/'research/kappa-causal-continuation/buffer-borrowing/verify_buffers.py', 'r13_rows') + X = F.load(ROOTP/'research/kappa-rebuild/complex/native_extensions.py', 'r13_literal') + rows, rec = X.literal_replay(V, c, prog, backward) + ok = all(rows['L', r] == V.expected(('L', r), [], backward, False) for r in range(632)) + F.need(ok, 'All632 arbitrary persistent endpoints') + prof = Counter({int(k): v for k, v in rec['paid_profile'].items()}) + rebound = deepcopy(c); rebound['R'] = len(c['start'])-2*c['v']; rebound['local_profile'] = dict(prof) + second = V.replay(prog, rebound, [], backward, False) + return prof, rec, second + +if __name__ == '__main__': + side = sys.argv[1]; sol = json.load(open(sys.argv[2])) + frames = {int(k): v for k, v in sol['frames'].items()} + w = load(); t = time.time(); c, prog = realize(w, side, frames) + print('program', len(prog), 'climbs', sum(e[0] == 'climb' for e in prog), 't', time.time()-t, flush=True) + prof, rec, second = replay(c, prog, side == 'backward') + print('PASS replay', dict(sorted(prof.items())), 'mass', sum(k*v for k, v in prof.items())) + from price import root + pp = dict(prof); pp.pop(8, None) if pp.get(8) == 8 else None + print('root', root({k: v for k, v in prof.items() if k != 8} | ({8: prof[8]-8} if prof.get(8, 0) > 8 else {}))) + if len(sys.argv) > 3: + open(sys.argv[3], 'wb').write(gzip.compress(json.dumps(dict(canonical=c, program=prog)).encode(), mtime=0)) diff --git a/research/frontier-word-reorder-ceilings/r13-reorder/tools/rewrite.py b/research/frontier-word-reorder-ceilings/r13-reorder/tools/rewrite.py new file mode 100644 index 0000000000..6855a712f3 --- /dev/null +++ b/research/frontier-word-reorder-ceilings/r13-reorder/tools/rewrite.py @@ -0,0 +1,150 @@ +"""Stage 3 probe: one-step non-commuting swaps with exact correction ADDs at thin helper visits. +Swap x=(A+=cB) with its adjacent conflicting neighbour q (first conflicting op after / last before): + next q=(B+=dE): q; x; A+=-cd E next q=(D+=eA): q; D+=ec B; x + prev q=(B+=dE): x; q; A+=cd E prev q=(D+=eA): x; q; D+=-ec B +Each candidate program is re-optimised by construct.py (medium domains) and replay-checked if better.""" +import sys, json, time, os +from fractions import Fraction as Q +from copy import deepcopy +sys.path.insert(0, str(__import__('pathlib').Path(__file__).resolve().parent)) +from load import * +from poset import reg_types + +def conflict(e1, e2): + t1 = dict(); t2 = dict() + for r, t in reg_types(e1): t1[r] = t + for r, t in reg_types(e2): t2[r] = t + for r in set(t1) & set(t2): + if not (t1[r] == t2[r] and t1[r] in 'TS'): return True + return False + +def add(a, b, q, frame): + q = Q(q); return ['scalar', ['add', ['L', a], ['L', b], q.numerator, q.denominator], frame] + +def is_LL_add(e): + return e[0] == 'scalar' and e[1][0] == 'add' and e[1][1][0] == 'L' and e[1][2][0] == 'L' + +def swap(prog, k, direction): + """prog: event list incl. climbs (climbs ignored/dropped). Returns new list or None.""" + ev = [e for e in prog if e[0] != 'climb'] + # map index k (in ev) + x = ev[k]; assert is_LL_add(x) + A, B = x[1][1][1], x[1][2][1]; c = Q(x[1][3], x[1][4]) + rng = range(k+1, len(ev)) if direction == 'next' else range(k-1, -1, -1) + for j in rng: + if ev[j][0] in ('phase', 'adapter', 'residual_adapter'): continue + if conflict(x, ev[j]): break + else: return None + q = ev[j] + if not is_LL_add(q): return None + D, E = q[1][1][1], q[1][2][1]; d = Q(q[1][3], q[1][4]) + f0 = x[2] + if D == B and E != A: # q writes x's source + corr = add(A, E, (-c*d if direction == 'next' else c*d), f0) + elif E == A and D != B: # q reads x's target + corr = add(D, B, (c*d if direction == 'next' else -c*d), f0) + else: return None + new = ev[:] + if direction == 'next': + # remove x, insert after q: q; [corr]; x (order matters only for the reads-target case) + del new[k]; jj = j-1 + ins = [corr, x] if E == A else [x, corr] + new[jj+1:jj+1] = ins + else: + del new[k] + new[j:j] = [x] # x before q + new[j+2:j+2] = [corr] + return new, (k, j, direction, x[1], q[1], corr[1]) + +def thin_sites(w, side): + c = w['canonical']; prog = w['programs'][side] + ev = [e for e in prog if e[0] != 'climb'] + visits = defaultdict(list) + for k, e in enumerate(ev): + if e[0] == 'scalar': + for r in roles(e): + if e[2] not in (c['start'][r], c['final'][r]): visits[r, e[2]].append(k) + return [(r, f, ks[0]) for (r, f), ks in visits.items() if len(ks) <= int(__import__('os').environ.get('MAXK', 1)) and r >= int(__import__('os').environ.get('RMIN', 224)) and is_LL_add(ev[ks[0]])] + +ROOTP = __import__('pathlib').Path.home()/'imb-r13' +sys.path.insert(0, str(ROOTP/'research/warp-interface-20261022')) +from warp_merge import synthesize + +def cost_of(c, ev, C=0.00302): + try: out = synthesize(c, ev) + except ValueError: return None, None + prof = Counter(e[5] for e in out if e[0] == 'climb') + return sum(n*r**(1-C) for r, n in prof.items()), prof + +SPANS = {} +def local_cost(c, ev, regs, C=0.00302): + """Chain cost restricted to registers regs; None if any chain is not nested (warps reset).""" + if not SPANS: + for i, b in enumerate(c['frames']): SPANS[i] = span(b) + tot = 0.0 + for r in regs: + cur = c['start'][r] + seq = [] + for e in ev: + if e[0] == 'scalar' and r in roles(e): seq.append(('s', e[2])) + elif e[0] == 'warp' and e[1][1] == r: seq.append(('w', e[3], e[4])) + seq.append(('s', c['final'][r])) + for t in seq: + new = t[1] + if new != cur: + if not SPANS[cur] < SPANS[new]: return None + tot += (len(c['frames'][new]) - len(c['frames'][cur]))**(1-C) + cur = t[2] if t[0] == 'w' else new + return tot + +def screen(w, side, site, direction): + c = w['canonical']; prog = w['programs'][side] + r, f, k = site + res = swap(prog, k, direction) + if res is None: return [] + new, info = res + visits = defaultdict(set) + for e in new: + if e[0] == 'scalar': + for rr in roles(e): visits[rr].add(e[2]) + # locate x and corr in new + xi = [i for i, e in enumerate(new) if e is not None and e[0] == 'scalar' and e[1] == info[3]] + ci = [i for i, e in enumerate(new) if e[0] == 'scalar' and e[1] == info[5]] + if len(ci) != 1: return [] + ci = ci[0] + A = info[3][1][1]; B = info[3][2][1] + others = visits[A] - {f} + out = [] + xs = [i for i in xi] + corr_regs = (info[5][1][1], info[5][2][1]) + copt = (visits[corr_regs[0]] & visits[corr_regs[1]]) | {0, 1} + regs = {A, B, *corr_regs} + ev0 = [e for e in prog if e[0] != 'climb'] + base = local_cost(c, ev0, regs) + for xf in sorted(others | {f}): + for cf in sorted(copt): + ev = [e[:] for e in new] + for i in xs: ev[i] = [ev[i][0], ev[i][1], xf] + ev[ci] = [ev[ci][0], ev[ci][1], cf] + cst = local_cost(c, ev, regs) + if cst is not None and cst < base - 1e-9: + full, prof = cost_of(c, ev) + if full is not None: out.append((full, xf, cf, prof)) + return out, info + +if __name__ == '__main__': + side = sys.argv[1]; part, nparts = int(sys.argv[2]), int(sys.argv[3]) + w = load(); c = w['canonical'] + base, bprof = cost_of(c, [e for e in w['programs'][side] if e[0] != 'climb']) + print('base', base, dict(bprof), flush=True) + sites = thin_sites(w, side)[part::nparts]; best = [] + t = time.time() + for n, s in enumerate(sites): + for d in ('next', 'prev'): + r = screen(w, side, s, d) + if not r: continue + res, info = r + for cst, xf, cf, prof in res: + if cst < base - 1e-9: + print('GAIN', base-cst, s, d, xf, cf, dict(prof), info, flush=True) + if n % 20 == 0: print('progress', n, len(sites), time.time()-t, flush=True) diff --git a/research/frontier-word-reorder-ceilings/r13-reorder/tools/sdom.py b/research/frontier-word-reorder-ceilings/r13-reorder/tools/sdom.py new file mode 100644 index 0000000000..626760d923 --- /dev/null +++ b/research/frontier-word-reorder-ceilings/r13-reorder/tools/sdom.py @@ -0,0 +1,72 @@ +"""Subspace domains for every op (fixed warps, pinned C ops), pruned to fixpoint by +forced-frame chain compatibility on every register segment.""" +import sys, time +sys.path.insert(0, str(__import__('pathlib').Path(__file__).resolve().parent)) +sys.path.insert(0, str(__import__('pathlib').Path.home()/'imb-r13/research/scalar-reorder-20261022')) +from lift import * +from intervals import complete_interval + +class Frames: + def __init__(s, fr): + s.spans = [span(b) for b in fr]; s.dims = [len(b) for b in fr]; s.fb = [list(b) for b in fr] + s.labels = {x: i for i, x in enumerate(s.spans)} + def lab(s, b): + x = span(b) + if x not in s.labels: + s.labels[x] = len(s.spans); s.spans.append(x); s.dims.append(len(b)); s.fb.append(list(join(b))) + return s.labels[x] + def le(s, a, b): return s.dims[a] <= s.dims[b] and s.spans[a] <= s.spans[b] + def comp(s, a, b): return s.le(a, b) or s.le(b, a) + +def domains(w, side, max_gap=6, relax_warps=False): + c = w['canonical']; fr = c['frames'] + p, groups = build(w, side) + lows, lowd, ups, upd, pinned = bounds(w, p, groups, relax_warps=relax_warps) + seg, nseg = segments(p, groups) + Fm = Frames(fr); st = {}; cache = {}; dom = {} + for i, e in enumerate(p): + if e[0] in ('center', 'warp'): continue + if i in pinned: + dom[i] = {Fm.lab(pinned[i])}; continue + key = (lows[i], ups[i]) + if key not in cache: + a = Fm.lab(lows[i]); b = Fm.lab(ups[i]) + cache[key] = complete_interval(Fm.spans, Fm.dims, Fm.fb, (a,), (b,), st, max_gap=max_gap) + dom[i] = set(cache[key]) + # register-segment membership + members = defaultdict(list) + for i in dom: + for R, k in seg[i].items(): + if isinstance(k, int): members[R, k].append(i) + ends = defaultdict(set) + for R in range(632): + ends[R, 0].add(c['start'][R]); ends[R, nseg.get(R, 0)].add(c['final'][R]) + for i, e in enumerate(p): + if e[0] == 'warp' and not relax_warps: + R = e[1][1]; k = seg[i][R][1]; ends[R, k].add(e[3]); ends[R, k+1].add(e[4]) + changed = True; rounds = 0 + while changed: + changed = False; rounds += 1 + forced = defaultdict(set) + for key in members: + forced[key] |= ends[key] + for i in members[key]: + if len(dom[i]) == 1: forced[key] |= dom[i] + for i, D in dom.items(): + if len(D) == 1: continue + keys = [(R, k) for R, k in seg[i].items() if isinstance(k, int)] + nd = {X for X in D if all(Fm.comp(X, Y) for key in keys for Y in forced[key])} + # must lie between segment start and end + if nd != D: + assert nd, ('empty', i) + dom[i] = nd; changed = True + return dict(p=p, groups=groups, dom=dom, seg=seg, nseg=nseg, members=members, ends=ends, Fm=Fm, lows=lows, ups=ups, stats=st, rounds=rounds) + +if __name__ == '__main__': + t = time.time(); w = load(); S = domains(w, sys.argv[1] if len(sys.argv) > 1 else 'forward') + dom = S['dom']; Fm = S['Fm'] + print('t', time.time()-t, 'rounds', S['rounds'], S['stats']) + print('free ops', sum(len(v) > 1 for v in dom.values()), 'total dom', sum(len(v) for v in dom.values())) + cand = {key: set().union(*(dom[i] for i in m)) | S['ends'][key] for key, m in S['members'].items()} + arcs = sum(1 for v in cand.values() for a in v for b in v if Fm.dims[a] < Fm.dims[b] and Fm.spans[a] < Fm.spans[b]) + print('max cand', max(map(len, cand.values())), 'sum cand', sum(map(len, cand.values())), 'arcs', arcs)