
#includeiostream#includeiomanip#includecmath#includevector#includedeque// // 极简反向模式自动微分引擎tape-based仅依赖标准库// structNode{doublevalue;doublegrad0.0;std::vectorNode*parents;// 依赖的前驱节点std::vectordoublelocal_deriv;// ∂本节点 / ∂每个父节点explicitNode(doublev):value(v){}};classTape{public:// deque 保证节点地址在增长过程中保持稳定std::dequeNodenodes;Node*make_node(doublev){nodes.emplace_back(v);returnnodes.back();}// 反向传播按节点创建顺序的逆序扫描等价于逆拓扑序voidbackward(Node*root){root-grad1.0;for(autoitnodes.rbegin();it!nodes.rend();it){Node*node(*it);for(std::size_t i0;inode-parents.size();i){node-parents[i]-gradnode-grad*node-local_deriv[i];}}}};structVar{Node*node;explicitVar(Node*n):node(n){}doubleval()const{returnnode-value;}doublegrad()const{returnnode-grad;}};// 全局 Tape单文件演示生产环境建议显式传递Tape g_tape;// ---------- 运算符重载 ----------inlineVaroperator(constVara,constVarb){Node*ng_tape.make_node(a.val()b.val());n-parents{a.node,b.node};n-local_deriv{1.0,1.0};returnVar(n);}inlineVaroperator*(constVara,constVarb){Node*ng_tape.make_node(a.val()*b.val());n-parents{a.node,b.node};n-local_deriv{b.val(),a.val()};// d(a*b)/da b, d(a*b)/db areturnVar(n);}inlineVarexp(constVarx){doubleestd::exp(x.val());Node*ng_tape.make_node(e);n-parents{x.node};n-local_deriv{e};// d exp(x)/dx exp(x)returnVar(n);}inlineVaroperator(constVara,doubleb){Node*bng_tape.make_node(b);returnaVar(bn);}// // 目标函数: f(x,y,z) (x y z) * exp(x*y*z)// 求值点: x1, y2, z3// intmain(){Varx(g_tape.make_node(1.0));Vary(g_tape.make_node(2.0));Varz(g_tape.make_node(3.0));// 前向计算同时记录计算图Var sxyz;Var px*y*z;Var eexp(p);Var outs*e;// 反向传播一次性求出全部输入的梯度g_tape.backward(out.node);std::coutstd::setprecision(15);std::coutu out.val()\n;std::coutdu/dx x.grad()\n;std::coutdu/dy y.grad()\n;std::coutdu/dz z.grad()\n;return0;}