#include "Chromosome.h"
#include "../PerformanceMeasure/PerformSingleObj.h"
#include "../Problems/DOPs/BinaryDOP.h"
unsigned int Chromosome::ms_objNumbers=1;
SolutionValidation Chromosome::ms_validationMode=VALIDATION_REMAP;
Chromosome::Chromosome():mc_length(Global::g_dimNumber){

    mp_gene=new Gene[mc_length];

    switch(Global::gp_problem->getId()){
    case Sphere: case Sphere_Noisy: case S_Sphere: case R_Sphere: case RS_Sphere: case S_Sphere_CEC05: case Sphere_Noisy_CEC05:
               case Rastrigin: case Rastrigin_Noisy: case S_Rastrigin: case R_Rastrigin: case RS_Rastrigin: case S_Rastrigin_CEC05: case RS_Rastrigin_CEC05:
               case Weierstrass: case RS_Weierstrass: case R_Weierstrass: case RS_Weierstrass_CEC05:
               case Griewank: case R_Griewank: case RS_Griewank:  case RS_Griewank_noBounds_CEC05: case Griewank_Rosenbrock_F13_CEC05: case S_Griewank_Rosenbrock_F13_CEC05:
               case Ackley: case Ackley_Noisy: case S_Ackley: case R_Ackley: case RS_Ackley: case RS_Ackley_Bound_CEC05:
               case Step:
               case Quartic_Noisy:
               case Scaffer_F6:  case Expanded_Scaffer_F6_CEC05: case Noncont_Expanded_Scaffer_F6_CEC05: case RS_Expanded_Scaffer_F6_CEC05:
               case Rosenbrock: case S_Rosenbrock: case S_Rosenbrock_CEC05:
               case Schwefel_2_13_CEC05:
               case Schwefel_2_22: case Schwefel_2_22_Noisy: case S_Schwefel_2_22: case R_Schwefel_2_22: case RS_Schwefel_2_22:
               case Schwefel: case Schwefel_Noisy: case S_Schwefel: case R_Schwefel: case RS_Schwefel:
               case Schwefel_1_2: case Schwefel_1_2_Noisy: case S_Schwefel_1_2: case S_Schwefel_1_2_Noisy: case R_Schwefel_1_2: case RS_Schwefel_1_2:  case S_Schwefel_1_2_CEC05:  case S_Schwefel_1_2_Noisy_CEC05:
               case Schwefel_2_21:
               case Schwefel_2_6_Bound_CEC05:
               case Penalized_1:
               case Penalized_2:
               case Noncont_Rastrigin:
               case RS_Elliptic_CEC05: case Elliptic:
               case Com: case R_Com: case Com_CEC05: case H_Com_CEC05: case H_Com_Noisy_CEC05:
               case RH_Com_CEC05: case RH_Com_NarrowBasin_CEC05: case RH_Com_Bound_CEC05:
               case RH_Com_F21_CEC05:  case RH_Com_HighConNumMatrix_F22_CEC05:  case Noncont_RH_Com_F23_CEC05:  case RH_Com_F24_CEC05:  case RH_Com_noBounds_F25_CEC05:
               case M_global1: case M_global2: case M_global3: case M_global4: case M_global5:
               case S_Sphere_CEC08: case Schwefel_2_21_CEC08: case S_Rosenbrock_CEC08: case S_Rastrigin_CEC08: case S_Griewank_CEC08: case S_Ackley_CEC08:
               case RW_Gear_Train: case RW_ParEst_FMSoundWaves:
    ///Dynamic Problems
    case CompositionDBG_DOP: case RotationDBG_DOP: case MovingPeak_DOP: case DF1_DOP:

        for(unsigned int i=0;i<mc_length;i++){
            mp_gene[i].m_length=1;
            mp_gene[i].m_coding=C_DECIMAL;
        }

        break;
    case Binary_DOP:
        for(unsigned int i=0;i<mc_length;i++){
            mp_gene[i].m_length=dynamic_cast<BinaryDOP*>(Global::gp_problem)->getLength();
            mp_gene[i].m_coding=C_BINARY;
        }
        break;
    }

    allocateMemory(mp_gene,mc_length);
    mp_obj=new double[Chromosome::ms_objNumbers];

}
Chromosome::~Chromosome(){
    freeMemory();
    delete [] mp_obj;
    delete [] mp_gene;
}
Chromosome::Chromosome(const Chromosome & chr):mc_length(chr.mc_length){
	
    mp_gene=new Gene[mc_length];

    switch(Global::gp_problem->getId()){
        case Sphere: case Sphere_Noisy: case S_Sphere: case R_Sphere: case RS_Sphere: case S_Sphere_CEC05: case Sphere_Noisy_CEC05:
               case Rastrigin: case Rastrigin_Noisy: case S_Rastrigin: case R_Rastrigin: case RS_Rastrigin: case S_Rastrigin_CEC05: case RS_Rastrigin_CEC05:
               case Weierstrass: case RS_Weierstrass: case R_Weierstrass: case RS_Weierstrass_CEC05:
               case Griewank: case R_Griewank: case RS_Griewank:  case RS_Griewank_noBounds_CEC05: case Griewank_Rosenbrock_F13_CEC05: case S_Griewank_Rosenbrock_F13_CEC05:
               case Ackley: case Ackley_Noisy: case S_Ackley: case R_Ackley: case RS_Ackley: case RS_Ackley_Bound_CEC05:
               case Step:
               case Quartic_Noisy:
               case Scaffer_F6:  case Expanded_Scaffer_F6_CEC05: case Noncont_Expanded_Scaffer_F6_CEC05: case RS_Expanded_Scaffer_F6_CEC05:
               case Rosenbrock: case S_Rosenbrock: case S_Rosenbrock_CEC05:
               case Schwefel_2_13_CEC05:
               case Schwefel_2_22: case Schwefel_2_22_Noisy: case S_Schwefel_2_22: case R_Schwefel_2_22: case RS_Schwefel_2_22:
               case Schwefel: case Schwefel_Noisy: case S_Schwefel: case R_Schwefel: case RS_Schwefel:
               case Schwefel_1_2: case Schwefel_1_2_Noisy: case S_Schwefel_1_2: case S_Schwefel_1_2_Noisy: case R_Schwefel_1_2: case RS_Schwefel_1_2:  case S_Schwefel_1_2_CEC05:  case S_Schwefel_1_2_Noisy_CEC05:
               case Schwefel_2_21:
               case Schwefel_2_6_Bound_CEC05:
               case Penalized_1:
               case Penalized_2:
               case Noncont_Rastrigin:
               case RS_Elliptic_CEC05: case Elliptic:
               case Com: case R_Com: case Com_CEC05: case H_Com_CEC05: case H_Com_Noisy_CEC05:
               case RH_Com_CEC05: case RH_Com_NarrowBasin_CEC05: case RH_Com_Bound_CEC05:
               case RH_Com_F21_CEC05:  case RH_Com_HighConNumMatrix_F22_CEC05:  case Noncont_RH_Com_F23_CEC05:  case RH_Com_F24_CEC05:  case RH_Com_noBounds_F25_CEC05:
               case M_global1: case M_global2: case M_global3: case M_global4: case M_global5:
               case S_Sphere_CEC08: case Schwefel_2_21_CEC08: case S_Rosenbrock_CEC08: case S_Rastrigin_CEC08: case S_Griewank_CEC08: case S_Ackley_CEC08:
               case RW_Gear_Train: case RW_ParEst_FMSoundWaves:
    ///Dynamic Problems
    case CompositionDBG_DOP: case RotationDBG_DOP: case MovingPeak_DOP: case DF1_DOP:

        for(unsigned int i=0;i<mc_length;i++){
            mp_gene[i].m_length=1;
            mp_gene[i].m_coding=C_DECIMAL;
        }

        break;
    case Binary_DOP:
        for(unsigned int i=0;i<mc_length;i++){
            mp_gene[i].m_length=dynamic_cast<BinaryDOP*>(Global::gp_problem)->getLength();
            mp_gene[i].m_coding=C_BINARY;
        }
        break;
    }

    allocateMemory(mp_gene,mc_length);
    mp_obj=new double[Chromosome::ms_objNumbers];
	
	Chromosome &rhs=const_cast<Chromosome&>(chr);

	(*this).operator=(rhs);

}
/*Chromosome::Chromosome(Chromosome & chr){

}*/
void Chromosome::allocateMemory(Gene * rGene, const int rLength){

    for( int i=0;i<rLength;i++){
            switch( rGene[i].m_coding){
                case C_DECIMAL:
                    rGene[i].mp_value=new double[rGene[i].m_length];
                    break;
                case C_BINARY:
                    rGene[i].mp_value=new bool[rGene[i].m_length];
                    break;
                case C_INTEGER:
                    rGene[i].mp_value=new int[rGene[i].m_length];
                    break;
                case C_STRING:
                    rGene[i].mp_value=new char[rGene[i].m_length];
                    break;
                case C_UNSER_DEFINED:
                ///TO DO
                //rGene[i].mp_value=new UNSER_DEFINED[rGene[i].m_length];
                    break;
            }

    }

}

void Chromosome::freeMemory(){

    for(unsigned int i=0;i<mc_length;i++){
            switch( mp_gene[i].m_coding){
                case C_DECIMAL:
                    delete [] (double *) mp_gene[i].mp_value;
                    break;
                case C_BINARY:
                    delete [] (bool *) mp_gene[i].mp_value;
                    break;
                case C_INTEGER:
                    delete [] (int *) mp_gene[i].mp_value;
                    break;
                case C_STRING:
                    delete [] (char *) mp_gene[i].mp_value;
                    break;
                case C_UNSER_DEFINED:
                ///TO DO
                //delete [] (UNSER_DEFINED *) mp_gene[i].mp_value;
                    break;
            }

    }


}


void Chromosome::evaluate(const bool rFlag){

    switch(Global::gp_problem->getId()){
          case Sphere: case Sphere_Noisy: case S_Sphere: case R_Sphere: case RS_Sphere: case S_Sphere_CEC05: case Sphere_Noisy_CEC05:
               case Rastrigin: case Rastrigin_Noisy: case S_Rastrigin: case R_Rastrigin: case RS_Rastrigin: case S_Rastrigin_CEC05: case RS_Rastrigin_CEC05:
               case Weierstrass: case RS_Weierstrass: case R_Weierstrass: case RS_Weierstrass_CEC05:
               case Griewank: case R_Griewank: case RS_Griewank:  case RS_Griewank_noBounds_CEC05: case Griewank_Rosenbrock_F13_CEC05: case S_Griewank_Rosenbrock_F13_CEC05:
               case Ackley: case Ackley_Noisy: case S_Ackley: case R_Ackley: case RS_Ackley: case RS_Ackley_Bound_CEC05:
               case Step:
               case Quartic_Noisy:
               case Scaffer_F6:  case Expanded_Scaffer_F6_CEC05: case Noncont_Expanded_Scaffer_F6_CEC05: case RS_Expanded_Scaffer_F6_CEC05:
               case Rosenbrock: case S_Rosenbrock: case S_Rosenbrock_CEC05:
               case Schwefel_2_13_CEC05:
               case Schwefel_2_22: case Schwefel_2_22_Noisy: case S_Schwefel_2_22: case R_Schwefel_2_22: case RS_Schwefel_2_22:
               case Schwefel: case Schwefel_Noisy: case S_Schwefel: case R_Schwefel: case RS_Schwefel:
               case Schwefel_1_2: case Schwefel_1_2_Noisy: case S_Schwefel_1_2: case S_Schwefel_1_2_Noisy: case R_Schwefel_1_2: case RS_Schwefel_1_2:  case S_Schwefel_1_2_CEC05:  case S_Schwefel_1_2_Noisy_CEC05:
               case Schwefel_2_21:
               case Schwefel_2_6_Bound_CEC05:
               case Penalized_1:
               case Penalized_2:
               case Noncont_Rastrigin:
               case RS_Elliptic_CEC05: case Elliptic:
               case Com: case R_Com: case Com_CEC05: case H_Com_CEC05: case H_Com_Noisy_CEC05:
               case RH_Com_CEC05: case RH_Com_NarrowBasin_CEC05: case RH_Com_Bound_CEC05:
               case RH_Com_F21_CEC05:  case RH_Com_HighConNumMatrix_F22_CEC05:  case Noncont_RH_Com_F23_CEC05:  case RH_Com_F24_CEC05:  case RH_Com_noBounds_F25_CEC05:
               case M_global1: case M_global2: case M_global3: case M_global4: case M_global5:
               case S_Sphere_CEC08: case Schwefel_2_21_CEC08: case S_Rosenbrock_CEC08: case S_Rastrigin_CEC08: case S_Griewank_CEC08: case S_Ackley_CEC08:
               case RW_Gear_Train: case RW_ParEst_FMSoundWaves:
    ///Dynamic Problems
    case CompositionDBG_DOP: case RotationDBG_DOP: case MovingPeak_DOP: case DF1_DOP:{


            double *s=new double[mc_length];
            for(unsigned int i=0;i<mc_length;i++) s[i]=((double*) mp_gene[i].mp_value)[0];

            mp_obj[0]= Global::gp_problem->evaluate(s,rFlag);

#ifdef EALIB
            PerformSingleObj::getPerformSingleObj()->record(mp_obj[0],rFlag);
#endif
            delete [] s;

            break;
        }
        case Binary_DOP:{
            bool *s=new bool[mc_length];
            for(unsigned int i=0;i<mc_length;i++) s[i]=((bool*) mp_gene[i].mp_value)[0];

            mp_obj[0]= Global::gp_problem->evaluate(s,rFlag);
			#ifdef EALIB
            PerformSingleObj::getPerformSingleObj()->record(mp_obj[0],rFlag);
			#endif

            delete [] s;

            break;
        }
    }
}
void Chromosome::initialize(const bool mode,PopInitMethod rMethod,const int rIndex, const int rSize){
    switch(Global::gp_problem->getId()){
            case Sphere: case Sphere_Noisy: case S_Sphere: case R_Sphere: case RS_Sphere: case S_Sphere_CEC05: case Sphere_Noisy_CEC05:
               case Rastrigin: case Rastrigin_Noisy: case S_Rastrigin: case R_Rastrigin: case RS_Rastrigin: case S_Rastrigin_CEC05: case RS_Rastrigin_CEC05:
               case Weierstrass: case RS_Weierstrass: case R_Weierstrass: case RS_Weierstrass_CEC05:
               case Griewank: case R_Griewank: case RS_Griewank:  case RS_Griewank_noBounds_CEC05: case Griewank_Rosenbrock_F13_CEC05: case S_Griewank_Rosenbrock_F13_CEC05:
               case Ackley: case Ackley_Noisy: case S_Ackley: case R_Ackley: case RS_Ackley: case RS_Ackley_Bound_CEC05:
               case Step:
               case Quartic_Noisy:
               case Scaffer_F6:  case Expanded_Scaffer_F6_CEC05: case Noncont_Expanded_Scaffer_F6_CEC05: case RS_Expanded_Scaffer_F6_CEC05:
               case Rosenbrock: case S_Rosenbrock: case S_Rosenbrock_CEC05:
               case Schwefel_2_13_CEC05:
               case Schwefel_2_22: case Schwefel_2_22_Noisy: case S_Schwefel_2_22: case R_Schwefel_2_22: case RS_Schwefel_2_22:
               case Schwefel: case Schwefel_Noisy: case S_Schwefel: case R_Schwefel: case RS_Schwefel:
               case Schwefel_1_2: case Schwefel_1_2_Noisy: case S_Schwefel_1_2: case S_Schwefel_1_2_Noisy: case R_Schwefel_1_2: case RS_Schwefel_1_2:  case S_Schwefel_1_2_CEC05:  case S_Schwefel_1_2_Noisy_CEC05:
               case Schwefel_2_21:
               case Schwefel_2_6_Bound_CEC05:
               case Penalized_1:
               case Penalized_2:
               case Noncont_Rastrigin:
               case RS_Elliptic_CEC05: case Elliptic:
               case Com: case R_Com: case Com_CEC05: case H_Com_CEC05: case H_Com_Noisy_CEC05:
               case RH_Com_CEC05: case RH_Com_NarrowBasin_CEC05: case RH_Com_Bound_CEC05:
               case RH_Com_F21_CEC05:  case RH_Com_HighConNumMatrix_F22_CEC05:  case Noncont_RH_Com_F23_CEC05:  case RH_Com_F24_CEC05:  case RH_Com_noBounds_F25_CEC05:
               case M_global1: case M_global2: case M_global3: case M_global4: case M_global5:
               case S_Sphere_CEC08: case Schwefel_2_21_CEC08: case S_Rosenbrock_CEC08: case S_Rastrigin_CEC08: case S_Griewank_CEC08: case S_Ackley_CEC08:
               case RW_Gear_Train: case RW_ParEst_FMSoundWaves:
    ///Dynamic Problems
    case CompositionDBG_DOP: case RotationDBG_DOP: case MovingPeak_DOP: case DF1_DOP:
            switch(rMethod){
                case POP_INIT_UNIFORM:{
                    //uniformly distributed in the entire search space
                    double l,u;
                    for(unsigned int i=0;i<mc_length;i++){
                        Global::gp_problem->getSearchRange<double>(l,u,i);
                        this->operator[]<double>(i)[0]= l+(u-l)*Global::gp_uniformAlg->Next();
                    }

                    }
                    break;
                case POP_INIT_ORTHONORM:
                    // orthonomalization method
                    {///warning: need to be checked for verification
                        double l,u;
                        for(unsigned int i=0;i<mc_length;i++){
                            Global::gp_problem->getSearchRange<double>(l,u,i);
                            if(rIndex==0){
                                this->operator[]<double>(i)[0]= l;
                            }else if(rIndex<rSize-1){
                                 this->operator[]<double>(i)[0]= l+rIndex*((u-l)/(rSize-1));
                            }else{
                                 this->operator[]<double>(i)[0]= u;
                            }

                        }

                    }

                    break;
                case POP_INIT_CENTER:
                    // nomarlly distributed in the center of the search space with variance of half domain
                    {
                        double l,u;
                        for(unsigned int i=0;i<mc_length;i++){
                        Global::gp_problem->getSearchRange<double>(l,u,i);
                        this->operator[]<double>(i)[0]= (l+u)/2+Global::gp_normalAlg->NextNonStand(0,(u-l)/2);
                    }

                    }
                    break;
                case POP_INIT_USER_DEFINED:
                ///TO DO
                    break;
            }

            break;
        case Binary_DOP:
            for(unsigned int i=0;i<mc_length;i++){
                  operator[]<bool>(i)[0]= Global::gp_uniformAlg->Next()>=0.5?1:0;
            }
            break;
    }

    evaluate(mode);
}

Chromosome& Chromosome::operator=( Chromosome& rhs){
    if (this == &rhs) return *this; // handle self assignment

    if(mc_length!=rhs.mc_length){
        Throw(Invalid_argument("Dimensions should be the same with the two Chromosome"));
        exit(0);
    }

    // In case of dimensional change
    //int dim=mc_length<rhs.mc_length?mc_length:rhs.mc_length;


    for(unsigned int i=0;i<mc_length;i++){
        switch(mp_gene[i].m_coding){
            case C_DECIMAL:
                for(unsigned int j=0;j<mp_gene[i].m_length;j++)   getGene<double>(i,j) = rhs.getGene<double>(i,j);
                break;
            case C_BINARY:
                for(unsigned int j=0;j<mp_gene[i].m_length;j++)  getGene<bool>(i,j) =rhs.getGene<bool>(i,j);
                break;
            case C_INTEGER:
                for(unsigned int j=0;j<mp_gene[i].m_length;j++)  getGene<int>(i,j) =rhs.getGene<int>(i,j);
                break;
            case C_STRING:
                for(unsigned int j=0;j<mp_gene[i].m_length;j++)  getGene<char>(i,j) =rhs.getGene<char>(i,j);
                break;
            case C_UNSER_DEFINED:
            ///TO DO
               // for(unsigned int j=0;j<mp_gene[i].m_length;j++) getGene<undefined>(i,j) =rhs.getGene<undefined>(i,j);
                break;
        }
    }
    //if(mc_length==rhs.mc_length)
    gCopy(mp_obj,rhs.mp_obj,ms_objNumbers);

    return *this;
}

//better than or equal to p
bool Chromosome::operator>=(const Chromosome &p){
bool flag=true;
for(unsigned int i=0;i<ms_objNumbers;i++){
    if(Global::gp_problem->getProblemType()==MIN_OPT){
        if(mp_obj[i]>p.mp_obj[i]) {
            flag=false;
            break;
        }
    }else{
        if(mp_obj[i]<p.mp_obj[i]) {
            flag=false;
            break;
        }

    }
}

return flag;

}
//worse than or equal to p
bool Chromosome::operator<=(const Chromosome &p){
bool flag=true;
for(unsigned int i=0;i<ms_objNumbers;i++){
    if(Global::gp_problem->getProblemType()==MIN_OPT){
        if(mp_obj[i]<p.mp_obj[i]) {
            flag=false;
            break;
        }
    }else{
        if(mp_obj[i]>p.mp_obj[i]) {
            flag=false;
            break;
        }

    }
}

return flag;
}
//equal to p


//better than p
bool Chromosome::operator>(const Chromosome &p){
 bool flag=true;
for(unsigned int i=0;i<ms_objNumbers;i++){
    if(Global::gp_problem->getProblemType()==MIN_OPT){
        if(mp_obj[i]>=p.mp_obj[i]) {
            flag=false;
            break;
        }
    }else{
        if(mp_obj[i]<=p.mp_obj[i]) {
            flag=false;
            break;
        }

    }
}

return flag;
}
bool Chromosome::operator>(const double obj){
    bool flag=true;

    if(Global::gp_problem->getProblemType()==MIN_OPT){
        if(mp_obj[0]>=obj) {
            flag=false;
        }
    }else{
        if(mp_obj[0]<=obj) {
            flag=false;
        }

    }
    return flag;
}
bool Chromosome::operator>(const double *obj){
    bool flag=true;
    for(unsigned int i=0;i<ms_objNumbers;i++){
    if(Global::gp_problem->getProblemType()==MIN_OPT){
        if(mp_obj[i]>=mp_obj[i]) {
            flag=false;
            break;
        }
    }else{
        if(mp_obj[i]<=mp_obj[i]) {
            flag=false;
            break;
        }

    }
    }


return flag;
}

bool Chromosome::operator<(const Chromosome &p){
 bool flag=true;
for(unsigned int i=0;i<ms_objNumbers;i++){
    if(Global::gp_problem->getProblemType()==MIN_OPT){
        if(mp_obj[i]<=p.mp_obj[i]) {
            flag=false;
            break;
        }
    }else{
        if(mp_obj[i]>=p.mp_obj[i]) {
            flag=false;
            break;
        }

    }
}

return flag;
}


bool Chromosome::operator==(Chromosome &rhs){
    bool flag=true;
    for(unsigned int i=0;i<mc_length;i++){

                switch(mp_gene[i].m_coding){
            case C_DECIMAL:
                for(unsigned int j=0;j<mp_gene[i].m_length;j++)
                    if(getGene<double>(i,j)!=rhs.getGene<double>(i,j)){
                        flag=false;
                        break;
                    }
                break;
            case C_BINARY:
                for(unsigned int j=0;j<mp_gene[i].m_length;j++)
                    if(getGene<bool>(i,j)!=rhs.getGene<bool>(i,j)){
                        flag=false;
                        break;
                    }

                break;
            case C_INTEGER:
                for(unsigned int j=0;j<mp_gene[i].m_length;j++)
                    if(getGene<int>(i,j)!=rhs.getGene<int>(i,j)){
                        flag=false;
                        break;
                    }
                break;
            case C_STRING:
                for(unsigned int j=0;j<mp_gene[i].m_length;j++)
                if(getGene<char>(i,j)!=rhs.getGene<char>(i,j)){
                        flag=false;
                        break;
                    }
                break;
            case C_UNSER_DEFINED:
            ///TO DO
               /* for(unsigned int j=0;j<mp_gene[i].m_length;j++)
                    if(getGene<undefined>(i,j)!=rhs.getGene<undefined>(i,j)){
                        flag=false;
                        break;
                    }
                    */
                break;
        }
        if(flag==false) break;
    }
    return flag;
}

bool Chromosome::operator!=( Chromosome &p){
    return !operator==(p);
}
double Chromosome::getObj(int const i){
    return mp_obj[i];
}

bool Chromosome::isValid(){
    bool flag=true;

    switch(Global::gp_problem->getId()){
            case Sphere: case Sphere_Noisy: case S_Sphere: case R_Sphere: case RS_Sphere: case S_Sphere_CEC05: case Sphere_Noisy_CEC05:
               case Rastrigin: case Rastrigin_Noisy: case S_Rastrigin: case R_Rastrigin: case RS_Rastrigin: case S_Rastrigin_CEC05: case RS_Rastrigin_CEC05:
               case Weierstrass: case RS_Weierstrass: case R_Weierstrass: case RS_Weierstrass_CEC05:
               case Griewank: case R_Griewank: case RS_Griewank:  case RS_Griewank_noBounds_CEC05: case Griewank_Rosenbrock_F13_CEC05: case S_Griewank_Rosenbrock_F13_CEC05:
               case Ackley: case Ackley_Noisy: case S_Ackley: case R_Ackley: case RS_Ackley: case RS_Ackley_Bound_CEC05:
               case Step:
               case Quartic_Noisy:
               case Scaffer_F6:  case Expanded_Scaffer_F6_CEC05: case Noncont_Expanded_Scaffer_F6_CEC05: case RS_Expanded_Scaffer_F6_CEC05:
               case Rosenbrock: case S_Rosenbrock: case S_Rosenbrock_CEC05:
               case Schwefel_2_13_CEC05:
               case Schwefel_2_22: case Schwefel_2_22_Noisy: case S_Schwefel_2_22: case R_Schwefel_2_22: case RS_Schwefel_2_22:
               case Schwefel: case Schwefel_Noisy: case S_Schwefel: case R_Schwefel: case RS_Schwefel:
               case Schwefel_1_2: case Schwefel_1_2_Noisy: case S_Schwefel_1_2: case S_Schwefel_1_2_Noisy: case R_Schwefel_1_2: case RS_Schwefel_1_2:  case S_Schwefel_1_2_CEC05:  case S_Schwefel_1_2_Noisy_CEC05:
               case Schwefel_2_21:
               case Schwefel_2_6_Bound_CEC05:
               case Penalized_1:
               case Penalized_2:
               case Noncont_Rastrigin:
               case RS_Elliptic_CEC05: case Elliptic:
               case Com: case R_Com: case Com_CEC05: case H_Com_CEC05: case H_Com_Noisy_CEC05:
               case RH_Com_CEC05: case RH_Com_NarrowBasin_CEC05: case RH_Com_Bound_CEC05:
               case RH_Com_F21_CEC05:  case RH_Com_HighConNumMatrix_F22_CEC05:  case Noncont_RH_Com_F23_CEC05:  case RH_Com_F24_CEC05:  case RH_Com_noBounds_F25_CEC05:
               case M_global1: case M_global2: case M_global3: case M_global4: case M_global5:
               case S_Sphere_CEC08: case Schwefel_2_21_CEC08: case S_Rosenbrock_CEC08: case S_Rastrigin_CEC08: case S_Griewank_CEC08: case S_Ackley_CEC08:
               case RW_Gear_Train: case RW_ParEst_FMSoundWaves:
    ///Dynamic Problems
    case CompositionDBG_DOP: case RotationDBG_DOP: case MovingPeak_DOP: case DF1_DOP:
            double l,u;
            for(unsigned int i=0;i<mc_length;i++){
                Global::gp_problem->getSearchRange<double>(l,u,i);
                if(getGene<double>(i,0)<l||getGene<double>(i,0)>u){
                    flag=false;
                    break;
                }
            }
            break;
        case Binary_DOP:
              for(unsigned int i=0;i<mc_length;i++){
                if(getGene<bool>(i,0)!=0&&getGene<bool>(i,0)!=1){
                    flag=false;
                    break;
                }
            }
            break;
    }

    return flag;

}

double Chromosome::getDistance( Chromosome & rhs,DistanceMode mode){//,int dim=0
    double dis=0;

    switch(mode){
        case DIS_EUCLIDEAN:
            for(unsigned int i=0;i<mc_length;i++){
				double x1,x2;
				x1=getGene<double>(i,0);
				x2=rhs.getGene<double>(i,0);
				dis+=(x1-x2)*(x1-x2);
                //dis+=(getGene<double>(i,0)-rhs.getGene<double>(i,0))*(getGene<double>(i,0)-rhs.getGene<double>(i,0));
            }
            dis= sqrt(dis);
            break;
        case DIS_MANHATTAN:
            for(unsigned int i=0;i<mc_length;i++){
                dis+=fabs(getGene<double>(i,0)-rhs.getGene<double>(i,0));
            }
            break;
        case DIS_HAMMING:
            for(unsigned int i=0;i<mc_length;i++){
                if(getGene<bool>(i,0)!=rhs.getGene<bool>(i,0)){
                    dis+=1;
                }
            }
            break;

    }

    return dis;

}
double Chromosome::getDistance(double * loc){
    double dis=0;
     for(unsigned int i=0;i<mc_length;i++){
        dis+=(getGene<double>(i,0)-loc[i])*(getGene<double>(i,0)-loc[i]);
    }
    dis= sqrt(dis);
 return dis;
}

 void Chromosome::increaseDimension(){

      Gene  *p_gene=new Gene[mc_length+1];
       for(unsigned int i=0;i<mc_length;i++){
                p_gene[i].m_coding=mp_gene[i].m_coding;
                p_gene[i].m_length=mp_gene[i].m_length;
        }

     switch(Global::gp_problem->getId()){
            case Sphere: case Sphere_Noisy: case S_Sphere: case R_Sphere: case RS_Sphere: case S_Sphere_CEC05: case Sphere_Noisy_CEC05:
               case Rastrigin: case Rastrigin_Noisy: case S_Rastrigin: case R_Rastrigin: case RS_Rastrigin: case S_Rastrigin_CEC05: case RS_Rastrigin_CEC05:
               case Weierstrass: case RS_Weierstrass: case R_Weierstrass: case RS_Weierstrass_CEC05:
               case Griewank: case R_Griewank: case RS_Griewank:  case RS_Griewank_noBounds_CEC05: case Griewank_Rosenbrock_F13_CEC05: case S_Griewank_Rosenbrock_F13_CEC05:
               case Ackley: case Ackley_Noisy: case S_Ackley: case R_Ackley: case RS_Ackley: case RS_Ackley_Bound_CEC05:
               case Step:
               case Quartic_Noisy:
               case Scaffer_F6:  case Expanded_Scaffer_F6_CEC05: case Noncont_Expanded_Scaffer_F6_CEC05: case RS_Expanded_Scaffer_F6_CEC05:
               case Rosenbrock: case S_Rosenbrock: case S_Rosenbrock_CEC05:
               case Schwefel_2_13_CEC05:
               case Schwefel_2_22: case Schwefel_2_22_Noisy: case S_Schwefel_2_22: case R_Schwefel_2_22: case RS_Schwefel_2_22:
               case Schwefel: case Schwefel_Noisy: case S_Schwefel: case R_Schwefel: case RS_Schwefel:
               case Schwefel_1_2: case Schwefel_1_2_Noisy: case S_Schwefel_1_2: case S_Schwefel_1_2_Noisy: case R_Schwefel_1_2: case RS_Schwefel_1_2:  case S_Schwefel_1_2_CEC05:  case S_Schwefel_1_2_Noisy_CEC05:
               case Schwefel_2_21:
               case Schwefel_2_6_Bound_CEC05:
               case Penalized_1:
               case Penalized_2:
               case Noncont_Rastrigin:
               case RS_Elliptic_CEC05: case Elliptic:
               case Com: case R_Com: case Com_CEC05: case H_Com_CEC05: case H_Com_Noisy_CEC05:
               case RH_Com_CEC05: case RH_Com_NarrowBasin_CEC05: case RH_Com_Bound_CEC05:
               case RH_Com_F21_CEC05:  case RH_Com_HighConNumMatrix_F22_CEC05:  case Noncont_RH_Com_F23_CEC05:  case RH_Com_F24_CEC05:  case RH_Com_noBounds_F25_CEC05:
               case M_global1: case M_global2: case M_global3: case M_global4: case M_global5:
               case S_Sphere_CEC08: case Schwefel_2_21_CEC08: case S_Rosenbrock_CEC08: case S_Rastrigin_CEC08: case S_Griewank_CEC08: case S_Ackley_CEC08:
               case RW_Gear_Train: case RW_ParEst_FMSoundWaves:
    ///Dynamic Problems
    case CompositionDBG_DOP: case RotationDBG_DOP: case MovingPeak_DOP: case DF1_DOP:

            p_gene[mc_length].m_coding=C_DECIMAL;
            p_gene[mc_length].m_length=1;

            allocateMemory(p_gene,mc_length+1);

            for(unsigned int i=0;i<mc_length;i++){
                ((double *) p_gene[i].mp_value)[0]=getGene<double>(i);
            }

            double l,u;
            Global::gp_problem->getSearchRange<double>(l,u,mc_length);
            ((double *) p_gene[mc_length].mp_value)[0]=l+(u-l)*Global::gp_uniformAlg->Next();

            freeMemory();
			delete [] mp_gene;
            mp_gene=p_gene;

            break;
        case Binary_DOP:
            p_gene[mc_length].m_coding=C_BINARY;
            p_gene[mc_length].m_length=1;

            allocateMemory(p_gene,mc_length+1);

            for(unsigned int i=0;i<mc_length;i++){
                ((bool *) p_gene[i].mp_value)[0]=getGene<bool>(i);
            }


            ((double *) p_gene[mc_length].mp_value)[0]=Global::gp_uniformAlg->Next()>=0.5?1:0;

            freeMemory();
			delete [] mp_gene;
            mp_gene=p_gene;

            break;
    }
        mc_length++;
        evaluate(false);

}
void Chromosome::decreaseDimension(){

      Gene  *p_gene=new Gene[mc_length-1];
       for(unsigned int i=0;i<mc_length-1;i++){
                p_gene[i].m_coding=mp_gene[i].m_coding;
                p_gene[i].m_length=mp_gene[i].m_length;
        }


     switch(Global::gp_problem->getId()){
           case Sphere: case Sphere_Noisy: case S_Sphere: case R_Sphere: case RS_Sphere: case S_Sphere_CEC05: case Sphere_Noisy_CEC05:
               case Rastrigin: case Rastrigin_Noisy: case S_Rastrigin: case R_Rastrigin: case RS_Rastrigin: case S_Rastrigin_CEC05: case RS_Rastrigin_CEC05:
               case Weierstrass: case RS_Weierstrass: case R_Weierstrass: case RS_Weierstrass_CEC05:
               case Griewank: case R_Griewank: case RS_Griewank:  case RS_Griewank_noBounds_CEC05: case Griewank_Rosenbrock_F13_CEC05: case S_Griewank_Rosenbrock_F13_CEC05:
               case Ackley: case Ackley_Noisy: case S_Ackley: case R_Ackley: case RS_Ackley: case RS_Ackley_Bound_CEC05:
               case Step:
               case Quartic_Noisy:
               case Scaffer_F6:  case Expanded_Scaffer_F6_CEC05: case Noncont_Expanded_Scaffer_F6_CEC05: case RS_Expanded_Scaffer_F6_CEC05:
               case Rosenbrock: case S_Rosenbrock: case S_Rosenbrock_CEC05:
               case Schwefel_2_13_CEC05:
               case Schwefel_2_22: case Schwefel_2_22_Noisy: case S_Schwefel_2_22: case R_Schwefel_2_22: case RS_Schwefel_2_22:
               case Schwefel: case Schwefel_Noisy: case S_Schwefel: case R_Schwefel: case RS_Schwefel:
               case Schwefel_1_2: case Schwefel_1_2_Noisy: case S_Schwefel_1_2: case S_Schwefel_1_2_Noisy: case R_Schwefel_1_2: case RS_Schwefel_1_2:  case S_Schwefel_1_2_CEC05:  case S_Schwefel_1_2_Noisy_CEC05:
               case Schwefel_2_21:
               case Schwefel_2_6_Bound_CEC05:
               case Penalized_1:
               case Penalized_2:
               case Noncont_Rastrigin:
               case RS_Elliptic_CEC05: case Elliptic:
               case Com: case R_Com: case Com_CEC05: case H_Com_CEC05: case H_Com_Noisy_CEC05:
               case RH_Com_CEC05: case RH_Com_NarrowBasin_CEC05: case RH_Com_Bound_CEC05:
               case RH_Com_F21_CEC05:  case RH_Com_HighConNumMatrix_F22_CEC05:  case Noncont_RH_Com_F23_CEC05:  case RH_Com_F24_CEC05:  case RH_Com_noBounds_F25_CEC05:
               case M_global1: case M_global2: case M_global3: case M_global4: case M_global5:
               case S_Sphere_CEC08: case Schwefel_2_21_CEC08: case S_Rosenbrock_CEC08: case S_Rastrigin_CEC08: case S_Griewank_CEC08: case S_Ackley_CEC08:
               case RW_Gear_Train: case RW_ParEst_FMSoundWaves:
    ///Dynamic Problems
    case CompositionDBG_DOP: case RotationDBG_DOP: case MovingPeak_DOP: case DF1_DOP:

           allocateMemory(p_gene,mc_length-1);
            for(unsigned int i=0;i<mc_length-1;i++){
                ((double *) p_gene[i].mp_value)[0]=getGene<double>(i);
            }

            freeMemory();
			delete [] mp_gene;
            mp_gene=p_gene;

            break;
        case Binary_DOP:
            allocateMemory(p_gene,mc_length-1);

            for(unsigned int i=0;i<mc_length-1;i++){
                ((bool *) p_gene[i].mp_value)[0]=getGene<bool>(i);
            }

            freeMemory();
			delete [] mp_gene;
            mp_gene=p_gene;

            break;
    }
        mc_length--;
        evaluate(false);
}
void Chromosome::printToScreen(){

    for(unsigned int i=0;i<mc_length;i++){
        switch(mp_gene[i].m_coding){
            case C_DECIMAL:
                for(unsigned int j=0;j<mp_gene[i].m_length;j++)   cout<<getGene<double>(i,j);
                break;
            case C_BINARY:
                for(unsigned int j=0;j<mp_gene[i].m_length;j++)  cout<<getGene<bool>(i,j);
                break;
            case C_INTEGER:
                for(unsigned int j=0;j<mp_gene[i].m_length;j++)  cout<<getGene<int>(i,j);
                break;
            case C_STRING:
                for(unsigned int j=0;j<mp_gene[i].m_length;j++)  cout<<getGene<char>(i,j);
                 break;
            case C_UNSER_DEFINED:
            ///TO DO
               // for(unsigned int j=0;j<mp_gene[i].m_length;j++) getGene<undefined>(i,j) =rhs.getGene<undefined>(i,j);
                break;
        }
        cout<<" ";
    }
    for(unsigned int i=0;i<ms_objNumbers;i++){
        cout<<"obj "<<i<<":"<<mp_obj[i]<<" ";
    }
    cout<<endl;
}
void Chromosome::printToFile(ofstream &out){
    for(unsigned int i=0;i<mc_length;i++){
        switch(mp_gene[i].m_coding){
            case C_DECIMAL:
                for(unsigned int j=0;j<mp_gene[i].m_length;j++)   out<<getGene<double>(i,j);
                break;
            case C_BINARY:
                for(unsigned int j=0;j<mp_gene[i].m_length;j++)  out<<getGene<bool>(i,j);
                break;
            case C_INTEGER:
                for(unsigned int j=0;j<mp_gene[i].m_length;j++)  out<<getGene<int>(i,j);
                break;
            case C_STRING:
                for(unsigned int j=0;j<mp_gene[i].m_length;j++)  out<<getGene<char>(i,j);
                 break;
            case C_UNSER_DEFINED:
            ///TO DO
               // for(unsigned int j=0;j<mp_gene[i].m_length;j++) getGene<undefined>(i,j) =rhs.getGene<undefined>(i,j);
                break;
        }
        out<<" ";
    }
    for(unsigned int i=0;i<ms_objNumbers;i++){
        out<<mp_obj[i]<<" ";
    }
    out<<endl;
}
void Chromosome::initialize( Chromosome & rhs, double radius,bool mode){
    switch(Global::gp_problem->getId()){
            case Sphere: case Sphere_Noisy: case S_Sphere: case R_Sphere: case RS_Sphere: case S_Sphere_CEC05: case Sphere_Noisy_CEC05:
               case Rastrigin: case Rastrigin_Noisy: case S_Rastrigin: case R_Rastrigin: case RS_Rastrigin: case S_Rastrigin_CEC05: case RS_Rastrigin_CEC05:
               case Weierstrass: case RS_Weierstrass: case R_Weierstrass: case RS_Weierstrass_CEC05:
               case Griewank: case R_Griewank: case RS_Griewank:  case RS_Griewank_noBounds_CEC05: case Griewank_Rosenbrock_F13_CEC05: case S_Griewank_Rosenbrock_F13_CEC05:
               case Ackley: case Ackley_Noisy: case S_Ackley: case R_Ackley: case RS_Ackley: case RS_Ackley_Bound_CEC05:
               case Step:
               case Quartic_Noisy:
               case Scaffer_F6:  case Expanded_Scaffer_F6_CEC05: case Noncont_Expanded_Scaffer_F6_CEC05: case RS_Expanded_Scaffer_F6_CEC05:
               case Rosenbrock: case S_Rosenbrock: case S_Rosenbrock_CEC05:
               case Schwefel_2_13_CEC05:
               case Schwefel_2_22: case Schwefel_2_22_Noisy: case S_Schwefel_2_22: case R_Schwefel_2_22: case RS_Schwefel_2_22:
               case Schwefel: case Schwefel_Noisy: case S_Schwefel: case R_Schwefel: case RS_Schwefel:
               case Schwefel_1_2: case Schwefel_1_2_Noisy: case S_Schwefel_1_2: case S_Schwefel_1_2_Noisy: case R_Schwefel_1_2: case RS_Schwefel_1_2:  case S_Schwefel_1_2_CEC05:  case S_Schwefel_1_2_Noisy_CEC05:
               case Schwefel_2_21:
               case Schwefel_2_6_Bound_CEC05:
               case Penalized_1:
               case Penalized_2:
               case Noncont_Rastrigin:
               case RS_Elliptic_CEC05: case Elliptic:
               case Com: case R_Com: case Com_CEC05: case H_Com_CEC05: case H_Com_Noisy_CEC05:
               case RH_Com_CEC05: case RH_Com_NarrowBasin_CEC05: case RH_Com_Bound_CEC05:
               case RH_Com_F21_CEC05:  case RH_Com_HighConNumMatrix_F22_CEC05:  case Noncont_RH_Com_F23_CEC05:  case RH_Com_F24_CEC05:  case RH_Com_noBounds_F25_CEC05:
               case M_global1: case M_global2: case M_global3: case M_global4: case M_global5:
               case S_Sphere_CEC08: case Schwefel_2_21_CEC08: case S_Rosenbrock_CEC08: case S_Rastrigin_CEC08: case S_Griewank_CEC08: case S_Ackley_CEC08:
               case RW_Gear_Train: case RW_ParEst_FMSoundWaves:
    ///Dynamic Problems
    case CompositionDBG_DOP: case RotationDBG_DOP: case MovingPeak_DOP: case DF1_DOP:

            double l,u;
            for(unsigned int i=0;i<mc_length;i++){
                Global::gp_problem->getSearchRange<double>(l,u,i);
                getGene<double>(i)=rhs.getGene<double>(i)+2*radius*(Global::gp_uniformAlg->Next()-0.5);
                if(getGene<double>(i)<l||getGene<double>(i) >u){
                    getGene<double>(i)=gRandFloat(l,u);
                }
            }

            break;
        case Binary_DOP:
            for(unsigned int i=0;i<mc_length;i++){
                double p=Global::gp_uniformAlg->Next();
                getGene<bool>(i)=p<0.01?!rhs.getGene<bool>(i):rhs.getGene<bool>(i);
            }

            break;
    }


    evaluate(mode);


}

void Chromosome::validate(){
    if(isValid()) return;

    switch(Global::gp_problem->getId()){
            case Sphere: case Sphere_Noisy: case S_Sphere: case R_Sphere: case RS_Sphere: case S_Sphere_CEC05: case Sphere_Noisy_CEC05:
               case Rastrigin: case Rastrigin_Noisy: case S_Rastrigin: case R_Rastrigin: case RS_Rastrigin: case S_Rastrigin_CEC05: case RS_Rastrigin_CEC05:
               case Weierstrass: case RS_Weierstrass: case R_Weierstrass: case RS_Weierstrass_CEC05:
               case Griewank: case R_Griewank: case RS_Griewank:  case RS_Griewank_noBounds_CEC05: case Griewank_Rosenbrock_F13_CEC05: case S_Griewank_Rosenbrock_F13_CEC05:
               case Ackley: case Ackley_Noisy: case S_Ackley: case R_Ackley: case RS_Ackley: case RS_Ackley_Bound_CEC05:
               case Step:
               case Quartic_Noisy:
               case Scaffer_F6:  case Expanded_Scaffer_F6_CEC05: case Noncont_Expanded_Scaffer_F6_CEC05: case RS_Expanded_Scaffer_F6_CEC05:
               case Rosenbrock: case S_Rosenbrock: case S_Rosenbrock_CEC05:
               case Schwefel_2_13_CEC05:
               case Schwefel_2_22: case Schwefel_2_22_Noisy: case S_Schwefel_2_22: case R_Schwefel_2_22: case RS_Schwefel_2_22:
               case Schwefel: case Schwefel_Noisy: case S_Schwefel: case R_Schwefel: case RS_Schwefel:
               case Schwefel_1_2: case Schwefel_1_2_Noisy: case S_Schwefel_1_2: case S_Schwefel_1_2_Noisy: case R_Schwefel_1_2: case RS_Schwefel_1_2:  case S_Schwefel_1_2_CEC05:  case S_Schwefel_1_2_Noisy_CEC05:
               case Schwefel_2_21:
               case Schwefel_2_6_Bound_CEC05:
               case Penalized_1:
               case Penalized_2:
               case Noncont_Rastrigin:
               case RS_Elliptic_CEC05: case Elliptic:
               case Com: case R_Com: case Com_CEC05: case H_Com_CEC05: case H_Com_Noisy_CEC05:
               case RH_Com_CEC05: case RH_Com_NarrowBasin_CEC05: case RH_Com_Bound_CEC05:
               case RH_Com_F21_CEC05:  case RH_Com_HighConNumMatrix_F22_CEC05:  case Noncont_RH_Com_F23_CEC05:  case RH_Com_F24_CEC05:  case RH_Com_noBounds_F25_CEC05:
               case M_global1: case M_global2: case M_global3: case M_global4: case M_global5:
               case S_Sphere_CEC08: case Schwefel_2_21_CEC08: case S_Rosenbrock_CEC08: case S_Rastrigin_CEC08: case S_Griewank_CEC08: case S_Ackley_CEC08:
               case RW_Gear_Train: case RW_ParEst_FMSoundWaves:
    ///Dynamic Problems
    case CompositionDBG_DOP: case RotationDBG_DOP: case MovingPeak_DOP: case DF1_DOP:{
        // default validation mode is remapping if a solution goes beyond the search range
            double l,u,x;
            switch(Chromosome::ms_validationMode){
                case VALIDATION_IGNORE:
                    break;
                case VALIDATION_REINITIALIZE:
                    for(unsigned int i=0;i<mc_length;i++){
                        Global::gp_problem->getSearchRange<double>(l,u,i);
                        getGene<double>(i)=l+(u-l)*Global::gp_uniformAlg->Next();
                    }
                    break;
                case VALIDATION_REMAP:
                    for(unsigned int i=0;i<mc_length;i++){
                        Global::gp_problem->getSearchRange<double>(l,u,i);
                        x=getGene<double>(i);
                        if(x<l){
                            getGene<double>(i)=l+(u-l)*(l-x)/(u-x);
                        }else if(x>u){
                            getGene<double>(i)=l+(u-l)*(x-u)/(x-l);
                        }
                    }
                    break;
                case VALIDATION_SETTOBOUND:
                    for(unsigned int i=0;i<mc_length;i++){
                        Global::gp_problem->getSearchRange<double>(l,u,i);
                        x=getGene<double>(i);
                        if(x<l){
                            getGene<double>(i)=l;
                        }else if(x>u){
                            getGene<double>(i)=u;
                        }
                    }
                    break;
            }
        }
            break;
        case Binary_DOP:
            /// can not figure out how it will go beyond the search range with the binary encoding, no validation available here
            break;
    }

}
