"""Authored finite Brier decomposition grouped by exact issued probability; coarse grouping counterexample."""
from fractions import Fraction as F
import json
P=[F(1,5)]*5+[F(4,5)]*5;Y=[0,0,0,0,1,0,0,1,1,1]
def decomposition(probabilities,labels,groups=None):
    n=len(labels);base=F(sum(labels),n);bs=sum(((p-y)**2 for p,y in zip(probabilities,labels)),F(0))/n
    groupkeys=probabilities if groups is None else groups;parts=[];rel=F(0);res=F(0)
    for key in sorted(set(groupkeys)):
        ids=[i for i,k in enumerate(groupkeys) if k==key];weight=F(len(ids),n);pf=sum((probabilities[i] for i in ids),F(0))/len(ids);rate=F(sum(labels[i] for i in ids),len(ids))
        rel+=weight*(pf-rate)**2;res+=weight*(rate-base)**2
        parts.append({'group':str(key),'indices':ids,'forecast_mean':str(pf),'event_rate':str(rate),'weight':str(weight),'unique_probabilities_in_group':len({probabilities[i] for i in ids})})
    unc=base*(1-base)
    return {'base_rate':str(base),'groups':parts,'Brier_direct':str(bs),'REL':str(rel),'RES':str(res),'UNC':str(unc),'REL_minus_RES_plus_UNC':str(rel-res+unc),'three_term_matches_direct':bs==rel-res+unc}
def demo():
    exact=decomposition(P,Y);constant=decomposition([F(2,5)]*10,Y);coarse=decomposition(P,Y,['all']*10)
    assert exact['Brier_direct']=='11/50' and exact['REL']=='1/50' and exact['RES']=='1/25' and exact['UNC']=='6/25' and exact['three_term_matches_direct']
    assert constant['Brier_direct']=='6/25' and constant['REL']=='0' and constant['RES']=='0' and constant['three_term_matches_direct']
    assert not coarse['three_term_matches_direct'] and coarse['REL_minus_RES_plus_UNC']=='1/4'
    return {'authored_probabilities':[str(p) for p in P],'authored_binary_labels':Y,'exact_probability_groups':exact,'same_sample_constant_base_rate_forecast':constant,'coarse_mixed_probability_group_counterexample':coarse,'constant_baseline_uses_same_sample_base_rate_not_heldout_fit':True,'population_unbiased_components_or_calibration_test_claimed':False,'real_model_or_customer_data_executed':False}
if __name__=='__main__':print(json.dumps(demo(),ensure_ascii=False,indent=2))
