//////////////////////////////////////////////////////////////////////
//
//	AxA3dNUMMatrixIterativeOptimizer.h: interface for MatrixItertiveMethods class
//
//	Written by: Matthias Wacker
//
//
//////////////////////////////////////////////////////////////////////

#ifndef _MATRIX_ITERATIVE_OPTIMIZER_H_
#define _MATRIX_ITERATIVE_OPTIMIZER_H_

#include "optimization/DerivativeBasedOptimizer.h"
#include "optimization/GoldenCutLineSearcher.h"
//#include "optimization/BrentLineSearcher.h"
#include "optimization/ArmijoLineSearcher.h"

/*!
	abstract base class of all matrix iterative based optimizers.

	Methods like the newton iterative method or BFGS inherit from this class
 */
class MatrixIterativeOptimizer : public DerivativeBasedOptimizer
{
public:
		typedef  DerivativeBasedOptimizer	SuperClass;	
		typedef  SuperClass::matrix_type	matrix_type;	

	    /*!
			Constructor.
			\param numOfParameters : Number of parameters to optimize
			\param objectiveFunction : CostFunction*
			\param loger : OptLogBase * to existing log class
		*/
		MatrixIterativeOptimizer(OptLogBase *loger);

		/*!
			Copy constructor
			\param opt .. optimizer to copy
		*/
		MatrixIterativeOptimizer( const MatrixIterativeOptimizer &opt);


		/*!
			operator =
		*/
		MatrixIterativeOptimizer & operator=(const MatrixIterativeOptimizer &opt);


		/*!
				Destructor.
		 */
		virtual ~MatrixIterativeOptimizer();

		/*!
			\brief Set the initial step size
			The initial stepsize is used to give the optimizer an initial value for the order of 
			magnitude to start with.
			(e.g. step 100000 in x direction or 0.01 ?)
			\param stepSize with the step size for the i-th dimension in the (i,0)-th position.
		*/
		void setStepSize(const matrix_type & stepSize);
		

		/*!
			\brief to set options for the internal line searcher, get the access
		
		*/
		ArmijoLineSearcher * getLineSearcher(){return &m_lin;};

		/*!
			initialize
		*/
		void init();

		/*!
			optimize
		*/
		int optimize();

protected:
		

		/*!
			\brief update the Iteration Matrix
		*/
		virtual void updateIterationMatrix() = 0;

		/*!
			the iteration matrix
		*/
		matrix_type m_IterationMatrix;

		/*!
			\brief compute the descent direction
		*/
		void computeDescentDirection();
		
		/*!
			the descent direction
		*/
		matrix_type m_hk;

		/*!
			\brief compute the steplength
		*/
		void ComputeStepLength();


		/*!
			\brief reset the matrix
		*/
		void resetMatrix();

		/*!
			the steplength
		*/
		double m_lambdak;

		/*!
			1-dim search to optimize the steplength
		*/
		//GoldenCutLineSearcher m_lin;
		//BrentLineSearcher m_lin;
		ArmijoLineSearcher m_lin;
		
		/*!
			step size vector
		*/
		matrix_type m_stepSize;

		/*
			needed for updates
		*/
		matrix_type m_oldParams;

		/*
			needed for updates
		*/
		matrix_type m_oldGradient;

		//double m_lin_Lower;
		//double m_lin_Upper;
		//double m_lin_Eps;


		
};

#endif