Vector UnconstrainedLocalSearch::find_gcp(const Vector& gk, const Matrix& Bk, const Vector& zk, const IntervalVector& region) { // ====================== STEP 2.0 : initialization ====================== //// cout << " [find_gcp] initial region=" << region << endl; // The Cauchy point Vector z_gcp = zk; // cout << " [find_gcp] initial zk=" << zk << endl; // The opposite of the gradient of z->z^T*Bk*z - gk^T z Vector g = gk - Bk*zk; // Compute a descent direction d // that must "point" inside the box Vector d(n); // If the function decreases wrt the ith dimension // and the point zk is very close (less than sigma) to the // ith "upper face" of the bounding box then we project // the gradient on this face (we nullify the ith component). // We apply the symmetric case with the "lower face". // The constraint x=ui or x=li is activated. for (int i = 0 ; i < n ; i++) { if( fabs(gk[i]) > sigma && ((gk[i] < 0 && zk[i] < box[i].ub() - sigma) || (gk[i] > 0 && zk[i] > box[i].lb() + sigma)) ) d[i] = -gk[i]; // else d[i] remains equal to 0. } // cout << " [find_gcp] initial d=" << d << endl; // compute f' double fp = gk*d; // cout << " [find_gcp] initial fp=" << fp << endl; // compute f'' double fs = d*(Bk*d); // cout << " [find_gcp] initial fs=" << fs << endl; bool gcp_found = (fp >= -eps); try { while (!gcp_found) { // ====================== STEP 2.1 : Find the next breakpoint ====================== LineSearch ls(region,z_gcp,d,data,sigma); // if d~0, an exception is raised double deltat = ls.alpha_max(); // cout << " [find_gcp] deltat=" << deltat << endl; // check if we are in a corner // deltat can be very large even if the norm of the gradient is > eps // because once the "large" dimensions are treated, it may only // remains directions with d[i] very small (but not less than sigma). // In any case, we have deltat <= 1/sigma*diam(region) <= 2*Delta/sigma. // assert(deltat<10*(2*Delta/sigma)); // ====================== STEP 2.2 : Test whether the GCP has been found ====================== // The minimum is in the segment [0,deltat] if ((fs > 0.0) && (0<-(fp/fs)) && (-(fp/fs)<deltat)) { z_gcp -= (fp/fs)*d; // Security check: z_gcp may be outside the region because of rounding ls.proj(z_gcp); gcp_found = true; } else { // ====================== STEP 2.3 : Update line derivatives ====================== // b = Bk*(\sum_{I[i]==2} di*ei) Vector b(n); for (int i=0; i<n; i++) { if (ls.next_activated(i)) { for (int j=0; j<n; j++) b[j]+=d[i]*Bk[j][i]; } } // set gcp to the the point on the face z_gcp = ls.endpoint(); // update f' fp += deltat*fs - b*z_gcp; for (int i=0; i<n; i++) { if (ls.next_activated(i)) fp -= d[i]*g[i]; } // update f'' for (int i=0; i<n; i++) { fs -= (ls.next_activated(i) ? b[i]*d[i] : 2.0*b[i]*d[i]); } // update d and I for (int i=0; i<n; i++) { if (ls.next_activated(i)) { // cout << " [find_gcp] activate ctr n°" << i << endl; d[i] = 0.0; } } // cout << " [find_gcp] current d=" << d << endl; // cout << " [find_gcp] current z_gcp=" << z_gcp << endl; // cout << " [find_gcp] current fp=" << fp << endl; // cout << " [find_gcp] current fs=" << fs << endl; // update the termination condition gcp_found = (fp >= -eps); // the minimum is at a breakpoint } } } catch(LineSearch::NullDirectionException&) { // we are in a corner of the region: we stop with current z_gcp } // ====================== STEP 2.4 : termination with GCP ====================== // cout << " [find_gcp] z_gcp =" << z_gcp << endl; assert(region.contains(z_gcp)); return z_gcp; }