// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2012 Desire Nuentsa <desire.nuentsa_wakam@inria.fr>
// Copyright (C) 2012 Gael Guennebaud <gael.guennebaud@inria.fr>
//
// 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/.

#include <iostream>
#include <fstream>
#include <iomanip>

#include "main.h"
#include <Eigen/LevenbergMarquardt>
using namespace std;
using namespace Eigen;

template <typename Scalar>
struct DenseLM : DenseFunctor<Scalar> {
  typedef DenseFunctor<Scalar> Base;
  typedef typename Base::JacobianType JacobianType;
  typedef Matrix<Scalar, Dynamic, 1> VectorType;

  DenseLM(int n, int m) : DenseFunctor<Scalar>(n, m) {}

  VectorType model(const VectorType& uv, VectorType& x) {
    VectorType y;  // Should change to use expression template
    int m = Base::values();
    int n = Base::inputs();
    eigen_assert(uv.size() % 2 == 0);
    eigen_assert(uv.size() == n);
    eigen_assert(x.size() == m);
    y.setZero(m);
    int half = n / 2;
    VectorBlock<const VectorType> u(uv, 0, half);
    VectorBlock<const VectorType> v(uv, half, half);
    for (int j = 0; j < m; j++) {
      for (int i = 0; i < half; i++) y(j) += u(i) * std::exp(-(x(j) - i) * (x(j) - i) / (v(i) * v(i)));
    }
    return y;
  }
  void initPoints(VectorType& uv_ref, VectorType& x) {
    m_x = x;
    m_y = this->model(uv_ref, x);
  }

  int operator()(const VectorType& uv, VectorType& fvec) {
    int m = Base::values();
    int n = Base::inputs();
    eigen_assert(uv.size() % 2 == 0);
    eigen_assert(uv.size() == n);
    eigen_assert(fvec.size() == m);
    int half = n / 2;
    VectorBlock<const VectorType> u(uv, 0, half);
    VectorBlock<const VectorType> v(uv, half, half);
    for (int j = 0; j < m; j++) {
      fvec(j) = m_y(j);
      for (int i = 0; i < half; i++) {
        fvec(j) -= u(i) * std::exp(-(m_x(j) - i) * (m_x(j) - i) / (v(i) * v(i)));
      }
    }

    return 0;
  }
  int df(const VectorType& uv, JacobianType& fjac) {
    int m = Base::values();
    int n = Base::inputs();
    eigen_assert(n == uv.size());
    eigen_assert(fjac.rows() == m);
    eigen_assert(fjac.cols() == n);
    int half = n / 2;
    VectorBlock<const VectorType> u(uv, 0, half);
    VectorBlock<const VectorType> v(uv, half, half);
    for (int j = 0; j < m; j++) {
      for (int i = 0; i < half; i++) {
        fjac.coeffRef(j, i) = -std::exp(-(m_x(j) - i) * (m_x(j) - i) / (v(i) * v(i)));
        fjac.coeffRef(j, i + half) = -2. * u(i) * (m_x(j) - i) * (m_x(j) - i) / (std::pow(v(i), 3)) *
                                     std::exp(-(m_x(j) - i) * (m_x(j) - i) / (v(i) * v(i)));
      }
    }
    return 0;
  }
  VectorType m_x, m_y;  // Data Points
};

template <typename FunctorType, typename VectorType>
int test_minimizeLM(FunctorType& functor, VectorType& uv) {
  LevenbergMarquardt<FunctorType> lm(functor);
  LevenbergMarquardtSpace::Status info;

  info = lm.minimize(uv);

  VERIFY_IS_EQUAL(info, 1);
  // FIXME Check other parameters
  return info;
}

template <typename FunctorType, typename VectorType>
int test_lmder(FunctorType& functor, VectorType& uv) {
  typedef typename VectorType::Scalar Scalar;
  LevenbergMarquardtSpace::Status info;
  LevenbergMarquardt<FunctorType> lm(functor);
  info = lm.lmder1(uv);

  VERIFY_IS_EQUAL(info, 1);
  // FIXME Check other parameters
  return info;
}

template <typename FunctorType, typename VectorType>
int test_minimizeSteps(FunctorType& functor, VectorType& uv) {
  LevenbergMarquardtSpace::Status info;
  LevenbergMarquardt<FunctorType> lm(functor);
  info = lm.minimizeInit(uv);
  if (info == LevenbergMarquardtSpace::ImproperInputParameters) return info;
  do {
    info = lm.minimizeOneStep(uv);
  } while (info == LevenbergMarquardtSpace::Running);

  VERIFY_IS_EQUAL(info, 1);
  // FIXME Check other parameters
  return info;
}

template <typename T>
void test_denseLM_T() {
  typedef Matrix<T, Dynamic, 1> VectorType;

  int inputs = 10;
  int values = 1000;
  DenseLM<T> dense_gaussian(inputs, values);
  VectorType uv(inputs), uv_ref(inputs);
  VectorType x(values);

  // Generate the reference solution
  uv_ref << -2, 1, 4, 8, 6, 1.8, 1.2, 1.1, 1.9, 3;

  // Generate the reference data points
  x.setRandom();
  x = 10 * x;
  x.array() += 10;
  dense_gaussian.initPoints(uv_ref, x);

  // Generate the initial parameters
  VectorBlock<VectorType> u(uv, 0, inputs / 2);
  VectorBlock<VectorType> v(uv, inputs / 2, inputs / 2);

  // Solve the optimization problem

  // Solve in one go
  u.setOnes();
  v.setOnes();
  test_minimizeLM(dense_gaussian, uv);

  // Solve until the machine precision
  u.setOnes();
  v.setOnes();
  test_lmder(dense_gaussian, uv);

  // Solve step by step
  v.setOnes();
  u.setOnes();
  test_minimizeSteps(dense_gaussian, uv);
}

EIGEN_DECLARE_TEST(denseLM) {
  CALL_SUBTEST_2(test_denseLM_T<double>());

  // CALL_SUBTEST_2(test_sparseLM_T<std::complex<double>());
}
