#!/usr/bin/env python3 """Pair up per-problem node counts from two ECM sd=N stdout logs (same input file, same order) and report a median/geomean ratio plus win/loss counts -- robust to the handful of huge forced-mate outliers that would otherwise dominate a raw sum. Mate-hunt problems (last iterated depth line containing MATE) are reported separately since their node count is chaotic w.r.t. move-ordering and not representative of typical branching-factor efficiency. """ import re import statistics import sys SEARCHED_RE = re.compile(r"Searched for\s+[\d.]+ seconds, saw (\d+) nodes") DEPTH_LINE_RE = re.compile(r"^\s*\d+[+]?\s+(\S+)\s+[\d:.]+\s+(\d+)\s") def parse(path): """Return list of (node_count, is_mate) per completed problem, in order.""" results = [] last_score = None with open(path) as f: for line in f: m = DEPTH_LINE_RE.match(line) if m: last_score = m.group(1) continue m = SEARCHED_RE.search(line) if m: is_mate = bool(last_score and "MATE" in last_score) results.append((int(m.group(1)), is_mate)) last_score = None return results 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)) base, cand = base[:n], cand[:n] normal_ratios = [] mate_ratios = [] wins = losses = ties = 0 mate_wins = mate_losses = mate_ties = 0 for (bn, bmate), (cn, cmate) in zip(base, cand): ratio = cn / bn if bn else 1.0 is_mate = bmate or cmate bucket = mate_ratios if is_mate else normal_ratios bucket.append(ratio) if is_mate: if cn < bn: mate_wins += 1 elif cn > bn: mate_losses += 1 else: mate_ties += 1 else: if cn < bn: wins += 1 elif cn > bn: losses += 1 else: ties += 1 print(f"Paired problems: {n}") print() print(f"=== Non-mate problems (n={len(normal_ratios)}) ===") if normal_ratios: print(f" median candidate/baseline node ratio: {statistics.median(normal_ratios):.4f}") print(f" geomean ratio: {statistics.geometric_mean(normal_ratios):.4f}") print(f" wins (candidate fewer nodes): {wins}") print(f" losses (candidate more nodes): {losses}") print(f" ties: {ties}") print() print(f"=== Mate-hunt problems (n={len(mate_ratios)}) -- reported separately, chaotic ===") if mate_ratios: print(f" median ratio: {statistics.median(mate_ratios):.4f}") print(f" wins: {mate_wins} losses: {mate_losses} ties: {mate_ties}") if __name__ == "__main__": main()