summaryrefslogtreecommitdiff
path: root/src/eval_tune/compare_ecm_shareddepth.py
diff options
context:
space:
mode:
authorScott Gasch <[email protected]>2026-08-29 23:17:31 -0700
committerScott Gasch <[email protected]>2026-08-29 23:17:31 -0700
commitfa210fb9645afd27e2991b3ee8139be231d0b5ec (patch)
tree1ee7be4d51d3d2bc4ffa2c512db5270cea6b2af2 /src/eval_tune/compare_ecm_shareddepth.py
parentf2613dfabb5ef3a7a08a73e74c83467dfad9ddcc (diff)
Various utils.
Diffstat (limited to 'src/eval_tune/compare_ecm_shareddepth.py')
-rw-r--r--src/eval_tune/compare_ecm_shareddepth.py74
1 files changed, 74 insertions, 0 deletions
diff --git a/src/eval_tune/compare_ecm_shareddepth.py b/src/eval_tune/compare_ecm_shareddepth.py
new file mode 100644
index 0000000..2194f02
--- /dev/null
+++ b/src/eval_tune/compare_ecm_shareddepth.py
@@ -0,0 +1,74 @@
+#!/usr/bin/env python3
+"""Pair up per-problem node counts at the DEEPEST depth BOTH binaries
+completed within their sn=N node budget (not the final/achieved depth,
+which is too coarse -- see compare_ecm_depth.py). Continuous signal,
+still fully bounded since we only ever compare depths both sides
+actually finished.
+"""
+import re
+import statistics
+import sys
+
+DEPTH_LINE_RE = re.compile(r"^\s*(\d+)[+]?\s+(\S+)\s+[\d:.]+\s+(\d+)\s")
+ROOT_POS_RE = re.compile(r"^The root position is:")
+
+
+def parse(path):
+ """Return list of {depth: node_count} dicts, one per problem, in order."""
+ problems = []
+ cur = {}
+ with open(path) as f:
+ for line in f:
+ if ROOT_POS_RE.match(line):
+ if cur:
+ problems.append(cur)
+ cur = {}
+ continue
+ m = DEPTH_LINE_RE.match(line)
+ if m:
+ depth = int(m.group(1))
+ nodes = int(m.group(3))
+ cur[depth] = nodes # later (deeper/re-searched) lines overwrite
+ if cur:
+ problems.append(cur)
+ return problems
+
+
+def main():
+ base_path, cand_path = sys.argv[1], sys.argv[2]
+ base = parse(base_path)
+ cand = parse(cand_path)
+ n = min(len(base), len(cand))
+
+ ratios = []
+ wins = losses = ties = 0
+ skipped = 0
+
+ for i in range(n):
+ b, c = base[i], cand[i]
+ shared_depths = set(b) & set(c)
+ if not shared_depths:
+ skipped += 1
+ continue
+ d = max(shared_depths)
+ bn, cn = b[d], c[d]
+ if bn == 0:
+ skipped += 1
+ continue
+ ratio = cn / bn
+ ratios.append(ratio)
+ if cn < bn: wins += 1
+ elif cn > bn: losses += 1
+ else: ties += 1
+
+ print(f"Paired problems: {n} (usable: {len(ratios)}, skipped: {skipped})")
+ if ratios:
+ print(f" median candidate/baseline ratio at shared depth: {statistics.median(ratios):.4f}")
+ print(f" geomean ratio: {statistics.geometric_mean(ratios):.4f}")
+ print(f" wins (candidate fewer nodes): {wins}")
+ print(f" losses (candidate more nodes): {losses}")
+ print(f" ties: {ties}")
+
+
+if __name__ == "__main__":
+ main()