"""W04: forward-mode automatic differentiation; each operation carries its tangent."""fromdataclassesimportdataclassimportmath@dataclass(frozen=True)classDual:value:floattangent:float=0.def__post_init__(self):ifnotall(type(x)in(int,float)andmath.isfinite(x)forxin(self.value,self.tangent)):raiseValueError("finite real value and tangent required")@staticmethoddefwrap(other):returnotherifisinstance(other,Dual)elseDual(other)def__add__(self,other):other=self.wrap(other)returnDual(self.value+other.value,self.tangent+other.tangent)__radd__=__add__def__neg__(self):returnDual(-self.value,-self.tangent)def__sub__(self,other):returnself+(-self.wrap(other))def__rsub__(self,other):returnself.wrap(other)+(-self)def__mul__(self,other):other=self.wrap(other)returnDual(self.value*other.value,self.tangent*other.value+self.value*other.tangent)__rmul__=__mul__def__truediv__(self,other):other=self.wrap(other)ifother.value==0:raiseZeroDivisionError("zero primal denominator")value=self.value/other.valuetangent=(self.tangent-value*other.tangent)/other.valuereturnDual(value,tangent)def__rtruediv__(self,other):returnself.wrap(other)/selfdefsin(x):x=Dual.wrap(x)returnDual(math.sin(x.value),math.cos(x.value)*x.tangent)defexp(x):x=Dual.wrap(x);value=math.exp(x.value)returnDual(value,value*x.tangent)deflog(x):x=Dual.wrap(x)ifx.value<=0:raiseValueError("log requires positive primal input")returnDual(math.log(x.value),x.tangent/x.value)if__name__=='__main__':w=Dual(2,1);x=2;b=1;y=3loss=(w*x+b-y)*(w*x+b-y)/2print(loss)# value 2; derivative with respect to w is 4