/*
* 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.hyperheuristics;
import hh.history.CreditHistory;
import hh.history.OperatorQualityHistory;
import hh.history.OperatorSelectionHistory;
import hh.nextheuristic.INextHeuristic;
import hh.creditassigment.ICreditAssignment;
import hh.creditassigment.Credit;
import hh.creditassignment.offspringparent.ParentDecomposition;
import hh.creditassignment.populationcontribution.DecompositionContribution;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import org.moeaframework.algorithm.MOEAD;
import org.moeaframework.core.Initialization;
import org.moeaframework.core.ParallelPRNG;
import org.moeaframework.core.Problem;
import org.moeaframework.core.Solution;
import org.moeaframework.core.Variation;
/**
* Implements MOEA/D-DRA.
*
* @author SEAK2
*/
public class MOEADHH extends MOEAD implements IHyperHeuristic {
/**
* The type of heuristic selection method
*/
private final INextHeuristic operatorSelector;
/**
* The Credit definition to be used that defines how much credit to receive
* for certain types of solutions
*/
private final ICreditAssignment creditDef;
/**
* The history that stores all the heuristics selected by the hyper
* heuristics. History can be extracted by getSelectionHistory(). Used for
* analyzing the results to see the dynamics of heuristics selected
*/
private OperatorSelectionHistory heuristicSelectionHistory;
/**
* The set of heuristics that the hyper heuristic is able to work with
*/
private final Collection<Variation> heuristics;
/**
* The history of the heuristics' qualities over time. Used for analyzing
* the results to see the dynamics of the heuristic qualities
*/
private OperatorQualityHistory qualityHistory;
/**
* parallel purpose random generator
*/
private final ParallelPRNG pprng;
/**
* Iteration count
*/
private int iteration;
/**
* Name to id the hyper-heuristic
*/
private String name;
/**
* The population contribution rewards from the previous iteration
*/
private HashMap<Variation, Credit> prevPopContRewards;
/**
* Probability that an offspring will mate with neighbors
*/
private final double delta;
/**
* Indices for the population
*/
private final List<Integer> popIndices;
/**
* History of credits received by each operator
*/
private final CreditHistory creditHistory;
public MOEADHH(Problem problem, int neighborhoodSize,
Initialization initialization, double delta, double eta, int updateUtility,
INextHeuristic operatorSelector, ICreditAssignment creditDef) {
super(problem, neighborhoodSize, initialization, operatorSelector.getOperators().iterator().next(), delta, eta, updateUtility);
this.heuristics = operatorSelector.getOperators();
this.operatorSelector = operatorSelector;
this.creditDef = creditDef;
this.delta = delta;
this.heuristicSelectionHistory = new OperatorSelectionHistory(heuristics);
this.creditHistory = new CreditHistory(heuristics);
this.qualityHistory = new OperatorQualityHistory(heuristics);
this.pprng = new ParallelPRNG();
this.iteration = 0;
super.initialize();
//initialize the previous population contribution rewards to all zero for each heuristic
prevPopContRewards = new HashMap<>();
for (Variation heur : heuristics) {
prevPopContRewards.put(heur, new Credit(0, 0.0));
}
popIndices = new ArrayList<>();
for (int i = 0; i < population.size(); i++) {
popIndices.add(i);
}
}
public List<Solution> getPopulation(){
ArrayList<Solution> out = new ArrayList<>();
for(Individual ind:population)
out.add(ind.getSolution());
return out;
}
@Override
public void iterate() {
List<Integer> indices = getSubproblemsToSearch();
for (Integer index : indices) {
iteration++;
//select next heuristic
Variation operator = operatorSelector.nextHeuristic();
List<Integer> matingIndices = getMatingIndices(index);
Solution[] parents = new Solution[operator.getArity()];
Individual parent = population.get(index);
parents[0] = parent.getSolution();
//decide mating pool
boolean useNeighborhood = pprng.nextDouble() < delta;
if(!useNeighborhood)
matingIndices = new ArrayList(popIndices);
if (operator.getArity() > 2) {
// mimic MOEA/D parent selection for differential evolution
pprng.shuffle(matingIndices);
for (int i = 1; i < operator.getArity() - 1; i++) {
parents[i] = population.get(
matingIndices.get(i - 1)).getSolution();
}
parents[operator.getArity() - 1]
= population.get(index).getSolution();
} else {
for (int i = 1; i < operator.getArity(); i++) {
parents[i] = population.get(
pprng.nextItem(matingIndices)).getSolution();
}
}
//create new offspring
Solution[] offspring= operator.evolve(parents);
//compute the credit assignment specific rewards
switch (creditDef.getInputType()) {
case OP:
double reward = 0;
for (Solution child : offspring) {
evaluate(child);
updateIdealPoint(child);
updateSolution(child, matingIndices);
ParentDecomposition OPDe = ((ParentDecomposition) creditDef);
OPDe.setWeights(parent.getWeights());
OPDe.setIdealPoint(getIdealPoint());
reward += OPDe.compute(child, parents[0], null, null);
}
if(reward <0)
reward = 0;
Credit operatorReward = new Credit(this.numberOfEvaluations, reward);
operatorSelector.update(operatorReward, operator);
creditHistory.add(operator, operatorReward);
break;
case SI:
double rewardSi = 0;
for (Solution child : offspring) {
evaluate(child);
updateIdealPoint(child);
updateSolution(child, matingIndices);
rewardSi += updateSolution(child, matingIndices);
}
if(rewardSi <0)
reward = 0;
Credit operatorRewardSi = new Credit(this.numberOfEvaluations, rewardSi);
operatorSelector.update(operatorRewardSi, operator);
creditHistory.add(operator, operatorRewardSi);
break;
case CS:
for (Solution child : offspring) {
evaluate(child);
updateIdealPoint(child);
updateSolution(child, matingIndices);
child.setAttribute("iteration", new SerializableVal(iteration));
child.setAttribute("heuristic", new SerializableVal(operator.toString()));
}
DecompositionContribution CDe = ((DecompositionContribution) creditDef);
HashMap<Variation, Credit> contRewards = CDe.compute(getNeighborhoodSolutions(index), heuristics, iteration);
Iterator<Variation> iter = contRewards.keySet().iterator();
while (iter.hasNext()) {
Variation operator_i = iter.next();
operatorSelector.update(contRewards.get(operator_i), operator_i);
creditHistory.add(operator_i, new Credit(this.numberOfEvaluations,contRewards.get(operator_i).getValue()));
}
break;
default:
throw new NullPointerException("Credit definition not "
+ "recognized. Used " + creditDef.getInputType() + ".");
}
heuristicSelectionHistory.add(operator,this.numberOfEvaluations);
// updateQualityHistory();
}
generation++;
if ((updateUtility >= 0) && (generation % updateUtility == 0)) {
updateUtility();
}
}
/**
* Updates the quality history every iteration for each heuristic
* according to the INextHeuristic class used
*/
private void updateQualityHistory() {
HashMap<Variation, Double> currentQualities = operatorSelector.getQualities();
for (Variation heuristic : heuristics) {
qualityHistory.add(heuristic, currentQualities.get(heuristic));
}
}
/**
* Reset the hyperheuristic. Clear all selection history and the credit
* repository
*/
@Override
public void reset() {
iteration = 0;
heuristicSelectionHistory.reset();
operatorSelector.reset();
numberOfEvaluations = 0;
qualityHistory.clear();
}
/**
* Returns the ordered history of heuristics that were selected
*
* @return The ordered history of heuristics that were selected
*/
@Override
public OperatorSelectionHistory getSelectionHistory() {
return heuristicSelectionHistory;
}
/**
* gets the quality history stored for each heuristic in the hyper-heuristic
*
* @return
*/
@Override
public OperatorQualityHistory getQualityHistory() {
return qualityHistory;
}
@Override
public ICreditAssignment getCreditDefinition() {
return creditDef;
}
@Override
public INextHeuristic getNextHeuristicSupplier() {
return operatorSelector;
}
@Override
public String getName() {
return name;
}
@Override
public void setName(String name) {
this.name = name;
}
@Override
public CreditHistory getCreditHistory() {
return creditHistory;
}
}