// -*- coding: utf-8
// vim: set fileencoding=utf-8
// SPDX-License-Identifier: MPL-2.0

// 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_HYBRIDNONLINEARSOLVER_H
#define EIGEN_HYBRIDNONLINEARSOLVER_H

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

namespace Eigen {

namespace HybridNonLinearSolverSpace {
enum Status {
  Running = -1,
  ImproperInputParameters = 0,
  RelativeErrorTooSmall = 1,
  TooManyFunctionEvaluation = 2,
  TolTooSmall = 3,
  NotMakingProgressJacobian = 4,
  NotMakingProgressIterations = 5,
  UserAsked = 6
};
}

/**
 * \ingroup NonLinearOptimization_Module
 * \brief Finds a zero of a system of n
 * nonlinear functions in n variables by a modification of the Powell
 * hybrid method ("dogleg").
 *
 * The user must provide a subroutine which calculates the
 * functions. The Jacobian is either provided by the user, or approximated
 * using a forward-difference method.
 *
 */
template <typename FunctorType, typename Scalar = double>
class HybridNonLinearSolver {
 public:
  typedef DenseIndex Index;

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

  struct Parameters {
    Parameters()
        : factor(Scalar(100.)),
          maxfev(1000),
          xtol(numext::sqrt(NumTraits<Scalar>::epsilon())),
          nb_of_subdiagonals(-1),
          nb_of_superdiagonals(-1),
          epsfcn(Scalar(0.)) {}
    Scalar factor;
    Index maxfev;  // maximum number of function evaluations
    Scalar xtol;
    Index nb_of_subdiagonals;
    Index nb_of_superdiagonals;
    Scalar epsfcn;
  };
  typedef Matrix<Scalar, Dynamic, 1> FVectorType;
  typedef Matrix<Scalar, Dynamic, Dynamic> JacobianType;
  /* TODO: if eigen provides a triangular storage, use it here */
  typedef Matrix<Scalar, Dynamic, Dynamic> UpperTriangularType;

  HybridNonLinearSolverSpace::Status hybrj1(FVectorType &x,
                                            const Scalar tol = numext::sqrt(NumTraits<Scalar>::epsilon()));

  HybridNonLinearSolverSpace::Status solveInit(FVectorType &x);
  HybridNonLinearSolverSpace::Status solveOneStep(FVectorType &x);
  HybridNonLinearSolverSpace::Status solve(FVectorType &x);

  HybridNonLinearSolverSpace::Status hybrd1(FVectorType &x,
                                            const Scalar tol = numext::sqrt(NumTraits<Scalar>::epsilon()));

  HybridNonLinearSolverSpace::Status solveNumericalDiffInit(FVectorType &x);
  HybridNonLinearSolverSpace::Status solveNumericalDiffOneStep(FVectorType &x);
  HybridNonLinearSolverSpace::Status solveNumericalDiff(FVectorType &x);

  void resetParameters(void) { parameters = Parameters(); }
  Parameters parameters;
  FVectorType fvec, qtf, diag;
  JacobianType fjac;
  UpperTriangularType R;
  Index nfev;
  Index njev;
  Index iter;
  Scalar fnorm;
  bool useExternalScaling;

 private:
  FunctorType &functor;
  Index n;
  bool sing;
  Scalar temp;
  Scalar delta;
  bool jeval;
  Index ncsuc;
  Scalar ratio;
  Scalar pnorm, xnorm, fnorm1;
  Index nslow1, nslow2;
  Index ncfail;
  Scalar actred, prered;
  FVectorType wa1, wa2, wa3, wa4;

  HybridNonLinearSolver &operator=(const HybridNonLinearSolver &) = delete;
};

template <typename FunctorType, typename Scalar>
HybridNonLinearSolverSpace::Status HybridNonLinearSolver<FunctorType, Scalar>::hybrj1(FVectorType &x,
                                                                                      const Scalar tol) {
  n = x.size();

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

  resetParameters();
  parameters.maxfev = 100 * (n + 1);
  parameters.xtol = tol;
  diag.setConstant(n, 1.);
  useExternalScaling = true;
  return solve(x);
}

template <typename FunctorType, typename Scalar>
HybridNonLinearSolverSpace::Status HybridNonLinearSolver<FunctorType, Scalar>::solveInit(FVectorType &x) {
  n = x.size();

  wa1.resize(n);
  wa2.resize(n);
  wa3.resize(n);
  wa4.resize(n);
  fvec.resize(n);
  qtf.resize(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'");

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

  /*     check the input parameters for errors. */
  if (n <= 0 || parameters.xtol < 0. || parameters.maxfev <= 0 || parameters.factor <= 0.)
    return HybridNonLinearSolverSpace::ImproperInputParameters;
  if (useExternalScaling)
    for (Index j = 0; j < n; ++j)
      if (diag[j] <= 0.) return HybridNonLinearSolverSpace::ImproperInputParameters;

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

  /*     initialize iteration counter and monitors. */
  iter = 1;
  ncsuc = 0;
  ncfail = 0;
  nslow1 = 0;
  nslow2 = 0;

  return HybridNonLinearSolverSpace::Running;
}

template <typename FunctorType, typename Scalar>
HybridNonLinearSolverSpace::Status HybridNonLinearSolver<FunctorType, Scalar>::solveOneStep(FVectorType &x) {
  using std::abs;

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

  Index j;
  std::vector<JacobiRotation<Scalar> > v_givens(n), w_givens(n);

  jeval = true;

  /* calculate the jacobian matrix. */
  if (functor.df(x, fjac) < 0) return HybridNonLinearSolverSpace::UserAsked;
  ++njev;

  wa2 = fjac.colwise().blueNorm();

  /* 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 qr factorization of the jacobian. */
  HouseholderQR<JacobianType> qrfac(fjac);  // no pivoting:

  /* copy the triangular factor of the qr factorization into r. */
  R = qrfac.matrixQR();

  /* accumulate the orthogonal factor in fjac. */
  fjac = qrfac.householderQ();

  /* form (q transpose)*fvec and store in qtf. */
  qtf.noalias() = fjac.transpose() * fvec;

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

  while (true) {
    /* determine the direction p. */
    internal::dogleg<Scalar>(R, diag, qtf, delta, 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 HybridNonLinearSolverSpace::UserAsked;
    ++nfev;
    fnorm1 = wa4.stableNorm();

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

    /* compute the scaled predicted reduction. */
    wa3.noalias() = R.template triangularView<Upper>() * wa1 + qtf;
    temp = wa3.stableNorm();
    prered = 0.;
    if (temp < fnorm) /* Computing 2nd power */
      prered = 1. - numext::abs2(temp / fnorm);

    /* 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(.1)) {
      ncsuc = 0;
      ++ncfail;
      delta = Scalar(.5) * delta;
    } else {
      ncfail = 0;
      ++ncsuc;
      if (ratio >= Scalar(.5) || ncsuc > 1) delta = (std::max)(delta, pnorm / Scalar(.5));
      if (abs(ratio - 1.) <= Scalar(.1)) {
        delta = pnorm / Scalar(.5);
      }
    }

    /* 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;
    }

    /* determine the progress of the iteration. */
    ++nslow1;
    if (actred >= Scalar(.001)) nslow1 = 0;
    if (jeval) ++nslow2;
    if (actred >= Scalar(.1)) nslow2 = 0;

    /* test for convergence. */
    if (delta <= parameters.xtol * xnorm || fnorm == 0.) return HybridNonLinearSolverSpace::RelativeErrorTooSmall;

    /* tests for termination and stringent tolerances. */
    if (nfev >= parameters.maxfev) return HybridNonLinearSolverSpace::TooManyFunctionEvaluation;
    if (Scalar(.1) * (std::max)(Scalar(.1) * delta, pnorm) <= NumTraits<Scalar>::epsilon() * xnorm)
      return HybridNonLinearSolverSpace::TolTooSmall;
    if (nslow2 == 5) return HybridNonLinearSolverSpace::NotMakingProgressJacobian;
    if (nslow1 == 10) return HybridNonLinearSolverSpace::NotMakingProgressIterations;

    /* criterion for recalculating jacobian. */
    if (ncfail == 2) break;  // leave inner loop and go for the next outer loop iteration

    /* calculate the rank one modification to the jacobian */
    /* and update qtf if necessary. */
    wa1 = diag.cwiseProduct(diag.cwiseProduct(wa1) / pnorm);
    wa2.noalias() = fjac.transpose() * wa4;
    if (ratio >= Scalar(1e-4)) qtf = wa2;
    wa2 = (wa2 - wa3) / pnorm;

    /* compute the qr factorization of the updated jacobian. */
    internal::r1updt<Scalar>(R, wa1, v_givens, w_givens, wa2, wa3, &sing);
    internal::r1mpyq<Scalar>(fjac, v_givens, w_givens);
    Transpose<FVectorType> qtf_row = qtf.transpose();
    internal::r1mpyq<Scalar>(qtf_row, v_givens, w_givens);

    jeval = false;
  }
  return HybridNonLinearSolverSpace::Running;
}

template <typename FunctorType, typename Scalar>
HybridNonLinearSolverSpace::Status HybridNonLinearSolver<FunctorType, Scalar>::solve(FVectorType &x) {
  HybridNonLinearSolverSpace::Status status = solveInit(x);
  if (status == HybridNonLinearSolverSpace::ImproperInputParameters) return status;
  while (status == HybridNonLinearSolverSpace::Running) status = solveOneStep(x);
  return status;
}

template <typename FunctorType, typename Scalar>
HybridNonLinearSolverSpace::Status HybridNonLinearSolver<FunctorType, Scalar>::hybrd1(FVectorType &x,
                                                                                      const Scalar tol) {
  n = x.size();

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

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

  diag.setConstant(n, 1.);
  useExternalScaling = true;
  return solveNumericalDiff(x);
}

template <typename FunctorType, typename Scalar>
HybridNonLinearSolverSpace::Status HybridNonLinearSolver<FunctorType, Scalar>::solveNumericalDiffInit(FVectorType &x) {
  n = x.size();

  if (parameters.nb_of_subdiagonals < 0) parameters.nb_of_subdiagonals = n - 1;
  if (parameters.nb_of_superdiagonals < 0) parameters.nb_of_superdiagonals = n - 1;

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

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

  /*     check the input parameters for errors. */
  if (n <= 0 || parameters.xtol < 0. || parameters.maxfev <= 0 || parameters.nb_of_subdiagonals < 0 ||
      parameters.nb_of_superdiagonals < 0 || parameters.factor <= 0.)
    return HybridNonLinearSolverSpace::ImproperInputParameters;
  if (useExternalScaling)
    for (Index j = 0; j < n; ++j)
      if (diag[j] <= 0.) return HybridNonLinearSolverSpace::ImproperInputParameters;

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

  /*     initialize iteration counter and monitors. */
  iter = 1;
  ncsuc = 0;
  ncfail = 0;
  nslow1 = 0;
  nslow2 = 0;

  return HybridNonLinearSolverSpace::Running;
}

template <typename FunctorType, typename Scalar>
HybridNonLinearSolverSpace::Status HybridNonLinearSolver<FunctorType, Scalar>::solveNumericalDiffOneStep(
    FVectorType &x) {
  using std::abs;
  using std::sqrt;

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

  Index j;
  std::vector<JacobiRotation<Scalar> > v_givens(n), w_givens(n);

  jeval = true;
  if (parameters.nb_of_subdiagonals < 0) parameters.nb_of_subdiagonals = n - 1;
  if (parameters.nb_of_superdiagonals < 0) parameters.nb_of_superdiagonals = n - 1;

  /* calculate the jacobian matrix. */
  if (internal::fdjac1(functor, x, fvec, fjac, parameters.nb_of_subdiagonals, parameters.nb_of_superdiagonals,
                       parameters.epsfcn) < 0)
    return HybridNonLinearSolverSpace::UserAsked;
  nfev += (std::min)(parameters.nb_of_subdiagonals + parameters.nb_of_superdiagonals + 1, n);

  wa2 = fjac.colwise().blueNorm();

  /* 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 qr factorization of the jacobian. */
  HouseholderQR<JacobianType> qrfac(fjac);  // no pivoting:

  /* copy the triangular factor of the qr factorization into r. */
  R = qrfac.matrixQR();

  /* accumulate the orthogonal factor in fjac. */
  fjac = qrfac.householderQ();

  /* form (q transpose)*fvec and store in qtf. */
  qtf.noalias() = fjac.transpose() * fvec;

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

  while (true) {
    /* determine the direction p. */
    internal::dogleg<Scalar>(R, diag, qtf, delta, 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 HybridNonLinearSolverSpace::UserAsked;
    ++nfev;
    fnorm1 = wa4.stableNorm();

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

    /* compute the scaled predicted reduction. */
    wa3.noalias() = R.template triangularView<Upper>() * wa1 + qtf;
    temp = wa3.stableNorm();
    prered = 0.;
    if (temp < fnorm) /* Computing 2nd power */
      prered = 1. - numext::abs2(temp / fnorm);

    /* 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(.1)) {
      ncsuc = 0;
      ++ncfail;
      delta = Scalar(.5) * delta;
    } else {
      ncfail = 0;
      ++ncsuc;
      if (ratio >= Scalar(.5) || ncsuc > 1) delta = (std::max)(delta, pnorm / Scalar(.5));
      if (abs(ratio - 1.) <= Scalar(.1)) {
        delta = pnorm / Scalar(.5);
      }
    }

    /* 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;
    }

    /* determine the progress of the iteration. */
    ++nslow1;
    if (actred >= Scalar(.001)) nslow1 = 0;
    if (jeval) ++nslow2;
    if (actred >= Scalar(.1)) nslow2 = 0;

    /* test for convergence. */
    if (delta <= parameters.xtol * xnorm || fnorm == 0.) return HybridNonLinearSolverSpace::RelativeErrorTooSmall;

    /* tests for termination and stringent tolerances. */
    if (nfev >= parameters.maxfev) return HybridNonLinearSolverSpace::TooManyFunctionEvaluation;
    if (Scalar(.1) * (std::max)(Scalar(.1) * delta, pnorm) <= NumTraits<Scalar>::epsilon() * xnorm)
      return HybridNonLinearSolverSpace::TolTooSmall;
    if (nslow2 == 5) return HybridNonLinearSolverSpace::NotMakingProgressJacobian;
    if (nslow1 == 10) return HybridNonLinearSolverSpace::NotMakingProgressIterations;

    /* criterion for recalculating jacobian. */
    if (ncfail == 2) break;  // leave inner loop and go for the next outer loop iteration

    /* calculate the rank one modification to the jacobian */
    /* and update qtf if necessary. */
    wa1 = diag.cwiseProduct(diag.cwiseProduct(wa1) / pnorm);
    wa2.noalias() = fjac.transpose() * wa4;
    if (ratio >= Scalar(1e-4)) qtf = wa2;
    wa2 = (wa2 - wa3) / pnorm;

    /* compute the qr factorization of the updated jacobian. */
    internal::r1updt<Scalar>(R, wa1, v_givens, w_givens, wa2, wa3, &sing);
    internal::r1mpyq<Scalar>(fjac, v_givens, w_givens);
    Transpose<FVectorType> qtf_row = qtf.transpose();
    internal::r1mpyq<Scalar>(qtf_row, v_givens, w_givens);

    jeval = false;
  }
  return HybridNonLinearSolverSpace::Running;
}

template <typename FunctorType, typename Scalar>
HybridNonLinearSolverSpace::Status HybridNonLinearSolver<FunctorType, Scalar>::solveNumericalDiff(FVectorType &x) {
  HybridNonLinearSolverSpace::Status status = solveNumericalDiffInit(x);
  if (status == HybridNonLinearSolverSpace::ImproperInputParameters) return status;
  while (status == HybridNonLinearSolverSpace::Running) status = solveNumericalDiffOneStep(x);
  return status;
}

}  // end namespace Eigen

#endif  // EIGEN_HYBRIDNONLINEARSOLVER_H

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