"""Independent Fraction and hypergeometric-tail check for the selected benchmark."""
import itertools,json,math
from fractions import Fraction
from pathlib import Path
ROOT=Path(__file__).resolve().parents[1];R=ROOT/'results'

def fisher_p(a,b,n):
    total=a+b;den=math.comb(2*n,total)
    observed=math.comb(n,a)*math.comb(n,b)
    return Fraction(sum(math.comb(n,x)*math.comb(n,total-x) for x in range(max(0,total-n),min(n,total)+1) if math.comb(n,x)*math.comb(n,total-x)<=observed),den)

# Independently use rising-factorial beta-binomial probabilities, not main combinatorial weights.
m=5;k=20;a=5
rf=lambda x,r:math.prod(range(x,x+r))
q=[Fraction(math.comb(k,x)*rf(a,x)*rf(a,k-x),rf(2*a,k)) for x in range(k+1)]
assert sum(q)==1
arm=[Fraction(1)]
for _ in range(m):
    result=[Fraction(0)]*(len(arm)+k)
    for i,p in enumerate(arm):
        for j,t in enumerate(q):result[i+j]+=p*t
    arm=result
reject=Fraction(0);oracle=Fraction(0);dist=[Fraction(0)]*(m*k+1)
for x,px in enumerate(arm):
    for y,py in enumerate(arm):
        w=px*py;dist[abs(x-y)]+=w
        if fisher_p(x,y,m*k)<=Fraction(1,20):reject+=w
for d,w in enumerate(dist):
    if sum(dist[d:])<=Fraction(1,20):oracle+=w
rows=json.loads((R/'exact-grid.json').read_text());target=next(r for r in rows if r['donors_per_arm']==m and r['cells_per_donor']==k and r['regime']=='5')
for value,key in [(reject,'fisher_null_rejection'),(oracle,'oracle_null_rejection')]:
    expected=target[key];assert value==Fraction(int(expected['numerator']),int(expected['denominator']))
# Full donor-path enumeration for a separate small beta-binomial scenario.
qsmall=[Fraction(1,3)]*3;hist={}
for donors in itertools.product(range(3),repeat=3):
    s=sum(donors);hist[s]=hist.get(s,Fraction(0))+Fraction(1,27)
rsmall=sum(pa*pb for x,pa in hist.items() for y,pb in hist.items() if fisher_p(x,y,6)<=Fraction(1,20))
expected=next(r for r in rows if r['donors_per_arm']==3 and r['cells_per_donor']==2 and r['regime']=='1')['fisher_null_rejection']
assert rsmall==Fraction(int(expected['numerator']),int(expected['denominator']))
result={'selected_fisher_fraction_match':True,'selected_oracle_fraction_match':True,'small_extra_case_m':3,'small_extra_case_k':2,'small_extra_case_shape':1,'small_extra_case_type1':float(rsmall),'small_extra_case_exact_fraction':str(rsmall),'method':'Independent Fraction convolution with rising-factorial probabilities and direct two-sided hypergeometric summation.'}
(R/'R2.json').write_text(json.dumps(result,indent=2)+'\n');print(json.dumps(result,indent=2))
