void Gradient::jacobian(const Array<Domain>& d, IntervalMatrix& J) { if (!f.expr().dim.is_vector()) { ibex_error("Cannot called \"jacobian\" on a real-valued function"); } int m=f.expr().dim.vec_size(); // calculate the gradient of each component of f for (int i=0; i<m; i++) { const Function* fi=dynamic_cast<const Function*>(&f[i]); if (fi!=NULL) { // if this is a Function object we can // directly calculate the gradient with d fi->deriv_calculator().gradient(d,J[i]); } else { // otherwise we must give a box in argument // TODO add gradient with Array<Domain> in argument // in Function interface? // But, for the moment, cannot happen, because // this function is called by apply_bwd. IntervalVector box(f.nb_var()); load(box,d); f[i].gradient(box,J[i]); if (J[i].is_empty()) { J.set_empty(); return; } } } }
bool proj_mul(const IntervalMatrix& y, IntervalMatrix& x1, IntervalMatrix& x2, double ratio) { int m=y.nb_rows(); int n=y.nb_cols(); assert(x1.nb_cols()==x2.nb_rows()); assert(x1.nb_rows()==m); assert(x2.nb_cols()==n); // each coefficient (i,j) of y is considered as a binary "dot product" constraint // between the ith row of x1 and the jth column of x2 // (advantage: we have exact projection for the dot product) // // we propagate these constraints using a simple agenda. Agenda a(m*n); //init for (int i=0; i<m; i++) for (int j=0; j<n; j++) a.push(i*n+j); int k; while (!a.empty()) { a.pop(k); int i=k/n; int j=k%n; IntervalVector x1old=x1[i]; IntervalVector x2j=x2.col(j); IntervalVector x2old=x2j; if (!proj_mul(y[i][j],x1[i],x2j)) { x1.set_empty(); x2.set_empty(); return false; } else { if (x1old.rel_distance(x1[i])>=ratio) { for (int j2=0; j2<n; j2++) if (j2!=j) a.push(i*n+j2); } if (x2old.rel_distance(x2j)>=ratio) { for (int i2=0; i2<m; i2++) if (i2!=i) a.push(i2*n+j); } x2.set_col(j,x2j); } } return true; }
bool proj_mul(const IntervalMatrix& y, Interval& x1, IntervalMatrix& x2) { int n=(y.nb_rows()); assert((x2.nb_rows())==n && (x2.nb_cols())==(y.nb_cols())); for (int i=0; i<n; i++) { if (!proj_mul(y[i],x1,x2[i])) { x2.set_empty(); return false; } } return true; }
bool proj_mul(const IntervalVector& y, IntervalMatrix& x1, IntervalVector& x2, double ratio) { assert(x1.nb_rows()==y.size()); assert(x1.nb_cols()==x2.size()); int last_row=0; int i=0; int n=y.size(); do { IntervalVector x2old=x2; if (!proj_mul(y[i],x1[i],x2)) { x1.set_empty(); return false; } if (x2old.rel_distance(x2)>ratio) last_row=i; i=(i+1)%n; } while(i!=last_row); return true; }