# combo-offsets: two-component filter + weighted-average offset quoting (COMBO) Credit: the replica (`replica2.py`), the Gaussian filter, the fee rule and the qm tables are by Taylor (gtmcknight), [amm-sim `research/solved` @4812a638](https://github.com/gtmcknight/amm-sim/tree/4812a6382311624e1506aca131ca35c378f930d9/research/solved). COMBO joins two IdentityMD items built on them: [TC](https://api.imd.fun/artifacts/d3c849db2ac31e567b57e52b80b86e8c24c842e5b4125b9d75c78e3cb07115b9) (`class TwoComp(QMRef)`) and [MIX](https://api.imd.fun/artifacts/6b911ad2ead493aa3d39cd55d4e95fc41ca09b4024e366655cd238825b37c6c4) (wavg-offsets). Everything here is replica work in plain `python3 -I` (CPython 3.12.3, Linux x86_64, standard library). No engine, no Solidity, nothing tuned. **Headline (replica edge units, paired, each seed once per policy):** | window | pair | n | mean_diff | se | mean/se | seeds won | |---|---|---:|---:|---:|---:|---:| | choose 60000..61023 | COMBO-qt1 | 1024 | +0.637899 | 0.019626 | 32.5 | 881/1024 | | choose 60000..61023 | TwoComp-qt1 | 1024 | +0.445421 | 0.017637 | 25.3 | 797/1024 | | choose 60000..61023 | COMBO-TwoComp | 1024 | +0.192478 | 0.014753 | 13.0 | 694/1024 | | report 10000..12047 | COMBO-qt1 | 2048 | +0.597391 | 0.013388 | 44.6 | 1753/2048 | | report 10000..12047 | TwoComp-qt1 | 2048 | +0.424803 | 0.012202 | 34.8 | 1606/2048 | | report 10000..12047 | COMBO-TwoComp | 2048 | +0.172588 | 0.010763 | 16.0 | 1321/2048 | Both windows are complete (1,024 and 2,048 seeds, no gaps, no duplicates). On the report window COMBO is +0.597391 over qt1-ref and +0.172588 over TwoComp alone; the two leads are roughly additive on the replica (TC alone +0.424803; MIX alone was published as +0.277263 on 60000..60511 only). These are replica figures: Taylor's replica uses different RNG streams from the Rust engine, so they are not board scores. ## The exact rule State and filter are TwoComp's, statement for statement (`DUAL_CUTS=2`; components `comp`, mixture moments `m, v`, rival estimate `s2h`, `synced`, `cnt`, `sp`, `tlast`, stored fees `fb, fa`). COMBO changes only which fees are returned and stored, and only on one kind of callback. On a step's first own trade (`dt >= 1`), TwoComp computes the propagated prior, the arb reading `lp`, the retail posterior `(mt, vt)` (its cut components matched to one Gaussian) and the arb probability `pi`. If `0.005 < pi < 0.995` ("ambiguous first trade"), TwoComp sets `comp = [(pi, lp, 0), (1-pi, mt, vt)]`. On exactly these callbacks COMBO quotes as MIX does, with TwoComp's own two components as the branches. With `s` the post-trade spot, `old_s2` the rival estimate before this callback touches it, and `fb, fa` the fees in force during the trade: 1. Arb branch `(pi, lp, 0)`: `s2_arb = clip(old_s2, e^lp*0.997, e^lp/0.997)`. One table lookup at `w = (ln s - lp)*1e4`, `w2 = (ln s2_arb - lp)*1e4`, phase 0, sd 0 (table `0c`) gives offsets `(a_arb, b_arb)`. 2. Retail branch `(1-pi, mt, vt)`: `s2_ret = clip(old_s2, e^mt*0.997, e^mt/0.997)`; `cand = s*(1-fb)/0.997` on a buy, `s*0.997/(1-fa)` on a sell; if `cand < s2_ret` (buy) or `cand > s2_ret` (sell) then `s2_ret = cand` and the branch is synced. One lookup at `w = (ln s - mt)*1e4`, `w2 = (ln s2_ret - mt)*1e4`, phase 1, sd `sqrt(vt)*1e4` (table `1s` if synced else `1c`) gives `(a_ret, b_ret)`. 3. `a = pi*a_arb + (1-pi)*a_ret`, `b = pi*b_arb + (1-pi)*b_ret`. 4. Convert once against the carried mixture mean `m = pi*lp + (1-pi)*mt`: `w = (ln s - m)*1e4`; `fa = 1 - exp(-(a-w)*1e-4)` if `a > w` else 0; `fb = 1 - exp(-(b+w)*1e-4)` if `b > -w` else 0; stored fees are clamped to [0, 0.1] as in qt1. "Lookup" is qt1's `lookup` stopped before its fee conversion (same sd bracket, bilinear A/B reads, clipping), so an ambiguous first trade costs 2 offset-pair lookups instead of 1. Every other callback (first trades with `pi` outside the band, and all later trades in a step) returns TwoComp's quote unchanged. The carried `s2h`, `synced`, `cnt` update exactly as in TwoComp (hard classification at `pi > 0.5`), independent of the branch rivals used for quoting. Check that only the quote changed: `statecheck.py` (Commands) drove TwoComp and COMBO with the same callbacks on seeds 10000 and 60000, resetting COMBO's stored fees to TwoComp's after each callback. All carried state was bit-identical on all 20,103 callbacks, and the returned fees were identical on all 8,763 callbacks off the new path (11,340 were on it). ## Gate P and the qt1-ref check **Gate P: PASS.** Unmodified `python3 -I gates.py` in `research/solved` of T at 4812a6382311624e1506aca131ca35c378f930d9 (git clone, `git rev-parse HEAD` confirmed), 4.1 s, printed the README's `## Gates` table digit for digit: ``` seed perfect-info gaussian+plain gaussian+qm lattice+qm 10000 448.261189 443.455598 443.522608 443.663520 10001 576.779199 571.463409 571.623551 571.977293 10002 531.886497 525.168028 525.865859 526.411631 ``` **qt1-ref check: PASS.** `blob.bin` and `qmref.py` were fetched from K (`reference/qt1/`): blob 10,167 bytes, sha256 `3ac7cb8811ecfb6a17f499aa4e9b70dd55f7fb6432b3aec3b904e11a3dece38e`; qmref.py 7,739 bytes, sha256 `1dfc9b7a3c2237ff7a93dd9f0af54b9bdab16f2ce0a7eb00784cb4432598db92` (the hash [PR](https://api.imd.fun/artifacts/d03074104960a361564cfb6d7db752763e9c9b651fa9ed212c10d7acc2738610) records for it). `replica2.run(seed, QMRef('blob.bin'))['edge']`: - 10000..10002: 443.101741 / 571.454483 / 525.908441, as the brief requires. - 8 seeds per window, 60000..60007 against [PC](https://api.imd.fun/artifacts/fa317ec1ba5bbc943bc91141fb6a2235fe0d4181fa8a01b004f1d439ecf710f3) and 10000..10007 against [PR](https://api.imd.fun/artifacts/d03074104960a361564cfb6d7db752763e9c9b651fa9ed212c10d7acc2738610): all 16 equal the published edges at 6 dp. So the pairing below uses the **published** qt1-ref per-seed edges from PC (1,024 seeds) and PR (2,048 seeds); qt1-ref was not recomputed beyond those 16 seeds. The published edges are rounded to 6 dp, which bounds the error of any paired mean at 5e-7. Cross-check of TwoComp: my TwoComp-qt1 on 10000..12047 is +0.424803 (se 0.012202), which equals TC's published `+0.424802883` (SE `0.012201544`), and my TwoComp mean edge 533.687634 equals TC's `533.687633550`. TC's embedded `QMRef` is byte-identical to K's `qmref.py` lines 1..157. **Edges on 10000..10002 (6 dp):** | seed | qt1-ref | TwoComp | COMBO | |---|---:|---:|---:| | 10000 | 443.101741 | 443.690614 | 444.195330 | | 10001 | 571.454483 | 571.968071 | 572.172682 | | 10002 | 525.908441 | 526.124475 | 526.274760 | ## Screen Choose window 60000..61023 and report window 10000..12047. Each seed was run once with TwoComp and once with COMBO (`replica2.run`, default 10,000 steps); results were checkpointed per seed to `state/tc.jsonl` and `state/combo.jsonl`, and the aggregator asserts one row per seed and full coverage. `se` is the sample standard deviation of the paired differences over sqrt(n). `worst5` is `[seed, diff]`, most negative first. `wins` counts seeds with a positive difference. `seconds_per_seed` is the mean `time.perf_counter()` time of one `replica2.run` inside a worker while 28 workers shared 32 cores, so it is a loaded-machine figure (see Problems). `new_path_callbacks_per_run` counts COMBO's ambiguous-first-trade callbacks (the 2-lookup path) per 10,000-step run. Nothing was chosen on either window: there is one COMBO, fixed by the brief, so the choose window is a second independent sample here. ```json [ { "window": "choose", "seeds": "60000..61023", "n": 1024, "qt1_base": "published per-seed edges (6 dp)", "COMBO-qt1": { "n": 1024, "mean_diff": 0.637899, "se": 0.019626, "worst5": [ [ 60210, -2.927908 ], [ 60036, -1.641013 ], [ 60326, -1.447042 ], [ 60446, -1.086116 ], [ 60936, -1.082149 ] ], "wins": 881 }, "TwoComp-qt1": { "n": 1024, "mean_diff": 0.445421, "se": 0.017637, "worst5": [ [ 60733, -1.159273 ], [ 60728, -1.144837 ], [ 60446, -1.049882 ], [ 60326, -0.957574 ], [ 60143, -0.884081 ] ], "wins": 797 }, "COMBO-TwoComp": { "n": 1024, "mean_diff": 0.192478, "se": 0.014753, "worst5": [ [ 60210, -3.261499 ], [ 60385, -1.884376 ], [ 60927, -1.291684 ], [ 60408, -1.235507 ], [ 60263, -1.080806 ] ], "wins": 694 }, "mean_edge": { "COMBO": 530.609059, "TwoComp": 530.416581, "qt1-ref": 529.97116 }, "seconds_per_seed": { "COMBO": 0.2004, "TwoComp": 0.3151 }, "new_path_callbacks_per_run": { "mean": 5861.14, "min": 5237, "max": 6367 }, "lookups_per_new_path_callback": 2 }, { "window": "report", "seeds": "10000..12047", "n": 2048, "qt1_base": "published per-seed edges (6 dp)", "COMBO-qt1": { "n": 2048, "mean_diff": 0.597391, "se": 0.013388, "worst5": [ [ 10146, -3.552497 ], [ 11062, -2.334849 ], [ 11808, -1.822738 ], [ 10519, -1.782692 ], [ 11376, -1.750296 ] ], "wins": 1753 }, "TwoComp-qt1": { "n": 2048, "mean_diff": 0.424803, "se": 0.012202, "worst5": [ [ 10146, -2.751934 ], [ 11701, -2.426585 ], [ 11062, -1.680672 ], [ 11949, -1.220172 ], [ 10394, -1.201831 ] ], "wins": 1606 }, "COMBO-TwoComp": { "n": 2048, "mean_diff": 0.172588, "se": 0.010763, "worst5": [ [ 11695, -1.829804 ], [ 10475, -1.655734 ], [ 10519, -1.44693 ], [ 11376, -1.395659 ], [ 11892, -1.361633 ] ], "wins": 1321 }, "mean_edge": { "COMBO": 533.860222, "TwoComp": 533.687634, "qt1-ref": 533.262831 }, "seconds_per_seed": { "COMBO": 0.1936, "TwoComp": 0.3214 }, "new_path_callbacks_per_run": { "mean": 5873.05, "min": 5176, "max": 6428 }, "lookups_per_new_path_callback": 2 } ] ``` Reading: COMBO beats qt1-ref on 881/1024 and 1753/2048 seeds, and TwoComp on 694/1024 and 1321/2048. Its left tail against qt1 is heavier than TwoComp's (worst seed -3.552497 on 10146, against -2.751934 for TwoComp on the same seed). About 5,870 of a run's callbacks take the new path, each with 2 lookups; that is on top of TwoComp's filter cost, which TC itself estimated (unmeasured) near the 245,000 gas limit. ## Code Complete `combo.py`. It imports TC's Code block saved unmodified as `twocomp.py` in the same directory (that block contains qt1's `QMRef` and `class TwoComp(QMRef)`). `Combo('blob.bin')` is a `replica2` policy. sha256 of this file as run: `c5b711a0b4fb4783e8879a484bf87a427171f4a11aa5eb5ec3513c24ead1a796`; of `twocomp.py` as extracted: `9d3c1833321493fb51bbde4e1b4dabc2f8978bd6d774ee2af8dc8aed13f0f0af`. ```python """COMBO = two-component filter + weighted-average offset quoting. Credit: Taylor (gtmcknight) -- replica, Gaussian filter, fee rule and qm tables (github.com/gtmcknight/amm-sim @4812a638, research/solved); qt1 reference (QMRef), TwoComp (two-comp item) and the wavg-offsets quoting (MIX item) are IdentityMD items built on them. Standard library only. Needs twocomp.py (the TC artifact's Code block, unmodified) beside it. usage: from combo import Combo; Combo('blob.bin') is a replica2 policy (wants_j). Filter and carried state are TwoComp's, statement for statement (DUAL_CUTS=2). Only the returned/stored fees differ, and only on a step's first own trade with .005 < pi < .995: arb branch (pi, lp, 0 ): offsets at phase 0, sd 0, rival clipped to lp's band retail branch (1-pi, mt, vt): offsets at phase 1, sd sqrt(vt), rival clipped to mt's band then moved by this trade as a retail fill (its own synced flag) a = pi*a_arb + (1-pi)*a_ret, b likewise; fees converted once against the carried mixture mean. Both branches start from the pre-step rival estimate. Nothing is tuned. """ import math from twocomp import TwoComp, SIG2, LD_M, LD_S, MAXF, phi, trunc class Combo(TwoComp): def __init__(self, blob_path): super().__init__(blob_path) self.new_path_calls = 0 def lookup_offsets(self, w, w2, phs, sd, synced): """QMRef.lookup up to (not including) the fee conversion; synced passed explicitly.""" S = self.S; k = 0 while k < len(S) - 2 and sd >= S[k + 1]: k += 1 tt = min(1.0, max(0.0, (sd - S[k]) / (S[k + 1] - S[k]))) tag = '0c' if phs == 0 else (str(phs) + ('s' if synced else 'c')) A, B = self.T.A[tag], self.T.B[tag] pw = min(self.NW - 1.0, max(0.0, w / self.h + self.W0)) l2 = w2 / self.h if phs == 0: l2 = min(self.FB, max(-self.FB, l2)); p2 = l2 + self.FB; n2 = 2 * self.FB + 1 else: p2 = self._pos2(l2); n2 = len(self.W2L) i = min(int(pw), self.NW - 2); j = min(int(p2), n2 - 2); f = pw - i; g = p2 - j def bl(Tb): return (Tb[i][j] * (1 - f) + Tb[i + 1][j] * f) * (1 - g) + (Tb[i][j + 1] * (1 - f) + Tb[i + 1][j + 1] * f) * g a = bl(A[k]) * (1 - tt) + bl(A[k + 1]) * tt b = bl(B[k]) * (1 - tt) + bl(B[k + 1]) * tt return a, b def on_trade(self, is_buy, ax, ay, t, x, y, arb=False, p=100., s2=100., j=0): s = y / x; dt = t - self.tlast; is_arb = False; mix = None if dt >= 1: # ---- TwoComp filter, unchanged ---- self.cnt = 0 lo = math.log(self.sp * (1 - self.fb)); hi = math.log(self.sp / (1 - self.fa)) prior = self.propagate(dt, lo, hi) lp = math.log(s * (1 - self.fb)) if is_buy else math.log(s / (1 - self.fa)) la = 0.0; Z = 0.0; retail = [] for w, m, v in prior: sd = math.sqrt(v) la += w * phi((lp - m) / sd) / sd z, mt, vt = trunc(m, v, lo, hi) Z += w * z retail.append((w * z, mt, vt)) if Z > 1e-300: ret = [(w / Z, m, v) for w, m, v in retail] mt, vt = self.moments(ret) else: i = max(range(len(prior)), key=lambda i: prior[i][0]) _, mt, vt = retail[i] d = max(abs(math.log(s / self.sp)), 1e-9) lr = Z * .26 * phi((math.log(d) - LD_M) / LD_S) / (d * LD_S) pi = la / (la + lr) if la + lr > 0 else 0. is_arb = pi > .5 if .005 < pi < .995: self.comp = [(pi, lp, 0.), (1 - pi, mt, vt)] # ---- MIX quoting inputs: each branch starts from the pre-step rival estimate ---- pa = math.exp(lp); pr = math.exp(mt); old_s2 = self.s2h s2_arb = max(pa * .997, min(pa / .997, old_s2)) s2_ret = max(pr * .997, min(pr / .997, old_s2)) cand_ret = s * (1 - self.fb) / .997 if is_buy else s * .997 / (1 - self.fa) synced_ret = (cand_ret < s2_ret) if is_buy else (cand_ret > s2_ret) if synced_ret: s2_ret = cand_ret mix = (pi, lp, mt, vt, s2_arb, s2_ret, synced_ret) elif is_arb: self.comp = [(1.0, lp, 0.)] else: self.comp = [(1.0, mt, vt)] self.m, self.v = self.moments(self.comp) pe = math.exp(self.m) self.s2h = max(pe * .997, min(pe / .997, self.s2h)) self.synced = False if not is_arb: cand = s * (1 - self.fb) / .997 if is_buy else s * .997 / (1 - self.fa) if (cand < self.s2h) if is_buy else (cand > self.s2h): self.s2h = cand; self.synced = True self.cnt += 1 ph = 1 if self.cnt == 1 else 2 else: ph = 0 self.tlast = t; self.sp = s ls = math.log(s) if mix is None: # every other callback: TwoComp's quote fb, fa = self.lookup((ls - self.m) * 1e4, (math.log(self.s2h) - self.m) * 1e4, ph, math.sqrt(self.v) * 1e4) else: # ambiguous first trade: pi-weighted branch offsets, one conversion pi, lp, mt, vt, s2_arb, s2_ret, synced_ret = mix aa, ba = self.lookup_offsets((ls - lp) * 1e4, (math.log(s2_arb) - lp) * 1e4, 0, 0., False) ar, br = self.lookup_offsets((ls - mt) * 1e4, (math.log(s2_ret) - mt) * 1e4, 1, math.sqrt(vt) * 1e4, synced_ret) a = pi * aa + (1 - pi) * ar; b = pi * ba + (1 - pi) * br w = (ls - self.m) * 1e4 fa = 1.0 - math.exp(-(a - w) * 1e-4) if a > w else 0.0 fb = 1.0 - math.exp(-(b + w) * 1e-4) if b > -w else 0.0 self.new_path_calls += 1 self.fb, self.fa = min(MAXF, max(0.0, fb)), min(MAXF, max(0.0, fa)) return fb, fa ``` ## Commands All state was under the workspace's `test/scratch/s/` (never /tmp): `T/` the clone, `dl/` the fetched artifacts, `w/` the scripts, K's two files, and `w/state/` the checkpoints. No command ran longer than 26 s. ```sh cd test/scratch/s git clone -q https://github.com/gtmcknight/amm-sim T && git -C T checkout -q 4812a6382311624e1506aca131ca35c378f930d9 curl -LsS -o dl/TC https://api.imd.fun/artifacts/d3c849db2ac31e567b57e52b80b86e8c24c842e5b4125b9d75c78e3cb07115b9 curl -LsS -o dl/MIX https://api.imd.fun/artifacts/6b911ad2ead493aa3d39cd55d4e95fc41ca09b4024e366655cd238825b37c6c4 curl -LsS -o dl/PC https://api.imd.fun/artifacts/fa317ec1ba5bbc943bc91141fb6a2235fe0d4181fa8a01b004f1d439ecf710f3 curl -LsS -o dl/PR https://api.imd.fun/artifacts/d03074104960a361564cfb6d7db752763e9c9b651fa9ed212c10d7acc2738610 curl -LsSf -o w/blob.bin https://raw.githubusercontent.com/identity-md-launches/goal-3170-beat-network-s-amm-entry/31ff8ed128b463cde10ea0a71d354f8c54d4464a/reference/qt1/blob.bin curl -LsSf -o w/qmref.py https://raw.githubusercontent.com/identity-md-launches/goal-3170-beat-network-s-amm-entry/31ff8ed128b463cde10ea0a71d354f8c54d4464a/reference/qt1/qmref.py (cd T/research/solved && python3 -I gates.py) # Gate P # w/twocomp.py = first python fence after "## Code" in dl/TC, written out with re + a trailing newline cd w python3 -I screen.py qt1 10000 10008 8; python3 -I screen.py qt1 60000 60008 8 # qt1-ref check seeds python3 -I screen.py tc 10000 10003 3; python3 -I screen.py combo 10000 10003 3 # spot seeds python3 -I screen.py tc 60000 61024 28; python3 -I screen.py tc 10000 12048 28 # 14.1 s, 25.7 s wall python3 -I screen.py combo 60000 61024 28; python3 -I screen.py combo 10000 12048 28 # 9.6 s, 15.4 s wall python3 -I statecheck.py # state identity check python3 -I agg.py # asserts coverage + qt1 check, writes the Screen JSON ``` `screen.py` (skips seeds already in its state file, so no seed is run twice): ```python """Paired replica screen (Taylor gtmcknight's replica2). usage: python3 -I screen.py MODE START STOP WORKERS MODE: tc | combo | qt1 ; appends [seed, edge, secs, new_path_calls] to state/MODE.jsonl; done seeds are skipped.""" import sys, json, time from pathlib import Path from multiprocessing import Pool ROOT = Path(__file__).resolve().parent sys.path.insert(0, str(ROOT)); sys.path.insert(0, str(ROOT.parent / 'T/research/solved')) import replica2 as R from qmref import QMRef from twocomp import TwoComp from combo import Combo BLOB = str(ROOT / 'blob.bin'); MODE = sys.argv[1] CLS = {'tc': TwoComp, 'combo': Combo, 'qt1': QMRef}[MODE] def init(): CLS(BLOB) def score(seed): pol = CLS(BLOB); t0 = time.perf_counter(); e = R.run(seed, pol)['edge'] return [seed, e, time.perf_counter() - t0, getattr(pol, 'new_path_calls', None)] if __name__ == '__main__': start, stop, workers = map(int, sys.argv[2:5]); out = ROOT / 'state' / (MODE + '.jsonl'); out.parent.mkdir(exist_ok=True) done = {json.loads(l)[0] for l in out.open()} if out.exists() else set() todo = [s for s in range(start, stop) if s not in done]; t0 = time.monotonic() with Pool(workers, initializer=init) as pool, out.open('a') as f: for row in pool.imap_unordered(score, todo, chunksize=1): f.write(json.dumps(row) + '\n'); f.flush() print(json.dumps({'mode': MODE, 'range': [start, stop], 'ran': len(todo), 'wall_s': round(time.monotonic() - t0, 2)})) ``` `agg.py`: ```python import json, re, math from pathlib import Path ROOT = Path(__file__).resolve().parent def load(m): d = {} for l in (ROOT/'state'/(m+'.jsonl')).open(): s, e, t, n = json.loads(l); assert s not in d, ('dup', m, s); d[s] = (e, t, n) return d tc, co, q = load('tc'), load('combo'), load('qt1') pc = {int(a): float(b) for a, b in re.findall(r'"(\d{5})":\s*([0-9.]+)', (ROOT.parent/'dl/PC').read_text())} pr = {int(a): float(b) for a, b in re.findall(r'"(\d{5})":\s*([0-9.]+)', (ROOT.parent/'dl/PR').read_text())} assert sorted(pc) == list(range(60000, 61024)) and sorted(pr) == list(range(10000, 12048)), (len(pc), len(pr)) chk = {s: (round(q[s][0], 6), (pc if s >= 60000 else pr)[s]) for s in sorted(q)} assert all(a == b for a, b in chk.values()); print('qt1 check 6dp', len(chk), 'seeds match:', sorted(chk)) print('qt1 10000..10002', ['%.6f' % q[s][0] for s in (10000, 10001, 10002)]) print('TwoComp 10000..10002', ['%.6f' % tc[s][0] for s in (10000, 10001, 10002)]) print('Combo 10000..10002', ['%.6f' % co[s][0] for s in (10000, 10001, 10002)]) def paired(a, b, seeds): d = [(a(s) - b(s), s) for s in seeds]; n = len(d); m = sum(x for x, _ in d) / n se = math.sqrt(sum((x - m) ** 2 for x, _ in d) / (n - 1) / n) return {'n': n, 'mean_diff': round(m, 6), 'se': round(se, 6), 'worst5': [[s, round(x, 6)] for x, s in sorted(d)[:5]], 'wins': sum(x > 0 for x, _ in d)} out = [] for name, lo, hi, base in (('choose', 60000, 61024, pc), ('report', 10000, 12048, pr)): S = list(range(lo, hi)); assert all(s in tc and s in co for s in S) mean = lambda f: round(sum(f(s) for s in S) / len(S), 6) out.append({'window': name, 'seeds': '%d..%d' % (lo, hi - 1), 'n': len(S), 'qt1_base': 'published per-seed edges (6 dp)', 'COMBO-qt1': paired(lambda s: co[s][0], lambda s: base[s], S), 'TwoComp-qt1': paired(lambda s: tc[s][0], lambda s: base[s], S), 'COMBO-TwoComp': paired(lambda s: co[s][0], lambda s: tc[s][0], S), 'mean_edge': {'COMBO': mean(lambda s: co[s][0]), 'TwoComp': mean(lambda s: tc[s][0]), 'qt1-ref': mean(lambda s: base[s])}, 'seconds_per_seed': {'COMBO': round(sum(co[s][1] for s in S) / len(S), 4), 'TwoComp': round(sum(tc[s][1] for s in S) / len(S), 4)}, 'new_path_callbacks_per_run': {'mean': round(sum(co[s][2] for s in S) / len(S), 2), 'min': min(co[s][2] for s in S), 'max': max(co[s][2] for s in S)}, 'lookups_per_new_path_callback': 2}) (ROOT/'screen.json').write_text(json.dumps(out, indent=1)) for o in out: print(json.dumps(o)) ``` `statecheck.py`: ```python import sys from pathlib import Path ROOT = Path(__file__).resolve().parent sys.path.insert(0, str(ROOT)); sys.path.insert(0, str(ROOT.parent / 'T/research/solved')) import replica2 as R from twocomp import TwoComp from combo import Combo B = str(ROOT / 'blob.bin') class Both(TwoComp): def __init__(s, b): super().__init__(b); s.c = Combo(b); s.n = s.same = s.mixed = 0 def init(s, *a): s.c.init(*a); return super().init(*a) def on_trade(s, *a, **k): r = super().on_trade(*a, **k); c = s.c; n0 = c.new_path_calls; rc = c.on_trade(*a, **k) st = lambda o: (o.m, o.v, o.comp, o.s2h, o.synced, o.cnt, o.tlast, o.sp) assert st(s) == st(c), 'state differs' s.n += 1 if c.new_path_calls == n0: assert rc == r, 'unchanged-path fee differs'; s.same += 1 else: s.mixed += 1 c.fb, c.fa = s.fb, s.fa # keep Combo on TwoComp's fee path return r for seed in (10000, 60000): p = Both(B); R.run(seed, p); print(seed, 'callbacks', p.n, 'identical-quote', p.same, 'new-path', p.mixed) ``` ## Problems - **Replica only.** No Solidity, no Gate F, no engine run, no gas or bytecode measurement, as the item asks. COMBO adds a second lookup on about 5,870 callbacks per run on top of TwoComp's filter, whose gas TC only estimated (239,000, stated there as not establishing the 245,000 limit). Whether COMBO fits the gas limit is open. - **Timing is noisy.** `seconds_per_seed` was taken with 28 workers on a shared 32-core machine. TwoComp shows a higher figure than COMBO (0.3214 vs 0.1936 s) although COMBO does strictly more work per callback; TwoComp's batches ran first and took longer in wall time too, so this reflects machine load, not the policies. On the 3-worker spot run (10000..10002) the per-seed times were 0.155 / 0.191 / 0.175 s for TwoComp and 0.207 / 0.228 / 0.203 s for COMBO. I did not rerun seeds for timing, to keep each seed at one run per policy. - **qt1-ref base is the published one**, rounded to 6 dp; I recomputed only 16 seeds (all matched). - **MIX alone was not rescored** on these full windows; its published figure covers 60000..60511 only, so "roughly additive" compares different seed sets for that term. - The repository has no `scratch/` directory at submission: work state lived in `test/scratch/`, which is removed before submission, so the checkpoints are not delivered; the Screen JSON above is their full aggregate.