summaryrefslogtreecommitdiff
path: root/src/eval_tune
diff options
context:
space:
mode:
Diffstat (limited to 'src/eval_tune')
-rwxr-xr-xsrc/eval_tune/match_play.py29
-rwxr-xr-xsrc/eval_tune/run_ecm.sh41
-rwxr-xr-xsrc/eval_tune/test_vs_head.sh2
3 files changed, 21 insertions, 51 deletions
diff --git a/src/eval_tune/match_play.py b/src/eval_tune/match_play.py
index 6891964..9591330 100755
--- a/src/eval_tune/match_play.py
+++ b/src/eval_tune/match_play.py
@@ -367,6 +367,18 @@ def elo_to_score(elo):
return 1.0 / (1.0 + 10.0 ** (-elo / 400.0))
+def sprt_bar(llr, la, lb, width=9):
+ """Render an ASCII gauge of where `llr` sits between the H0 (`la`) and
+ H1 (`lb`) SPRT bounds, e.g. '|---------|V---------|' with V marking
+ the rounded llr position."""
+ frac = 0.5 if lb == la else (llr - la) / (lb - la)
+ frac = min(max(frac, 0.0), 1.0)
+ slot = round(frac * (2 * width))
+ bar = "|" + "-" * width + "|" + "-" * width + "|"
+ idx = slot + 1
+ return bar[:idx] + "V" + bar[idx:]
+
+
class Sprt:
"""Sequential Probability Ratio Test for engine-vs-engine gating, same
formulation fishtest/cutechess-cli use for exactly this problem: two
@@ -602,17 +614,16 @@ def main():
avg_game_sec = sum(game_durations) / len(game_durations)
eta_sec = (avg_game_sec *
max(len(jobs) - done, 0)) / args.workers
+ score = candidate_points / done
sprt_note = ""
if sprt is not None:
- sprt_note = (f" llr={sprt.llr():+.2f} "
- f"(H0<={sprt.la:.2f} "
- f"H1>={sprt.lb:.2f})")
- print(f" {done} games played "
- f"(score, in submission order through game "
- f"{next_report_idx}: "
- f"{reported_points/max(reported_count,1):.3f}) "
- f"avg={avg_game_sec:.1f}s/game "
- f"ETA={eta_sec/60:.1f}min{sprt_note}",
+ sprt_note = (f": llr={sprt.llr():+.2f}, "
+ f"H0={sprt.la:+.2f}"
+ f"{sprt_bar(sprt.llr(), sprt.la, sprt.lb)}"
+ f"H1={sprt.lb:+.2f}")
+ print(f" {done} games: -{losses} ={draws} +{wins} "
+ f"({avg_game_sec:.1f}s avg, eta={eta_sec/60:.0f}min, "
+ f"score={score:.3f}){sprt_note}",
file=sys.stderr)
if sprt is not None and sprt_decision is None:
diff --git a/src/eval_tune/run_ecm.sh b/src/eval_tune/run_ecm.sh
deleted file mode 100755
index a6c1284..0000000
--- a/src/eval_tune/run_ecm.sh
+++ /dev/null
@@ -1,41 +0,0 @@
-#!/bin/sh
-# Run the ECM tactical suite at a fixed search depth (not fixed time --
-# see CLAUDE.md: st introduces machine-load noise that sd avoids) and
-# print just the "correct solutions" tally so callers can parse it.
-#
-# Usage: run_ecm.sh <label> [depth]
-# Writes eval_tune/ecm_logs/<label>.log (full Trace() output) and
-# appends one line to eval_tune/ecm_history.log.
-
-set -e
-cd "$(dirname "$0")/.." # repo src/ root
-
-label="$1"
-depth="${2:-11}"
-if [ -z "$label" ]; then
- echo "Usage: $0 <label> [depth]" >&2
- exit 1
-fi
-
-mkdir -p eval_tune/ecm_logs
-logfile="eval_tune/ecm_logs/${label}.log"
-
-opts='--cpus 1 --hash 256m --egtbpath /zscratch/egtb'
-# --batch exits non-zero on normal EOF ("Exhausted input in batch
-# mode") -- that's expected, not a failure, so don't let set -e treat
-# it as one; the real success/failure check is the grep below.
-./typhoon ${opts} --logfile "$logfile" --batch \
- --command "sd ${depth}; script ../tests/ecm.ep_" || true
-
-correct=$(grep -o 'correct solutions : [0-9]*' "$logfile" | tail -1 | grep -o '[0-9]*$')
-total=$(grep -o 'total problems : [0-9]*' "$logfile" | tail -1 | grep -o '[0-9]*$')
-
-if [ -z "$correct" ] || [ -z "$total" ]; then
- echo "ERROR: couldn't parse solved count from $logfile" >&2
- exit 1
-fi
-
-echo "$(date -u +%Y-%m-%dT%H:%M:%SZ) label=$label depth=$depth solved=${correct}/${total}" \
- >> eval_tune/ecm_history.log
-
-echo "${correct} ${total}"
diff --git a/src/eval_tune/test_vs_head.sh b/src/eval_tune/test_vs_head.sh
index c7c578e..d5d8006 100755
--- a/src/eval_tune/test_vs_head.sh
+++ b/src/eval_tune/test_vs_head.sh
@@ -3,7 +3,7 @@
python3 ./match_play.py ../../head_reference/typhoon ../typhoon \
--pgn ../../pgn/twic_filtered.pgn \
--games 20000 \
- --workers 20 \
+ --workers 12 \
--st 1 \
--sprt --elo0 0 --elo1 5 \
--scratch /usr/local/tmp/typhoon_match_overnight \