package search.searchtechniques;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.jgap.*;
import org.jgap.impl.DefaultConfiguration;
import org.jgap.impl.IntegerGene;
import org.jgap.impl.StockRandomGenerator;
import primitives.cluster.ClusterHead;
import search.fitnessfunctions.util.TreeTranslator;
import search.genes.*;
public class RandomMutationHillClimbingSearch extends Search {
private ArrayList<Gene> individual;
private ArrayList<Gene> mutant;
RandomGenerator rng;
double fitness;
public RandomMutationHillClimbingSearch() {
}
public ArrayList<Gene> newIndividual() throws InvalidConfigurationException {
Configuration gaConf = new DefaultConfiguration();
GeneFactory gf = new GeneFactory(geneType, in.getSize());
ArrayList<Gene> a_individual = new ArrayList<Gene>();
for (int i = 0; i < chromesize; i++) {
Gene g = gf.getInstance(gaConf);
g.setToRandomValue(rng);
a_individual.add(g);
}
return a_individual;
}
public ArrayList<Gene> copy(ArrayList<Gene> individual) {
ArrayList<Gene> copy = new ArrayList<Gene>();
for (int i = 0; i < individual.size(); i++) {
Gene ind = individual.get(i);
if(ind instanceof InstructionGene){
copy.add(((InstructionGene)ind).clone());
}else if(ind instanceof StackInstructionGene){
copy.add(((StackInstructionGene)ind).clone());
}else if(ind instanceof IntegerGene){
IntegerGene c = (IntegerGene)ind;
IntegerGene n = null;
try {
n = new IntegerGene(ind.getConfiguration(), c.getLowerBounds(), c.getUpperBounds());
} catch (InvalidConfigurationException ex) {
Logger.getLogger(RandomMutationHillClimbingSearch.class.getName()).log(Level.SEVERE, null, ex);
}
n.setAllele(c.intValue());
copy.add(n);
}else{
throw new RuntimeException(String.format("Can't make a clone of gene of type %s object is: %s ",ind.getClass().toString(), ind));
}
}
return copy;
}
public ArrayList<Gene> mutateIndividual(ArrayList<Gene> individual) {
ArrayList<Gene> toMutate = copy(individual);
int position = rng.nextInt(individual.size() - 1);
Gene target = toMutate.get(position);
int sign = 1;
if(Math.random() >= 0.5) sign = -1;
//most genes will ignore the position argument (first one), but bitfield needs it to choose which bits to modify.
target.applyMutation(rng.nextInt(32),sign * rng.nextDouble());
return toMutate;
}
private double evaluateIndividual(ArrayList<Gene> individual){
return ff.evaluateTree(TreeTranslator.getTree(individual, in, geneType));
}
public void setup() throws InvalidConfigurationException{
rng = new StockRandomGenerator();
//todo: allow setting seed of rng;
individual = newIndividual();
fitness = evaluateIndividual(individual);
}
public double iteration(){
mutant = mutateIndividual(individual);
double mutant_fitness = evaluateIndividual(mutant);
if (mutant_fitness > fitness) {
Logger.getLogger(RandomMutationHillClimbingSearch.class.getName()).log(Level.FINE, "RMHC: got a fitness increase: {0} to {1} (delta {2})",new Object[]{fitness, mutant_fitness,mutant_fitness-fitness});
fitness = mutant_fitness;
individual = mutant;
}
return fitness;
}
public ClusterHead getClustering(){
return TreeTranslator.getTree(individual, in, geneType);
}
public double getFitness(){
return fitness;
}
}