// -*- coding: utf-8
// vim: set fileencoding=utf-8

// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2009 Thomas Capricelli <orzel@freehackers.org>
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.

#ifndef EIGEN_LEVENBERGMARQUARDT__H
#define EIGEN_LEVENBERGMARQUARDT__H

// IWYU pragma: private
#include "./InternalHeaderCheck.h"

namespace Eigen {

namespace LevenbergMarquardtSpace {
enum Status {
  NotStarted = -2,
  Running = -1,
  ImproperInputParameters = 0,
  RelativeReductionTooSmall = 1,
  RelativeErrorTooSmall = 2,
  RelativeErrorAndReductionTooSmall = 3,
  CosinusTooSmall = 4,
  TooManyFunctionEvaluation = 5,
  FtolTooSmall = 6,
  XtolTooSmall = 7,
  GtolTooSmall = 8,
  UserAsked = 9
};
}

/**
 * \ingroup NonLinearOptimization_Module
 * \brief Performs non linear optimization over a non-linear function,
 * using a variant of the Levenberg Marquardt algorithm.
 *
 * Check wikipedia for more information.
 * http://en.wikipedia.org/wiki/Levenberg%E2%80%93Marquardt_algorithm
 */
template <typename FunctorType, typename Scalar = double>
class LevenbergMarquardt {
  static Scalar sqrt_epsilon() {
    using std::sqrt;
    return sqrt(NumTraits<Scalar>::epsilon());
  }

 public:
  LevenbergMarquardt(FunctorType &_functor) : functor(_functor) {
    nfev = njev = iter = 0;
    fnorm = gnorm = 0.;
    useExternalScaling = false;
  }

  typedef DenseIndex Index;

  struct Parameters {
    Parameters()
        : factor(Scalar(100.)),
          maxfev(400),
          ftol(sqrt_epsilon()),
          xtol(sqrt_epsilon()),
          gtol(Scalar(0.)),
          epsfcn(Scalar(0.)) {}
    Scalar factor;
    Index maxfev;  // maximum number of function evaluation
    Scalar ftol;
    Scalar xtol;
    Scalar gtol;
    Scalar epsfcn;
  };

  typedef Matrix<Scalar, Dynamic, 1> FVectorType;
  typedef Matrix<Scalar, Dynamic, Dynamic> JacobianType;

  LevenbergMarquardtSpace::Status lmder1(FVectorType &x, const Scalar tol = sqrt_epsilon());

  LevenbergMarquardtSpace::Status minimize(FVectorType &x);
  LevenbergMarquardtSpace::Status minimizeInit(FVectorType &x);
  LevenbergMarquardtSpace::Status minimizeOneStep(FVectorType &x);

  static LevenbergMarquardtSpace::Status lmdif1(FunctorType &functor, FVectorType &x, Index *nfev,
                                                const Scalar tol = sqrt_epsilon());

  LevenbergMarquardtSpace::Status lmstr1(FVectorType &x, const Scalar tol = sqrt_epsilon());

  LevenbergMarquardtSpace::Status minimizeOptimumStorage(FVectorType &x);
  LevenbergMarquardtSpace::Status minimizeOptimumStorageInit(FVectorType &x);
  LevenbergMarquardtSpace::Status minimizeOptimumStorageOneStep(FVectorType &x);

  void resetParameters(void) { parameters = Parameters(); }

  Parameters parameters;
  FVectorType fvec, qtf, diag;
  JacobianType fjac;
  PermutationMatrix<Dynamic, Dynamic> permutation;
  Index nfev;
  Index njev;
  Index iter;
  Scalar fnorm, gnorm;
  bool useExternalScaling;

  Scalar lm_param(void) { return par; }

 private:
  FunctorType &functor;
  Index n;
  Index m;
  FVectorType wa1, wa2, wa3, wa4;

  Scalar par, sum;
  Scalar temp, temp1, temp2;
  Scalar delta;
  Scalar ratio;
  Scalar pnorm, xnorm, fnorm1, actred, dirder, prered;

  LevenbergMarquardt &operator=(const LevenbergMarquardt &);
};

template <typename FunctorType, typename Scalar>
LevenbergMarquardtSpace::Status LevenbergMarquardt<FunctorType, Scalar>::lmder1(FVectorType &x, const Scalar tol) {
  n = x.size();
  m = functor.values();

  /* check the input parameters for errors. */
  if (n <= 0 || m < n || tol < 0.) return LevenbergMarquardtSpace::ImproperInputParameters;

  resetParameters();
  parameters.ftol = tol;
  parameters.xtol = tol;
  parameters.maxfev = 100 * (n + 1);

  return minimize(x);
}

template <typename FunctorType, typename Scalar>
LevenbergMarquardtSpace::Status LevenbergMarquardt<FunctorType, Scalar>::minimize(FVectorType &x) {
  LevenbergMarquardtSpace::Status status = minimizeInit(x);
  if (status == LevenbergMarquardtSpace::ImproperInputParameters) return status;
  do {
    status = minimizeOneStep(x);
  } while (status == LevenbergMarquardtSpace::Running);
  return status;
}

template <typename FunctorType, typename Scalar>
LevenbergMarquardtSpace::Status LevenbergMarquardt<FunctorType, Scalar>::minimizeInit(FVectorType &x) {
  n = x.size();
  m = functor.values();

  wa1.resize(n);
  wa2.resize(n);
  wa3.resize(n);
  wa4.resize(m);
  fvec.resize(m);
  fjac.resize(m, n);
  if (!useExternalScaling) diag.resize(n);
  eigen_assert((!useExternalScaling || diag.size() == n) &&
               "When useExternalScaling is set, the caller must provide a valid 'diag'");
  qtf.resize(n);

  /* Function Body */
  nfev = 0;
  njev = 0;

  /*     check the input parameters for errors. */
  if (n <= 0 || m < n || parameters.ftol < 0. || parameters.xtol < 0. || parameters.gtol < 0. ||
      parameters.maxfev <= 0 || parameters.factor <= 0.)
    return LevenbergMarquardtSpace::ImproperInputParameters;

  if (useExternalScaling)
    for (Index j = 0; j < n; ++j)
      if (diag[j] <= 0.) return LevenbergMarquardtSpace::ImproperInputParameters;

  /*     evaluate the function at the starting point */
  /*     and calculate its norm. */
  nfev = 1;
  if (functor(x, fvec) < 0) return LevenbergMarquardtSpace::UserAsked;
  fnorm = fvec.stableNorm();

  /*     initialize levenberg-marquardt parameter and iteration counter. */
  par = 0.;
  iter = 1;

  return LevenbergMarquardtSpace::NotStarted;
}

template <typename FunctorType, typename Scalar>
LevenbergMarquardtSpace::Status LevenbergMarquardt<FunctorType, Scalar>::minimizeOneStep(FVectorType &x) {
  using std::abs;
  using std::sqrt;

  eigen_assert(x.size() == n);  // check the caller is not cheating us

  /* calculate the jacobian matrix. */
  Index df_ret = functor.df(x, fjac);
  if (df_ret < 0) return LevenbergMarquardtSpace::UserAsked;
  if (df_ret > 0)
    // numerical diff, we evaluated the function df_ret times
    nfev += df_ret;
  else
    njev++;

  /* compute the qr factorization of the jacobian. */
  wa2 = fjac.colwise().blueNorm();
  ColPivHouseholderQR<JacobianType> qrfac(fjac);
  fjac = qrfac.matrixQR();
  permutation = qrfac.colsPermutation();

  /* on the first iteration and if external scaling is not used, scale according */
  /* to the norms of the columns of the initial jacobian. */
  if (iter == 1) {
    if (!useExternalScaling)
      for (Index j = 0; j < n; ++j) diag[j] = (wa2[j] == 0.) ? 1. : wa2[j];

    /* on the first iteration, calculate the norm of the scaled x */
    /* and initialize the step bound delta. */
    xnorm = diag.cwiseProduct(x).stableNorm();
    delta = parameters.factor * xnorm;
    if (delta == 0.) delta = parameters.factor;
  }

  /* form (q transpose)*fvec and store the first n components in */
  /* qtf. */
  wa4 = fvec;
  wa4.applyOnTheLeft(qrfac.householderQ().adjoint());
  qtf = wa4.head(n);

  /* compute the norm of the scaled gradient. */
  gnorm = 0.;
  if (fnorm != 0.)
    for (Index j = 0; j < n; ++j)
      if (wa2[permutation.indices()[j]] != 0.)
        gnorm = (std::max)(gnorm,
                           abs(fjac.col(j).head(j + 1).dot(qtf.head(j + 1) / fnorm) / wa2[permutation.indices()[j]]));

  /* test for convergence of the gradient norm. */
  if (gnorm <= parameters.gtol) return LevenbergMarquardtSpace::CosinusTooSmall;

  /* rescale if necessary. */
  if (!useExternalScaling) diag = diag.cwiseMax(wa2);

  do {
    /* determine the levenberg-marquardt parameter. */
    internal::lmpar2<Scalar>(qrfac, diag, qtf, delta, par, wa1);

    /* store the direction p and x + p. calculate the norm of p. */
    wa1 = -wa1;
    wa2 = x + wa1;
    pnorm = diag.cwiseProduct(wa1).stableNorm();

    /* on the first iteration, adjust the initial step bound. */
    if (iter == 1) delta = (std::min)(delta, pnorm);

    /* evaluate the function at x + p and calculate its norm. */
    if (functor(wa2, wa4) < 0) return LevenbergMarquardtSpace::UserAsked;
    ++nfev;
    fnorm1 = wa4.stableNorm();

    /* compute the scaled actual reduction. */
    actred = -1.;
    if (Scalar(.1) * fnorm1 < fnorm) actred = 1. - numext::abs2(fnorm1 / fnorm);

    /* compute the scaled predicted reduction and */
    /* the scaled directional derivative. */
    wa3 = fjac.template triangularView<Upper>() * (qrfac.colsPermutation().inverse() * wa1);
    temp1 = numext::abs2(wa3.stableNorm() / fnorm);
    temp2 = numext::abs2(sqrt(par) * pnorm / fnorm);
    prered = temp1 + temp2 / Scalar(.5);
    dirder = -(temp1 + temp2);

    /* compute the ratio of the actual to the predicted */
    /* reduction. */
    ratio = 0.;
    if (prered != 0.) ratio = actred / prered;

    /* update the step bound. */
    if (ratio <= Scalar(.25)) {
      if (actred >= 0.) temp = Scalar(.5);
      if (actred < 0.) temp = Scalar(.5) * dirder / (dirder + Scalar(.5) * actred);
      if (Scalar(.1) * fnorm1 >= fnorm || temp < Scalar(.1)) temp = Scalar(.1);
      /* Computing MIN */
      delta = temp * (std::min)(delta, pnorm / Scalar(.1));
      par /= temp;
    } else if (!(par != 0. && ratio < Scalar(.75))) {
      delta = pnorm / Scalar(.5);
      par = Scalar(.5) * par;
    }

    /* test for successful iteration. */
    if (ratio >= Scalar(1e-4)) {
      /* successful iteration. update x, fvec, and their norms. */
      x = wa2;
      wa2 = diag.cwiseProduct(x);
      fvec = wa4;
      xnorm = wa2.stableNorm();
      fnorm = fnorm1;
      ++iter;
    }

    /* tests for convergence. */
    if (abs(actred) <= parameters.ftol && prered <= parameters.ftol && Scalar(.5) * ratio <= 1. &&
        delta <= parameters.xtol * xnorm)
      return LevenbergMarquardtSpace::RelativeErrorAndReductionTooSmall;
    if (abs(actred) <= parameters.ftol && prered <= parameters.ftol && Scalar(.5) * ratio <= 1.)
      return LevenbergMarquardtSpace::RelativeReductionTooSmall;
    if (delta <= parameters.xtol * xnorm) return LevenbergMarquardtSpace::RelativeErrorTooSmall;

    /* tests for termination and stringent tolerances. */
    if (nfev >= parameters.maxfev) return LevenbergMarquardtSpace::TooManyFunctionEvaluation;
    if (abs(actred) <= NumTraits<Scalar>::epsilon() && prered <= NumTraits<Scalar>::epsilon() &&
        Scalar(.5) * ratio <= 1.)
      return LevenbergMarquardtSpace::FtolTooSmall;
    if (delta <= NumTraits<Scalar>::epsilon() * xnorm) return LevenbergMarquardtSpace::XtolTooSmall;
    if (gnorm <= NumTraits<Scalar>::epsilon()) return LevenbergMarquardtSpace::GtolTooSmall;

  } while (ratio < Scalar(1e-4));

  return LevenbergMarquardtSpace::Running;
}

template <typename FunctorType, typename Scalar>
LevenbergMarquardtSpace::Status LevenbergMarquardt<FunctorType, Scalar>::lmstr1(FVectorType &x, const Scalar tol) {
  n = x.size();
  m = functor.values();

  /* check the input parameters for errors. */
  if (n <= 0 || m < n || tol < 0.) return LevenbergMarquardtSpace::ImproperInputParameters;

  resetParameters();
  parameters.ftol = tol;
  parameters.xtol = tol;
  parameters.maxfev = 100 * (n + 1);

  return minimizeOptimumStorage(x);
}

template <typename FunctorType, typename Scalar>
LevenbergMarquardtSpace::Status LevenbergMarquardt<FunctorType, Scalar>::minimizeOptimumStorageInit(FVectorType &x) {
  n = x.size();
  m = functor.values();

  wa1.resize(n);
  wa2.resize(n);
  wa3.resize(n);
  wa4.resize(m);
  fvec.resize(m);
  // Only R is stored in fjac. Q is only used to compute 'qtf', which is
  // Q.transpose()*rhs. qtf will be updated using givens rotation,
  // instead of storing them in Q.
  // The purpose it to only use a nxn matrix, instead of mxn here, so
  // that we can handle cases where m>>n :
  fjac.resize(n, n);
  if (!useExternalScaling) diag.resize(n);
  eigen_assert((!useExternalScaling || diag.size() == n) &&
               "When useExternalScaling is set, the caller must provide a valid 'diag'");
  qtf.resize(n);

  /* Function Body */
  nfev = 0;
  njev = 0;

  /*     check the input parameters for errors. */
  if (n <= 0 || m < n || parameters.ftol < 0. || parameters.xtol < 0. || parameters.gtol < 0. ||
      parameters.maxfev <= 0 || parameters.factor <= 0.)
    return LevenbergMarquardtSpace::ImproperInputParameters;

  if (useExternalScaling)
    for (Index j = 0; j < n; ++j)
      if (diag[j] <= 0.) return LevenbergMarquardtSpace::ImproperInputParameters;

  /*     evaluate the function at the starting point */
  /*     and calculate its norm. */
  nfev = 1;
  if (functor(x, fvec) < 0) return LevenbergMarquardtSpace::UserAsked;
  fnorm = fvec.stableNorm();

  /*     initialize levenberg-marquardt parameter and iteration counter. */
  par = 0.;
  iter = 1;

  return LevenbergMarquardtSpace::NotStarted;
}

template <typename FunctorType, typename Scalar>
LevenbergMarquardtSpace::Status LevenbergMarquardt<FunctorType, Scalar>::minimizeOptimumStorageOneStep(FVectorType &x) {
  using std::abs;
  using std::sqrt;

  eigen_assert(x.size() == n);  // check the caller is not cheating us

  Index i, j;
  bool sing;

  /* compute the qr factorization of the jacobian matrix */
  /* calculated one row at a time, while simultaneously */
  /* forming (q transpose)*fvec and storing the first */
  /* n components in qtf. */
  qtf.fill(0.);
  fjac.fill(0.);
  Index rownb = 2;
  for (i = 0; i < m; ++i) {
    if (functor.df(x, wa3, rownb) < 0) return LevenbergMarquardtSpace::UserAsked;
    internal::rwupdt<Scalar>(fjac, wa3, qtf, fvec[i]);
    ++rownb;
  }
  ++njev;

  /* if the jacobian is rank deficient, call qrfac to */
  /* reorder its columns and update the components of qtf. */
  sing = false;
  for (j = 0; j < n; ++j) {
    if (fjac(j, j) == 0.) sing = true;
    wa2[j] = fjac.col(j).head(j).stableNorm();
  }
  permutation.setIdentity(n);
  if (sing) {
    wa2 = fjac.colwise().blueNorm();
    // TODO We have no unit test covering this code path, do not modify
    // until it is carefully tested
    ColPivHouseholderQR<JacobianType> qrfac(fjac);
    fjac = qrfac.matrixQR();
    wa1 = fjac.diagonal();
    fjac.diagonal() = qrfac.hCoeffs();
    permutation = qrfac.colsPermutation();
    // TODO : avoid this:
    for (Index ii = 0; ii < fjac.cols(); ii++)
      fjac.col(ii).segment(ii + 1, fjac.rows() - ii - 1) *= fjac(ii, ii);  // rescale vectors

    for (j = 0; j < n; ++j) {
      if (fjac(j, j) != 0.) {
        sum = 0.;
        for (i = j; i < n; ++i) sum += fjac(i, j) * qtf[i];
        temp = -sum / fjac(j, j);
        for (i = j; i < n; ++i) qtf[i] += fjac(i, j) * temp;
      }
      fjac(j, j) = wa1[j];
    }
  }

  /* on the first iteration and if external scaling is not used, scale according */
  /* to the norms of the columns of the initial jacobian. */
  if (iter == 1) {
    if (!useExternalScaling)
      for (j = 0; j < n; ++j) diag[j] = (wa2[j] == 0.) ? 1. : wa2[j];

    /* on the first iteration, calculate the norm of the scaled x */
    /* and initialize the step bound delta. */
    xnorm = diag.cwiseProduct(x).stableNorm();
    delta = parameters.factor * xnorm;
    if (delta == 0.) delta = parameters.factor;
  }

  /* compute the norm of the scaled gradient. */
  gnorm = 0.;
  if (fnorm != 0.)
    for (j = 0; j < n; ++j)
      if (wa2[permutation.indices()[j]] != 0.)
        gnorm = (std::max)(gnorm,
                           abs(fjac.col(j).head(j + 1).dot(qtf.head(j + 1) / fnorm) / wa2[permutation.indices()[j]]));

  /* test for convergence of the gradient norm. */
  if (gnorm <= parameters.gtol) return LevenbergMarquardtSpace::CosinusTooSmall;

  /* rescale if necessary. */
  if (!useExternalScaling) diag = diag.cwiseMax(wa2);

  do {
    /* determine the levenberg-marquardt parameter. */
    internal::lmpar<Scalar>(fjac, permutation.indices(), diag, qtf, delta, par, wa1);

    /* store the direction p and x + p. calculate the norm of p. */
    wa1 = -wa1;
    wa2 = x + wa1;
    pnorm = diag.cwiseProduct(wa1).stableNorm();

    /* on the first iteration, adjust the initial step bound. */
    if (iter == 1) delta = (std::min)(delta, pnorm);

    /* evaluate the function at x + p and calculate its norm. */
    if (functor(wa2, wa4) < 0) return LevenbergMarquardtSpace::UserAsked;
    ++nfev;
    fnorm1 = wa4.stableNorm();

    /* compute the scaled actual reduction. */
    actred = -1.;
    if (Scalar(.1) * fnorm1 < fnorm) actred = 1. - numext::abs2(fnorm1 / fnorm);

    /* compute the scaled predicted reduction and */
    /* the scaled directional derivative. */
    wa3 = fjac.topLeftCorner(n, n).template triangularView<Upper>() * (permutation.inverse() * wa1);
    temp1 = numext::abs2(wa3.stableNorm() / fnorm);
    temp2 = numext::abs2(sqrt(par) * pnorm / fnorm);
    prered = temp1 + temp2 / Scalar(.5);
    dirder = -(temp1 + temp2);

    /* compute the ratio of the actual to the predicted */
    /* reduction. */
    ratio = 0.;
    if (prered != 0.) ratio = actred / prered;

    /* update the step bound. */
    if (ratio <= Scalar(.25)) {
      if (actred >= 0.) temp = Scalar(.5);
      if (actred < 0.) temp = Scalar(.5) * dirder / (dirder + Scalar(.5) * actred);
      if (Scalar(.1) * fnorm1 >= fnorm || temp < Scalar(.1)) temp = Scalar(.1);
      /* Computing MIN */
      delta = temp * (std::min)(delta, pnorm / Scalar(.1));
      par /= temp;
    } else if (!(par != 0. && ratio < Scalar(.75))) {
      delta = pnorm / Scalar(.5);
      par = Scalar(.5) * par;
    }

    /* test for successful iteration. */
    if (ratio >= Scalar(1e-4)) {
      /* successful iteration. update x, fvec, and their norms. */
      x = wa2;
      wa2 = diag.cwiseProduct(x);
      fvec = wa4;
      xnorm = wa2.stableNorm();
      fnorm = fnorm1;
      ++iter;
    }

    /* tests for convergence. */
    if (abs(actred) <= parameters.ftol && prered <= parameters.ftol && Scalar(.5) * ratio <= 1. &&
        delta <= parameters.xtol * xnorm)
      return LevenbergMarquardtSpace::RelativeErrorAndReductionTooSmall;
    if (abs(actred) <= parameters.ftol && prered <= parameters.ftol && Scalar(.5) * ratio <= 1.)
      return LevenbergMarquardtSpace::RelativeReductionTooSmall;
    if (delta <= parameters.xtol * xnorm) return LevenbergMarquardtSpace::RelativeErrorTooSmall;

    /* tests for termination and stringent tolerances. */
    if (nfev >= parameters.maxfev) return LevenbergMarquardtSpace::TooManyFunctionEvaluation;
    if (abs(actred) <= NumTraits<Scalar>::epsilon() && prered <= NumTraits<Scalar>::epsilon() &&
        Scalar(.5) * ratio <= 1.)
      return LevenbergMarquardtSpace::FtolTooSmall;
    if (delta <= NumTraits<Scalar>::epsilon() * xnorm) return LevenbergMarquardtSpace::XtolTooSmall;
    if (gnorm <= NumTraits<Scalar>::epsilon()) return LevenbergMarquardtSpace::GtolTooSmall;

  } while (ratio < Scalar(1e-4));

  return LevenbergMarquardtSpace::Running;
}

template <typename FunctorType, typename Scalar>
LevenbergMarquardtSpace::Status LevenbergMarquardt<FunctorType, Scalar>::minimizeOptimumStorage(FVectorType &x) {
  LevenbergMarquardtSpace::Status status = minimizeOptimumStorageInit(x);
  if (status == LevenbergMarquardtSpace::ImproperInputParameters) return status;
  do {
    status = minimizeOptimumStorageOneStep(x);
  } while (status == LevenbergMarquardtSpace::Running);
  return status;
}

template <typename FunctorType, typename Scalar>
LevenbergMarquardtSpace::Status LevenbergMarquardt<FunctorType, Scalar>::lmdif1(FunctorType &functor, FVectorType &x,
                                                                                Index *nfev, const Scalar tol) {
  Index n = x.size();
  Index m = functor.values();

  /* check the input parameters for errors. */
  if (n <= 0 || m < n || tol < 0.) return LevenbergMarquardtSpace::ImproperInputParameters;

  NumericalDiff<FunctorType> numDiff(functor);
  // embedded LevenbergMarquardt
  LevenbergMarquardt<NumericalDiff<FunctorType>, Scalar> lm(numDiff);
  lm.parameters.ftol = tol;
  lm.parameters.xtol = tol;
  lm.parameters.maxfev = 200 * (n + 1);

  LevenbergMarquardtSpace::Status info = LevenbergMarquardtSpace::Status(lm.minimize(x));
  if (nfev) *nfev = lm.nfev;
  return info;
}

}  // end namespace Eigen

#endif  // EIGEN_LEVENBERGMARQUARDT__H

// vim: ai ts=4 sts=4 et sw=4
