Skip to content

Commit

Permalink
Implemtacao das classes AG,Individuo,Cidade e Main em java, seguindo …
Browse files Browse the repository at this point in the history
…a base da implementacao em python
  • Loading branch information
Davi committed Dec 10, 2024
1 parent 7a15574 commit 0fee68f
Show file tree
Hide file tree
Showing 4 changed files with 394 additions and 0 deletions.
146 changes: 146 additions & 0 deletions src/java/deliveryAG/AlgoritmoGenetico.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
package deliveryAG;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;


public class AlgoritmoGenetico {
private int tamanhoPopulacao;
private double taxaMutacao;
private boolean debugMode;
private List<deliveryAG.Individuo> populacao;
private List<deliveryAG.Individuo> melhoresSolucoesGeracao;
private List<deliveryAG.Individuo> historicoPopulacao;
private deliveryAG.Individuo melhorSolucao;

public AlgoritmoGenetico(int tamanhoPopulacao, double taxaMutacao, boolean debugMode) {
this.tamanhoPopulacao = tamanhoPopulacao;
this.taxaMutacao = taxaMutacao;
this.debugMode = debugMode;
this.populacao = new ArrayList<>();
this.melhoresSolucoesGeracao = new ArrayList<>();
this.historicoPopulacao = new ArrayList<>();
this.melhorSolucao = null;
}

public void inicializaPopulacao(List<deliveryAG.Cidade> cidades, int[][] rotas, List<Integer> caminho, int centroDistribuicao) {
for (int i = 0; i < this.tamanhoPopulacao; i++) {
this.populacao.add(new deliveryAG.Individuo(cidades, rotas, caminho, centroDistribuicao,1 , null));
}
this.melhorSolucao = this.populacao.get(0);
this.historicoPopulacao = this.populacao;
}

public void ordenaPopulacao() {
this.populacao.sort((individuo1, individuo2) -> Double.compare(individuo1.getNotaAvaliacao(), individuo2.getNotaAvaliacao()));
}

public void melhorIndividuo(deliveryAG.Individuo individuo) {
if (individuo.getNotaAvaliacao() < this.melhorSolucao.getNotaAvaliacao()) {
this.melhorSolucao = individuo;
}
}

public double somaAvaliacoes() {
return this.populacao.stream().mapToDouble(deliveryAG.Individuo::getNotaAvaliacao).sum();
}

public void visualizaGeracao() {
/* if (!this.debugMode) {
return;
}*/
deliveryAG.Individuo melhor = this.populacao.get(0);
System.out.println(" *****");
System.out.println(" Geração: " + melhor.getGeracao());
System.out.println(" Melhor solução: " + melhor.getNotaAvaliacao());
System.out.println(" Distância percorrida: " + melhor.getDistanciaPercorrida());
System.out.println(" Cidades percorridas: " + melhor.getCidadesPercorridas());
System.out.println(" Cromossomo: " + melhor.cromossomoToView());
System.out.println(" *****");
}

public void visualizaMelhorGeracao() {
if (!this.debugMode) {
return;
}
deliveryAG.Individuo melhor = this.melhorSolucao;
System.out.println(" ***** (Melhor solução) *****");
System.out.println(" Geração: " + melhor.getGeracao());
System.out.println(" Melhor solução: " + melhor.getNotaAvaliacao());
System.out.println(" Distância percorrida: " + melhor.getDistanciaPercorrida());
System.out.println(" Cidades percorridas: " + melhor.getCidadesPercorridas());
System.out.println(" Cromossomo: " + melhor.cromossomoToView());
System.out.println(" ***** ================ *****");
}

public void gerarProbabilidade() {
List<Double> pesos = new ArrayList<>();
for (int i = 0; i < this.populacao.size(); i++) {
pesos.add(1.0 / (i + 1));
}
double somaPesos = pesos.stream().mapToDouble(Double::doubleValue).sum();

for (int i = 0; i < this.populacao.size(); i++) {
deliveryAG.Individuo individuo = this.populacao.get(i);
individuo.setProbabilidade((pesos.get(i) / somaPesos) * 100);
}
}

public int selecionaPai() {
List<Double> cumulativas = new ArrayList<>();
double soma = 0;
for (deliveryAG.Individuo individuo : this.populacao) {
soma += individuo.getProbabilidade();
cumulativas.add(soma);
}

Random random = new Random();
int numeroAleatorio = random.nextInt(100);

for (int i = 0; i < cumulativas.size(); i++) {
if (numeroAleatorio < cumulativas.get(i)) {
return i;
}
}
return selecionaPai();
}

public deliveryAG.Individuo resolver(int numeroGeracoes, List<deliveryAG.Cidade> cidades, int[][] rotas, List<Integer> caminho, int centroDistribuicao) {
inicializaPopulacao(cidades, rotas, caminho, centroDistribuicao);
ordenaPopulacao();
gerarProbabilidade();
visualizaGeracao();
this.melhoresSolucoesGeracao.add(this.populacao.get(0));

for (int i = 0; i < numeroGeracoes; i++) {
List<deliveryAG.Individuo> novaPopulacao = new ArrayList<>();

for (int j = 0; j < this.tamanhoPopulacao; j += 2) {
int pai1 = selecionaPai();
int pai2 = selecionaPai();

List<deliveryAG.Individuo> filhos = this.populacao.get(pai1).crossover(this.populacao.get(pai2));
novaPopulacao.add(filhos.get(0).mutacao(this.taxaMutacao));
novaPopulacao.add(filhos.get(1).mutacao(this.taxaMutacao));
}

novaPopulacao = novaPopulacao.subList(0, novaPopulacao.size() - 5);
novaPopulacao.addAll(this.populacao.subList(0, 5));

this.populacao = novaPopulacao;
ordenaPopulacao();
gerarProbabilidade();
visualizaGeracao();
this.historicoPopulacao.addAll(this.populacao);

deliveryAG.Individuo melhor = this.populacao.get(0);
melhorIndividuo(melhor);
this.melhoresSolucoesGeracao.add(melhor);
}

visualizaMelhorGeracao();
return this.melhorSolucao;
}
}

25 changes: 25 additions & 0 deletions src/java/deliveryAG/Cidade.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package deliveryAG;

public class Cidade {
private String nome; // Nome da cidade

// Construtor
public Cidade(String nome) {
this.nome = nome;
}

// Getter para o nome da cidade
public String getNome() {
return nome;
}

// Setter para o nome da cidade (opcional, se necessário)
public void setNome(String nome) {
this.nome = nome;
}

@Override
public String toString() {
return nome;
}
}
154 changes: 154 additions & 0 deletions src/java/deliveryAG/Individuo.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
package deliveryAG;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class Individuo {
private List<deliveryAG.Cidade> cidades; // Lista de cidades disponíveis
private int[][] rotas; // Matriz de distâncias entre as cidades
private List<Integer> caminho; // Cidades obrigatórias a serem visitadas
private int centroDistribuicao; // Cidade inicial e final obrigatória
private int geracao; // Número da geração do indivíduo
private List<Integer> cromossomo; // Sequência de cidades percorridas
private double distanciaPercorrida; // Distância total percorrida
private int cidadesPercorridas; // Número de cidades diferentes visitadas
private double notaAvaliacao; // Avaliação da qualidade da rota
private double probabilidade; // Probabilidade de seleção

private static final Random RANDOM = new Random();

// Construtor
public Individuo(List<deliveryAG.Cidade> cidades, int[][] rotas, List<Integer> caminho, int centroDistribuicao, int geracao, List<Integer> cromossomo) {
this.cidades = cidades;
this.rotas = rotas;
this.caminho = caminho;
this.centroDistribuicao = centroDistribuicao;
//this.geracao = geracao;
this.geracao = (geracao > 0) ? geracao : 1;
this.cromossomo = cromossomo != null ? cromossomo : gerarCromossomo();
this.notaAvaliacao = avaliacao();
}

// Gera um cromossomo aleatório
private List<Integer> gerarCromossomo() {
List<Integer> novoCromossomo = new ArrayList<>();
for (int i = 0; i < rotas.length; i++) {
novoCromossomo.add(RANDOM.nextInt(rotas.length));
}
return novoCromossomo;
}

// Calcula a avaliação do indivíduo
private double avaliacao() {
double somaDistancia = 0;
List<Integer> cidadesVisitadas = new ArrayList<>();

for (int i = 0; i < cromossomo.size() - 1; i++) {
int origem = cromossomo.get(i);
int destino = cromossomo.get(i + 1);
int distancia = rotas[origem][destino];

somaDistancia += (distancia == -1) ? 5000 : distancia;

if (caminho.contains(origem) && !cidadesVisitadas.contains(origem)) {
cidadesVisitadas.add(origem);
}
}

distanciaPercorrida = somaDistancia;
cidadesPercorridas = cidadesVisitadas.size();

int cidadesFaltando = caminho.size() - cidadesVisitadas.size();
somaDistancia += 100 * cidadesFaltando;

if (cromossomo.get(0) != centroDistribuicao) {
somaDistancia += 5000;
}
if (cromossomo.get(cromossomo.size() - 1) != centroDistribuicao) {
somaDistancia += 5000;
}

return somaDistancia;
}

// Realiza o crossover com outro indivíduo
public List<Individuo> crossover(Individuo outroIndividuo) {
int corte = RANDOM.nextInt(cromossomo.size());
List<Integer> filho1 = new ArrayList<>();
List<Integer> filho2 = new ArrayList<>();

filho1.addAll(outroIndividuo.cromossomo.subList(0, corte));
filho1.addAll(cromossomo.subList(corte, cromossomo.size()));

filho2.addAll(cromossomo.subList(0, corte));
filho2.addAll(outroIndividuo.cromossomo.subList(corte, outroIndividuo.cromossomo.size()));

List<Individuo> filhos = new ArrayList<>();
filhos.add(new Individuo(cidades, rotas, caminho, centroDistribuicao, geracao + 1, filho1));
filhos.add(new Individuo(cidades, rotas, caminho, centroDistribuicao, geracao + 1, filho2));

return filhos;
}

// Aplica mutação ao cromossomo
public Individuo mutacao(double taxaMutacao) {
for (int i = 0; i < cromossomo.size(); i++) {
if (RANDOM.nextDouble() <= taxaMutacao) {
cromossomo.set(i, RANDOM.nextInt(rotas.length));
}
}
notaAvaliacao = avaliacao();
return this;
}

// Converte o cromossomo para uma visualização com os nomes das cidades
public List<String> cromossomoToView() {
List<String> nomesCidades = new ArrayList<>();
for (int indice : cromossomo) {
nomesCidades.add(cidades.get(indice).getNome());
}
return nomesCidades;
}

// Imprime informações do indivíduo
public void print() {
System.out.println(" ***** ");
System.out.println(" Geração: " + geracao);
System.out.println(" Cromossomo: " + cromossomoToView());
System.out.println(" Distância percorrida: " + distanciaPercorrida);
System.out.println(" Cidades percorridas: " + cidadesPercorridas);
System.out.println(" Avaliação: " + notaAvaliacao);
System.out.println(" ***** ");
}

// Getters
public double getNotaAvaliacao() {
return notaAvaliacao;
}

public List<Integer> getCromossomo() {
return cromossomo;
}

// Métodos adicionais para corrigir os erros
public int getGeracao() {
return geracao;
}

public double getDistanciaPercorrida() {
return distanciaPercorrida;
}

public int getCidadesPercorridas() {
return cidadesPercorridas;
}

public void setProbabilidade(double probabilidade) {
this.probabilidade = probabilidade;
}

public double getProbabilidade() {
return probabilidade;
}
}
69 changes: 69 additions & 0 deletions src/java/deliveryAG/Main.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package deliveryAG;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;


public class Main {
public static void main(String[] args) {
// Lista de cidades
List<deliveryAG.Cidade> cidades = Arrays.asList(
new deliveryAG.Cidade("X"),
new deliveryAG.Cidade("A"),
new deliveryAG.Cidade("B"),
new deliveryAG.Cidade("C"),
new deliveryAG.Cidade("D"),
new deliveryAG.Cidade("E")
);

// Matriz de rotas (-1 indica rota inexistente)
int[][] rotas = {
{-1, 30, 50, 20, -1, -1},
{30, -1, 10, -1, -1, -1},
{50, 40, -1, 15, 30, 20},
{20, -1, 15, -1, -1, -1},
{-1, -1, 30, -1, -1, -1},
{-1, -1, 20, -1, -1, -1}
};

// Índices das cidades obrigatórias no percurso
List<Integer> rotasEntrega = Arrays.asList(2, 3, 5);

// Centro de distribuição (índice da cidade inicial/final)
int centroDistribuicao = 0;

// Parâmetros do algoritmo genético
double taxaMutacao = 0.05;
int numeroGeracoes = 400;
int tamanhoPopulacao = 20;
boolean debugMode = false;

// Inicializa o algoritmo genético
deliveryAG.AlgoritmoGenetico ag = new deliveryAG.AlgoritmoGenetico(
tamanhoPopulacao, taxaMutacao, debugMode
);

// Resolve o problema
ag.resolver(
numeroGeracoes,
cidades,
rotas,
rotasEntrega,
centroDistribuicao
);

// Exibe o melhor resultado encontrado
//System.out.println("\n\nO melhor resultado: \n");

ag.visualizaMelhorGeracao();
//ag.visualizaGeracao();



// Exibe estatísticas (caso exista a classe Estatistica)
/* Estatistica.mostrarEstatistica(
ag, cidades, rotas, false // false indica que não será gerado um GIF
);*/
}
}

0 comments on commit 0fee68f

Please sign in to comment.