/**
 * MOEADACD_main.java
 * 
 * @author Luping Wang <zjlxwlp8412@126.com>
 * 
 * Copyright (c) 2015 Luping Wang
 * 
 * Note: This is a free software developed based on the open source project 
 * jMetal<http://jmetal.sourceforge.net>. The copy right of jMetal belongs to 
 * its original authors, Antonio J. Nebro and Juan J. Durillo. Nevertheless, 
 * this current version can be redistributed and/or modified under the terms of 
 * the GNU Lesser General Public License as published by the Free Software 
 * Foundation, either version 3 of the License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful, 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *  
 */
package jmetal.metaheuristics.moead.main;

import jmetal.metaheuristics.moead.*;

import jmetal.core.*;
import jmetal.operators.crossover.*;
import jmetal.operators.mutation.*;
import jmetal.problems.DTLZ.*;
import jmetal.problems.ZDT.*;
import jmetal.problems.WFG.*;
import jmetal.problems.MOP.*;
import jmetal.problems.LZ09.*;
import jmetal.problems.*;
import jmetal.qualityIndicator.*;
import jmetal.util.*;

import java.io.*;
import java.util.*;
import java.util.logging.*;

public class MOEADACD_main
{
	
	public static Logger      logger_;      
	public static FileHandler fileHandler_;
	static String[] problemSet = {"ZDT1", "ZDT2","ZDT3","ZDT4","ZDT6",
								  "LZ09_F1","LZ09_F2","LZ09_F3","LZ09_F4","LZ09_F5","LZ09_F6","LZ09_F7","LZ09_F8","LZ09_F9",
								  "MOP1","MOP2","MOP3","MOP4","MOP5","MOP6","MOP7"};
	static int[] parDim          = {30,30,30,10,30,
									30,30,30,30,30,10,30,10,30,
									10,10,10,10,10,10,10};
	static int[] objDim          = {2,2,2,2,2,
									2,2,2,2,2,3,2,2,2,
									2,2,2,2,2,3,3};
	static int[] popsize       = {100,100,100,100,100,
								  200,200,200,200,200,300,200,200,200,
								  200,200,200,200,200,300,300};
	static int[] maxGen      = {200,200,200,1000,200,
								750,750,750,750,750,500,750,750,750,
								750,750,750,750,750,500,500};

	static String savePF = "N";
	static String savePS = "N";
	static String saveMETRICS = "N";
	static String PFFILE;
	static String PSFILE;
	static String METRICSFILE;
	
	static String algName = "MOEADACD";
	static String functionType = "_TE";
	static double delta	= 0.9;
	static int nr		= 2;
	static int maxRun  = 2;

	public static void main(String [] args) throws JMException, SecurityException, IOException, ClassNotFoundException { 
		logger_      = Configuration.logger_ ;
		fileHandler_ = new FileHandler(algName+".log");
		logger_.addHandler(fileHandler_) ;
		String curDir = System.getProperty("user.dir");
		Problem problem;
		Algorithm algorithm;
		HashMap parameters;
		Operator crossover;
		Operator mutation;
		QualityIndicator indicators = null;
		Object[] params;
		for (int problemIndex=0;problemIndex<problemSet.length ;problemIndex++ )
		{			
				if (problemIndex <=4)
				{
					params = new Object[]{"Real", parDim[problemIndex]};//----ZDT
				}else if (problemIndex <=13)
				{
					params = new Object[]{"Real"};
				}else if (problemIndex <= 18)
				{
					params = new Object[]{"Real", parDim[problemIndex]};
				}else{
					params = new Object[]{"Real", parDim[problemIndex],objDim[problemIndex]};
				}
				
				problem = (new ProblemFactory()).getProblem(problemSet[problemIndex], params);

				algorithm = new MOEADACD(problem,functionType);
				algorithm.setInputParameter("algName",algName);
				algorithm.setInputParameter("populationSize",popsize[problemIndex]);
				algorithm.setInputParameter("maxEvaluations",popsize[problemIndex]*maxGen[problemIndex]);
				algorithm.setInputParameter("dataDirectory", "DirectionVector");
				algorithm.setInputParameter("T", (int)(0.1*popsize[problemIndex])) ;
				algorithm.setInputParameter("delta", delta) ;
				algorithm.setInputParameter("nr", nr) ;
				algorithm.setInputParameter("savePF",savePF);

				String paretoFrontFile = curDir + "/" + "trueParetoFront/" + problem.getName() + ".txt";
				indicators = new QualityIndicator(problem, paretoFrontFile);

				// operator 
				parameters = new HashMap() ;
				parameters.put("CR", 1.0) ;
				parameters.put("F", 0.5) ;
				parameters.put("probability", 1.0/problem.getNumberOfVariables()) ;
				parameters.put("distributionIndex", 20.0) ;
				crossover = CrossoverFactory.getCrossoverOperator("DifferentialEvolutionCrossover", parameters);                   
				mutation = MutationFactory.getMutationOperator("PolynomialMutation", parameters);                    
				algorithm.addOperator("crossover",crossover);
				algorithm.addOperator("mutation",mutation);

				/*	create files	*/
				String  DATAFILE 	  = curDir + "/"+"ExperimentalData";	createFolder(DATAFILE);
				if (savePF.equals("Y"))
				{
					PFFILE 	  = DATAFILE + "/"+ "PF";	createFolder(PFFILE);
					PFFILE 	  = PFFILE + "/"+ algName;	createFolder(PFFILE);
				}
				if (savePS.equals("Y"))
				{
					PSFILE 	  = DATAFILE + "/"+"PS";	createFolder(PSFILE);
					PSFILE 	  = PSFILE + "/"+ algName;	createFolder(PSFILE);
				}
				if (saveMETRICS.equals("Y"))
				{
					METRICSFILE 	  = DATAFILE + "/"+"METRICS";	createFolder(METRICSFILE);
					METRICSFILE 	  = METRICSFILE + "/"+ algName;	createFolder(METRICSFILE);
					String METRICSPATH = METRICSFILE + "/" + problem.getName();
					indicators.printVectorToFile(METRICSPATH, new String[]{"Delta_p", "IGD", "HV"}, false);
				}
				System.out.println("============================================================================");
				for (int run=1;run<=maxRun ;run++ )
				{
					long initTime = System.currentTimeMillis();
					SolutionSet population = algorithm.execute();
					long estimatedTime = System.currentTimeMillis() - initTime;
					System.out.println(problem.getName() + ":  "+ "	Run:" + Integer.toString(run) + "	TimeUsed:" + estimatedTime + "ms");
					if (savePF.equals("Y"))
					{
						String PFPATH = PFFILE + "/" + problem.getName() + "R" + Integer.toString(run);
						population.printObjectivesToFile(PFPATH);
					}
					if (savePS.equals("Y"))
					{
						String PSPATH = PSFILE + "/" + problem.getName() + "R" + Integer.toString(run);
						population.printVariablesToFile(PSPATH);
					}
					
					if (saveMETRICS.equals("Y"))
					{
						String METRICSPATH = METRICSFILE + "/" + problem.getName();					
						indicators.printVectorToFile(METRICSPATH, 
							new Double[]{indicators.getDelta_p(population),
											indicators.getIGD(population),
												indicators.getHypervolume(population)}, true);
					}
					System.out.println(indicators.getIGD(population));
					System.out.println();
				}			
		}

	}

	private static void createFolder(String str) {
		boolean success = (new File(str)).mkdir();

		if (success) {
			System.out.println("Directory: " + str + " created");
		} else {
			System.out.println("Directory: " + str + " NOT created");
		}
	}


}
