summaryrefslogtreecommitdiff
path: root/src/eval_tune/compare_ecm_shareddepth.py
blob: 2194f02dbde7d2212cee01c9b335d4ae16327c97 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
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()