/*************************************************************************
* 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: 21 July 2011
// Last modified:
#include "FGriewank.h"

FGriewank::FGriewank(){
    //ctor
}
FGriewank::FGriewank(const int rId, const int rDimNumber, char *rName):BenchmarkFunction(rId, rDimNumber, rName){
     if(m_id == RS_Griewank_noBounds_CEC05)  {
          setSearchRange<double>(0,600);
         for(int i=0; i<m_dimNumber; ++i)   ((Boundary<double> *)m_searchRange[i])->m_flag = false;
     }
     else if(m_id == S_Griewank_Rosenbrock_F13_CEC05)  {
          setSearchRange<double>(-5, 5);
     }
     else setSearchRange<double>(-600,600);

    initialize();
}
FGriewank::FGriewank(const int rId, const int rDimNumber, char *rName, double rL, double rU):BenchmarkFunction(rId, rDimNumber, rName){
    setSearchRange<double>(rL,rU);
    initialize();
}
FGriewank::FGriewank(const int rId, const int rDimNumber, char *rName, double *rL, double *rU):BenchmarkFunction(rId, rDimNumber, rName){

    setSearchRange<double>(rL,rU);
    initialize();
}
FGriewank::~FGriewank(){
    //dtor
}

void FGriewank::initialize(){
    setOriginalGlobalOpt();
    switch(m_id){
        case Griewank:
            break;
        case S_Griewank_CEC08:
            loadTranslation();
            setBias(-180);
            break;
        case R_Griewank:
            setConditionNumber(2);
            loadRotation();
            break;
        case RS_Griewank:
            setConditionNumber(3);
            loadTranslation();
            loadRotation();
            break;
        case RS_Griewank_noBounds_CEC05:
            setConditionNumber(3);
            loadTranslation();
            loadRotation();
            setBias(-180);
            break;
        case S_Griewank_Rosenbrock_F13_CEC05:
               loadTranslation();
               setBias(-130);
               break;
        case Griewank_Rosenbrock_F13_CEC05:
               setBias(0);
               break;
        default:
        Throw(Invalid_argument("Error: please check the problem ID"));
        exit(0);
        break;
    }
    setGlobalOpt();
    setAccuracy(1.0e-2);

}
void FGriewank::setGlobalOpt(){
    m_globalOpt.m_knownFlag=true;
    gCopy(m_globalOpt.mp_location,mp_translation,m_dimNumber);
    m_globalOpt.m_value=BenchmarkFunction::evaluate(m_globalOpt.mp_location,false);
}

double FGriewank::evaluate_(double const *x){
     double result = 0;
     if(m_id == S_Griewank_Rosenbrock_F13_CEC05 || m_id == Griewank_Rosenbrock_F13_CEC05)  {
          for(int i=0; i<m_dimNumber; ++i) {
               double result001 = 0;
               double result002 = 0;
               double x001 = x[i] + 1;
               double x002 = x[(i+1) % m_dimNumber] + 1;
               result001 += 100 * pow((x002 - x001 * x001), 2.0) + (x001 - 1) * (x001 - 1);
               result002 += result001 * result001 / 4000.0 - cos(result001 / sqrt((double)(i+1))) + 1;
               result += result002;
          }
          result += m_bias;
     }
     else {
          double s1=0,s2=1;
          for(int i=0;i<m_dimNumber;i++){
               s1+=x[i]*x[i]/4000.;
               s2*=cos(x[i]/sqrt((double) (i+1)));
          }
          result = s1-s2+1.+m_bias;
     }
     return result;
}
