Boa noite pessoas. Bom, estou tendo problemas com HashSet. Após consultar diversos tópicos aqui, ainda continuo sem entender o que estou fazendo de errado. Pois bem, Vamos começar:
/**
* Resolve um problema pelo metodo da busca em arvore.
* @return os passos para resolver o problema, caso haja
* solucao.
*/
public String[] busca() {
List<No> borda = estrategia.criaLista(); // criando a borda
Collection<Long> gerados = new HashSet<>(); // estados gerados
No no;
// Adiciona o no do estado inicial a borda
borda.add(new No(null, problema.getEstadoInicial(), null, 0, 0));
nos = 0;
profundidade = 0;
while (true) {
// Se a borda for vazia, entao retorna fracasso
if (borda.isEmpty())
return new String[] {};
// Remove o primeiro no da borda
no = borda.remove(0);
// Diga que este estado ja foi gerado
gerados.add(no.getEstado().getId());
nos ++;
profundidade = no.getProfundidade();
// Se o estado atual for o estado objetivo, entao
if (no.getEstado().eObjetivo())
// retorne a solucao do problema
return solucao(no);
// Senao, expande o no e adiciona os seus sucessores a borda
estrategia.adiciona(borda, expande(no, gerados));
}
}
Para cada nó visitado (como visto acima), eu guardo o seu ID gerado pelo método getId(). Estou fazendo isso para que, no método abaixo, não haja a possibilidade de algum estado gerado anteriormente (de mesma ID) entre novamente na lista e seja expandido futuramente:
/**
* Expande um no e retorna a lista de nos sucessores, ou seja, os
* outros estados que podem ser alcancados a partir deste no.
* @param no no do estado atual do ambiente
* @param gerados lista dos estados gerados anteriormente
* @return a lista de estados sucessores do estado do no atual
*/
private List<No> expande(No no, Collection<Long> gerados) {
List<No> sucessores = estrategia.criaLista();
Acao acao;
Estado resultado;
// Para cada (acao, sucessor) em sucessor(estado) faca
for (Object[] ar : problema.sucessor(no.getEstado())) {
acao = (Acao) ar[0];
resultado = (Estado) ar[1];
// Se o estado ainda nao foi gerado anteriormente, entao
if (!gerados.contains(resultado.getId()))
// adicione ele a lista de sucessores
sucessores.add(new No(no, resultado, acao,
resultado.distancia(no.getEstado()) +
resultado.heuristica() + no.getDistancia(),
1 + no.getProfundidade()));
}
return sucessores;
}
Como funciona a funcao ID no caso do problema? Dada a seguinte matriz (quebra cabeça de 8 onde 0 é o espaco vazio):
±-±-±-+
| 6 | 0 | 4 |
±-±-±-+
| 5 | 2 | 3 |
±-±-±-+
| 1 | 7 | 8 |
±-±-±-+
id = 871325406
Aqui está a implementação da função ID:
@Override
public long getId() {
// TODO Auto-generated method stub
int i, j, id;
id = 0;
for (i = 0; i < 3; i++)
for (j = 0; j < 3; j++)
id = id * 10 + pecas[i][j];
return id;
}
Pelo que andei lendo, A funcao HashCode retorna o próprio valor do Integer guardado no HashSet. Porém estados repetidos estão sendo analisados mais de uma vez resultando em 458138 nós que é superior a 9!/2 = 181440. Já não sei mais o que fazer e não sei o que estou fazendo de errado.