// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2012 Desire NUENTSA WAKAM <desire.nuentsa_wakam@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/.

#ifndef EIGEN_ITERSCALING_H
#define EIGEN_ITERSCALING_H

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

namespace Eigen {

/**
  * \ingroup IterativeSolvers_Module
  * \brief iterative scaling algorithm to equilibrate rows and column norms in matrices
  * 
  * This class can be used as a preprocessing tool to accelerate the convergence of iterative methods 
  * 
  * This feature is  useful to limit the pivoting amount during LU/ILU factorization
  * The  scaling strategy as presented here preserves the symmetry of the problem
  * NOTE It is assumed that the matrix does not have empty row or column, 
  * 
  * Example with key steps 
  * \code
  * VectorXd x(n), b(n);
  * SparseMatrix<double> A;
  * // fill A and b;
  * IterScaling<SparseMatrix<double> > scal; 
  * // Compute the left and right scaling vectors. The matrix is equilibrated at output
  * scal.computeRef(A); 
  * // Scale the right hand side
  * b = scal.LeftScaling().cwiseProduct(b); 
  * // Now, solve the equilibrated linear system with any available solver
  * 
  * // Scale back the computed solution
  * x = scal.RightScaling().cwiseProduct(x); 
  * \endcode
  * 
  * \tparam MatrixType_ the type of the matrix. It should be a real square sparsematrix
  * 
  * References : D. Ruiz and B. Ucar, A Symmetry Preserving Algorithm for Matrix Scaling, INRIA Research report RR-7552
  * 
  * \sa \ref IncompleteLUT 
  */
template<typename MatrixType_>
class IterScaling
{
  public:
    typedef MatrixType_ MatrixType;
    typedef typename MatrixType::Scalar Scalar;
    typedef typename MatrixType::Index Index;
    
  public:
    IterScaling() { init(); }
    
    IterScaling(const MatrixType& matrix)
    {
      init();
      compute(matrix);
    }
    
    ~IterScaling() { }
    
    /** 
     * Compute the left and right diagonal matrices to scale the input matrix @p mat
     * 
     * FIXME This algorithm will be modified such that the diagonal elements are permuted on the diagonal. 
     * 
     * \sa LeftScaling() RightScaling()
     */
    void compute (const MatrixType& mat)
    {
      using std::abs;
      int m = mat.rows(); 
      int n = mat.cols();
      eigen_assert((m>0 && m == n) && "Please give a non - empty matrix");
      m_left.resize(m); 
      m_right.resize(n);
      m_left.setOnes();
      m_right.setOnes();
      m_matrix = mat;
      VectorXd Dr, Dc, DrRes, DcRes; // Temporary Left and right scaling vectors
      Dr.resize(m); Dc.resize(n);
      DrRes.resize(m); DcRes.resize(n);
      double EpsRow = 1.0, EpsCol = 1.0;
      int its = 0; 
      do
      { // Iterate until the infinite norm of each row and column is approximately 1
        // Get the maximum value in each row and column
        Dr.setZero(); Dc.setZero();
        for (int k=0; k<m_matrix.outerSize(); ++k)
        {
          for (typename MatrixType::InnerIterator it(m_matrix, k); it; ++it)
          {
            if ( Dr(it.row()) < abs(it.value()) )
              Dr(it.row()) = abs(it.value());
            
            if ( Dc(it.col()) < abs(it.value()) )
              Dc(it.col()) = abs(it.value());
          }
        }
        for (int i = 0; i < m; ++i) 
        {
          Dr(i) = std::sqrt(Dr(i));
        }
        for (int i = 0; i < n; ++i) 
        {
          Dc(i) = std::sqrt(Dc(i));
        }
        // Save the scaling factors 
        for (int i = 0; i < m; ++i) 
        {
          m_left(i) /= Dr(i);
        }
        for (int i = 0; i < n; ++i) 
        {
          m_right(i) /= Dc(i);
        }
        // Scale the rows and the columns of the matrix
        DrRes.setZero(); DcRes.setZero(); 
        for (int k=0; k<m_matrix.outerSize(); ++k)
        {
          for (typename MatrixType::InnerIterator it(m_matrix, k); it; ++it)
          {
            it.valueRef() = it.value()/( Dr(it.row()) * Dc(it.col()) );
            // Accumulate the norms of the row and column vectors   
            if ( DrRes(it.row()) < abs(it.value()) )
              DrRes(it.row()) = abs(it.value());
            
            if ( DcRes(it.col()) < abs(it.value()) )
              DcRes(it.col()) = abs(it.value());
          }
        }  
        DrRes.array() = (1-DrRes.array()).abs();
        EpsRow = DrRes.maxCoeff();
        DcRes.array() = (1-DcRes.array()).abs();
        EpsCol = DcRes.maxCoeff();
        its++;
      }while ( (EpsRow >m_tol || EpsCol > m_tol) && (its < m_maxits) );
      m_isInitialized = true;
    }
    /** Compute the left and right vectors to scale the vectors
     * the input matrix is scaled with the computed vectors at output
     * 
     * \sa compute()
     */
    void computeRef (MatrixType& mat)
    {
      compute (mat);
      mat = m_matrix;
    }
    /** Get the vector to scale the rows of the matrix 
     */
    VectorXd& LeftScaling()
    {
      return m_left;
    }
    
    /** Get the vector to scale the columns of the matrix 
     */
    VectorXd& RightScaling()
    {
      return m_right;
    }
    
    /** Set the tolerance for the convergence of the iterative scaling algorithm
     */
    void setTolerance(double tol)
    {
      m_tol = tol; 
    }
      
  protected:
    
    void init()
    {
      m_tol = 1e-10;
      m_maxits = 5;
      m_isInitialized = false;
    }
    
    MatrixType m_matrix;
    mutable ComputationInfo m_info; 
    bool m_isInitialized; 
    VectorXd m_left; // Left scaling vector
    VectorXd m_right; // m_right scaling vector
    double m_tol; 
    int m_maxits; // Maximum number of iterations allowed
};
}
#endif
