55void linearSearch(
unsigned int dim,
double *oldPt,
double oldVal,
double *grad,
56 double *dir,
double *newPt,
double &newVal,
57 EnergyFunctor func,
double maxStep,
int &resCode) {
63 const unsigned int MAX_ITER_LINEAR_SEARCH = 1000;
64 double sum = 0.0, slope = 0.0, test = 0.0, lambda = 0.0;
65 double lambda2 = 0.0, lambdaMin = 0.0, tmpLambda = 0.0, val2 = 0.0;
71 for (
unsigned int i = 0; i < dim; i++) {
72 sum += dir[i] * dir[i];
78 for (
unsigned int i = 0; i < dim; i++) {
79 dir[i] *= maxStep / sum;
86 for (
unsigned int i = 0; i < dim; i++) {
87 slope += dir[i] * grad[i];
94 for (
unsigned int i = 0; i < dim; i++) {
95 double temp = fabs(dir[i]) / std::max(fabs(oldPt[i]), 1.0);
104 while (it < MAX_ITER_LINEAR_SEARCH) {
105 if (lambda < lambdaMin) {
110 for (
unsigned int i = 0; i < dim; i++) {
111 newPt[i] = oldPt[i] + lambda * dir[i];
113 newVal = func(newPt);
114 if (newVal - oldVal <=
FUNCTOL * lambda * slope) {
122 tmpLambda = -slope / (2.0 * (newVal - oldVal - slope));
124 double rhs1 = newVal - oldVal - lambda * slope;
125 double rhs2 = val2 - oldVal - lambda2 * slope;
126 double a = (rhs1 / (lambda * lambda) - rhs2 / (lambda2 * lambda2)) /
128 double b = (-lambda2 * rhs1 / (lambda * lambda) +
129 lambda * rhs2 / (lambda2 * lambda2)) /
132 tmpLambda = -slope / (2.0 * b);
134 double disc = b * b - 3 * a * slope;
136 tmpLambda = 0.5 * lambda;
137 }
else if (b <= 0.0) {
138 tmpLambda = (-b + sqrt(disc)) / (3.0 * a);
140 tmpLambda = -slope / (b + sqrt(disc));
143 if (tmpLambda > 0.5 * lambda) {
144 tmpLambda = 0.5 * lambda;
149 lambda = std::max(tmpLambda, 0.1 * lambda);
153 for (
unsigned int i = 0; i < dim; i++) {
184int minimize(
unsigned int dim,
double *pos,
double gradTol,
185 unsigned int &numIters,
double &funcVal, EnergyFunctor func,
186 GradientFunctor gradFunc,
unsigned int snapshotFreq,
188 unsigned int maxIts =
MAXITS) {
193 std::vector<double> grad(dim);
194 std::vector<double> dGrad(dim);
195 std::vector<double> hessDGrad(dim);
196 std::vector<double> xi(dim);
197 std::vector<double> invHessian(dim * dim, 0);
198 std::unique_ptr<double[]> newPos(
new double[dim]);
199 snapshotFreq = std::min(snapshotFreq, maxIts);
201 double fp = func(pos);
202 gradFunc(pos, grad.data());
205#ifdef RDK_SVE_AVAILABLE
211 sveInitXiAndSum(dim, grad.data(), xi.data(), pos, &sum);
212 for (
unsigned int i = 0; i < dim; i++) invHessian[i * dim + i] = 1.0;
219 for (
unsigned int i = 0; i < dim; i++) {
220 unsigned int itab = i * dim;
221 invHessian[itab + i] = 1.0;
223 sum += pos[i] * pos[i];
226 double maxStep =
MAXSTEP * std::max(sqrt(sum),
static_cast<double>(dim));
228 for (
unsigned int iter = 1; iter <= maxIts; ++iter) {
232 linearSearch(dim, pos, fp, grad.data(), xi.data(), newPos.get(), funcVal,
233 func, maxStep, status);
240 for (
unsigned int i = 0; i < dim; i++) {
241 xi[i] = newPos[i] - pos[i];
243 double temp = fabs(xi[i]) / std::max(fabs(pos[i]), 1.0);
250 if (snapshotVect && snapshotFreq) {
252 snapshotVect->push_back(s);
258 double gradScale = gradFunc(pos, grad.data());
266 double term = std::max(fabs(funcVal) * gradScale, 1.0);
267 for (
unsigned int i = 0; i < dim; i++) {
268 double temp = fabs(grad[i]) * std::max(fabs(pos[i]), 1.0);
269 test = std::max(test, temp);
270 dGrad[i] = grad[i] - dGrad[i];
273 if (test < gradTol) {
274 if (snapshotVect && snapshotFreq) {
276 snapshotVect->push_back(s);
282 double fac = 0, fae = 0, sumDGrad = 0, sumXi = 0;
283#ifdef RDK_SVE_AVAILABLE
288 sveHessianVecMul(dim, invHessian.data(), dGrad.data(), hessDGrad.data(),
289 xi.data(), &fac, &fae, &sumDGrad, &sumXi);
296 for (
unsigned int i = 0; i < dim; i++) {
297 double *ivh = &(invHessian[i * dim]);
298 double &hdgradi = hessDGrad[i];
299 double *dgj = dGrad.data();
301 for (
unsigned int j = 0; j < dim; ++j, ++ivh, ++dgj) {
302 hdgradi += *ivh * *dgj;
304 fac += dGrad[i] * xi[i];
305 fae += dGrad[i] * hessDGrad[i];
306 sumDGrad += dGrad[i] * dGrad[i];
307 sumXi += xi[i] * xi[i];
310 if (fac > sqrt(
EPS * sumDGrad * sumXi)) {
312 double fad = 1.0 / fae;
313 for (
unsigned int i = 0; i < dim; i++) {
314 dGrad[i] = fac * xi[i] - fad * hessDGrad[i];
317#ifdef RDK_SVE_AVAILABLE
321 sveHessianRank1Update(dim, invHessian.data(), xi.data(),
322 hessDGrad.data(), dGrad.data(), fac, fad, fae);
329 for (
unsigned int i = 0; i < dim; i++) {
330 unsigned int itab = i * dim;
331 double pxi = fac * xi[i], hdgi = fad * hessDGrad[i],
332 dgi = fae * dGrad[i];
333 double *pxj = &(xi[i]), *hdgj = &(hessDGrad[i]), *dgj = &(dGrad[i]);
334 for (
unsigned int j = i; j < dim; ++j, ++pxj, ++hdgj, ++dgj) {
335 invHessian[itab + j] += pxi * *pxj - hdgi * *hdgj + dgi * *dgj;
336 invHessian[j * dim + i] = invHessian[itab + j];
342#ifdef RDK_SVE_AVAILABLE
344 sveHessianVecMulNeg(dim, invHessian.data(), grad.data(), xi.data());
348 for (
unsigned int i = 0; i < dim; i++) {
349 unsigned int itab = i * dim;
352 double *ivh = &(invHessian[itab]);
353 double *gj = grad.data();
354 for (
unsigned int j = 0; j < dim; ++j, ++ivh, ++gj) {
359 if (snapshotVect && snapshotFreq && !(iter % snapshotFreq)) {
361 snapshotVect->push_back(s);
362 newPos.reset(
new double[dim]);