"""One scalar linear update to separate model state from training config."""
from decimal import Decimal
import json
def one_step(rate):
    xs=list(map(Decimal,["1","2"]));ys=list(map(Decimal,["3","5"]))
    w=b=Decimal(0);n=Decimal(2)
    errors=[w*x+b-y for x,y in zip(xs,ys)]
    dw=2*sum(e*x for e,x in zip(errors,xs))/n;db=2*sum(errors)/n
    w=w-rate*dw;b=b-rate*db
    loss=sum((w*x+b-y)**2 for x,y in zip(xs,ys))/n
    return {"model_state":{"weight":str(w),"bias":str(b)},"training_config":{"learning_rate":str(rate),"steps":1,"loss":"mean_squared_error"},"training_loss_after":str(loss)}
if __name__=="__main__":
    a=one_step(Decimal('.1'));b=one_step(Decimal('.2'))
    assert a["model_state"]=={"weight":"1.3","bias":"0.8"} and Decimal(a["training_loss_after"])==Decimal('1.685')
    assert b["model_state"]=={"weight":"2.6","bias":"1.6"} and Decimal(b["training_loss_after"])==Decimal('2.34')
    assert Decimal(a["model_state"]["weight"])*Decimal(3)+Decimal(a["model_state"]["bias"])==Decimal('4.7')
    print(json.dumps({"two_teaching_runs":[a,b],"run_A_inference_x3":"4.7","external_library_training":False},indent=2))
