13 #ifndef EIGEN_HYBRIDNONLINEARSOLVER_H
14 #define EIGEN_HYBRIDNONLINEARSOLVER_H
18 namespace HybridNonLinearSolverSpace {
42 template<
typename FunctorType,
typename Scalar=
double>
120 template<
typename FunctorType,
typename Scalar>
130 if (
n <= 0 || tol < 0.)
134 parameters.maxfev = 100*(
n+1);
135 parameters.xtol = tol;
136 diag.setConstant(
n, 1.);
137 useExternalScaling =
true;
141 template<
typename FunctorType,
typename Scalar>
147 wa1.resize(
n); wa2.resize(
n); wa3.resize(
n); wa4.resize(
n);
151 if (!useExternalScaling)
153 eigen_assert( (!useExternalScaling || diag.size()==
n) &&
"When useExternalScaling is set, the caller must provide a valid 'diag'");
160 if (
n <= 0 || parameters.xtol < 0. || parameters.maxfev <= 0 || parameters.factor <= 0. )
162 if (useExternalScaling)
163 for (
Index j = 0; j <
n; ++j)
170 if ( functor(
x, fvec) < 0)
172 fnorm = fvec.stableNorm();
184 template<
typename FunctorType,
typename Scalar>
193 std::vector<JacobiRotation<Scalar> > v_givens(
n), w_givens(
n);
198 if ( functor.df(
x, fjac) < 0)
202 wa2 = fjac.colwise().blueNorm();
207 if (!useExternalScaling)
208 for (j = 0; j <
n; ++j)
209 diag[j] = (wa2[j]==0.) ? 1. : wa2[j];
213 xnorm = diag.cwiseProduct(
x).stableNorm();
214 delta = parameters.factor * xnorm;
216 delta = parameters.factor;
232 if (!useExternalScaling)
233 diag = diag.cwiseMax(wa2);
237 internal::dogleg<Scalar>(R, diag, qtf, delta, wa1);
242 pnorm = diag.cwiseProduct(wa1).stableNorm();
249 if ( functor(wa2, wa4) < 0)
252 fnorm1 = wa4.stableNorm();
260 wa3 = R.template triangularView<Upper>()*wa1 + qtf;
261 temp = wa3.stableNorm();
269 ratio = actred / prered;
275 delta =
Scalar(.5) * delta;
279 if (ratio >=
Scalar(.5) || ncsuc > 1)
282 delta = pnorm /
Scalar(.5);
287 if (ratio >=
Scalar(1e-4)) {
290 wa2 = diag.cwiseProduct(
x);
292 xnorm = wa2.stableNorm();
299 if (actred >=
Scalar(.001))
307 if (delta <= parameters.xtol * xnorm || fnorm == 0.)
311 if (nfev >= parameters.maxfev)
326 wa1 = diag.cwiseProduct( diag.cwiseProduct(wa1)/pnorm );
327 wa2 = fjac.transpose() * wa4;
328 if (ratio >=
Scalar(1e-4))
330 wa2 = (wa2-wa3)/pnorm;
333 internal::r1updt<Scalar>(R, wa1, v_givens, w_givens, wa2, wa3, &sing);
334 internal::r1mpyq<Scalar>(
n,
n, fjac.data(), v_givens, w_givens);
335 internal::r1mpyq<Scalar>(1,
n, qtf.data(), v_givens, w_givens);
342 template<
typename FunctorType,
typename Scalar>
350 status = solveOneStep(
x);
356 template<
typename FunctorType,
typename Scalar>
366 if (
n <= 0 || tol < 0.)
370 parameters.maxfev = 200*(
n+1);
371 parameters.xtol = tol;
373 diag.setConstant(
n, 1.);
374 useExternalScaling =
true;
375 return solveNumericalDiff(
x);
378 template<
typename FunctorType,
typename Scalar>
384 if (parameters.nb_of_subdiagonals<0) parameters.nb_of_subdiagonals=
n-1;
385 if (parameters.nb_of_superdiagonals<0) parameters.nb_of_superdiagonals=
n-1;
387 wa1.resize(
n); wa2.resize(
n); wa3.resize(
n); wa4.resize(
n);
391 if (!useExternalScaling)
393 eigen_assert( (!useExternalScaling || diag.size()==
n) &&
"When useExternalScaling is set, the caller must provide a valid 'diag'");
400 if (
n <= 0 || parameters.xtol < 0. || parameters.maxfev <= 0 || parameters.nb_of_subdiagonals< 0 || parameters.nb_of_superdiagonals< 0 || parameters.factor <= 0. )
402 if (useExternalScaling)
403 for (
Index j = 0; j <
n; ++j)
410 if ( functor(
x, fvec) < 0)
412 fnorm = fvec.stableNorm();
424 template<
typename FunctorType,
typename Scalar>
434 std::vector<JacobiRotation<Scalar> > v_givens(
n), w_givens(
n);
437 if (parameters.nb_of_subdiagonals<0) parameters.nb_of_subdiagonals=
n-1;
438 if (parameters.nb_of_superdiagonals<0) parameters.nb_of_superdiagonals=
n-1;
441 if (
internal::fdjac1(functor,
x, fvec, fjac, parameters.nb_of_subdiagonals, parameters.nb_of_superdiagonals, parameters.epsfcn) <0)
443 nfev += (
std::min)(parameters.nb_of_subdiagonals+parameters.nb_of_superdiagonals+ 1,
n);
445 wa2 = fjac.colwise().blueNorm();
450 if (!useExternalScaling)
451 for (j = 0; j <
n; ++j)
452 diag[j] = (wa2[j]==0.) ? 1. : wa2[j];
456 xnorm = diag.cwiseProduct(
x).stableNorm();
457 delta = parameters.factor * xnorm;
459 delta = parameters.factor;
475 if (!useExternalScaling)
476 diag = diag.cwiseMax(wa2);
480 internal::dogleg<Scalar>(R, diag, qtf, delta, wa1);
485 pnorm = diag.cwiseProduct(wa1).stableNorm();
492 if ( functor(wa2, wa4) < 0)
495 fnorm1 = wa4.stableNorm();
503 wa3 = R.template triangularView<Upper>()*wa1 + qtf;
504 temp = wa3.stableNorm();
512 ratio = actred / prered;
518 delta =
Scalar(.5) * delta;
522 if (ratio >=
Scalar(.5) || ncsuc > 1)
525 delta = pnorm /
Scalar(.5);
530 if (ratio >=
Scalar(1e-4)) {
533 wa2 = diag.cwiseProduct(
x);
535 xnorm = wa2.stableNorm();
542 if (actred >=
Scalar(.001))
550 if (delta <= parameters.xtol * xnorm || fnorm == 0.)
554 if (nfev >= parameters.maxfev)
569 wa1 = diag.cwiseProduct( diag.cwiseProduct(wa1)/pnorm );
570 wa2 = fjac.transpose() * wa4;
571 if (ratio >=
Scalar(1e-4))
573 wa2 = (wa2-wa3)/pnorm;
576 internal::r1updt<Scalar>(R, wa1, v_givens, w_givens, wa2, wa3, &sing);
577 internal::r1mpyq<Scalar>(
n,
n, fjac.data(), v_givens, w_givens);
578 internal::r1mpyq<Scalar>(1,
n, qtf.data(), v_givens, w_givens);
585 template<
typename FunctorType,
typename Scalar>
593 status = solveNumericalDiffOneStep(
x);
599 #endif // EIGEN_HYBRIDNONLINEARSOLVER_H