"""Owned two-number logistic toy: input gradient perturbation, fixed weights; no external system."""
import math,json
from fractions import Fraction as F
W=(F(1),F(1));BIAS=-F(7,10);X=(F(2,5),F(2,5));Y=1
def margin(x):return sum((w*v for w,v in zip(W,x)),BIAS)
def loss(x):
    z=float(margin(x));return math.log1p(math.exp(-z))
def demo():
    z=float(margin(X));p=1/(1+math.exp(-z));gradient=[(p-Y)*float(w) for w in W]
    numerical=[]
    for i in range(2):
        plus=list(X);minus=list(X);h=F(1,1000000);plus[i]+=h;minus[i]-=h
        numerical.append((loss(plus)-loss(minus))/(2*float(h)))
    assert max(abs(a-b) for a,b in zip(gradient,numerical))<1e-8
    rows=[]
    for eps in [F(0),F(1,25),F(3,50)]:
        perturbed=tuple(min(F(1),max(F(0),v+eps*(1 if g>0 else -1 if g<0 else 0))) for v,g in zip(X,gradient))
        norm=max(abs(a-b) for a,b in zip(X,perturbed));score=margin(perturbed)
        assert norm<=eps
        rows.append({'epsilon':str(eps),'input':[str(v) for v in perturbed],'linf_change':str(norm),'margin':str(score),'prediction':int(score>=0),'loss':loss(perturbed),'reference_label_declared_by_author':Y})
    assert [r['margin'] for r in rows]==['1/10','1/50','-1/50']
    assert [r['prediction'] for r in rows]==[1,1,0]
    assert rows[0]['loss']<rows[1]['loss']<rows[2]['loss']
    return {'initial_input':[str(v) for v in X],'weights_fixed':[str(v) for v in W],'bias':str(BIAS),'authored_reference_label':Y,'gradient_at_initial_input':gradient,'finite_difference_gradient':numerical,'clip_interval':['0','1'],'rows':rows,'semantic_label_invariance_verified':False,'image_or_real_model_test':False,'pytorch_executed':False,'external_system_contacted':False}
if __name__=='__main__':print(json.dumps(demo(),ensure_ascii=False,indent=2))
