forked from ReinanHS/algoritmo-genetico-ifs
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implemtacao das classes AG,Individuo,Cidade e Main em java, seguindo …
…a base da implementacao em python
- Loading branch information
Davi
committed
Dec 10, 2024
1 parent
7a15574
commit 0fee68f
Showing
4 changed files
with
394 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
);*/ | ||
} | ||
} |