TProcura
Biblioteca em C++ para testes paramétricos de algoritmos, e coleção de algoritmos de procura e otimização
Loading...
Searching...
No Matches
TProcuraAdversa.cpp
Go to the documentation of this file.
1#include "TProcuraAdversa.h"
2#include <stdio.h>
3#include <time.h>
4#include <math.h>
5#include <string.h>
6
7constexpr int BUFFER_SIZE = 1024;
8
9// valor de infinito (vitoria/derrota), omissao 1000
11// controlo para indicar se a procura foi realizada de forma completa (c.c. foi cortada)
13// hashtable / valor e nível obtido
15// profundidade máxima no método iterativo
17// número de vezes que uma avaliação é reutilizada
19
20TProcuraAdversa::TProcuraAdversa(void) : minimizar(true), indiceHT(-1)
21{
22
23}
24
28
30{
31 static const char* nomesAlgoritmos[] = { "MiniMax", "MiniMax alfa/beta" };
33
34 // adicionar parâmetros da procura adversa
35 // alterar algoritmos
36 parametro[ALGORITMO] = { "ALGORITMO",2,1,2,"Seleção do algoritmo de procura adversa base.", nomesAlgoritmos };
37
38 Parametro(LIMITE) = 0; // procura iterativa preferencial
39 Parametro(ESTADOS_REPETIDOS) = 1; // nas procuras adversas, não utilizar este parametro (utilizar ordenar=2)
40 Parametro(BARALHAR_SUCESSORES) = 0; // de omissão está com valor 0, para facilitar nos testes, mas deve ficar com 1 para obter jogos distintos
41
42 // O "infinito" é dependente do problema, não faz sentido alterar senão no código
43
44 // adicionar parametros da procura adversa
45 parametro += {
46 { "ORDENAR_SUCESSORES", 2, 0, 2, "0 não ordena sucessores, 1 ordena por heurística, 2 usa o melhor valor de procuras anteriores." },
47 { "PODA_HEURISTICA",0,0,1000, "0 não existe poda, caso contrário é o número máximo de sucessores a considerar (tem de se ordenar sucessores)." },
48 { "PODA_CEGA",0,0,10000, "Igual a PodaHeuristica, mas é efetuado de forma aleátoria, sem calcular a heurística. Utilizar um valor sempre maior que Poda. " }
49 };
50}
51
52
54// Algoritmo MiniMax
56// retorna o valor do estado actual, apos procura de profundidade nivel
58{
60 // no final da árvore, retornar (valor da heuristica)
61 if (nivel == 1 || Parar()) {
62 completo = false; // árvore cortada, a procura deixa de ser completa
63 return NoFolha(true);
64 }
65
66 if (nivel == 0)
67 return MetodoIterativo(false);
68
69 // expandir o estado
70 TVector<TNo> sucessores;
71 Sucessores(sucessores);
72 // caso não existam sucessores, é como se fosse um nó folha
73 if (sucessores.Empty())
74 return NoFolha(false);
75
76 TVector<int> id; // índice para ordenar os sucessores por heurística
77 OrdenarSucessores(sucessores, id, nivel);
78
79 int resultado = 0, melhor = -1;
80 // processar os sucessores
81 for (int i = 0; i < sucessores.Count(); i++) {
82 DebugExpansao(i, sucessores.Count(), minimizar);
83 int valor;
84 TValorEstado valorConhecido;
85
86 if (((TProcuraAdversa*)sucessores[id[i]])->ValorEstado(valorConhecido, LER) &&
87 valorConhecido.nivel >= nivel)
88 {
89 valor = valorConhecido.valor;
90 }
91 else {
92 // chamada recursiva, com um nível a menos, idêntico à procura em profundidade
93 valor = ((TProcuraAdversa*)sucessores[id[i]])->MiniMax(nivel - 1);
94 valorConhecido = { valor, nivel, EXATO };
95 ((TProcuraAdversa*)sucessores[id[i]])->ValorEstado(valorConhecido, GRAVAR);
96 }
97
98 // pretende-se obter o melhor resultado, que oscila entre minimizar ou maximizar
99 if (i == 0 || (minimizar ? resultado > valor : resultado < valor)) {
100 resultado = valor;
101 melhor = id[i];
102 if (nivel > 1 && Parametro(NIVEL_DEBUG) >= PASSOS) { // colocar valor actual alterado
103 NovaLinha();
104 printf("(%d)", resultado);
105 }
107 break; // nao e possivel melhorar
108 }
109 }
110 // todos os sucessores analizados, se houver uma solução melhor, retornar
111 if (melhor >= 0) {
112 if (solucao != NULL)
113 delete solucao;
115 }
118 return resultado;
119}
120
123 heuristica = TProcuraConstrutiva::Heuristica(); // incrementa avaliações e adiciona ruído se for caso disso
124 // valor da heurística já calculado, gravar
125 calculado = { heuristica,0,EXATO }; // valor da heurística com nível 0
127 return heuristica;
128}
129
130// chamar em CSubProblema::Heuristica() para verificar se a heurística já existe, ou precisa de ser calculada
133 if (ValorEstado(calculado, LER)) {
135 return true;
136 }
137 return false;
138}
139
141 TVector<TNo>& sucessores, TVector<int>& id, int nivel)
142{
143 if (Parametro(PODA_CEGA) > 0 &&
144 sucessores.Count() > Parametro(PODA_CEGA))
145 {
146 // podar de forma aleatória, nem heurística deve ser calculada
147 while (sucessores.Count() > Parametro(PODA_CEGA)) {
148 int id = TRand::rand() % sucessores.Count();
149 delete sucessores[id];
150 sucessores[id] = sucessores.Last();
151 sucessores.Pop();
152 }
153 }
154
155 id = {};
156 if (nivel > 2 && Parametro(ORDENAR_SUCESSORES) >= 1) {
157 CalcularHeuristicas(sucessores, &id); // id fica ordenado por heurística
158
159 if (!minimizar)
160 id.Invert();
161
162 // podar sucessores
163 if (Parametro(PODA_HEURISTICA) > 0 &&
164 Parametro(PODA_HEURISTICA) < id.Count()) {
166 for (int i = 0; i < Parametro(PODA_HEURISTICA); i++)
167 manterSuc += sucessores[id[i]];
168 for (int i = Parametro(PODA_HEURISTICA); i < id.Count(); i++)
169 delete sucessores[id[i]];
171 id = {};
172 for (int i = 0; i < sucessores.Count(); i++)
173 id += i;
174 }
175
176 }
177 else
178 for (int i = 0; i < sucessores.Count(); i++)
179 id += i;
180}
181
182// iteração, aumentando o nível progressivamente
184 int resultado = 0, resOK = 0, nivel = 0;
185 nivelOK = 0;
186 TNo solOK = NULL;
187 do {
188 DebugIteracao(nivel + 1);
189 completo = true;
190 // chamar a profundidade nível 1, e se não resolver, o nível 2, e assim sucessivamente
191 resultado = (alfaBeta ? MiniMaxAlfaBeta(++nivel) : MiniMax(++nivel));
192 if (!Parar() || nivel == 0) {
193 // guardar a última solução realizada sem interrupções, bem como o resultado
194 if (solOK != NULL)
195 delete solOK;
196 solOK = solucao;
197 solucao = NULL;
199 nivelOK = nivel;
200 if (Parametro(NIVEL_DEBUG) > NADA && solOK != NULL)
201 printf("\n%d: %s (%d)", nivel, Acao(solOK), resultado);
202 }
203 else
204 completo = false;
205 } while (!completo && !Parar());
206 if (solucao != NULL)
207 delete solucao;
208 solucao = solOK;
209 return resOK;
210}
211
212// Utilitário para calculo de uma heurística standard em jogos simples (tipicamente sem empates):
213// - calcular o número de ameaças de vitória, para cada lado, de menor comprimento:
214// - qMin - vetor com número de ameaças (1 ou mais) a 1 jogada (na primeira posição), a 2 (na segunda posição), e assim sucessivamente;
215// - qMax - vetor com número de ameaças (1 ou mais) a 1 jogada (na primeira posição), a 2 (na segunda posição), e assim sucessivamente;
216int TProcuraAdversa::MaiorAmeaca(TVector<int>& qMin, TVector<int>& qMax, int maxAmeaca) const
217{
218 int pontos = 0, peso = 1;
219
220 // verificar situações de ganho imediato
221 if (!minimizar && qMax.First() > 0)
222 return infinito; // Vitória imediata para o max
223 if (minimizar && qMin.First() > 0)
224 return -infinito; // Vitória imediata para o min
225
226 // Ameaças iguais a maxAmeaca ou superior, valem 1, todas as outras valem conforme
227 if (maxAmeaca > qMin.Count())
228 peso <<= (maxAmeaca - qMin.Count());
229 for (int i = qMin.Count() - 1, peso = 1; i >= 0; i--) {
230 pontos -= qMin[i] * peso;
231 if (i < maxAmeaca) // peço começa a duplicar
232 peso <<= 1;
233 }
234 peso = 1;
235 if (maxAmeaca > qMax.Count())
236 peso <<= (maxAmeaca - qMin.Count());
237 for (int i = qMax.Count() - 1, peso = 1; i >= 0; i--) {
238 pontos += qMax[i] * peso;
239 if (i < maxAmeaca) // peço começa a duplicar
240 peso <<= 1;
241 }
242
243 return (int)(infinito * (2 / (1 + exp(-0.01 * pontos)) - 1));
244}
245
246// fim da procura, por corte de nível (ou não haver sucessores), retornar heurística
248 int resultado;
249 DebugCorte(nivel ? -1 : 0, minimizar);
250
252
253 if (resultado >= infinito) {
254 resultado = infinito - custo; // subtrair
255 // jogo ganho pelo branco
256 // se o agente minimiza, tentar o jogo mais longo possível
257 // caso contrário, quanto maior o jogo pior, quer o jogo mais curto
258 // a minimizar, entre um nível 10 e 20, irá preferir o 20, já que -20 é menor que -10
259 // a maximizar, entre um nível 10 e 20, irá preferir o 10, já que 10 é menor que 20
260 }
261 else if (resultado <= -infinito) {
262 resultado = custo - infinito; // somar
263 // jogo ganho pelo preto
264 // se o agente maximiza, tentar o jogo mais longo possível
265 // caso contrário, quanto maior o jogo pior, quer o jogo mais curto
266 // a maximizar, entre 10 e 20, irá preferir 20, sempre é maior
267 // a minimizar, entre 10 e 20, irá preferir 10 que é menor
268 }
269 Debug(PASSOS, false, "%d", resultado);
270 return resultado;
271}
272
274// Algoritmo MiniMaxAlfaBeta
276// retorna o valor do estado actual, apos procura de profundidade nivel
277// idêntico a MiniMax
278int TProcuraAdversa::MiniMaxAlfaBeta(int nivel, int alfa, int beta)
279{
280 DebugChamada();
281 if (nivel == 1 || Parar()) {
282 completo = false;
283 return NoFolha(true);
284 }
285
286 if (nivel == 0)
287 return MetodoIterativo(true);
288
291 if (sucessores.Empty())
292 return NoFolha(false);
293
294 TVector<int> id; // índice para ordenar os sucessores por heurística
295 OrdenarSucessores(sucessores, id, nivel);
296
297 int resultado = 0, melhor = -1;
298 for (int i = 0; i < sucessores.Count(); i++) {
300 int valor;
302
305 {
306 valor = valorConhecido.valor;
307 }
308 else {
309 // chamada recursiva, com um nível a menos, idêntico à procura em profundidade
310 valor = ((TProcuraAdversa*)sucessores[id[i]])->MiniMaxAlfaBeta(nivel - 1, alfa, beta);
311 valorConhecido = { valor, nivel, EXATO };
312 if (valor <= alfa)
313 valorConhecido.tipo = UPPER_BOUND; // Causado por corte alfa
314 else if (valor >= beta)
315 valorConhecido.tipo = LOWER_BOUND; // Causado por corte beta
316 // registar valor apenas se estiver dentro de alfa/beta (para não influenciarem o resultado)
317 ((TProcuraAdversa*)sucessores[id[i]])->ValorEstado(valorConhecido, GRAVAR);
318 }
319
320 if (i == 0 || (minimizar ? resultado > valor : resultado < valor)) {
321 resultado = valor;
322 melhor = id[i];
323 if (nivel > 1 && Parametro(NIVEL_DEBUG) >= PASSOS) {
324 // colocar valor actual alterado
325 NovaLinha();
326 printf("(%d)", resultado);
327 }
328 }
329 // corte alfa/beta bem como atualização
330 if (i < sucessores.Count() - 1) { // nao interessa cortar quando não há mais nada para cortar
332 break;
333 }
334 }
335 if (melhor >= 0) {
336 if (solucao != NULL)
337 delete solucao;
339 }
342 return resultado;
343}
344
345bool TProcuraAdversa::Utilizavel(TValorEstado& valor, int nivel, int alfa, int beta) {
346 return valor.nivel >= nivel &&
347 (valor.tipo == EXATO ||
348 (valor.tipo == lowerBound && valor.valor >= beta) ||
349 (valor.tipo == UPPER_BOUND && valor.valor <= alfa));
350}
351
352
353// verifica se há um corte alfa/beta, atualizando alfa e beta
354bool TProcuraAdversa::CorteAlfaBeta(int valor, int& alfa, int& beta) {
355 if (minimizar) { // pretas
356 // ver se ja e maximo
357 if (valor <= custo + 1 - infinito)
358 return true;
359 if (alfa >= valor) {
360 // corte alfa
362 // substituir o ultimo caracter por um corte
363 ramo.Last() = '>';
364 NovaLinha();
365 printf(" alfa(%d)", alfa);
366 }
367 return true; // as brancas tem uma alternativa, e escusado continuar a procurar aqui
368 }
369 // atualização beta
370 if (beta > valor)
371 beta = valor;
372 }
373 else { // brancas
374 // ver se atingiu o maximo
375 if (valor >= infinito - custo - 1)
376 return true;
377 if (beta <= valor) {
378 // corte beta
380 ramo.Last() = '>';
381 NovaLinha();
382 printf(" beta(%d)", beta);
383 }
384 return true; // as pretas tem uma alternativa, e escusado continuar a procurar aqui
385 }
386 // atualização alfa
387 if (alfa < valor)
388 alfa = valor;
389 }
390 // não há corte
391 return false;
392}
393
394// utilizar para executar testes empíricos, utilizando todas as instâncias,
395// Utiliza as configurações existentes, ou parâmetros atuais
396// Efetua um torneio entre configurações
397void TProcuraAdversa::TesteEmpirico(TVector<int> instancias, bool mostrarSolucoes, char* ficheiro) {
398 TVector<int> atual;
400 for (auto item : instancias)
402 item = -1;
403 instancias -= (-1);
404 ConfiguracaoAtual(atual, LER);
405 if (configuracoes.Empty()) {
406 // não foram feitas configurações, utilizar a atual
408 configuracoes.Last() = atual;
409 }
410 if (configuracoes.Count() == 1) {
411 // apenas há uma configuração, utilizar a atual como segunda
413 configuracoes.Last() = atual;
414 }
415
416 TVector<TVector<int>> torneio; // pares de configurações: 1 melhor, 0 igual -1 pior
417 TVector<double> tempoTotal; // tempo total de resposta, em todos os jogos
419 for (int i = 0; i < configuracoes.Count(); i++) {
420 torneio[i].Count(configuracoes.Count());
421 torneio[i].Reset(0);
422 }
424 tempoTotal.Reset(0);
425
426 // dois jogadores, brancas é o primeiro a jogar, pretas é o segundo
427 for (int brancas = 0; brancas < configuracoes.Count(); brancas++)
428 for (int pretas = 0; pretas < configuracoes.Count(); pretas++)
429 if (brancas != pretas) {
430 printf("\nMatch %d vs %d:", brancas + 1, pretas + 1);
431 for (auto inst : instancias) {
432 instancia.valor = inst;
433 int resultado = -1, njogada = 0;
434 printf("\n Instância %d: ", instancia.valor);
435 // carregar instância
436 Inicializar();
437 // jogar ora de brancas ora de pretas, até o jogo terminar
438 while (!SolucaoCompleta()) {
444 if (solucao != NULL) { // efetuado um lance
445 const char* strAcao = Acao(solucao);
447 if (mostrarSolucoes) {
448 if (Parametro(VER_ACOES) == 1 ||
449 njogada % Parametro(VER_ACOES) == 0) {
450 printf("\n%s %d %s",
451 (njogada % 2 == 0 ? "Brancas" : "Pretas"),
452 (njogada / 2) + 1, strAcao);
453 Debug();
454 printf(" f:%d ", resultado);
455 }
456 else // mostrar apenas a ação
457 printf(" %s", strAcao);
458 }
459 njogada++;
460 }
461 else {
462 break; // não há lance efetuado
463 resultado = 0; // erro, mas considerar empatado
464 }
465 }
466 // jogo terminou, registar resultdo
467 if (resultado != 0) {
468 bool inverter;
469 // brancas e minimizar ou pretas e maximizar, inverter
470 inverter = ((njogada % 2 == 0) && minimizar) ||
471 ((njogada % 2 == 1) && !minimizar);
472 // vitória/derrota branca/preta
473 torneio[brancas][pretas] += (resultado < 0 ? -1 : 1) * (inverter ? -1 : 1);
474 printf(" Vitória %s", (inverter ? resultado < 0 : resultado > 0) ? "Branca" : "Preta");
475 }
476 else
477 printf(" Empate");
478 }
479 }
480
481 if (ficheiro == NULL || strlen(ficheiro) <= 1) {
482 MostrarTorneio(torneio, true);
483 printf("\nTempos: ");
484 for (auto tempo : tempoTotal)
485 printf("%.3fs ", tempo);
487 printf("\n");
488 }
489 else {
490 char* pt = strtok(ficheiro, " \n\t\r");
491 char str[BUFFER_SIZE];
492 strcpy(str, pt);
493 strcat(str, ".csv");
494 FILE* f = fopen(str, "wt");
495 if (f != NULL) {
496 // escrever BOM UTF-8
497 const unsigned char bom[] = { 0xEF,0xBB,0xBF };
498 fwrite(bom, 1, sizeof(bom), f);
499 fprintf(f, "sep=;\n");
501 printf("\nFicheiro %s gravado.", str);
502 fclose(f);
503 }
504 else
505 printf("\nErro ao gravar ficheiro %s.", str);
506
507 }
508
512 Inicializar();
513}
514
515
517 // Jogador, Adversário, cor, resultado (positivo caso o jogador ganhe, negativo c.c.)
518 // Nota: cada confronto fica com 2 entradas; se existir várias instâncias, o resultado do confronto é somado
519 fprintf(f, "Jogador;Adversário;Cor;Resultado\n");
520 for (int jogador = 0; jogador < torneio.Count(); jogador++)
521 for (int adversario = 0; adversario < torneio[jogador].Count(); adversario++)
522 if (jogador != adversario) {
523 fprintf(f, "%d;%d;%s;%d\n", jogador, adversario, "Brancas", torneio[jogador][adversario]);
524 fprintf(f, "%d;%d;%s;%d\n", adversario, jogador, "Pretas", -torneio[jogador][adversario]);
525 }
526 if (configuracoes.Count() != torneio.Count())
527 return;
528 // No final, mostrar as configurações
529 fprintf(f, "\nJogador;");
530 for (int i = 0; i < parametro.Count(); i++)
531 fprintf(f, "P%d(%s);", i + 1, parametro[i].nome);
532 fprintf(f, "\n");
533 for (int jogador = 0; jogador < configuracoes.Count(); jogador++) {
534 fprintf(f, "%d;", jogador);
535 for (int j = 0; j < parametro.Count(); j++)
536 if (parametro[j].nomeValores == NULL)
537 fprintf(f, "%d;", configuracoes[jogador][j]);
538 else
539 fprintf(f, "%d:%s;",
541 parametro[j].nomeValores[configuracoes[jogador][j] - parametro[j].min]);
542 fprintf(f, "\n");
543 }
544}
545
546
548 int resultado = -1;
549 if (Parametro(ORDENAR_SUCESSORES) == 2) {
552 float taxa = (float)(1.0 * reutilizadoAvaliacao / colocadosHT);
553 LimparHT();
554 printf(" HT: reutilização %.2f vezes ", taxa);
555 }
556 else
557 LimparHT();
560 }
561 switch (Parametro(ALGORITMO)) {
562 case 1: resultado = MiniMax(Dominio(Parametro(LIMITE), 0)); break;
563 case 2: resultado = MiniMaxAlfaBeta(Dominio(Parametro(LIMITE), 0)); break;
564 }
565 return resultado;
566}
567
568// necessário redefinir para atualizar valorHT em caso de colisão
571 valorHT[indiceHT = indice].nivel = -1;
572}
573
575 // caso não exista, retorna falso e insere
576 // se existe retorna falso à mesma para não remover, dado que é uma alternativa para este lance concreto
577 // se estiver lá outro elemento, substitui
578 unsigned int original = Hash();
579 unsigned int indice = original % TAMANHO_HASHTABLE;
580 indiceHT = indice;
581 for (int i = 0; i < tamanhoCodificado; i++) {
582 if (elementosHT[indice][i] != estadoCodHT[i]) {
583 SubstituirHT(indice);
584 colocadosHT++;
585 return false; // não existia
586 }
587 }
588 return false; // é como se não existisse, mas está lá
589}
590
591
592bool TProcuraAdversa::ValorEstado(TValorEstado& valor, int operacao) {
594 return false;
595 ExisteHT(); // calcula indiceHT
596 if (operacao == LER) {
597 if (indiceHT >= 0 && valorHT[indiceHT].nivel >= 0) {
598 valor = valorHT[indiceHT];
600 return true;
601 }
602 return false;
603 }
604 // gravar
605 if (indiceHT >= 0 && valorHT[indiceHT].nivel < valor.nivel)
606 valorHT[indiceHT] = valor;
607
608 return true;
609}
610
611
612
constexpr int BUFFER_SIZE
@ PODA_HEURISTICA
permite cortar sucessores, mas calcula a heurística a todos, de modo a mantendo os melhores
@ ORDENAR_SUCESSORES
opção de ordenar sucessores por heurística, ou por último valor registado
@ PODA_CEGA
corta os sucessores, mesmo sem calcular a heurística, por ordem aleatória
@ EXATO
o valor foi calculado sem cortes, ou seja, não sofreu influência de alfa ou beta;
@ LOWER_BOUND
o valor foi afetado por um corte de beta (ou seja, ele é pelo menos esse valor, mas pode ser maior);
@ UPPER_BOUND
o valor foi afetado por um corte de alfa (ou seja, ele é no máximo esse valor, mas pode ser menor).
@ VER_ACOES
Mostra estado a cada K ações. Se 1, mostra sempre estados e nunca ações.
@ LIMITE
Valor dependente do algoritmo. Exemplo: Profundidade limitada.
@ BARALHAR_SUCESSORES
Baralhar os sucessores ao expandir.
@ ESTADOS_REPETIDOS
Forma de lidar com estados repetidos (ignorá-los, ascendentes, gerados).
@ IGNORADOS
ignorados os estados gerados repetidos
@ GERADOS
estados são comparados com todos os gerados, e se forem repetidos são removidos
constexpr int TAMANHO_HASHTABLE
@ GRAVAR
Definition TProcura.h:76
@ LER
Definition TProcura.h:76
@ PASSOS
Exibe passos intermediários.
Definition TProcura.h:65
@ ATIVIDADE
Apenas eventos principais.
Definition TProcura.h:64
@ NADA
Sem informações de debug.
Definition TProcura.h:63
@ CONT_ALGORITMO
Tempo da execução do algoritmo por instância.
Definition TProcura.h:84
@ ALGORITMO
Algoritmo base a executar.
Definition TProcura.h:42
@ SEMENTE
Semente aleatória para inicializar a sequência de números pseudo-aleatórios.
Definition TProcura.h:44
@ NIVEL_DEBUG
Nível de debug, de reduzido a completo.
Definition TProcura.h:43
Representa um estado no espaço de estados.
int NoFolha(bool nivel)
fim da procura, por corte de nível (ou não haver sucessores), retornar heurística
void OrdenarSucessores(TVector< TNo > &sucessores, TVector< int > &id, int nivel)
void TesteEmpirico(TVector< int > instancias, bool mostrarSolucoes=true, char *ficheiro=NULL)
int MiniMax(int nivel=4)
retorna o valor do estado actual, apos procura de profundidade nivel
void RelatorioCSV(TVector< TVector< int > > &torneio, FILE *f)
Gera um relatório CSV com os resultados.
int MaiorAmeaca(TVector< int > &qMin, TVector< int > &qMax, int maxAmeaca) const
Utilitário para calculo de uma heurística standard em jogos simples.
static bool completo
controlo para indicar se a procura foi realizada de forma completa (c.c. foi cortada)
bool minimizar
o jogador actual deve minimizar o custo (ou maximizar caso tenha o valor falso)
int Heuristica(void)
chamar após calcular a heurística (grava o valor, dependendo da parametrização)
int MetodoIterativo(int alfaBeta)
iteração, aumentando o nível progressivamente
bool CorteAlfaBeta(int valor, int &alfa, int &beta)
verifica se há um corte alfa/beta, atualizando alfa e beta
bool ValorEstado(TValorEstado &valor, int operacao)
ler ou gravar o melhor valor conhecido
bool ExisteHeuritica(void)
void ResetParametros()
Método para inicializar os parâmetros (redefinir se forem adicionados parâmetros específicos)
void SubstituirHT(int indice)
static int reutilizadoAvaliacao
bool Utilizavel(TValorEstado &valor, int nivel, int alfa, int beta)
ver se o valor obtido é utilizável no contexto atual
static int infinito
valor de infinito (vitoria/derrota), omissao 1000
static int nivelOK
profundidade máxima no método iterativo
int MiniMaxAlfaBeta(int nivel=4, int alfa=-infinito, int beta=+infinito)
retorna o valor do estado actual, apos procura de profundidade nivel. Idêntico a MiniMax
static TValorEstado valorHT[TAMANHO_HASHTABLE]
int ExecutaAlgoritmo()
Executa o algoritmo com os parametros atuais.
Representa um estado no espaço de estados.
void DebugCorte(int sucessores=-1, bool duplo=false)
static uint64_t elementosHT[TAMANHO_HASHTABLE][OBJETO_HASHTABLE]
void CalcularHeuristicas(TVector< TNo > &sucessores, TVector< int > *id=NULL, bool sortLB=false)
void NovaLinha(bool tudo=true)
static void LibertarVector(TVector< TNo > &vector, int excepto=-1, int maiorQue=-1)
virtual void SubstituirHT(int indice)
void DebugExpansao(int sucessor, int sucessores, bool duplo=false)
void LimparEstatisticas() override
Chapar antes da execução do algoritmo. Limpa valores estatísticos, e fixa o instante limite de tempo para...
void DebugIteracao(int iteracao)
static uint64_t estadoCodHT[OBJETO_HASHTABLE]
virtual void Debug(bool completo=true)
Mostra o estado no ecrã, para debug.
Definition TProcura.cpp:93
int Parametro(int id) const
Definition TProcura.h:522
static int Dominio(int &variavel, int min=INT_MIN, int max=INT_MAX)
Limita o domínio de um parâmetro inteiro.
static TVector< TVector< int > > configuracoes
Conjuntos de configurações para teste empírico.
Definition TProcura.h:491
static int resultado
Resultado retornado pelo algoritmo na última execução.
Definition TProcura.h:493
void MostrarTorneio(TVector< TVector< int > > &torneio, bool jogo=false)
Mostra os resultados do torneio.
void MostrarConfiguracoes(int detalhe, int atual=-1)
Mostra as configurações disponíveis.
Definition TProcura.cpp:468
virtual bool Parar(void)
Verifica se a procura deve ser interrompida.
Definition TProcura.h:363
void ConfiguracaoAtual(TVector< int > &parametros, int operacao)
Grava ou lê a configuração atual.
Definition TProcura.cpp:269
static TParametro instancia
ID da instância atual, a ser utilizado em SolucaoVazia().
Definition TProcura.h:24
static TVector< TParametro > parametro
Parâmetros a serem utilizados na configuração atual.
Definition TProcura.h:485
static double Cronometro(enum ECronometro id=CONT_ALGORITMO, bool inicialiar=false)
retorna o tempo em segundos desde que o cronómetro foi inicializado
Definition TProcura.h:750
static double tempo
tempo consumido na última execução.
Definition TProcura.h:495
bool Empty() const
Definition TVector.h:230
Item & Last()
Definition TVector.h:224
int Count() const
Definition TVector.h:227
virtual void Sucessores(TVector< TNo > &sucessores)
Coloca em sucessores a lista de estados sucessores.
virtual bool SolucaoCompleta(void)
Verifica se o estado actual é objectivo (é uma solução completa)
void Inicializar(void) override
Coloca o objecto no estado inicial da procura.
void ResetParametros() override
Redefinição. Ver TProcura::ResetParametros().
virtual void Copiar(TNo objecto)
Fica com uma cópia do objecto.
virtual int Heuristica(void)
Função para calcular quanto falta para o final, o valor da heurística.
virtual const char * Acao(TNo sucessor)
Retorna a ação (movimento, passo, jogada, lance, etc.) que gerou o sucessor.
int heuristica
Estimativa para o custo até um estado objetivo, se disponível.
int custo
Custo total acumulado desde o estado inicial.
static int lowerBound
Valor mínimo que a solução pode apresentar, obtido pela procura.
static int tamanhoCodificado
Número de inteiros de 64 bits utilizados para codificar um objeto (≤ OBJETO_HASHTABLE).
static TVector< unsigned char > ramo
static TNo solucao
Estado objetivo encontrado, retornado pela procura (deve ser libertado).
unsigned int rand(int seq)
Retorna o próximo valor pseudo-aleatório.
Definition TRand.cpp:46
void srand(unsigned int seed, int seq)
Inicializa a semente da geração pseudo-aleatória.
Definition TRand.cpp:34
int valor
valor do parametro
Definition TProcura.h:139
int max
valor máximo que o parametro pode tomar
Definition TProcura.h:143
registo do valor de um estado, em procuras anteriores
ETipoValor tipo