/*************************************************************************
* Project: Library of Evolutionary Algoriths
*************************************************************************
* Author: Changhe Li & Ming Yang
* Email: changhe.lw@google.com Or yangming0702@gmail.com
* Language: C++
*************************************************************************
*  This file is part of EAlib. This library is free software;
*  you can redistribute it and/or modify it under the terms of the
*  GNU General Public License as published by the Free Software
*  Foundation; either version 2, or (at your option) any later version.
*************************************************************************/
// Created: 11 May 2011
// Last modified:


#ifndef PROBLEM_H
#define PROBLEM_H
#include <sstream>
#include "../ToolnDef/Global.h"
#include "../ToolnDef/StructDec.h"

extern  string gProName[],gAlgName[];
extern map<string, ProblemTag>gProblem;
extern map<string, AlgorithmTag>gAlgorithm;
extern bool **gAlgPro;


using namespace std;

class Problem{
    public:
        char ma_name[MAX_NAME_LENGTH+1];
        stringstream m_proPar;
     protected:
        /// problem ID
        int m_id;
        int m_dimNumber;

        Compare m_problemType;
        Encoding  m_encoding;
        ProCategory m_cat;

        //warning: take care this varibale, the memory will be allocate when the problem is instantiated
        void **m_searchRange;

        int m_evals;
		int m_objectives;
		int m_objIdx;				// current objective index
		double *mp_bestSoFar;						// TODU :here only for single objective problem
    public:
        Problem();
        Problem(const int rId, const int rDimNumber,const  Encoding rEncoding, const ProCategory rCat, char *rName=0);
        /// can not be instantiate
        virtual ~Problem()=0;

        Problem& operator=(const Problem & rP);

        int getId() const{
            return m_id;
        };
         int getDimNumber() const{
            return m_dimNumber;
        };
         Compare getProblemType() const{
            return m_problemType;
        };
         Encoding getEncoding() const{
            return  m_encoding;
        };
        ProCategory getProblemCat()const{
            return m_cat;
        };

         int getEvaluations() const{
            return m_evals;
        };
		int getObjIndex() const{
			return m_objIdx;
		}
		void setObjIndex(const int idx){
			m_objIdx=idx;
		}
		void setObjNumber(const int ObjNum){
			m_objectives=ObjNum;
		}
        void resetEvaluations(){
            m_evals=0;
        }
		double getBestSolutionSoFar(const int objIdx=0){
			
			return mp_bestSoFar[objIdx];
		}
        template<typename T>
        void setSearchRange(const T rLower, const T rUpper){
            for(int i=0;i<m_dimNumber;i++)
             ( (Boundary<T> *) m_searchRange[i])->setBoundary(rLower,rUpper);
        }
        template<typename T>
        void setSearchRange(const T *const rLower, const T * const rUpper){
            if(sizeof(rLower)/(sizeof(T))!=m_dimNumber||sizeof(rUpper)/(sizeof(T))!=m_dimNumber){
                Throw(Out_of_range("the number of dimensions must be ....."));
                exit(0);
            }
            for(int i=0;i<m_dimNumber;i++)     ( (Boundary<T> *) m_searchRange[i])->setBoundary(rLower[i],rUpper[i]);
        }
        template<typename T>
        void getSearchRange(T &rLower, T &rUpper, const int rD){
            rLower=((Boundary<T> *) m_searchRange[rD])->lower;

            rUpper=( (Boundary<T> *) m_searchRange[rD])->upper;
        }
        template<typename T>
        bool getBoundaryFlag(const int rD){
            return ((Boundary<T> *) m_searchRange[rD])->m_flag;
        }
        void setProblemType(const Compare rT){
            m_problemType=rT;
        }

		int getObjectives(){ return m_objectives;}
        virtual double evaluate( double const *s, bool rFlag=true ){return 0.;}
        virtual double evaluate( bool const  *s, bool rFlag=true ){return 0.;}
        virtual bool getObjGlobalOpt(double *rObj, int rNumObj=1){ return false;}
        virtual void reset(){}
    protected:
        virtual void  freeMemory();
        void allocateMemory(int const rDim);
		virtual void parameterSetting(Problem * rDP);

};

#endif // PROBLEM_H
