//==============================================================================================//
// JY test suite : A set of benchmark problems for dynamic multiobjective optimization		//
//												//
//  Refer to the following paper for more detail about the JY test suite:			//
//												//
//  Shouyong Jiang and Shengxiang Yang, "Evolutionary dynamic multi-objective optimization:	//
//  Benchmarks and algorithm comparisons,'' IEEE Transactions Cybernetics, in press, 2016.	//
//												//
//  The source code of the JY toolbox was implemented by Shouyong Jiang (Oct. 2016).		//
//												//
//  If you have any questions about the codes, please contact 					//
//  Shouyong Jiang at math4neu@gmail.com  or Shengxiang Yang at syang@dmu.ac.uk			//
//==============================================================================================//

#ifndef __OBJECTIVE_H_
#define __OBJECTIVE_H_

#include <vector>
#include <math.h>
#include <random>

using namespace std;

#define PI 3.141592653589793238462643383279502884197169399375105

#define strTestInstance		"JY1"        // test problem name
#define nvar			10	     // number of decision variables
					   
static int Randint;			     // random interger for varying the type of JY10

// ===============================================================================//
// Illustration of parameters in the "dobjective" function		 	  //
//										  //
//			x_var --> decision variable vector			  //
//			y_obj --> objective function vector			  //
//			iter  --> iteration count				  //
//			taut  --> frequency of change				  //
//			nt    --> severity of change				  //
//										  //
// ===============================================================================//
void dobjective(vector<double> &x_var, vector<double> &y_obj, int iter, int taut, int nt)
{
	//--------------------------------------------------------------------------------//
	if (iter <= 1) Randint = 0;  // make sure Randint is initialized. 
	if (!(iter%taut))
	{
		random_device rd;
		mt19937 gen(rd());
		uniform_int_distribution<> dis(0, 100000);
		Randint = dis(gen)%3;  //srand(iter/taut);
	}

	double Tstep = (double)(iter / taut) / nt; // time steps (change every taut iterations)

	//--------------------------------------------------------------------------------//

	if (!strcmp(strTestInstance, "JY1")) //JY1
	{
		unsigned int j, count1, count2;
		double a, w, g, sum1;

		a = 0.05, w = 6;
		g = sin(0.5*PI*Tstep);
		sum1 = 0;
		for (j = 1; j < nvar; j++)
		{
			double x = 2 * x_var[j] - 1.0;
			double yj = x - g;
			yj = yj*yj;
			sum1 += yj;
		}
		y_obj[0] = (1 + sum1)*(x_var[0] + a*sin(w*PI*x_var[0]));
		y_obj[1] = (1 + sum1)*(1 - x_var[0] + a*sin(w*PI*x_var[0]));

		return;
	}

	if (!strcmp(strTestInstance, "JY2")) //JY2
	{
		unsigned int j, count1, count2;
		double a, w, g, sum1;

		a = 0.05, w = floor(6 * sin(0.5*PI*(Tstep - 1)));
		g = sin(0.5*PI*Tstep);
		sum1 = 0;

		for (j = 1; j < nvar; j++)
		{
			double x = 2 * x_var[j] - 1.0;
			double yj = x - g;
			yj = yj*yj;
			sum1 += yj;
		}
		y_obj[0] = (1 + sum1)*(x_var[0] + a*sin(w*PI*x_var[0]));
		y_obj[1] = (1 + sum1)*(1 - x_var[0] + a*sin(w*PI*x_var[0]));

		return;
	}

	if (!strcmp(strTestInstance, "JY3")) //JY3
	{
		unsigned int j, count1, count2;
		double a, aa, y1, w, g, sum1;

		aa = floor(100 * sin(0.5*PI*Tstep)*sin(0.5*PI*Tstep));
		y1 = fabs(x_var[0] * sin((2 * aa + 1)*PI*x_var[0]));

		a = 0.05, w = floor(6 * sin(0.5*PI*(Tstep - 1)));
		//g=sin(0.5*PI*Tstep);

		sum1 = 0;

		for (j = 1; j < nvar; j++)
		{
			double x = 2 * x_var[j] - 1.0;
			double x0 = 2 * x_var[j - 1] - 1.0;
			double yj;
			if (j == 1){ yj = x*x - y1; }
			else{ yj = x*x - x0; }

			yj = yj*yj;
			sum1 += yj;
		}
		y_obj[0] = (1 + sum1)*(x_var[0] + a*sin(w*PI*x_var[0]));
		y_obj[1] = (1 + sum1)*(1 - x_var[0] + a*sin(w*PI*x_var[0]));

		return;
	}

	if (!strcmp(strTestInstance, "JY4")) //JY4
	{
		unsigned int j, count1, count2;
		double a, w, g, sum1;

		g = sin(0.5*PI*Tstep);
		a = 0.05, w = pow(10.0, 1.0 + fabs(g));

		sum1 = 0;

		for (j = 1; j < nvar; j++)
		{
			double x = 2 * x_var[j] - 1.0;
			double yj = x - g;
			yj = yj*yj;
			sum1 += yj;
		}
		y_obj[0] = (1 + sum1)*(x_var[0] + a*sin(w*PI*x_var[0]));
		y_obj[1] = (1 + sum1)*(1 - x_var[0] + a*sin(w*PI*x_var[0]));

		return;
	}

	if (!strcmp(strTestInstance, "JY5")) //JY5
	{
		unsigned int j, count1, count2;
		double a, w, g, sum1;

		g = sin(0.5*PI*Tstep);
		a = 0.3*sin(0.5*PI*(Tstep - 1)), w = 1.0;

		sum1 = 0;

		for (j = 1; j < nvar; j++)
		{
			double x = 2 * x_var[j] - 1.0;
			double yj = x;
			yj = yj*yj;
			sum1 += yj;
		}
		y_obj[0] = (1 + sum1)*(x_var[0] + a*sin(w*PI*x_var[0]));
		y_obj[1] = (1 + sum1)*(1 - x_var[0] + a*sin(w*PI*x_var[0]));

		return;
	}

	if (!strcmp(strTestInstance, "JY6")) //JY6
	{
		unsigned int j, count1, count2;
		double a, w, g, k, sum1;

		g = sin(0.5*PI*Tstep);
		a = 0.1, w = 3;
		k = 2 * floor(10 * fabs(g));

		sum1 = 0;

		for (j = 1; j < nvar; j++)
		{
			double x = 2 * x_var[j] - 1.0;
			double yj = x - g;
			yj = 4 * yj*yj - cos(k*PI*yj) + 1;
			sum1 += yj;
		}
		y_obj[0] = (1 + sum1)*(x_var[0] + a*sin(w*PI*x_var[0]));
		y_obj[1] = (1 + sum1)*(1 - x_var[0] + a*sin(w*PI*x_var[0]));

		return;
	}

	if (!strcmp(strTestInstance, "JY7")) //JY7
	{
		unsigned int j, count1, count2;
		double a, w, g, s, t, sum1;

		g = sin(0.5*PI*Tstep);
		a = 0.1, w = 3;
		s = t = 0.2 + 2.8*fabs(g);

		sum1 = 0;

		for (j = 1; j < nvar; j++)
		{
			double x = 2 * x_var[j] - 1.0;
			double yj = x - g;
			yj = yj*yj - 10 * cos(2 * PI*yj) + 10;
			sum1 += yj;
		}
		y_obj[0] = (1 + sum1)*pow(x_var[0] + a*sin(w*PI*x_var[0]), s);
		y_obj[1] = (1 + sum1)*pow(1 - x_var[0] + a*sin(w*PI*x_var[0]), t);

		return;
	}

	if (!strcmp(strTestInstance, "JY8")) //JY8
	{
		unsigned int j, count1, count2;
		double a, w, g, s, t, sum1;

		g = sin(0.5*PI*Tstep);
		a = 0.05, w = 6;
		t = 10.0 - 9.8*fabs(g);
		s = 2.0 / t;

		sum1 = 0;

		for (j = 1; j < nvar; j++)
		{
			double x = 2 * x_var[j] - 1.0;
			double yj = x;
			yj = yj*yj;
			sum1 += yj;
		}
		y_obj[0] = (1 + sum1)*pow(x_var[0] + a*sin(w*PI*x_var[0]), s);
		y_obj[1] = (1 + sum1)*(1 - x_var[0] + a*sin(w*PI*x_var[0]), t);

		return;
	}

	if (!strcmp(strTestInstance, "JY9")) //JY9
	{
		unsigned int j, d, count1, count2;
		double a, w, g, sum1;

		d = (int)floor(Tstep*nt / 5) % 3;
		g = floor(sin(0.5*PI*Tstep));
		a = 0.05, w = floor(6 * pow(sin(0.5*PI*(Tstep - 1)), d));

		sum1 = 0;

		for (j = 1; j < nvar; j++)
		{
			double x = 2 * x_var[j] - 1.0;
			double yj = x + d - g;
			yj = yj*yj;
			sum1 += yj;
		}
		y_obj[0] = (1 + sum1)*(x_var[0] + a*sin(w*PI*x_var[0]));
		y_obj[1] = (1 + sum1)*(1 - x_var[0] + a*sin(w*PI*x_var[0]));

		return;
	}

	if (!strcmp(strTestInstance, "JY10")) //JY10
	{
		unsigned int j, d, count1, count2;
		double a, w, g, s, t, sum1;

		d = int (floor(Tstep*nt / 5) + Randint) % 3;

		g = fabs(sin(0.5*PI*Tstep));
		a = 0.05, w = 6;
		t = 1 + d*g;
		s = t;

		sum1 = 0;

		for (j = 1; j < nvar; j++)
		{
			double x = 2 * x_var[j] - 1.0;
			double yj = x + d - g;
			yj = yj*yj;
			sum1 += yj;
		}
		y_obj[0] = (1 + sum1)*pow(x_var[0] + a*sin(w*PI*x_var[0]), s);
		y_obj[1] = (1 + sum1)*(1 - x_var[0] + a*sin(w*PI*x_var[0]), t);

		return;
	}
}

#endif
