/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package hh.experiment;
import hh.IO.IOCreditHistory;
import hh.IO.IOQualityHistory;
import hh.IO.IOSelectionHistory;
import hh.hyperheuristics.HHFactory;
//import hh.hyperheuristics.HeMOEA;
import hh.hyperheuristics.IHyperHeuristic;
import hh.hyperheuristics.MOEADHH;
import hh.nextheuristic.INextHeuristic;
import hh.creditassigment.CreditFitnessFunctionType;
import hh.creditassigment.ICreditAssignment;
import hh.creditassigment.CreditDefFactory;
import hh.hyperheuristics.AOSIBEA;
import hh.hyperheuristics.AOSNSGAII;
import hh.hyperheuristics.AOSSSIBEA;
import hh.hyperheuristics.AOSSSNSGAII;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Collection;
import java.util.Iterator;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.moeaframework.Instrumenter;
import org.moeaframework.analysis.collector.Accumulator;
import org.moeaframework.analysis.collector.InstrumentedAlgorithm;
import org.moeaframework.analysis.sensitivity.EpsilonHelper;
import org.moeaframework.core.Algorithm;
import org.moeaframework.core.EpsilonBoxDominanceArchive;
import org.moeaframework.core.Initialization;
import org.moeaframework.core.NondominatedPopulation;
import org.moeaframework.core.NondominatedSortingPopulation;
import org.moeaframework.core.Population;
import org.moeaframework.core.PopulationIO;
import org.moeaframework.core.Problem;
import org.moeaframework.core.Solution;
import org.moeaframework.core.Variation;
import org.moeaframework.core.comparator.ChainedComparator;
import org.moeaframework.core.comparator.CrowdingComparator;
import org.moeaframework.core.comparator.DominanceComparator;
import org.moeaframework.core.comparator.FitnessComparator;
import org.moeaframework.core.comparator.ParetoDominanceComparator;
import org.moeaframework.core.fitness.HypervolumeFitnessEvaluator;
import org.moeaframework.core.fitness.IndicatorFitnessEvaluator;
import org.moeaframework.core.fitness.R2FitnessEvaluator;
import org.moeaframework.core.indicator.InvertedGenerationalDistance;
import org.moeaframework.core.indicator.jmetal.FastHypervolume;
import org.moeaframework.core.operator.RandomInitialization;
import org.moeaframework.core.operator.TournamentSelection;
import org.moeaframework.util.TypedProperties;
/**
* This sets up the experimental run. Need to define the problem, the
* hyperheuristic components, and the search parameters
*
* @author nozomihitomi
*/
public class TestRun implements Callable {
protected TypedProperties properties;
protected Problem problem;
protected String probName;
protected String path;
private ICreditAssignment creditDef;
protected double[] epsilonDouble;
protected int maxEvaluations;
private final Collection<Variation> heuristics;
protected final NondominatedPopulation referenceSet;
protected Solution refPointObj;
/**
*
* @param path
* @param problem
* @param probName
* @param referenceSet
* @param properties
* @param heuristics
* @param maxEvaluations
*/
public TestRun(String path, Problem problem, String probName, NondominatedPopulation referenceSet, TypedProperties properties,
Collection<Variation> heuristics, int maxEvaluations) {
this.heuristics = heuristics;
this.properties = properties;
this.problem = problem;
this.epsilonDouble = properties.getDoubleArray("ArchiveEpsilon",
new double[]{EpsilonHelper.getEpsilon(problem)});
this.probName = probName;
this.maxEvaluations = maxEvaluations;
this.path = path;
this.referenceSet = referenceSet;
}
// /**
// * Returns a new instance of AOSIBEA
// *
// * @return
// */
// private IHyperHeuristic newAOSIBEA() {
// int populationSize = (int) properties.getDouble("populationSize", 600);
//
// Initialization initialization = new RandomInitialization(problem,
// populationSize);
//
// Population population = new Population();
//
// IndicatorFitnessEvaluator fitnesseval = new HypervolumeFitnessEvaluator(problem);
//
// FitnessComparator fitnessComparator = new FitnessComparator(fitnesseval.areLargerValuesPreferred());
// TournamentSelection selection = new TournamentSelection(fitnessComparator);
//
// //all other properties use default parameters
// INextHeuristic selector = HHFactory.getInstance().getHeuristicSelector(properties.getString("HH", null), properties, heuristics);
//
// AOSSSIBEA aosibea = new AOSSSIBEA(problem, population, null, selection,
// initialization, fitnesseval, selector, creditDef);
//
// return aosibea;
// }
/**
* Returns a new instance of AOSIBEA
*
* @return
*/
private IHyperHeuristic newAOSIBEA() {
int populationSize = (int) properties.getDouble("populationSize", 600);
Initialization initialization = new RandomInitialization(problem,
populationSize);
Population population = new Population();
// IndicatorFitnessEvaluator fitnesseval = new HypervolumeFitnessEvaluator(problem);
int numVectors = (int) properties.getDouble("r2.numberVectors", 100);
R2FitnessEvaluator fitnesseval = new R2FitnessEvaluator(problem,numVectors,1.0);
FitnessComparator fitnessComparator = new FitnessComparator(fitnesseval.areLargerValuesPreferred());
TournamentSelection selection = new TournamentSelection(fitnessComparator);
//all other properties use default parameters
INextHeuristic selector = HHFactory.getInstance().getHeuristicSelector(properties.getString("HH", null), properties, heuristics);
AOSIBEA aosibea = new AOSIBEA(problem, population, null, selection,
initialization, fitnesseval, selector, creditDef);
return aosibea;
}
// /**
// * Returns a new instance of AOSNSGAII
// *
// * @return
// */
// private IHyperHeuristic newAOSSSNSGAII() {
// int populationSize = (int) properties.getDouble("populationSize", 600);
//
// Initialization initialization = new RandomInitialization(problem,
// populationSize);
//
// NondominatedSortingPopulation population = new NondominatedSortingPopulation();
//
// TournamentSelection selection = new TournamentSelection(2,
// new ChainedComparator(new ParetoDominanceComparator(),
// new CrowdingComparator()));
//
// //all other properties use default parameters
// INextHeuristic selector = HHFactory.getInstance().getHeuristicSelector(properties.getString("HH", null), properties, heuristics);
//
// AOSSSNSGAII aosnsgaii = new AOSSSNSGAII(problem, population, null, selection,
// initialization, selector, creditDef);
//
// return aosnsgaii;
// }
/**
* Returns a new instance of AOSNSGAII
*
* @return
*/
private IHyperHeuristic newAOSNSGAII() {
int populationSize = (int) properties.getDouble("populationSize", 600);
Initialization initialization = new RandomInitialization(problem,
populationSize);
NondominatedSortingPopulation population = new NondominatedSortingPopulation();
TournamentSelection selection = new TournamentSelection(2,
new ChainedComparator(new ParetoDominanceComparator(),
new CrowdingComparator()));
//all other properties use default parameters
INextHeuristic selector = HHFactory.getInstance().getHeuristicSelector(properties.getString("HH", null), properties, heuristics);
AOSNSGAII aosnsgaii = new AOSNSGAII(problem, population, null, selection,
initialization, selector, creditDef);
return aosnsgaii;
}
// /**
// * Returns a new Hyper eMOEA instance.
// *
// * @param properties the properties for customizing the new {@code eMOEA}
// * instance
// * @param problem the problem
// * @return a new {@code eMOEA} instance
// */
// private IHyperHeuristic newHeMOEA() {
//
// int populationSize = (int) properties.getDouble("populationSize", 600);
//
// int injectionRate = (int) properties.getDouble("injectionRate", 0.25);
//
// //for injection
// int lagWindow = (int) properties.getDouble("lagWindow", 50);
//
// Initialization initialization = new RandomInitialization(problem,
// populationSize);
//
// Population population = new Population();
//
// DominanceComparator comparator = new ParetoDominanceComparator();
//
// EpsilonBoxDominanceArchive archive = new EpsilonBoxDominanceArchive(epsilonDouble);
//
// final TournamentSelection selection = new TournamentSelection(
// 2, comparator);
//
// //all other properties use default parameters
// INextHeuristic selector = HHFactory.getInstance().getHeuristicSelector(properties.getString("HH", null), properties, heuristics);
//
// HeMOEA hemoea = new HeMOEA(problem, population, archive, selection,
// initialization, selector, creditDef, injectionRate, lagWindow);
//
// return hemoea;
// }
/**
* Returns a new Hyper eMOEA instance.
*
* @param properties the properties for customizing the new {@code eMOEA}
* instance
* @param problem the problem
* @return a new {@code eMOEA} instance
*/
private IHyperHeuristic newMOEADHH() throws IOException {
int populationSize = (int) properties.getDouble("populationSize", 600);
Initialization initialization = new RandomInitialization(problem,
populationSize);
int neighborhoodSize = properties.getInt("neighborhood", 20);
double delta = properties.getDouble("delta", 0.9);
double eta = properties.getDouble("eta", 2.0);
int updateUtility = properties.getInt("updateUtility", 50);
INextHeuristic selector = HHFactory.getInstance().getHeuristicSelector(properties.getString("HH", null), properties, heuristics);
MOEADHH moeadhh = new MOEADHH(problem, neighborhoodSize, initialization,
delta, eta, updateUtility, selector, creditDef);
return moeadhh;
}
/**
* Goes through one run of the algorithm. Returns the algorithm object. Can
* get the population from the algorithm object
*
* @return the algorithm object. Can get the population from the algorithm
* object
* @throws Exception
*/
@Override
public IHyperHeuristic call() throws Exception {
IHyperHeuristic hh;
try {
creditDef = CreditDefFactory.getInstance().getCreditDef(properties.getString("CredDef", null), properties, problem);
} catch (IOException ex) {
Logger.getLogger(TestRun.class.getName()).log(Level.SEVERE, null, ex);
}
if (creditDef.getFitnessType() == CreditFitnessFunctionType.De) {
hh = newMOEADHH();
} else if (creditDef.getFitnessType() == CreditFitnessFunctionType.Do) {
hh = newAOSNSGAII();
} else if (creditDef.getFitnessType() == CreditFitnessFunctionType.I) {
hh = newAOSIBEA();
} else {
throw new IllegalArgumentException("Credit fitness type " + creditDef.getFitnessType() + "not recognized");
}
InstrumentedAlgorithm instAlgorithm = instrument(hh);
// run the executor using the listener to collect results
System.out.println("Starting " + hh.getNextHeuristicSupplier() + creditDef + " on " + probName + " with pop size: " + properties.getDouble("populationSize", 600));
long startTime = System.currentTimeMillis();
try {
while (!instAlgorithm.isTerminated() && (instAlgorithm.getNumberOfEvaluations() < maxEvaluations)) {
instAlgorithm.step();
if (instAlgorithm.getNumberOfEvaluations() % 1000 == 0) {
System.out.println(instAlgorithm.getNumberOfEvaluations());
}
}
} catch (Exception ex) {
Logger.getLogger(TestRun.class.getName()).log(Level.SEVERE, null, ex);
}
hh.terminate();
long finishTime = System.currentTimeMillis();
System.out.println("Done with optimization. Execution time: " + ((finishTime - startTime) / 1000) + "s");
hh.setName(String.valueOf(System.nanoTime()));
String filename = path + File.separator + properties.getProperties().getProperty("saveFolder") + File.separator + probName + "_" // + problem.getNumberOfObjectives()+ "_"
+ hh.getNextHeuristicSupplier() + "_" + hh.getCreditDefinition() + "_" + hh.getName();
saveIndicatorValues(instAlgorithm, filename);
if (Boolean.parseBoolean(properties.getProperties().getProperty("saveFinalPopulation"))) {
NondominatedPopulation ndPop = instAlgorithm.getResult();
try {
PopulationIO.writeObjectives(new File(filename + ".NDpop"), ndPop);
} catch (IOException ex) {
Logger.getLogger(TestRun.class.getName()).log(Level.SEVERE, null, ex);
}
}
if (Boolean.parseBoolean(properties.getProperties().getProperty("saveOperatorCreditHistory"))) {
IOCreditHistory ioch = new IOCreditHistory();
ioch.saveHistory(((IHyperHeuristic) hh).getCreditHistory(), filename + ".creditcsv",",");
}
if (Boolean.parseBoolean(properties.getProperties().getProperty("saveOperatorSelectionHistory"))) {
IOSelectionHistory iosh = new IOSelectionHistory();
iosh.saveHistory(((IHyperHeuristic) hh).getSelectionHistory(), filename + ".hist");
}
//save operator quality history
if (Boolean.parseBoolean(properties.getProperties().getProperty("saveOperatorQualityHistory"))) {
IOQualityHistory.saveHistory(((IHyperHeuristic) hh).getQualityHistory(), filename + ".qual");
}
return hh;
}
/**
* Attaches the collectors to the instrumented algorithm
*
* @param alg
* @return
*/
protected InstrumentedAlgorithm instrument(Algorithm alg) {
refPointObj = problem.newSolution();
for (int i = 0; i < problem.getNumberOfObjectives(); i++) {
refPointObj.setObjective(i, 1.1);
}
Instrumenter instrumenter = new Instrumenter().withFrequency(maxEvaluations / 100)
.withProblem(probName)
.attachAdditiveEpsilonIndicatorCollector()
.attachGenerationalDistanceCollector()
.attachInvertedGenerationalDistanceCollector()
.attachHypervolumeJmetalCollector(refPointObj)
.withEpsilon(epsilonDouble)
.withReferenceSet(referenceSet)
.attachElapsedTimeCollector();
return instrumenter.instrument(alg);
}
/**
* Saves the indicator values collected during the run.
*
* @param instAlgorithm
* @param filename
*/
protected void saveIndicatorValues(InstrumentedAlgorithm instAlgorithm, String filename) {
Accumulator accum = instAlgorithm.getAccumulator();
if (Boolean.parseBoolean(properties.getProperties().getProperty("saveIndicators"))) {
File results = new File(filename + ".res");
System.out.println("Saving results");
try (FileWriter writer = new FileWriter(results)) {
Set<String> keys = accum.keySet();
Iterator<String> keyIter = keys.iterator();
while (keyIter.hasNext()) {
String key = keyIter.next();
int dataSize = accum.size(key);
writer.append(key).append(",");
for (int i = 0; i < dataSize; i++) {
writer.append(accum.get(key, i).toString());
if (i + 1 < dataSize) {
writer.append(",");
}
}
writer.append("\n");
}
//also record the final HV
NondominatedPopulation ndPop = instAlgorithm.getResult();
FastHypervolume fHV = new FastHypervolume(problem, referenceSet, refPointObj);
double hv = fHV.evaluate(ndPop);
writer.append("Final HV, " + hv + "\n");
//also record the final IGD
InvertedGenerationalDistance igd = new InvertedGenerationalDistance(problem, referenceSet);
double figd = igd.evaluate(ndPop);
writer.append("Final IGD, " + figd + "\n");
writer.flush();
} catch (Exception ex) {
Logger.getLogger(TestRun.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}