38 parametro[
ALGORITMO] = {
"ALGORITMO",2,1,2,
"Seleção do algoritmo de procura adversa base.",
39 {
"MiniMax",
"MiniMax alfa/beta" } };
51 {
"ORDENAR_SUCESSORES", 2, 0, 2,
"0 não ordena sucessores, 1 ordena por heurística, 2 usa o melhor valor de procuras anteriores." },
52 {
"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)." },
53 {
"PODA_CEGA",0,0,10000,
"Igual a PodaHeuristica, mas é efetuado de forma aleatória, sem calcular a heurística. Utilizar um valor sempre maior que Poda. " },
54 {
"HEUR_BASE", 200, 100, 1000,
"Valor base para diferença entre ameaças de K e K-1 (100 não há diferença, 200 corresponde ao dobro e é o valor por omissão)" }
78 printf(
" α=%d β=%d ═══", alfa, beta);
80 printf(
" %-2s%s", Icon(EIcon::ACCAO), *
pai->
Acao(
this));
94 bool noFolha = (nivel == 1 ||
Parar());
110 if (sucessores.
Empty())
118 for (
int i = 0; i <
id.Count(); i++) {
124 valorConhecido.
nivel >= nivel)
126 valor = valorConhecido.
valor;
129 DebugFolha(
false,
"%-2s%d", Icon(EIcon::MEMORIA), valor);
135 valorConhecido = { valor, nivel,
EXATO };
154 for (
int j =
i + 1;
j <
id.Count();
j++)
244 if (!
Parar() || nivel == 0) {
253 printf(
"\n │ %-2s%-2s %d %-2s%s %-2s%d ",
254 Icon(EIcon::ARVORE), Icon(EIcon::LIMITE), nivel,
286 for (
int i =
qMin.Count() - 1;
i >= 0;
i--) {
292 for (
int i =
qMax.Count() - 1;
i >= 0;
i--) {
352 for (
int i = 0;
i <
id.Count();
i++) {
363 DebugFolha(
false,
"%-2s%d", Icon(EIcon::MEMORIA), valor);
372 else if (valor >=
beta)
393 for (
int j =
i + 1;
j <
id.Count();
j++)
412 return valor.
nivel >= nivel &&
486 "\n ├─ %-2sTarefas:%d %-2sInstâncias: %d %-2sConfigurações: %d %-2sProcessos: %d.",
496 if (brancas != pretas) {
506 "\n ├─ %-2s%-15s %-2s%-5d %-2s%-5d %-2s%-5d %-2s%-5d %-2s%-5d",
509 Icon(EIcon::INST), inst,
510 Icon(EIcon::CONF), brancas + 1,
511 Icon(EIcon::CONF), pretas + 1,
526 printf(
"\n │ Ficheiro %s gravado.", *
ficheiro);
536 printf(
"\n═╧═ %-2s Fim do Teste (%-2s%d %-2s%s) ═══",
537 Icon(EIcon::FIM), Icon(EIcon::PROCESSO),
mpiID,
593 (*torneio)[brancas][pretas] +=
resultados.Last().resultado;
595 (
resultados.Last().resultado < 0 ? Icon(EIcon::VIT_PRETA) :
596 (
resultados.Last().resultado > 0 ? Icon(EIcon::VIT_BRANCA) :
597 Icon(EIcon::EMPATE))));
601 (
lance =
"").printf(
" 🏆 %s", (
resultados.Last().resultado < 0 ? Icon(EIcon::VIT_PRETA) :
602 (
resultados.Last().resultado > 0 ? Icon(EIcon::VIT_BRANCA) :
603 Icon(EIcon::EMPATE))));
611 int dados[6] = { 0, 0, 0, 4,0,0 };
644 if (brancas != pretas)
646 tarefas += { inst, brancas, pretas };
650 Debug(
ATIVIDADE,
false,
"\n ├─ %-2sTarefas:%d %-2sInstâncias: %d %-2sConfigurações: %d %-2sProcessos: %d.",
651 Icon(EIcon::TAREFA),
tarefas.Count(),
698 "\n ├─ %-2s%-15s %-2s%-5d %-2s%-5d %-2s%-5d %-2s%-5d %-2s%-5d %-2s ",
701 Icon(EIcon::INST),
resultados.Last().instancia,
739 "\n ├─ %-2s Ficheiro %s.csv gravado.\n"
740 " │ %-2s Tempo real: %s",
749 Debug(
ATIVIDADE,
false,
"\n │ %-2s Utilização:\n │ - Total: %.1f%%\n │ - Gestor: %.1f%%\n │ - Trabalhadores: %.1f%% ",
761 int dados[6] = { 0, 0, 0, 0, 0, 0 };
830 printf(
"\nComment :=>> histórico do jogo alterado.\nGrade :=>> 0\n");
860 "\n │ Ação inválida: %s (%d ações válidas)", *
acao,
nAcoes))
910 case 0: jogo +=
TString(
" Empate");
break;
911 case 1: jogo +=
TString(
" Brancas");
break;
912 case -1: jogo +=
TString(
" Pretas");
break;
938 for (
auto& jogo :
jogos) {
939 int jogadas = jogo.tok().Count();
947 printf(
"\nComment :=>> Jogos:");
949 for (
int i = 0;
i <
jogos.Count();
i++) {
954 printf(
"\nComment :=>> %s ", *
bullets[
i]);
955 printf(
deBrancas ?
"%d🖥️ vs 🧍 — " :
"🧍 vs %d🖥️ — ",
i / 2 + 1);
958 printf(
"%s ", *
lance);
998 printf(
"\nComment :=>> \nComment :=>> Resultados:\nComment :=>> ➤ 🏆 A: %d pontos\nComment :=>> ➤ ⚔️ DEFG: %d\n"
999 "Comment :=>> ➤ 💰 Pontuação (0-100): %d\nGrade :=>> %d\n",
1018 printf(
"\nComment :=>> jogo %d, tendo terminado foi alterado '%s'!='%s'.",
i, *
anterior[
i], *
jogos[
i]);
1040 printf(
"\nComment :=>> alterado lances no jogo %d: '%s'!='%s'.",
i, *
anterior[
i], *
jogos[
i]);
1049 else if (
diff == 2) {
1081 linhas +=
TString(
"Instância;Brancas;Pretas;Resultado;Jogadas;TempoBranco;TempoPreto;Jogo");
1104 linhas.Last().printf(
"%d:%s;",
1126 printf(
" HT: reutilização %.2f vezes ",
taxa);
@ HEUR_BASE
valor base para diferença entre ameaças de K e K-1 (100 não há diferença, 200 é o valor por omissão)
@ 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).
@ LIMITE
Valor dependente do algoritmo. Exemplo: Profundidade limitada.
@ BARALHAR_SUCESSORES
Baralhar os sucessores ao expandir.
@ RUIDO_HEURISTICA
Ruído a adicionar à heurística para testes de robustez.
@ 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
@ PASSOS
Exibe passos intermediários.
@ ATIVIDADE
Apenas eventos principais.
@ COMPLETO
Mostra toda a execução detalhadamente.
@ NADA
Sem informações de debug.
@ DETALHE
Debug detalhada sobre estados e decisões.
@ CONT_TESTE
Tempo total do teste (todas as execuções)
@ CONT_REPORTE
Tempo entre mensagens durante o teste.
@ CONT_ALGORITMO
Tempo da execução do algoritmo por instância.
@ ALGORITMO
Algoritmo base a executar.
@ SEMENTE
Semente aleatória para inicializar a sequência de números pseudo-aleatórios.
@ NIVEL_DEBUG
Nível de debug, de reduzido a completo.
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 PontuacaoJogos(TVector< TString > &jogos)
bool Validar(TVector< TString > solucao) override
Verifica a validade de uma solução para a instância atual.
bool SolucaoCompleta(void)=0
Verifica se o estado actual é objectivo (é uma solução completa)
int Pontos(int resultado)
converte -infinito, 0, +infinito em -1 (vitória preta), 1 (vitória branca), 0 empate
void OrdenarSucessores(TVector< TNo > &sucessores, TVector< int > &id, int nivel)
void TesteValidacao(TVector< int > instancias, TVector< int > impossiveis, TVector< int > referencias, TString fichSolucoes, TString fichResultados="") override
Executa testes de validação, executando cada solução na instância respetiva, e verificando a sua vali...
void TesteEmpiricoTrabalhador(TVector< int > instancias, TString ficheiro="") override
Teste empírico com modo mestre-escravo (este é o escravo)
int MiniMax(int nivel=4)
retorna o valor do estado actual, apos procura de profundidade nivel
int MaiorAmeaca(TVector< int > &qMin, TVector< int > &qMax, int maxAmeaca) const
Utilitário para calculo de uma heurística standard em jogos simples.
void Sucessores(TVector< TNo > &sucessores)
Coloca em sucessores a lista de estados sucessores.
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
void TesteEmpirico(TVector< int > instancias, TString ficheiro="") override
Executa testes empíricos, em todas as configurações guardadas, nas instâncias selecionadas.
bool CorteAlfaBeta(int valor, int &alfa, int &beta)
verifica se há um corte alfa/beta, atualizando alfa e beta
bool RelatorioCSV(TVector< TResultadoJogo > &resultados, TString ficheiro)
Gera um relatório CSV com os resultados.
void JogoTerminado(TString &jogo)
bool ValorEstado(TValorEstado &valor, int operacao)
ler ou gravar o melhor valor conhecido
bool ExisteHeuritica(void)
void ExecutaTarefa(TVector< TResultadoJogo > &resultados, int inst, int brancas, int pretas, TVector< TVector< int > > *torneio=NULL)
Executa uma tarefa num teste empírico.
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
void TesteEmpiricoGestor(TVector< int > instancias, TString ficheiro="") override
Teste empírico com modo mestre-escravo (este é o mestre)
static int infinito
valor de infinito (vitoria/derrota), omissao 1000
TString Jogar(TString jogo, int configID)
static int nivelOK
profundidade máxima no método iterativo
void DebugChamada(bool noFolha, int alfa=0, int beta=0)
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]
static int resultadoCompleto
resultado após SolucaoCompleta() retornar true (-1 vitória minimizar, 0 empate, 1 vitória maximizar)
bool CoerenciaJogo(TVector< TString > &jogos, TVector< TString > &anterior)
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)
void DebugEstado(bool novaLinha=true) const
void DebugFolha(bool fimLinha, const char *fmt,...)
static TBits elementosHT[TAMANHO_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 minimizar=true)
void DebugIteracao(int iteracao, const char *simbolo)
void LimparEstatisticas() override
Chamar antes da execução do algoritmo. Limpa valores estatísticos, e fixa o instante limite de tempo ...
virtual void Debug(bool completo=true)
Mostra o estado no ecrã, para debug.
int Parametro(int id) const
static int Dominio(int &variavel, int min=INT_MIN, int max=INT_MAX)
Limita o domínio de um parâmetro inteiro.
static int modoMPI
Modo MPI.
static TVector< TVector< int > > configuracoes
Conjuntos de configurações para teste empírico.
static int resultado
Resultado retornado pelo algoritmo na última execução.
void MostrarTorneio(TVector< TVector< int > > &torneio, bool jogo=false)
Mostra os resultados do torneio.
static int mpiID
MPI - rank do processo.
void MostrarConfiguracoes(int detalhe, int atual=-1)
Mostra as configurações disponíveis.
static int gravarSolucao
Gravar solução CSV (todas as ações)
void TesteInicio(TVector< int > &instancias, TVector< int > &configAtual)
arranque de teste, auxiliar aos Testes Empíricos
virtual bool Parar(void)
Verifica se a procura deve ser interrompida.
bool JuntarCSV(TString ficheiro)
Juntar ficheiros CSV gerados por diferentes processos MPI em um único ficheiro.
static TString MostraTempo(double segundos)
Mostra tempo num formato humano.
static int mpiCount
MPI - número de processos.
void ConfiguracaoAtual(TVector< int > ¶metros, int operacao)
Grava ou lê a configuração atual.
static TParametro instancia
ID da instância atual, a ser utilizado em SolucaoVazia().
static double Cronometro(enum ECronometro id=CONT_ALGORITMO, bool inicializar=false)
retorna o tempo em segundos desde que o cronómetro foi inicializado
static TVector< TParametro > parametro
Parâmetros a serem utilizados na configuração atual.
static void MostraConjunto(TVector< int > valores, const char *etiqueta)
TVector< TString > tok(const char *delim=" \t\n\r") const
TString & printf(const char *fmt,...)
TString & writeLines(const TVector< TString > &lines, bool append=false)
virtual bool Empty() const
TVector< Item > & Push(Item a)
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 TString 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.
TNo pai
Ponteiro para o estado pai, na árvore de procura.
int debugID
ID do estado, para efeitos de debug.
static constexpr const char * RAMO_ESTADO
static int expansoes
Número de expansões efetuadas.
static constexpr const char * RAMO_ESTADO2
static TVector< const char * > ramo
static TNo solucao
Estado objetivo encontrado, retornado pela procura (deve ser libertado).
static constexpr const char * RAMO_CONTINUA
static constexpr const char * RAMO_VAZIO
unsigned int rand(int seq)
Retorna o próximo valor pseudo-aleatório.
void srand(unsigned int seed, int seq)
Inicializa a semente da geração pseudo-aleatória.
int valor
valor do parâmetro
registo do valor de um estado, em procuras anteriores