#include "FSchwefel_2_6.h"
#include "../../Algorithms/DE/Ming_DE/Ming_Global.h"

FSchwefel_2_6::FSchwefel_2_6(){
    //ctor
}
FSchwefel_2_6::FSchwefel_2_6(const int rId, const int rDim, char *rName):BenchmarkFunction(rId, rDim, rName){
     a = new int * [m_dimNumber];
    for(int i=0; i<m_dimNumber; ++i) {
          a[i] = new int [m_dimNumber];
     }
     b = new double [m_dimNumber];
    setSearchRange<double>(-100, 100);
    initialize();
}
FSchwefel_2_6::FSchwefel_2_6(const int rId, const int rDim, char *rName, double rL, double rU):BenchmarkFunction(rId, rDim, rName){
     a = new int * [m_dimNumber];
    for(int i=0; i<m_dimNumber; ++i) {
          a[i] = new int [m_dimNumber];
     }
    b = new double [m_dimNumber];
    setSearchRange<double>(rL,rU);
    initialize();
}
FSchwefel_2_6::FSchwefel_2_6(const int rId, const int rDim,   char *rName, double *rL, double *rU):BenchmarkFunction(rId, rDim, rName){
     a = new int * [m_dimNumber];
    for(int i=0; i<m_dimNumber; ++i) {
          a[i] = new int [m_dimNumber];
     }
     b = new double [m_dimNumber];
    setSearchRange<double>(rL,rU);
    initialize();
}
FSchwefel_2_6::~FSchwefel_2_6(){
    //dtor
    for(int i=0; i<m_dimNumber; ++i) {
          delete[] a[i];
    }
    delete[] a;
    delete[] b;
}

void FSchwefel_2_6::initialize(){
     setOriginalGlobalOpt();
    switch(m_id){
        case Schwefel_2_6_Bound_CEC05:
            break;
        default:
        Throw(Invalid_argument("Error: please check the problem ID"));
        exit(0);
        break;
    }
    loadData();
    setBias(-310);
    setGlobalOpt();
    setAccuracy(1.0e-2);
}

void FSchwefel_2_6::loadData()
{
     string sa;
	char astr[100];
	sprintf(astr,"%d",m_dimNumber);
	strcat(astr,"Dim.txt");
	sa=astr;
	sa.insert(0,gProName[m_id]+"_a_");
	sa.insert(0,probDataPath);

	ifstream in_a;
	in_a.open(sa.data());
	if(in_a.fail()){
	     for(int i=0; i<m_dimNumber; ++i) {
               for(int j=0; j<m_dimNumber; ++j) {
                    a[i][j] = int(-500.0 + Global::gp_uniformPro->Next() * 1000);
               }
	     }
          ofstream out(sa.c_str());
          for(int i=0; i<m_dimNumber; ++i) {
               for(int j=0;j<m_dimNumber;j++)  {
                    out<<a[i][j]<<" ";
               }
          }
          out.close();
	}else{
	     for(int i=0; i<m_dimNumber; ++i) {
             for(int j=0;j<m_dimNumber;j++) {
                 in_a>>a[i][j];
               }
	     }
	}
	in_a.close();


	string so;
	char ostr[100];
	sprintf(ostr,"%d",m_dimNumber);
	strcat(ostr,"Dim.txt");
	so=ostr;
	so.insert(0,gProName[m_id]+"_Opt_");

	so.insert(0,probDataPath);
	ifstream in;
	in.open(so.data());
	if(in.fail()){
            for(int j=0;j<m_dimNumber;j++){
                double rl,ru,range;
                ru=((Boundary<double> *)m_searchRange[j])->upper-m_originalGlobalOpt.mp_location[j];
                rl=m_originalGlobalOpt.mp_location[j]-((Boundary<double> *)m_searchRange[j])->lower;
                range=rl<ru?rl:ru;
                mp_translation[j]=(Global::gp_uniformPro->Next()-0.5)*2*range;
            }
            for(int i=0; i<m_dimNumber; ++i) {
                    if(i < m_dimNumber / 4) mp_translation[i] = -100;
                    else if(i >= m_dimNumber * 3 / 4 - 1) mp_translation[i] = 100;
               }

          ofstream out(so.c_str());
          for(int j=0;j<m_dimNumber;j++)        out<<mp_translation[j]<<" ";
		out.close();
	}
	else{

        for(int j=0;j<m_dimNumber;j++) {
            in>>mp_translation[j];

		}
	}
	in.close();



	for(int i=0; i<m_dimNumber; ++i) {
          b[i] = 0;
          for(int j=0; j<m_dimNumber; ++j) {
               b[i] += a[i][j] * mp_translation[j];
          }
	}
}

void FSchwefel_2_6::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 FSchwefel_2_6::evaluate_(double const *x){
     for(int i=0; i<m_dimNumber; ++i) {
         // const_cast<double *>(x)[i] = mp_translation[i];
     }

     double fit = 0;
     double * tempVector = new double[m_dimNumber];
     if(m_id == Schwefel_2_6_Bound_CEC05) {
          for(int i=0; i<m_dimNumber; ++i) {
               for(int j=0; j<m_dimNumber; ++j) {
                    tempVector[j] = 0;
                    for(int k=0; k<m_dimNumber; ++k) {
                         tempVector[j] += a[j][k] * x[k];
                    }
               }
               for(int j=0; j<m_dimNumber; ++j) {
                    tempVector[j] -= b[j];
               }
               double temp = 0;
               for(int  j=0; j<m_dimNumber; ++j) {
                    temp += pow(tempVector[j], 2.0);
               }
               temp = sqrt(temp);
               if(fit < temp) fit = temp;
          }
     }
     delete[] tempVector;
    return fit+m_bias;
}
