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 0000000000..dd85cd6764 Binary files /dev/null and b/research/frontier-word-reorder-ceilings/r13-reorder/data/cons-backward-medium.json.gz differ diff --git a/research/frontier-word-reorder-ceilings/r13-reorder/data/cons-forward-True.json.gz b/research/frontier-word-reorder-ceilings/r13-reorder/data/cons-forward-True.json.gz new file mode 100644 index 0000000000..d81721a749 Binary files /dev/null and b/research/frontier-word-reorder-ceilings/r13-reorder/data/cons-forward-True.json.gz differ 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 0000000000..9d11bf5f7a Binary files /dev/null and b/research/frontier-word-reorder-ceilings/r13-reorder/data/cons-forward-medium.json.gz differ 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 0000000000..cf90a49cfe Binary files /dev/null and b/research/frontier-word-reorder-ceilings/r13-reorder/data/cons-forward-wide.json.gz differ 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 0000000000..3ca1746b60 Binary files /dev/null and b/research/frontier-word-reorder-ceilings/r13-reorder/data/cons-forward.json.gz differ diff --git a/research/frontier-word-reorder-ceilings/r13-reorder/data/mip-backward-pinw.json.gz b/research/frontier-word-reorder-ceilings/r13-reorder/data/mip-backward-pinw.json.gz new file mode 100644 index 0000000000..cb057b4917 Binary files /dev/null and b/research/frontier-word-reorder-ceilings/r13-reorder/data/mip-backward-pinw.json.gz differ 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 0000000000..a58290315c Binary files /dev/null and b/research/frontier-word-reorder-ceilings/r13-reorder/data/mip-backward.json.gz differ 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 0000000000..6da817e9ae Binary files /dev/null and b/research/frontier-word-reorder-ceilings/r13-reorder/data/mip-forward-pinw.json.gz differ 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 0000000000..e7c21cec63 Binary files /dev/null and b/research/frontier-word-reorder-ceilings/r13-reorder/data/mip-forward.json.gz differ 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)