// Copyright (C) 2025 EDF
// All Rights Reserved
// This code is published under the GNU Lesser General Public License (GNU LGPL)
#ifndef OPTIMIZERDPCUTGRIDADAPTBASE_H
#define OPTIMIZERDPCUTGRIDADAPTBASE_H
#include <memory>
#include <Eigen/Dense>
#include "StOpt/core/utils/StateWithStocks.h"
#include "StOpt/core/grids/GridAdaptBase.h"
#include "StOpt/regression/BaseRegression.h"
#include "StOpt/regression/ContinuationCutsGridAdaptNonConcave.h"
#include "StOpt/dp/SimulatorDPBase.h"
#include "StOpt/dp/OptimizerBase.h"

/** \file OptimizerDPCutGridAdaptBase.h
 *  \brief Define an abstract class for Dynamic Programming problems solved by regression  methods using cust to approximate
 *         Bellman values
 *         Special version for stocks, concavity non supposed (it is imposed by mesh). Adaptation of the grid provided.
 *     \author Xavier Warin
 */

namespace StOpt
{

/// \class OptimizerDPCutGridAdaptBase OptimizerDPCutGridAdaptBase.h
///  Base class for optimizer for Dynamic Programming  with regression methods and cuts, so using LP to solve transitional problems
class OptimizerDPCutGridAdaptBase : public OptimizerBase
{


public :

    OptimizerDPCutGridAdaptBase() {}

    virtual ~OptimizerDPCutGridAdaptBase() {}

    /// \brief defines the dimension to split for MPI parallelism
    ///        For each dimension return true is the direction can be split
    virtual Eigen::Array< bool, Eigen::Dynamic, 1> getDimensionToSplit() const = 0 ;

    /// \brief defines a step in optimization
    /// \param p_stock     coordinates of the stock point to treat
    /// \param p_condEsp   continuation values 
    /// \return    For a given simulation , cuts components (C) at a point stock \$ \bar S \f$  are given such that the cut is given by
    ///            \f$  C[0] + \sum_{i=1}^d C[i] (S_i - \bat S_i)   \f$
    virtual Eigen::ArrayXd   stepOptimize(const Eigen::ArrayXd   &p_stock,  const StOpt::ContinuationCutsGridAdaptNonConcave  &p_condEsp) const = 0;


    /// \brief defines a step in simulation
    /// Control are recalculated during simulation using a local optimzation using the LP
    /// \param p_continuation  defines the continuation operator
    /// \param p_state         defines the state value (modified)
    /// \param p_phiInOut      defines the value functions (modified) : size number of functions  to follow
    virtual void stepSimulate(const StOpt::ContinuationCutsGridAdaptNonConcave   &p_continuation,
                              StOpt::StateWithStocks &p_state,
                              Eigen::Ref<Eigen::ArrayXd> p_phiInOut) const = 0 ;


    /// \brief define a refinement of the grid to get a given precision
    /// \param  p_gridToAdapt grid to be adapted
    /// \return True if a refinement has been achieved  in the grid   
    virtual  bool refineGrid( std::shared_ptr<GridAdaptBase> &  p_gridToAdapt, const  Eigen::ArrayXXd & pCuts ) =0;
    
    // virtual void setRefinementToFalse()=0;
  
    /// \brief get the simulator back
    virtual std::shared_ptr< StOpt::SimulatorDPBase > getSimulator() const = 0;

    /// \brief get back the dimension of the control
  virtual int getNbControl() const  { return 0;} 

    /// \brief get size of the  function to follow in simulation
    virtual int getSimuFuncSize() const = 0;

};
}
#endif /* OPTIMIZERDPCUTBASE_H */
