void Gradient::apply_bwd (const ExprApply& a, ExprLabel** x, const ExprLabel& y) { Array<Domain> d(a.nb_args); Array<Domain> g(a.nb_args); int n=0; for (int i=0; i<a.nb_args; i++) { d.set_ref(i,*x[i]->d); g.set_ref(i,*x[i]->g); n+=x[i]->d->dim.size(); } // we unvectorize the components of the gradient. IntervalVector old_g(n); load(old_g, g); IntervalVector tmp_g(n); if (a.func.expr().dim.is_scalar()) { gradient(a.func,d,tmp_g); //cout << "tmp-g=" << tmp_g << endl; tmp_g *= y.g->i(); // pre-multiplication by y.g tmp_g += old_g; // addition to the old value of g load(g,tmp_g); } else { assert(a.func.expr().dim.is_vector()); // matrix-valued function not implemented... int m=a.func.expr().dim.vec_size(); IntervalMatrix J(m,n); jacobian(a.func,d,J); tmp_g = y.g->v()*J; // pre-multiplication by y.g tmp_g += old_g; load(g,tmp_g); } }
void Gradient::apply_bwd(int* x, int y) { const ExprApply& a = (const ExprApply&) f.node(y); Array<Domain> d2(a.func.nb_arg()); Array<Domain> g2(a.nb_args); int n=0; for (int i=0; i<a.func.nb_arg(); i++) { d2.set_ref(i,d[x[i]]); g2.set_ref(i,g[x[i]]); n+=d[x[i]].dim.size(); } // we unvectorize the components of the gradient. IntervalVector old_g(n); load(old_g, g2); IntervalVector tmp_g(n); if (a.func.expr().dim.is_scalar()) { a.func.deriv_calculator().gradient(d2,tmp_g); //cout << "tmp-g=" << tmp_g << endl; tmp_g *= g[y].i(); // pre-multiplication by y.g tmp_g += old_g; // addition to the old value of g load(g2,tmp_g); } else { if (!a.func.expr().dim.is_vector()) not_implemented("automatic differentiation of matrix-valued function"); int m=a.func.expr().dim.vec_size(); IntervalMatrix J(m,n); a.func.deriv_calculator().jacobian(d2,J); tmp_g = g[y].v()*J; // pre-multiplication by y.g tmp_g += old_g; load(g2,tmp_g); } }