52void linearSearch(
unsigned int dim,
double *oldPt,
double oldVal,
double *grad,
53 double *dir,
double *newPt,
double &newVal,
54 EnergyFunctor func,
double maxStep,
int &resCode) {
60 const unsigned int MAX_ITER_LINEAR_SEARCH = 1000;
61 double sum = 0.0, slope = 0.0, test = 0.0, lambda = 0.0;
62 double lambda2 = 0.0, lambdaMin = 0.0, tmpLambda = 0.0, val2 = 0.0;
68 for (
unsigned int i = 0; i < dim; i++) {
69 sum += dir[i] * dir[i];
75 for (
unsigned int i = 0; i < dim; i++) {
76 dir[i] *= maxStep / sum;
83 for (
unsigned int i = 0; i < dim; i++) {
84 slope += dir[i] * grad[i];
91 for (
unsigned int i = 0; i < dim; i++) {
92 double temp = fabs(dir[i]) / std::max(fabs(oldPt[i]), 1.0);
101 while (it < MAX_ITER_LINEAR_SEARCH) {
103 if (lambda < lambdaMin) {
108 for (
unsigned int i = 0; i < dim; i++) {
109 newPt[i] = oldPt[i] + lambda * dir[i];
111 newVal = func(newPt);
113 if (newVal - oldVal <=
FUNCTOL * lambda * slope) {
121 tmpLambda = -slope / (2.0 * (newVal - oldVal - slope));
123 double rhs1 = newVal - oldVal - lambda * slope;
124 double rhs2 = val2 - oldVal - lambda2 * slope;
125 double a = (rhs1 / (lambda * lambda) - rhs2 / (lambda2 * lambda2)) /
127 double b = (-lambda2 * rhs1 / (lambda * lambda) +
128 lambda * rhs2 / (lambda2 * lambda2)) /
131 tmpLambda = -slope / (2.0 * b);
133 double disc = b * b - 3 * a * slope;
135 tmpLambda = 0.5 * lambda;
136 }
else if (b <= 0.0) {
137 tmpLambda = (-b + sqrt(disc)) / (3.0 * a);
139 tmpLambda = -slope / (b + sqrt(disc));
142 if (tmpLambda > 0.5 * lambda) {
143 tmpLambda = 0.5 * lambda;
148 lambda = std::max(tmpLambda, 0.1 * lambda);
153 for (
unsigned int i = 0; i < dim; i++) {
193int minimize(
unsigned int dim,
double *pos,
double gradTol,
194 unsigned int &numIters,
double &funcVal, EnergyFunctor func,
195 GradientFunctor gradFunc,
unsigned int snapshotFreq,
197 unsigned int maxIts =
MAXITS) {
202 double sum, maxStep, fp;
204 double *grad, *dGrad, *hessDGrad;
208 grad =
new double[dim];
209 dGrad =
new double[dim];
210 hessDGrad =
new double[dim];
211 newPos =
new double[dim];
212 xi =
new double[dim];
213 invHessian =
new double[dim * dim];
214 snapshotFreq = std::min(snapshotFreq, maxIts);
221 memset(invHessian, 0, dim * dim *
sizeof(
double));
222 for (
unsigned int i = 0; i < dim; i++) {
223 unsigned int itab = i * dim;
225 invHessian[itab + i] = 1.0;
228 sum += pos[i] * pos[i];
231 maxStep =
MAXSTEP * std::max(sqrt(sum),
static_cast<double>(dim));
233 for (
unsigned int iter = 1; iter <= maxIts; iter++) {
238 linearSearch(dim, pos, fp, grad, xi, newPos, funcVal, func, maxStep,
247 for (
unsigned int i = 0; i < dim; i++) {
248 xi[i] = newPos[i] - pos[i];
250 double temp = fabs(xi[i]) / std::max(fabs(pos[i]), 1.0);
259 if (snapshotVect && snapshotFreq) {
261 snapshotVect->push_back(s);
269 double gradScale = gradFunc(pos, grad);
273 double term = std::max(funcVal * gradScale, 1.0);
274 for (
unsigned int i = 0; i < dim; i++) {
275 double temp = fabs(grad[i]) * std::max(fabs(pos[i]), 1.0);
276 test = std::max(test, temp);
277 dGrad[i] = grad[i] - dGrad[i];
282 if (test < gradTol) {
283 if (snapshotVect && snapshotFreq) {
285 snapshotVect->push_back(s);
297 double fac = 0, fae = 0, sumDGrad = 0, sumXi = 0;
298 for (
unsigned int i = 0; i < dim; i++) {
300 unsigned int itab = i * dim;
302 for (
unsigned int j = 0; j < dim; j++) {
303 hessDGrad[i] += invHessian[itab + j] * dGrad[j];
307 double *ivh = &(invHessian[i * dim]);
308 double &hdgradi = hessDGrad[i];
311 for (
unsigned int j = 0; j < dim; ++j, ++ivh, ++dgj) {
312 hdgradi += *ivh * *dgj;
315 fac += dGrad[i] * xi[i];
316 fae += dGrad[i] * hessDGrad[i];
317 sumDGrad += dGrad[i] * dGrad[i];
318 sumXi += xi[i] * xi[i];
320 if (fac > sqrt(
EPS * sumDGrad * sumXi)) {
322 double fad = 1.0 / fae;
323 for (
unsigned int i = 0; i < dim; i++) {
324 dGrad[i] = fac * xi[i] - fad * hessDGrad[i];
327 for (
unsigned int i = 0; i < dim; i++) {
328 unsigned int itab = i * dim;
330 for (
unsigned int j = i; j < dim; j++) {
331 invHessian[itab + j] += fac * xi[i] * xi[j] -
332 fad * hessDGrad[i] * hessDGrad[j] +
333 fae * dGrad[i] * dGrad[j];
334 invHessian[j * dim + i] = invHessian[itab + j];
337 double pxi = fac * xi[i], hdgi = fad * hessDGrad[i],
338 dgi = fae * dGrad[i];
339 double *pxj = &(xi[i]), *hdgj = &(hessDGrad[i]), *dgj = &(dGrad[i]);
340 for (
unsigned int j = i; j < dim; ++j, ++pxj, ++hdgj, ++dgj) {
341 invHessian[itab + j] += pxi * *pxj - hdgi * *hdgj + dgi * *dgj;
342 invHessian[j * dim + i] = invHessian[itab + j];
348 for (
unsigned int i = 0; i < dim; i++) {
349 unsigned int itab = i * dim;
352 for (
unsigned int j = 0; j < dim; j++) {
353 xi[i] -= invHessian[itab + j] * grad[j];
356 double &pxi = xi[i], *ivh = &(invHessian[itab]), *gj = grad;
357 for (
unsigned int j = 0; j < dim; ++j, ++ivh, ++gj) {
362 if (snapshotVect && snapshotFreq && !(iter % snapshotFreq)) {
364 snapshotVect->push_back(s);
365 newPos =
new double[dim];