#!/usr/bin/env python3 """ЗАМОR 22: §C2-3 consolidation weights at n>=2. $0. Engine's bank-stop `drafts:` are already ScoreVariants-ordered => drafts[0] = engine §C2-3-top. We reproduce the freq+lemma part exactly (neighbour=1.0 cold; conform neutral in python) and detect conformance-decisive cases empirically as (name/place where engine-top != my freq/lemma-top).""" from parse_common import parse_bankstop, parse_minedsig import re FREQ_FLOOR=0.5; LEMMA_PEN=0.4 def well_formed(dst): t=dst.strip() if len(t)<2: return False if t.startswith("-") or t.endswith("-"): return False if any(ch in t for ch in "[]{}<>|\t\n"): return False return True def score_variants(variants): """variants: list of (dst, chunks). Return ranked list of (dst,chunks,score) by §C2-3 share*lemma (conform=1, neighbour=1). Deterministic tiebreak: score desc, chunks desc, dst asc.""" if not variants: return [] maxc=max(c for _,c in variants) or 1 scored=[] for dst,c in variants: share=FREQ_FLOOR+(1-FREQ_FLOOR)*c/maxc s=share*(1.0) # conform neutral in python if not well_formed(dst): s*=LEMMA_PEN scored.append((dst,c,s)) scored.sort(key=lambda x:(-x[2],-x[1],x[0])) return scored def freq_top(variants): return sorted(variants,key=lambda x:(-x[1],x[0]))[0][0] bs=parse_bankstop() ms={r["src"]:r for r in parse_minedsig()} # n>=2 population: >=2 distinct draft variants n2={s:r for s,r in bs.items() if len({d for d,_ in r["drafts"]})>=2} print(f"=== POPULATION: total bank-stop terms={len(bs)} ; n>=2 (>=2 distinct drafts)={len(n2)} ===") by_type={} for s,r in n2.items(): by_type[r["type"]]=by_type.get(r["type"],0)+1 print(" n>=2 by type:", by_type) # --- (i) is formula a pure ranking (no score 0)? --- zero=0 for s,r in n2.items(): for d,c,sc in score_variants(r["drafts"]): if sc<=0: zero+=1 print(f"\n=== (i) pure ranking: variants scoring 0 = {zero} (expect 0) ===") # --- SECOND PATH cross-check: bank-stop drafts vs mined-sig other_proposals --- mismatch=[] for s,r in n2.items(): bs_set={d:c for d,c in r["drafts"]} if s in ms: # mined-sig lists the NON-winning as "other proposals"; winner is dst. Reconstruct full set. prop={d:c for d,c in ms[s].get("other_proposals",[])} # the winner variant equals ms dst with its own chunk count (banknote_chunks) — approx # We compare the set of NON-top variants counts. bs_others={d:c for d,c in r["drafts"][1:]} if prop and bs_others and set(prop)!=set(bs_others): mismatch.append((s,bs_others,prop)) print(f"\n=== SECOND PATH: bank-stop 'other drafts' vs mined-sig 'other proposals' mismatch = {len(mismatch)} of {sum(1 for s in n2 if s in ms and ms[s].get('other_proposals'))} comparable ===") for s,a,b in mismatch[:8]: print(f" {s}: bankstop={a} minedsig={b}") # --- (a) TERM contested: engine §C2-3-top == freq-majority-top? (conform inert on terms) --- term_n2={s:r for s,r in n2.items() if r["type"]=="term"} a_ok=a_bad=0; a_examples=[] for s,r in term_n2.items(): eng_top=r["drafts"][0][0] ft=freq_top(r["drafts"]) if eng_top==ft: a_ok+=1 else: a_bad+=1; a_examples.append((s,eng_top,ft,r["drafts"])) print(f"\n=== (a) TERM-contested (N={len(term_n2)}): engine-top==freq-majority-top: {a_ok} ; differ: {a_bad} ===") for s,e,f,dr in a_examples[:10]: print(f" {s}: engine-top={e} freq-top={f} drafts={dr}") # --- (b) NAME/PLACE contested: engine-top != my freq/lemma-top => conformance decisive --- np_n2={s:r for s,r in n2.items() if r["type"] in ("name","place")} conf_flips=[]; conf_same=0 for s,r in np_n2.items(): eng_top=r["drafts"][0][0] my_top=score_variants(r["drafts"])[0][0] if eng_top!=my_top: conf_flips.append((s,r["type"],eng_top,my_top,r["drafts"])) else: conf_same+=1 print(f"\n=== (b) NAME/PLACE-contested (N={len(np_n2)}): conform-decisive (engine-top != freq/lemma-top): {len(conf_flips)} ; same: {conf_same} ===") for s,t,e,m,dr in conf_flips[:12]: print(f" {s} [{t}]: engine-top={e} freqtop={m} drafts={dr}") # --- (c) engine §C2-3-top-variant vs FINAL dst (terminologist) --- follow=diverge=0; div_examples=[] for s,r in n2.items(): eng_top=r["drafts"][0][0] final=r["dst"] # normalize light: strip quotes/case for a lenient match too if final==eng_top: follow+=1 else: diverge+=1; div_examples.append((s,r["type"],eng_top,final,[d for d,_ in r["drafts"]])) print(f"\n=== (c) engine §C2-3-top vs FINAL terminologist dst (N={len(n2)}): follow={follow} diverge={diverge} ({diverge/len(n2)*100:.1f}%) ===") for s,t,e,f,dr in div_examples[:15]: print(f" {s} [{t}]: §C2-3-top='{e}' -> FINAL='{f}' (drafts={dr})")