package catolica.ia;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import catolica.ia.ser.Populacao;
public class Ag {
public static void main(String[] args) {
File arquivo = new File("resultado.txt");
FileWriter fr = null;
try {
fr = new FileWriter(arquivo);
System.out.println("Inicio do experimento! (processando...) ");
Populacao p = new Populacao(100);
for (int i = 0; i < 25; i++) { fr.write("geracao: " + i + "\n"); p.novaGeracao(0.10, 0.01); fr.write(p.toString()); } System.out.println("fim do experimento!"); fr.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } Populacao.java package catolica.ia.ser; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; /** * Esta classe tem o objetivo de prover a abstração necessaria para o * funcionamento de uma populacao de individuos. * * @author Daniel Gatis Carrazzoni * */ public class Populacao { private Collection
individuos;
private int tamanho;
/**
* construtor.
*
* @param tamanho
* tamanho da populacao.
*/
public Populacao(int tamanho) {
this.tamanho = tamanho;
individuos = new ArrayList
(tamanho);
initPopulacao(tamanho);
}
/**
* inicializa populacao.
*
* @param tamanho
* tamanho da populacao.
*/
private void initPopulacao(int tamanho) {
for (int i = 0; i < tamanho; i++) { individuos.add(new Individuo()); } } /** * cria uma nova geração da população. * * @param taxaDeCruzamento * taxa de cruzamento. * @param taxaDeMutacao * taxa de mutacao. */ public void novaGeracao(double taxaDeCruzamento, double taxaDeMutacao) { int iteracoes = (int)(taxaDeCruzamento * tamanho); for (int i = 0; i < iteracoes; i++) { addIndividuo(getCasal().cruzar(taxaDeMutacao)); } } /** * adiciona um individuo na população. caso o individuo a ser adicionado * seja um mutante ele é colocado no lugar do individuo de menor fitness da * populacao. caso a individuo não seja mutante só adiciona se o fitness do * individuo seja maior que o menor fitness da populacao. * * @param individuo novo individuo. */ private void addIndividuo(Individuo individuo) { double menorFit = Integer.MAX_VALUE; int indiceASubstituir = 0; Individuo[] temp = new Individuo[tamanho]; individuos.toArray(temp); for (int i = 0; i < temp.length; i++) { if (temp[i].getFitness() <= menorFit) { indiceASubstituir = i; menorFit = temp[i].getFitness(); } } if (individuo.isMutante()) { individuos.remove(temp[indiceASubstituir]); individuos.add(individuo); } else { if (temp[indiceASubstituir].getFitness() < individuo.getFitness()) { individuos.remove(temp[indiceASubstituir]); individuos.add(individuo); } } } /** * seleciona um casal apto ao cruzamento. * @return casal. */ private Casal getCasal() { Individuo pai = selecionar(); Individuo mae; do { mae = selecionar(); } while (pai.equals(mae)); return new Casal(pai, mae); } /** * selecao baseada no metodo da roleta. * @return o individuo selecionado. */ private Individuo selecionar() { double somatorioDosFitness = 0; double fitnessAcumulado = 0; Individuo retorno = null; Collection
roleta = new ArrayList(); Iterator it = individuos.iterator(); while (it.hasNext()) { somatorioDosFitness += it.next().getFitness(); } Iterator it2 = individuos.iterator(); while (it2.hasNext()) { Individuo individuo = it2.next(); roleta.add(new Object[] { new Double(fitnessAcumulado), new Double(fitnessAcumulado + individuo.getFitness() / somatorioDosFitness), individuo }); fitnessAcumulado += individuo.getFitness() / somatorioDosFitness; } double sorteio = Math.random(); Iterator it3 = roleta.iterator(); while (it3.hasNext()) { Object[] atual = it3.next(); double limiteInferior = ((Double) atual[0]).doubleValue(); double limiteSuperior = ((Double) atual[1]).doubleValue(); Individuo individuo = (Individuo) atual[2]; if (sorteio >= limiteInferior && sorteio < limiteSuperior) { retorno = individuo; break; } } return retorno; } /** * @see #toString() */ public String toString() { StringBuffer saida = new StringBuffer("Populacao: \n"); Iterator it = individuos.iterator(); while (it.hasNext()) { saida.append("\n"); saida.append(it.next().toString()); } return saida.toString(); } } Casal.java package catolica.ia.ser; /** * Esta classe tem o objetivo de prover a abstração necessaria para o funcionamento * de um casal de individuos. * * @author Daniel Gatis Carrazzoni * */ public class Casal { private Individuo pai; private Individuo mae; /** * construtor. * @param pai individuo 1. * @param mae individuo 2. */ public Casal(Individuo pai, Individuo mae) { this.pai = pai; this.mae = mae; } /** * realiza o cruzamento entre o casal. * @param taxaDeMutacao taxa de mutacao. * @return filho gerado do cruzamento. */ public Individuo cruzar(double taxaDeMutacao) { return pai.cruzar(mae, taxaDeMutacao); } } Individuo.java package catolica.ia.ser; import java.util.ArrayList; import java.util.Collection; import catolica.ia.gen.Cromossomo; /** * Esta classe tem o objetivo de prover a abstração necessaria para o funcionamento * de um individuo. * * @author Daniel Gatis Carrazzoni */ public class Individuo implements Comparable { private static final int TAMANHO_DO_DNA = 1; private Cromossomo[] dna; private boolean mutante; /** * construtor. * @param dna array de cromossomos. */ public Individuo(Cromossomo[] dna) { this.dna = dna; } /** * construtor simples. * */ public Individuo() { this.dna = new Cromossomo[TAMANHO_DO_DNA]; for (int i = 0; i < dna.length; i++) { this.dna[i] = new Cromossomo(); } } /** * faz o cruzamento entre individuos e depois faz a mutacao no filho. * @param individuo individuo para cruzar. * @param taxaDeMutacao taxa de mutacao. * @return filho gerado do cruzamento. */ public Individuo cruzar(Individuo individuo, double taxaDeMutacao) { boolean mutante = false; Collection novoDna = new ArrayList(); for (int i = 0; i < dna.length; i++) { Cromossomo novoCromossomo = getDna()[i].crossover(individuo .getDna()[i]); if (novoCromossomo.mutation(taxaDeMutacao)) { mutante = true; } novoDna.add(novoCromossomo); } Cromossomo[] temp = new Cromossomo[TAMANHO_DO_DNA]; Individuo filho = new Individuo(novoDna.toArray(temp)); filho.setMutante(mutante); return filho; } /** * retorna o fenotipo custo do individuo. * @return custo. */ public double getCusto() { int limiteSuperior = 20; int limiteInferior = 1; return limiteInferior + ((limiteSuperior-limiteInferior)/255.0) *dna[0].getFenotipo(0, 8); } /** * retorna o fenotipo beneficio do individuo. * @return beneficio. */ public double getBeneficio() { int limiteSuperior = 100; int limiteInferior = 1; return limiteInferior + ((limiteSuperior-limiteInferior)/255.0) *dna[0].getFenotipo(8, 16); } /** * retorna o dna do indivduo. * @return array de cromossomos. */ public Cromossomo[] getDna() { return dna; } /** * @see #toString() */ public String toString() { StringBuffer saida = new StringBuffer("Individuo: \n"); for (int i = 0; i < dna.length; i++) saida.append(dna[i].toString() + "\n"); saida.append("mutante: " + isMutante() + "\n"); saida.append("custo: " + getCusto() + "\n"); saida.append("beneficio: " + getBeneficio() + "\n"); saida.append("fitness: " + getFitness() + "\n"); return saida.toString(); } /** * retorna o fitness do individuo. * maximiza o beneficio e reduz o custo. * @return fitness */ public double getFitness() { return 1.00 / ((getCusto() / getBeneficio()) + getCusto()); } /** * compara dois individuos * @param inidviduo * @return 0 se for igual, 1 se for maior, -1 se for menor */ public int compareTo(Object inidviduo) { Individuo that = (Individuo) inidviduo; double esse = this.getFitness(); double aquele = that.getFitness(); return new Double(esse).compareTo(new Double(aquele)); } /** * retorna se o individuo sofreu mutacao. * @return true caso tenha sofrido mutacao. */ public boolean isMutante() { return mutante; } /** * seta o individuo mutante. * @param mutante true ou false. */ public void setMutante(boolean mutante) { this.mutante = mutante; } /** * @see #equals(Object) */ public boolean equals(Object individuo) { if (individuo == this) { return true; } if (!(individuo instanceof Individuo)) { return false; } Individuo that = (Individuo) individuo; return this.getDna().equals(that.getDna()); } } Cromossomo.java package catolica.ia.gen; /** * Esta classe tem o objetivo de prover a abstração necessaria para o funcionamento * de um cromosso. * * @author Daniel Gatis Carrazzoni */ public class Cromossomo { private static final int TAMANHO_DO_CROMOSSOMO = 16; private Gene[] genes; /** * construtor simples. * */ public Cromossomo() { genes = new Gene[TAMANHO_DO_CROMOSSOMO]; initCromossomo(); } /** * inicializa o cromossomo de uma forma aleatoria. * */ private void initCromossomo() { for (int i = 0; i < genes.length; i++) { genes[i] = new Gene(); } } /** * faz o cruzamento entre cromossomos. * seguindo a regra: * posicao par : gene do pai * posicao impar: gene da mae * * exemplo * * pai : 01011100 * mae : 11100010 * * filho : 01001000 * * * * @param cromossomo cromossomo para cruzar. * @return cromossomo filho. */ public Cromossomo crossover(Cromossomo cromossomo) { Cromossomo novoCromossomo = new Cromossomo(); for (int i = 0; i < genes.length; i++) { Gene novoGene; if (i % 2 == 0) { novoGene = new Gene(this.getGenes()[i] .getValor()); } else { novoGene = new Gene(cromossomo.getGenes()[i] .getValor()); } novoCromossomo.getGenes()[i] = novoGene; } return novoCromossomo; } /** * causa a mutacao para cada gene cromossomo. * * @param porcentagem taxa de mutacao. * @return caso o cromossomo tenha sofrido mutacao retorna true. */ public boolean mutation(double porcentagem) { boolean retorno = false; for (int i = 0; i < genes.length; i++) { if (genes[i].mutation(porcentagem)) { retorno = true; } } return retorno; } /** * retorna uma caracteristica baseado no cromossomo. * * @param geneInicial gene inicial. * @param geneFinal gene final. * @return valor da caracteristica. */ public int getFenotipo(int geneInicial, int geneFinal) { int valor = 0; int delta = geneFinal - geneInicial; for (int i = 0; i < delta; i++) valor += genes[i + geneInicial].getValor() * Math.pow(2, delta - i); return valor / 2; } /** * pega o array de genes do cromossomo. * @return um array de genes. */ public Gene[] getGenes() { return genes; } /** * seta um array de genes do cromossomo. * @param genes array de genes. */ public void setGenes(Gene[] genes) { this.genes = genes; } /** * @see #toString() */ public String toString() { StringBuffer saida = new StringBuffer("Cromossomo: [ "); for (int i = 0; i < genes.length; i++) { if (i == TAMANHO_DO_CROMOSSOMO / 2) { saida.append("| "); } saida.append(genes[i].toString()); saida.append(" "); } saida.append("]"); return saida.toString(); } /** * @see #equals(Object) */ public boolean equals(Object cromossomo) { if (cromossomo == this) { return true; } if (!(cromossomo instanceof Cromossomo)) { return false; } Cromossomo that = (Cromossomo) cromossomo; for (int i = 0; i < genes.length; i++) { if (!this.getGenes()[i].equals(that.getGenes()[i])){ return false; } } return true; } } Gene.java package catolica.ia.gen; import java.util.Random; /** * Esta classe tem o objetivo de prover a abstração necessaria para o funcionamento * de um gene. * * @author Daniel Gatis Carrazzoni */ public class Gene implements Comparable { private byte valor; /** * construtor simples. */ public Gene() { Random r = new Random(); this.valor = (byte) r.nextInt(2); } /** * seta um valor para o gene 0 ou 1 * @param valor valor. */ public Gene(byte valor) { setValor(valor); } /** * retorna o valor do gene. * @return valor. */ public byte getValor() { return valor; } /** * causa a mutacao no gene dependendo da porcentagem. * * @param porcentagem * @return caso tenha ocorrido a mutacao no gene retorna true. */ public boolean mutation(double porcentagem) { boolean retorno = false; if (Math.random() < porcentagem) { if (valor == 1) valor = 0; else valor = 1; retorno = true; } return retorno; } /** * seta um valor no gene. * * @param valor valor. */ public void setValor(byte valor) { if (valor > 1) { this.valor = 1; } else { if (valor < 0) { this.valor = 0; } } this.valor = valor; } /** * @see #toString() */ public String toString() { return String.valueOf(valor); } /** * @see #equals(Object) */ public boolean equals(Object cromossomo) { if (cromossomo == this) { return true; } if (!(cromossomo instanceof Gene)) { return false; } Gene that = (Gene) cromossomo; return this.getValor() == that.getValor(); } public int compareTo(Object cromossomo) { return new Byte(valor).compareTo((Byte)cromossomo); } }