Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014Ad9rqAB8pXXvyzh7f4X8v
69 lines
4.6 KiB
Python
69 lines
4.6 KiB
Python
"""Why does the delivered interval stay wide? Per-question funnel on v5 (research harness, static probe list)."""
|
|
import json, sys, statistics as st
|
|
from pathlib import Path
|
|
WT = Path('/workspace/Jyotisha/.worktrees/karaka-interval-20261016')
|
|
sys.path.insert(0, str(WT)); sys.path.insert(0, str(WT/'scripts'))
|
|
from scripts.research import cluster_width_probe as cwp
|
|
from scripts.research import probe_supply_after_six as ps
|
|
from scripts.research import cluster_width_lib as cl
|
|
cases = json.loads((WT/'references/real_case_calibration/minute_rectification_holdout_v5.json').read_text())['cases']
|
|
shard, n = map(int, sys.argv[1].split('/'))
|
|
MAXQ = 12
|
|
out = []
|
|
def clock(t): h, m = map(int, t.split(':')); return h*60+m
|
|
for i, case in enumerate(cases):
|
|
if i % n != shard: continue
|
|
true_time = str(case['birth']['time'])[:5]
|
|
for R in (10, 30, 60):
|
|
req = cwp.scoring_request_for(case, R)
|
|
built = cwp.build_event_contribution_matrix(req)
|
|
rows = cwp.score_from_matrix(req, built)
|
|
contexts = list(built.get('static_contexts') or [])
|
|
window_times = [str(r['time'])[:5] for r in rows]
|
|
raw = cwp.raw_signature_clusters(contexts)
|
|
probes = cwp.discriminating_event_probes({**req, 'refresh_probes': False}, built, scan=cwp.window_scan(built),
|
|
candidate_times=list(window_times), representative_time=true_time, today=cwp.TODAY)
|
|
merged, _ = cwp.merge_adjacent_traced(raw, cwp._by_time_rows(rows), max_clusters=cwp.Variant('baseline').max_clusters,
|
|
max_peak_delta=cwp.Variant('baseline').max_peak_delta)
|
|
public = cwp.public_from_clusters(merged, rows)
|
|
reps = [str(r['time'])[:5] for r in public]
|
|
size = {str(r['time'])[:5]: len(r.get('cluster_times') or [1]) for r in public}
|
|
truth_rep = next((str(r['time'])[:5] for r in public if true_time in (r.get('cluster_times') or [str(r['time'])[:5]])), None)
|
|
prior = {t: float(r.get('score') or 0) for t, r in zip(reps, public)}
|
|
scores = dict(prior); conflicts = {t: 0 for t in reps}; elim = set()
|
|
prior_spread = max(prior.values()) - min(prior.values())
|
|
prior_truth_gap = max(prior.values()) - prior.get(truth_rep, 0)
|
|
steps = []
|
|
for q, probe in enumerate(probes[:MAXQ]):
|
|
alive = [t for t in reps if t not in elim]
|
|
yes, no = ps.outcome_groups(probe)
|
|
ans = ps.optimal_answer(probe, true_time)
|
|
sides = {}
|
|
for t in alive:
|
|
d = 'support' if t in yes else 'conflict' if t in no else ps.inherit_direction(t, yes, no)
|
|
sides[t] = d
|
|
truth_d = 'support' if ans == 'yes' else 'conflict' if ans == 'no' else 'neutral'
|
|
same = sum(size[t] for t in alive if sides[t] == truth_d) ; opp = sum(size[t] for t in alive if sides[t] not in (truth_d, 'neutral'))
|
|
neu = sum(size[t] for t in alive if sides[t] == 'neutral')
|
|
if ans is not None:
|
|
scores, conflicts, elim = ps.apply_answer(scores, conflicts, elim, probe, ans, reps)
|
|
valid = cl.still_valid_public(public, scores, elim, lead=8)
|
|
d = cl.delivery_from_public(valid)
|
|
steps.append(dict(q=q+1, answer=ans, same=same, opp=opp, neutral=neu, alive_min=sum(size[t] for t in reps if t not in elim),
|
|
span8=d['width'], set8=len(d['times']), domain=probe.get('domain') or probe.get('kind')))
|
|
def deliver(lead, upto, flip=None):
|
|
sc = dict(prior); cf = {t: 0 for t in reps}; el = set()
|
|
for k, probe in enumerate(probes[:upto]):
|
|
a = ps.optimal_answer(probe, true_time)
|
|
if a and flip is not None and k == flip: a = 'no' if a == 'yes' else 'yes'
|
|
if a: sc, cf, el = ps.apply_answer(sc, cf, el, probe, a, reps)
|
|
v = cl.still_valid_public(public, sc, el, lead=lead); d = cl.delivery_from_public(v)
|
|
alive = [t for t in reps if t not in el]
|
|
best = max(sc[t] for t in alive); leaders = [t for t in alive if sc[t] == best]
|
|
return dict(span=d['width'], set=len(d['times']), cov=true_time in d['times'], top1=leaders == [truth_rep])
|
|
out.append(dict(case=case['case_id'], R=R, true=true_time, n_reps=len(reps), n_probes=len(probes),
|
|
prior_spread=prior_spread, prior_truth_gap=prior_truth_gap, steps=steps,
|
|
alt={f'L{lead}_Q{q}_F{f}': deliver(lead, q, None if f < 0 else f) for lead in (8, 6, 5, 4) for q in (6, 12) for f in (-1, 0, 2, 4)}))
|
|
print(case['case_id'], flush=True)
|
|
Path(f'funnel2_shard{shard}.json').write_text(json.dumps(out)); print('DONE')
|