"""Authored nested learning curves: actually refit two restricted regressors at each training size and order."""
from fractions import Fraction as F
import json
XS=[F(-1),F(1),F(-2),F(2),F(-3),F(3)];NOISE=[F(1,5),-F(1,10),F(1,10),-F(1,5),F(3,10),-F(3,10)]
DATA=[{'id':'R'+str(i+1),'x':x,'y':x*x+e} for i,(x,e) in enumerate(zip(XS,NOISE))]
VALID=[{'id':'V'+str(i+1),'x':F(x,2),'y':F(x,2)**2} for i,x in enumerate([-5,-1,1,5])]
def fit(rows,family):
    if family=='constant':return sum((r['y'] for r in rows),F(0))/len(rows)
    return sum((r['x']**2*r['y'] for r in rows),F(0))/sum((r['x']**4 for r in rows),F(0))
def predict(parameter,x,family):return parameter if family=='constant' else parameter*x*x
def mse(rows,parameter,family):return sum(((predict(parameter,r['x'],family)-r['y'])**2 for r in rows),F(0))/len(rows)
def demo():
    rows=[];orders={'balanced_prefix':[0,1,2,3,4,5],'outer_negative_first':[4,2,0,1,3,5]}
    for order,indices in orders.items():
        for n in [2,4,6]:
            training=[DATA[i] for i in indices[:n]]
            assert not {r['id'] for r in training}&{r['id'] for r in VALID}
            for family in ['constant','quadratic_feature_no_intercept']:
                parameter=fit(training,family);rows.append({'order':order,'n':n,'family':family,'training_ids':[r['id'] for r in training],'fitted_parameter':str(parameter),'train_MSE':str(mse(training,parameter,family)),'validation_MSE':str(mse(VALID,parameter,family))})
    assert len(rows)==12
    for family in ['constant','quadratic_feature_no_intercept']:
        last=[r for r in rows if r['n']==6 and r['family']==family];assert last[0]['fitted_parameter']==last[1]['fitted_parameter']
    return {'authored_training_rows':[{k:str(v) for k,v in r.items()} for r in DATA],'fixed_validation_rows':[{k:str(v) for k,v in r.items()} for r in VALID],'families':['constant mean only','coefficient*x^2 with no intercept; feature supplied by author'],'training_sizes':[2,4,6],'orders':orders,'rows':rows,'model_refits':12,'validation_used_for_fit':False,'cross_validation_or_final_untouched_test':False,'sklearn_or_real_model_executed':False}
if __name__=='__main__':print(json.dumps(demo(),ensure_ascii=False,indent=2))
