maxVals; protected int[] bitsPerVar; protected boolean[] genotype; protected int[] fenotype; protected float fitness; protected int totalBits; public BinaryIntChromosome(int[] minVals, int[] maxVals, Random random) { this.minVals = minVals; this.maxVals = maxVals; this.bitsPerVar = new int[minVals.length]; for (int i = 0; i < minVals.length; i++) { int nBits = maxVals[i] - minVals[i] + 1; double bits = Math.log(nBits)/Math.log(2); bitsPerVar[i] = (int) Math.ceil(bits); this.totalBits += bitsPerVar[i]; } this.genotype = new boolean[totalBits]; this.fenotype = new int[minVals.length]; if (random != null) this.randomizeGenotype(random); } protected void randomizeGenotype(Random random) { for (int i = 0; i < totalBits; i++) genotype[i] = random.nextBoolean(); } protected static int binToDec(boolean[] string, int startIndex, int endIndex) { int val = 0; int slot = 0; for (int i = startIndex; i <= endIndex; i++) { if (string[i]) val += (int) Math.pow(2, slot); slot++; } return val; } protected void mutate(Random random, float mutationRate) { for (int i = 0; i < genotype.length; i++) { float f = random.nextFloat(); if (f < mutationRate) genotype[i] = !genotype[i]; } } protected BinaryIntChromosome duplicate() { int[] lb = new int[minVals.length]; int[] ub = new int[maxVals.length]; for (int i = 0; i < minVals.length; i++) { lb[i] = minVals[i]; ub[i] = maxVals[i]; } BinaryIntChromosome theCopy = new BinaryIntChromosome(lb, ub, null); for (int i = 0; i < this.genotype.length; i++) theCopy.genotype[i] = this.genotype[i]; for (int i = 0; i < this.fenotype.length; i++) theCopy.fenotype[i] = this.fenotype[i]; return theCopy; } protected void decode() { int bitIndex = 0; for (int var = 0; var < bitsPerVar.length; var++) { int bitsToRead = bitsPerVar[var]; int startIndex = bitIndex; int endIndex = startIndex + bitsToRead - 1; int decVal = BinaryIntChromosome.binToDec(this.genotype, startIndex, endIndex); int n = (int)(Math.pow(2, bitsToRead) - 1); int range = maxVals[var] - minVals[var]; this.fenotype[var] = this.minVals[var] + (range * decVal) / n; bitIndex += bitsToRead; } } public int compareTo(BinaryIntChromosome other) { if (this.fitness > other.fitness) return 1; else if (this.fitness < other.fitness) return -1; return 0; } } Interface FitnessDelegateEssa interface define o metodo getFitness, onde a qualidade do individuo seradeterminada passando-se o fenotipo como argumento:public interface FitnessDelegate{ float getFitness(int[] fenotype);}Classe HillClimb Agora que ja sabemos como codificar/decodificar nossas variaveis, e uma boa hora para implementar o HC. O construtor da classe recebe os vetores de minimo e maximo e tambem a taxa de mutacao que sera aplicada ao cromossomo. O objeto passado em delegate implementa a interface FitnessDelegate, sendo responsavel pelo calculo de fitness. O metodo evolve simplesmente avanca uma geracao, podendo ser executado em uma Thread separada e notificar outras Threads, caso necessario. Por fim, getBest nos retorna a melhor solucao obtida ate entao, que no caso do HC e sempre igual a solucao atual, ja que se trata de um algoritmo 'greedy'. Segue a classe:import java.util.Random;import java.util.concurrent.CountDownLatch;public class HillClimb implements Runnable{ protected BinaryIntChromosome current; protected BinaryIntChromosome best; protected float mutationRate; protected FitnessDelegate delegate; protected Random random = new Random(); protected CountDownLatch signal; public HillClimb(int[] lower, int[] upper, FitnessDelegate delegate, float mutationRate, CountDownLatch signal, boolean randomizeStart) { this.delegate = delegate; this.mutationRate = mutationRate; this.signal = signal; current = new BinaryIntChromosome(lower, upper, randomizeStart ? random : null); current.decode(); current.fitness