TProcura
Biblioteca em C++ para testes paramétricos de algoritmos, e coleção de algoritmos de procura e otimização
Loading...
Searching...
No Matches
TProcura.cpp
Go to the documentation of this file.
1#include "TProcura.h"
2#include <locale>
3#include <stdio.h>
4#include <time.h>
5#include <string.h>
6#include <ctype.h>
7#ifdef MPI_ATIVO
8#include <mpi.h>
9#endif
10constexpr int BUFFER_SIZE = 1024;
11
12// Resultado retornado pelo algoritmo na última execução.
14// tempo consumido na última execução.
15double TProcura::tempo = 0;
16// numero de iterações, conforme definido no algoritmo
18
19// deadline da corrida atual
20clock_t TProcura::instanteFinal = 0;
21// flag de problemas de memória esgotada
22bool TProcura::memoriaEsgotada = false;
23// ID da instância atual (problemas com várias instâncias, a utilizar em SolucaoVazia())
24TParametro TProcura::instancia = { NULL,1,1,1, NULL, NULL };
25// nome do ficheiro de uma instância (utilizar como prefixo, concatenando com ID da instância)
26char TProcura::ficheiroInstancia[256] = "instancia_";
27
28// adicionar parâmetros específicos, se necessário
30// adicionar indicadores conforme a necessidade
32// lista por ordem dos indicadores a utilizar
34
35// MPI - rank do processo
36int TProcura::mpiID = 0;
37// MPI - número de processos
38int TProcura::mpiCount = 1;
39// Modo MPI : 0 = divisão estática, 1 = mestre-escravo
40int TProcura::modoMPI = 0;
41
42
43// conjuntos de valores de parâmetros, para teste
45
46
48{
49 static const char* nomesAlgoritmos[] = {
50 "Algoritmo base" };
51 static const char* nomesDebug[] = {
52 "NADA",
53 "ATIVIDADE",
54 "PASSOS",
55 "DETALHE",
56 "COMPLETO" };
57
58 // definir parametros base
59 parametro = {
60 { "ALGORITMO", 1, 1, 1, "Algoritmo base a executar.", nomesAlgoritmos },
61 { "NIVEL_DEBUG", 0, 0, 4, "Nível de debug, de reduzido a completo.", nomesDebug },
62 { "SEMENTE", 1, 1, 1000000, "Semente aleatória para inicializar a sequência de números pseudo-aleatórios." },
63 { "LIMITE_TEMPO", 10, 1, 3600, "Limnite de tempo em segundos. " },
64 { "LIMITE_ITERACOES", 0, 0, 1000000000, "Limite de número de iterações (0 não há limite). " }
65 };
66
67 // definir indicadores base
68 indicador = {
69 { "Resultado", "Resultado do algoritmo, interpretado conforme o algoritmo (sucesso/insucesso, custo, qualidade, valor, etc.).", IND_RESULTADO },
70 { "Tempo(ms)", "Tempo em milisegundos da execução (medida de esforço computacional).", IND_TEMPO },
71 { "Iterações", "Iterações do algoritmo, intrepretadas conforme o algoritmo (medida de esforço independente do hardware).", IND_ITERACOES }
72 };
74
75 // colocar as configurações vazias (podem ser inicializadas se existirem configurações de omissão)
76 configuracoes = {};
77}
78
79// retorna o valor do indicador[id]
80int64_t TProcura::Indicador(int id) {
81 switch (id) {
82 case IND_RESULTADO:
83 return resultado;
84 case IND_TEMPO:
85 return (int64_t)(1000 * tempo + 0.5);
86 case IND_ITERACOES:
87 return iteracoes;
88 }
89 return 0;
90}
91
92// Escrever informacao de debug sobre o objecto atual
93void TProcura::Debug(bool completo)
94{
95 Debug(ATIVIDADE, false, "\nTProcura::Debug() método não redefinido.");
96}
97
98// Chamar antes de iniciar uma procura
107
108// Metodo para teste manual do objecto (chamadas aos algoritmos, construcao de uma solucao manual)
109// Este metodo destina-se a testes preliminares, e deve ser redefinido apenas se forem definidos novos algoritmos
110void TProcura::TesteManual(const char* nome)
111{
112 int selecao;
116 Inicializar();
118 while (true) {
119 printf("\n%s", nome);
121 Debug();
123 printf("\n\
124____________________________________________________________________\n\
125| 1 - Inicializar | 2 - Explorar | 3 - Parâmetros | 4 - Solução |\n\
126| 5 - Indicadores | 6 - Executar | 7 - Configurações | 8 - Teste |");
127 if ((selecao = NovoValor("\nOpção: ")) == NAO_LIDO)
128 return;
129 switch (Dominio(selecao, 0, 9)) {
130 case 0: return;
132 case 2: Explorar(); break;
133 case 3: EditarParametros(); break;
134 case 4: MostrarSolucao(); break;
135 case 5: if (EditarIndicadores())
136 resultados = {};
137 break;
138 case 6:
139 // executar um algoritmo
146 break;
147 case 7: EditarConfiguracoes(); break;
148 case 8: {
150 TesteEmpirico(instancias, NovoTexto("Ficheiro (nada para mostrar no ecrã):"));
151 break;
152 }
153 case 9: return;
154 default: printf("\nOpção não definida."); break;
155 }
156 }
157}
158
159void TProcura::MostraParametros(int detalhe, TVector<int>* idParametros) {
160 int nElementos = (idParametros == NULL ? parametro.Count() : idParametros->Count());
161 int count = 0;
162 printf("\n ");
163 for (int i = 0; i < nElementos; i++) {
164 int parID = (idParametros == NULL ? i : (*idParametros)[i]);
165 if (!ParametroAtivo(parID))
166 continue;
167 count++;
168 // identificação do parâmetro
169 if (detalhe == 0 || parametro[parID].nome == NULL)
170 printf("P%d=", parID + 1);
171 else
172 printf("P%d(%s): ", parID + 1, parametro[parID].nome);
173 // valor do parâmetro
174 if (detalhe == 0 || parametro[parID].nomeValores == NULL)
175 printf("%d", Parametro(parID));
176 else
177 printf("%s", parametro[parID].nomeValores[Parametro(parID) - parametro[parID].min]);
178 // mostrar intervalo permitido
179 if (detalhe > 1)
180 printf(" (%d a %d)", parametro[parID].min, parametro[parID].max);
181 // separador/mudança de linha
182 if (i < nElementos - 1) {
183 if (detalhe > 1 || count % (detalhe == 0 ? 8 : 4) == 0)
184 printf("\n ");
185 else if (detalhe > 0)
186 printf(" | ");
187 else
188 printf(" ");
189 }
190 }
191}
192
194 int opcao = 0;
195 bool editado = false;
196 while (true) {
198 if ((opcao = NovoValor("\nAlterar indicador: ")) == NAO_LIDO || opcao == 0)
199 return editado;
200 opcao = Dominio(opcao, 1, indicador.Count());
201 if (indicador[opcao - 1].indice >= 0) {
202 for (int i = 0; i < indicador.Count(); i++)
203 if (i != opcao - 1 && indicador[i].indice > indicador[opcao - 1].indice)
204 indicador[i].indice--;
205 indicador[opcao - 1].indice = -1;
206 indAtivo -= (opcao - 1);
207 }
208 else {
209 indicador[opcao - 1].indice = 0;
210 for (int i = 0; i < indicador.Count(); i++)
211 if (i != opcao - 1 && indicador[i].indice >= indicador[opcao - 1].indice)
212 indicador[opcao - 1].indice = indicador[i].indice + 1;
213 indAtivo += (opcao - 1); // coloca no fim
214 }
215 // invalidar resultados atuais
216 editado = true;
217 }
218 return editado;
219}
220
222 int opcao = 0, valor;
223 while (true) {
225 if ((opcao = NovoValor("\nParametro:")) == NAO_LIDO || opcao == 0)
226 return;
227 opcao = Dominio(opcao, 1, parametro.Count());
228 // mostrar descrição se existir
229 if (parametro[opcao - 1].descricao != NULL)
230 printf("\n%s", parametro[opcao - 1].descricao);
231 // mostrar textos dos valores possíveis, caso existam
232 if (parametro[opcao - 1].nomeValores != NULL)
233 for (int i = parametro[opcao - 1].min; i <= parametro[opcao - 1].max; i++)
234 printf("\n%d: %s", i,
235 parametro[opcao - 1].nomeValores[i - parametro[opcao - 1].min]);
236
237 // valor atual
238 if (parametro[opcao - 1].nome != NULL)
239 printf("\n%s (atual %d): ", parametro[opcao - 1].nome, Parametro(opcao - 1));
240 else
241 printf("\nP%d (atual %d): ", opcao, Parametro(opcao - 1));
242 // solicitar valor
243 valor = NovoValor("");
244 if (valor != NAO_LIDO || valor == 0)
245 Parametro(opcao - 1) =
246 Dominio(valor,
247 parametro[opcao - 1].min,
248 parametro[opcao - 1].max);
249 }
250}
251
253{
254 int id = -1;
255 // procurar pela configuração
256 for (int i = 0; i < configuracoes.Count() && id < 0; i++)
257 if (configuracoes[i].Equal(parametros))
258 id = i;
259 if (id < 0) {
262 return configuracoes.Count() - 1;
263 }
264 return id;
265}
266
267
268// gravar (ou ler) a configuração atual
269void TProcura::ConfiguracaoAtual(TVector<int>& parametros, int operacao) {
270 if (operacao == GRAVAR) {
271 for (int i = 0; i < parametro.Count() && i < parametros.Count(); i++)
273 }
274 else if (operacao == LER) {
275 parametros = {};
276 for (int i = 0; i < parametro.Count(); i++)
278 }
279}
280
281char* TProcura::MostraTempo(double segundos)
282{
283 static char str[BUFFER_SIZE];
284 static const int64_t segundo = 1000;
285 static const int64_t minuto = 60 * segundo;
286 static const int64_t hora = 60 * minuto;
287 static const int64_t dia = 24 * hora;
288 static const int64_t semana = 7 * dia;
289 static const int64_t mes = 30 * dia;
290 static const int64_t ano = 365 * dia;
291
293
294 static TVector<char> unidadesStr = {
295 'a', 'm', 's', 'd', 'h', '\'', '"'
296 };
297
298 int64_t ms = (int64_t)(1000 * segundos + 0.5);
299 int len = 0;
300 str[0] = 0;
301
302 for (int i = 0; i < unidades.Count(); i++)
303 if (ms >= unidades[i]) {
304 len += snprintf(str + len, sizeof(str) - len, "%" PRId64 "%c ", ms / unidades[i], unidadesStr[i]);
305 ms %= unidades[i];
306 }
307 if (ms > 0)
308 len += snprintf(str + len, sizeof(str) - len, "%" PRId64 "ms ", ms);
309
310 return str;
311}
312
313void TProcura::InserirRegisto(TVector<TResultado>& resultados, int inst, int conf)
314{
315 resultados += { inst, conf };
316 for (auto ind : indAtivo)
318 // adicionar no final a solução codificada em inteíros
319 resultados.Last().valor += CodificarSolucao();
320}
321
322int64_t TProcura::Registo(TResultado& resultado, int id)
323{
324 if (id >= 0 && id < indicador.Count() && indicador[id].indice >= 0)
325 return resultado.valor[indicador[id].indice];
326 return 0;
327}
328
329void TProcura::Registo(TResultado& resultado, int id, int64_t valor)
330{
331 if (id >= 0 && id < indicador.Count() && indicador[id].indice >= 0)
332 resultado.valor[indicador[id].indice] = valor;
333}
334
336{
337 char str[BUFFER_SIZE];
338 printf("\nSintaxe (apenas inteiros, sem espaços):\n\
339 A ou A,B,C - único valor ou enumeração\n\
340 A:B ou A:B:C - intervalo A a B, ou com passo C\n\
341Introduza IDs das instâncias (de %d a %d): ", instancia.min, instancia.max);
343 if (strlen(str) > 1)
344 return _TV(str);
345 // colocar apenas a instância atual
346 return TVector<int>() += instancia.valor;
347}
348
349
351 TVector<int> atual; // parâmetros atuais
352 int id = -1, auxID;
353 char* str;
354
355 ConfiguracaoAtual(atual, LER);
356
357 id = NovaConfiguracao(atual);
358
359 do {
361
362 str = NovoTexto("\nSintaxe comando:\n\
363 id / -id - Seleciona configuração como atual ou apaga 'id'\n\
364 Pk=<conj.> - Varia Pk na configuração atual (gera N configurações)\n\
365 Pk=<conj.> x Pw=<conj.> - produto externo de Pk e Pw (gera NxM configurações)\n\
366Sintaxe de <conj.> (apenas inteiros, sem espaços):\n\
367 A ou A,B,C - único valor ou enumeração\n\
368 A:B ou A:B:C - intervalo A a B, ou com passo C\n\
369Comando: ");
370 if (strlen(str) <= 1)
371 break;
372
373 if ((auxID = atoi(str)) != 0) {
374 id = auxID;
376 if (id < 0) {
377 id++;
379 }
380 else if (id > 0) {
381 id--;
382 atual = configuracoes[id];
383 }
384 }
385 else {
387 configuracoes[id] = atual; // alterar atual se necessário
389 }
390 } while (true);
392}
393
395 char* pt, *contexto;
398
399 // processar todos os itens a iniciar em P, obtendo informação entre quais existe x
400 pt = compat::strtok(str, " \n\t\r", &contexto);
401 while (pt) {
402 if (*pt == 'P') {
403 char* pt2;
404 int param;
405 if ((pt2 = strchr(pt + 1, '='))) {
406 *pt2 = 0;
407 param = atoi(pt + 1);
408 if (param > 0 && param <= parametro.Count()) {
409 valores.Count(valores.Count() + 1);
410 valores.Last() = {};
411 valores.Last() += param; // primeiro valor é ID do parâmetro
412 valores.Last() += _TV(pt2 + 1); // valores para o parâmetro tomar
413 if (valores.Last().Count() == 2) {
414 // apenas um elemento, altera a configuração atual
415 // (se fosse para alternar, colocava o valor base masi o valor a alternar)
416 int valor = valores.Last().Last();
417 if (valor >= parametro[param - 1].min &&
418 valor <= parametro[param - 1].max)
419 base[param - 1] = valor;
420 }
421 if (valores.Last().Count() <= 2)
422 valores.Count(valores.Count() - 1);
423 }
424 }
425 }
426 else if (*pt == 'x') {
427 valores.Count(valores.Count() + 1);
428 valores.Last() += 0; // produto externo
429 }
430 pt = compat::strtok(NULL, " \n\t\r", &contexto);
431 }
432 // inserir configurações de acordo com o pretendido (produto externo, ou apenas à configuração base)
433 produto = {};
434 for (int i = 0; i < valores.Count(); i++)
435 if (valores[i].First() > 0) { // c.c. é o operador produto externo
436 if (i == valores.Count() - 1 || valores[i + 1].First() != 0) { // não há outro produto externo, colocar na configuração atual
437 produto += i;
439 produto = {};
440 }
441 else
442 produto += i;
443 }
444}
445
447{
448 // inserir os valores do último elemento de forma recursiva
449 int idLista = produto.Pop();
452 int param = lista.First();
453
454 for (int i = 1; i < lista.Count(); i++)
455 if (lista[i] >= parametro[param - 1].min &&
456 lista[i] <= parametro[param - 1].max)
457 {
458 base[param - 1] = lista[i];
459 if (produto.Empty())
461 else
463 }
464 base = backup;
465 produto += idLista;
466}
467
468void TProcura::MostrarConfiguracoes(int detalhe, int atual) {
470 // identificar parametros comuns e distintos entre as parametrizações
471 for (int i = 0; i < configuracoes.First().Count(); i++) {
472 bool igual = true;
473 for (int j = 1; j < configuracoes.Count() && igual; j++)
475 if (igual)
476 comum += i;
477 else
478 distinto += i;
479 }
480 // mostra parametros comuns, evitando repetição em cada configuração
481 printf("\nParâmetros comuns:");
483
484 // visualizar configurações atuais, assinalando a atualmente escolhida
485 printf("\n- Configurações geradas (total: %d) -", configuracoes.Count());
486 for (int i = 0; i < configuracoes.Count(); i++) {
489 printf(" [%d]", i + 1);
490 if (i == atual)
491 printf(" --- atual");
492 }
493}
494
495
496// utilizar para executar testes empíricos, utilizando todas as instãncias,
497// com o último algoritmo executado e configurações existentes
498void TProcura::TesteEmpirico(TVector<int> instancias, char* ficheiro) {
499 TVector<TResultado> resultados; // guarda as soluções obtidas
500 TVector<int> atual;
502 int nTarefa = 0;
503 double periodoReporte = 60;
504 switch (Parametro(NIVEL_DEBUG)) {
505 case DETALHE: periodoReporte = 10; break;
506 case COMPLETO: periodoReporte = 1; break;
507 }
508 Cronometro(CONT_TESTE, true); // reiniciar cronómetro global
509 Cronometro(CONT_REPORTE, true); // reiniciar cronómetro evento
510 for (auto item : instancias)
512 item = -1;
513 instancias -= (-1);
514 ConfiguracaoAtual(atual, LER);
515 if (configuracoes.Empty()) {
516 // não foram feitas configurações, utilizar a atual
518 configuracoes.Last() = atual;
519 }
520 if (mpiID == 0)
521 Debug(ATIVIDADE, false,
522 "\nTeste com %d tarefas, %d instâncias, %d configurações, utilizando %d processo(s). ",
524 fflush(stdout);
525 // percorrer todas as instâncias
526 for (int configuracao = 0; configuracao < configuracoes.Count(); configuracao++) {
527 ConfiguracaoAtual(configuracoes[configuracao], GRAVAR);
528
529 for (auto inst : instancias) {
530 // distribuir tarefas por MPI
531 if ((nTarefa++) % mpiCount != mpiID)
532 continue;
533
535 Debug(ATIVIDADE, false, "\n%s Tarefa %d. ",
537 fflush(stdout);
539 }
540
541 ExecutaTarefa(resultados, inst, configuracao);
542 }
543 }
544
545 if (ficheiro == NULL || strlen(ficheiro) <= 1)
547 else {
548 // gravar resultados em ficheiro CSV
550
552 double tempoTotal = tempoLocal;
553 double tempoMaximo = tempoLocal;
554#ifdef MPI_ATIVO
557#endif
558
559 if (mpiCount > 1 && mpiID == 0)
560 // tenta juntar ficheiros, caso existam os ficheiros dos outros processos
562 if (mpiID == 0)
563 Debug(ATIVIDADE, false,
564 "\nFicheiro %s.csv gravado.\n"
565 "Tempo real: %s",
567 Debug(ATIVIDADE, false, "\nCPU total: %s",
569 Debug(ATIVIDADE, false, "\nTaxa de utilização: %.1f%%",
570 100. * tempoTotal / (tempoMaximo * mpiCount));
571 }
572
576 Inicializar();
577}
578
579void TProcura::TesteEmpiricoGestor(TVector<int> instancias, char* ficheiro)
580{
581#ifdef MPI_ATIVO
582 int dados[3] = { 0, 0, 0 }; // instância, configuração
583 double esperaTrabalhadores = 0, esperaGestor = 0;
584 TVector<double> terminou; // instante em que terminou cada trabalhador
586 double periodoReporte = 60;
587 switch (Parametro(NIVEL_DEBUG)) {
588 case DETALHE: periodoReporte = 10; break;
589 case COMPLETO: periodoReporte = 1; break;
590 }
591 for (int i = 1; i < mpiCount; i++)
592 trabalhador += i;
593
595 terminou.Reset(0);
596
597 // Ciclo:
598 // 1. Enviar trabalho para os escravos
599 // 2. Encerrar escravos a mais
600 // 3. Receber resultados e repetir 1 ou 2 conforme as necessidades
601
602 TVector<TResultado> resultados; // guarda as soluções obtidas
603 TVector<TResultado> tarefas; // guarda informação apenas das tarefas a realizar (sem resultados)
604 TVector<int> atual;
606 Cronometro(CONT_TESTE, true); // reiniciar cronómetro global
607 Cronometro(CONT_REPORTE, true); // reiniciar cronómetro evento
608 for (auto item : instancias)
610 item = -1;
611 instancias -= (-1);
612 ConfiguracaoAtual(atual, LER);
613 if (configuracoes.Empty()) {
614 // não foram feitas configurações, utilizar a atual
616 configuracoes.Last() = atual;
617 }
618
619 // construir todas as tarefas
620 for (int configuracao = 0; configuracao < configuracoes.Count(); configuracao++)
621 for (auto inst : instancias)
622 tarefas += { inst, configuracao };
623
624 Debug(ATIVIDADE, false, "\nTeste com %d tarefas, %d instâncias, %d configurações, utilizando %d processo(s). ",
625 tarefas.Count(), instancias.Count(), configuracoes.Count(),
626 trabalhador.Count() + 1) &&
627 fflush(stdout);
628
629 // dar uma tarefa a cada escravo
630 while (!tarefas.Empty() && !trabalhador.Empty()) {
631 auto tarefa = tarefas.Pop();
632 dados[0] = tarefa.instancia;
633 dados[1] = tarefa.configuracao;
634 trabalhar += trabalhador.Last();
636 esperaTrabalhadores += Cronometro(CONT_TESTE); // estava parado até esta altura
637 }
638 // caso existam escravos sem trabalho, mandar fechar todos, não há mais tarefas
639 dados[0] = dados[1] = -1;
640 while (!trabalhador.Empty()) {
641 auto trabalhadorID = trabalhador.Pop();
644 }
645
646 // receber resultados e continuar a dar trabalho caso exista
647 while (!trabalhar.Empty()) {
649
651 // mostrar uma linha por cada execução
652 Debug(ATIVIDADE, false, "\n%s Faltam %d tarefas, em curso %d",
653 MostraTempo(Cronometro(CONT_TESTE)), tarefas.Count(), trabalhar.Count()) &&
654 fflush(stdout);
656 }
657
661 resultados += {dados[0], dados[1]};
662 resultados.Last().valor.Count(dados[2]);
663 trabalhar -= stat.MPI_SOURCE;
664 trabalhador += stat.MPI_SOURCE;
665 MPI_Recv(resultados.Last().valor.Data(), dados[2], MPI_LONG_LONG,
667 // tempo de espera do trabalhador
668 esperaTrabalhadores += (double)((int64_t)resultados.Last().valor.Pop()) / 1000.;
669
670 // ainda há tarefas
671 if (!tarefas.Empty()) {
672 auto tarefa = tarefas.Pop();
673 dados[0] = tarefa.instancia;
674 dados[1] = tarefa.configuracao;
675 trabalhar += trabalhador.Last();
677 }
678 else { // tudo feito, mandar sair
679 dados[0] = dados[1] = -1;
680 auto trabalhadorID = trabalhador.Pop();
683 }
684 }
685
686 // contar a espera dos trabalhadores, após terminarem
687 for (int i = 1; i < mpiCount; i++)
689
690 // escrever o ficheiro de resultados
691 int backupCount = mpiCount;
695 mpiCount = 1; // forçar a escrita do ficheiro apenas neste processo
697 Debug(ATIVIDADE, false,
698 "\nFicheiro %s.csv gravado.\n"
699 "Tempo real: %s",
701 Debug(ATIVIDADE, false, "\nCPU total: %s",
703 Debug(ATIVIDADE, false, "\nEspera do gestor: %s",
705 Debug(ATIVIDADE, false, "\nEspera total dos trabalhadores: %s",
707 Debug(ATIVIDADE, false, "\nTaxa de utilização:\n- Total: %.1f%%\n- Gestor: %.1f%%\n- Trabalhadores: %.1f%% ",
710
711#endif
712}
713
714void TProcura::TesteEmpiricoTrabalhador(TVector<int> instancias, char* ficheiro)
715{
716#ifdef MPI_ATIVO
717 int dados[3] = { 0, 0, 0 }; // instância, configuração
718 // Ciclo:
719 // 1. Solicitar tarefa ao mestre
720 // 2. Executar tarefa
721 // 3. Enviar resultados ao mestre
722 // 4. Repetir até receber ordem de paragem
723
724 TVector<TResultado> resultados; // guarda as soluções obtidas
725 TVector<int> atual;
727 Cronometro(CONT_TESTE, true); // reiniciar cronómetro global
728 for (auto item : instancias)
730 item = -1;
731 instancias -= (-1);
732 ConfiguracaoAtual(atual, LER);
733 if (configuracoes.Empty()) {
734 // não foram feitas configurações, utilizar a atual
736 configuracoes.Last() = atual;
737 }
738
739 for (;;) {
740 // receber nova tarefa
742 if (dados[0] < 0)
743 break;
744
746
747 // enviar registo para master, e apagar
748 // dados[0] e dados[1] já têm a configuração e instância
749 dados[2] = resultados.Last().valor.Count() + 1;
752 // colocar a espera no final do vetor de resultados
753 resultados.Last().valor += (int64_t)((Cronometro(CONT_TESTE) - inicioEspera) * 1000 + 0.5);
754 MPI_Send(resultados.Last().valor.Data(), dados[2], MPI_LONG_LONG, 0, TAG_VALORES, MPI_COMM_WORLD);
755
756 resultados.Pop();
757 }
758
759 // saída, enviar o tempo de trabalho e tempo de espera totais
760
761#endif
762}
763
764void TProcura::ExecutaTarefa(TVector<TResultado>& resultados, int inst, int conf)
765{
766 // carregar a configuração
768 instancia.valor = inst;
770 // carregar instância
771 Inicializar();
772 // executar um algoritmo
773 Debug(COMPLETO, false, "instância %d: ", instancia.valor) && fflush(stdout);
775 {
777 Parametro(NIVEL_DEBUG) = NADA; // remover informação de debug do algoritmo, já que é um teste empírico
780 }
783
784 if (resultado >= 0) {
787 }
788 else {
789 if (Parar())
790 Debug(COMPLETO, false, "Não resolvido. ");
791 if (TempoExcedido())
792 Debug(COMPLETO, false, "Tempo excedido. ");
793 if (memoriaEsgotada)
794 Debug(COMPLETO, false, "Memória esgotada. ");
795 if (resultado < 0 && !Parar())
796 Debug(COMPLETO, false, "Instância Impossível! (se algoritmo completo) ");
797 else // não resolvido, cancelar resultados
798 resultados.Last().valor.First() = -2;
799 }
800 Debug(COMPLETO, false, "DONE.") && fflush(stdout);
801}
802
803// processa os argumentos da função main
804void TProcura::main(int argc, char* argv[], const char* nome) {
806 char fichResultados[256];
807 char argParametros[BUFFER_SIZE] = "";
808
809 std::locale::global(std::locale(""));
810
811 if (argc <= 1) {
812 TesteManual(nome);
813 return;
814 }
815 else if (strcmp(argv[1], "-h") == 0) {
817 return;
818 }
819
820 // 1:10 --- conjunto de instâncias (idêntico ao interativo)
821 instancias = argv[1];
822 if (instancias.Empty()) {
824 return;
825 }
826
827 snprintf(fichResultados, sizeof(fichResultados), "resultados");
828
830
831 // opcionais:
832 // -R resultados --- ficheiro de resultados em CSV (adicionada extensão .csv)
833 // -F instancia_ --- prefixo dos ficheiros de instâncias
834 // -I 2,1,3 --- indicadores selecionados por ordem
835 // -P P1=1:3 x P2=0:2 --- formatação de parâmetros (idêntico ao interativo)
836 for (int i = 2; i < argc; i++) {
837 if (strcmp(argv[i], "-R") == 0 && i + 1 < argc) {
838 snprintf(fichResultados, sizeof(fichResultados), "%s", argv[i + 1]);
839 }
840 else if (strcmp(argv[i], "-F") == 0 && i + 1 < argc) {
841 snprintf(ficheiroInstancia, sizeof(ficheiroInstancia), "%s", argv[i + 1]);
842 }
843 else if (strcmp(argv[i], "-M") == 0 && i + 1 < argc) {
844 if ((modoMPI = atoi(argv[i + 1])) != 1)
845 modoMPI = 0; // apenas 0 ou 1
846 }
847 else if (strcmp(argv[i], "-I") == 0 && i + 1 < argc) {
848 char* contexto;
849 char* pt = compat::strtok(argv[i + 1], ",", &contexto);
850 indAtivo = {};
851 while (pt) {
852 indAtivo += (atoi(pt) - 1);
853 indicador[indAtivo.Last()].indice = indAtivo.Count() - 1;
854 pt = compat::strtok(NULL, ",", &contexto);
855 }
856 }
857 else if (strcmp(argv[i], "-P") == 0 && i + 1 < argc) {
859 // o resto é para concatenar e enviar
860 int len = 0;
861 argParametros[0] = 0;
862 while (++i < argc)
863 len += snprintf(argParametros + len, sizeof(argParametros) - len, " %s", argv[i]);
867 break;
868 }
869 }
870
871 // arrancar MPI apenas após processar os argumentos
873
874 if (Parametro(NIVEL_DEBUG) >= DETALHE && mpiID == 0)
876
877 if (modoMPI == 0 || mpiCount == 1)
878 // divisão estática ou execução em série
880 else {
881 if (mpiID == 0)
882 // processo mestre
884 else
885 // processos escravos
887 }
888
889 FinalizaMPI();
890}
891
892void TProcura::AjudaUtilizacao(const char* programa) {
893 printf(
894 "Uso: %s <instâncias> [opções]\n"
895 " <instâncias> Conjunto de IDs: A | A,B,C | A:B[:C]\n"
896 "Opções:\n"
897 " -R <ficheiro> Nome do CSV de resultados (omissão: resultados.csv)\n"
898 " -F <prefixo> Prefixo dos ficheiros de instância (omissão: instancia_)\n"
899 " -M <modo> Modo MPI: 0 = divisão estática, 1 = gestor-trabalhador\n"
900 " -I <ind> Lista de indicadores (e.g. 2,1,3)\n"
901 " -h Esta ajuda\n"
902 " -P <expr> Parâmetros (e.g. P1=1:3 x P2=0:2) - último campo\n"
903 "Exemplo: %s 1:5 -R out -F fich_ -I 3,1,4,2 -P P1=1:5 x P6=1,2 \n"
904 " Executar sem argumentos entra em modo interativo, para explorar todos os parametros e indicadores\n",
906 );
908 printf("\nLista de parâmetros:");
910 printf("\n\nLista de indicadores:");
912}
913
914
915bool TProcura::RelatorioCSV(TVector<TResultado>& resultados, char* ficheiro) {
916 char * contexto;
917 char* pt = compat::strtok(ficheiro, " \n\t\r", &contexto);
918 char str[BUFFER_SIZE];
919 if (mpiCount > 1)
920 snprintf(str, sizeof(str), "%s_%d.csv", pt, mpiID);
921 else
922 snprintf(str, sizeof(str), "%s.csv", pt);
923 FILE* f = compat::fopen(str, "wt");
924 if (f != NULL) {
925 // escrever BOM UTF-8 (apenas no mpiID 0)
926 const unsigned char bom[] = { 0xEF,0xBB,0xBF };
927 if (mpiID == 0) {
928 fwrite(bom, 1, sizeof(bom), f);
929 fprintf(f, "sep=;\n");
930 }
931
932 // cabeçalho: instância, parametros, indicadores
933 fprintf(f, "Instância;");
934 for (int i = 0; i < parametro.Count(); i++)
935 fprintf(f, "P%d(%s);", i + 1, parametro[i].nome);
936 for (auto item : indAtivo)
937 fprintf(f, "I%d(%s);", item + 1, indicador[item].nome);
938 fprintf(f, "\n");
939
940 for (auto& res : resultados) {
941 fprintf(f, "%d;", res.instancia);
942 for (int j = 0; j < parametro.Count(); j++)
943 // ver se parametro j está ativo na configuração configuracoes[res.configuracao]
944 if (!ParametroAtivo(j, &(configuracoes[res.configuracao])))
945 fprintf(f, ";"); // parametro inativo, não mostrar
946 else if (parametro[j].nomeValores == NULL)
947 fprintf(f, "%d;", configuracoes[res.configuracao][j]); // mostrar valor
948 else
949 fprintf(f, "%d:%s;", // mostrar valor e texto
950 configuracoes[res.configuracao][j],
951 parametro[j].nomeValores[configuracoes[res.configuracao][j] - parametro[j].min]);
952 for (auto ind : indAtivo)
953 fprintf(f, "%" PRId64 ";", Registo(res, ind));
954 fprintf(f, "\n");
955 }
956
957 fclose(f);
958 }
959 else {
960 printf("\nErro ao gravar ficheiro %s.", str);
961 return false;
962 }
963 return true;
964}
965
966void TProcura::MostraRelatorio(TVector<TResultado>& resultados, bool ultimo)
967{
968 if (ultimo) {
969 if (!resultados.Empty()) {
970 int elementos = 0;
971 for (auto ind : indAtivo) {
972 if (elementos > 0)
973 printf(" | ");
974 if (elementos % 5 == 0)
975 printf("\n");
976 printf("I%d(%s): %" PRId64, ind + 1, indicador[ind].nome, Registo(resultados.Last(), ind));
977 elementos++;
978 }
979 }
980 return;
981 }
982
983 TVector<TResultado> total; // totais por cada configuração
985 for (int i = 0; i < total.Count(); i++) {
986 total[i].instancia = total[i].configuracao = 0;
987 total[i].valor.Count(indicador.Count());
988 total[i].valor.Reset(0);
989 }
990
991 // mostrar os resultados dos indicadores escolhidos
992 printf("\n ID |conf|");
993 for (auto ind : indAtivo)
994 printf("%10s|", indicador[ind].nome);
995
996 printf("\n----|----|");
997 for (int i = 0; i < indAtivo.Count(); i++)
998 printf("----------|");
999
1000 for (auto &res : resultados) {
1001 if (Registo(res, IND_RESULTADO) >= -1)
1002 total[res.configuracao].instancia++;
1003 printf("\n%3d |%3d |", res.instancia, res.configuracao + 1);
1004
1005 for (auto ind : indAtivo)
1006 printf(" %8" PRId64 " |", Registo(res, ind));
1007
1008 for (auto ind : indAtivo)
1009 Registo(total[res.configuracao], ind,
1010 Registo(total[res.configuracao], ind) +
1011 Registo(res, ind));
1012 }
1013 printf("\n----|----|");
1014 for (int i = 0; i < indAtivo.Count(); i++)
1015 printf("----------|");
1016 printf("resolvidas");
1017 // tabela com os totais por configuração
1018 for (int i = 0; i < total.Count(); i++) {
1019 printf("\nTotal%3d |", i + 1);
1020
1021 for (auto ind : indAtivo)
1022 printf(" %8" PRId64 " |", Registo(total[i], ind));
1023
1024 printf(" %d", total[i].instancia);
1025 }
1026 // mostrar torneio entre configurações
1029 printf("\n");
1030}
1031
1033 TVector<TVector<int>> torneio; // pares de configurações: 1 melhor, 0 igual -1 pior
1035 for (int i = 0; i < torneio.Count(); i++) {
1036 torneio[i].Count(configuracoes.Count());
1037 torneio[i].Reset(0);
1038 }
1039 // registar resultados mediante o melhor resultado
1040 for (int i = 0; i < configuracoes.Count(); i++) {
1042 for (int j = 0; j < configuracoes.Count(); j++)
1043 if (i != j) {
1045 // resultados sempre por mesma ordem de instância
1046 for (int k = 0; k < configuracaoI.Count() && k < configuracaoJ.Count(); k++)
1048 }
1049 }
1051}
1052
1054{
1055 printf("\n");
1056 for (int i = 0; i < indicador.Count(); i++) {
1057 printf("\nI%d(%s): ", i + 1, indicador[i].nome);
1058 if (indicador[i].indice < 0)
1059 printf("inativo ");
1060 else
1061 printf("%dº lugar ", indicador[i].indice + 1);
1062 printf("(%s)", indicador[i].descricao);
1063 }
1064}
1065
1066
1068{
1070 pontos.Count(torneio.Count());
1071 pontos.Reset(0);
1072 // registar resultados mediante o melhor resultado
1073 for (int i = 0; i < torneio.Count(); i++)
1074 for (int j = 0; j < torneio.Count(); j++)
1075 if (i != j) {
1076 pontos[i] += torneio[i][j];
1077 if (jogo) // contar pontos perdidos de pretas
1078 pontos[j] -= torneio[i][j];
1079 }
1080
1081 // mostrar tabela do torneio
1082 printf("\nTorneio (#instâncias melhores):");
1083 BarraTorneio(true);
1084 for (int i = 0; i < pontos.Count(); i++) {
1085 printf("\n%2d", i + 1);
1086 for (int j = 0; j < pontos.Count(); j++)
1087 if (i == j)
1088 printf(" |");
1089 else
1090 printf("%3d |", torneio[i][j]);
1091 // no final colocar os pontos totais
1092 printf("%3d", pontos[i]);
1093 BarraTorneio(false);
1094 }
1095}
1096
1099 for (auto &res : resultados)
1100 if (res.configuracao == configuracao)
1101 extracao += res;
1102 return extracao;
1103}
1104
1105
1106void TProcura::BarraTorneio(bool nomes) {
1107 // barra inical/final: |----|----|----|
1108 printf("\n |");
1109 for (int i = 0; i < configuracoes.Count(); i++)
1110 if (nomes)
1111 printf("-%02d-|", i + 1);
1112 else
1113 printf("----|");
1114}
1115
1116
1118 // se não resolvido por ambos, retornar igualdade (assumir código -1 para impossível, -2 para não resolvido, menor é melhor)
1120 return 0;
1121 // se igual no custo e o tempo menor que 100, retornar igualdade
1124 return 0;
1125 // primeiro custo (ou não resolvido, -2)
1126 if ((Registo(base, IND_RESULTADO) == -2 &&
1130 return -1;
1131 if ((Registo(base, IND_RESULTADO) > -2 &&
1133 (Registo(base, IND_RESULTADO) > 0 &&
1135 return 1;
1136 // agora o tempo
1137 return Registo(base, IND_TEMPO) < Registo(alternativa, IND_TEMPO) ? 1 : -1;
1138}
1139
1141{
1142 if (TempoExcedido())
1143 printf(" Tempo excedido.");
1144 else if (memoriaEsgotada)
1145 printf(" Memória esgotada.");
1146}
1147
1148// MostrarSolucao: definir para visualizar a solução
1151 printf("\nSolução: ");
1152 for (auto& x : solucao)
1153 printf("%" PRId64 " ", x);
1154 printf(".");
1155}
1156
1157
1158int TProcura::NovoValor(const char* prompt) {
1159 char str[BUFFER_SIZE];
1160 printf("%s", prompt);
1162 if (strlen(str) > 1)
1163 return atoi(str);
1164 return NAO_LIDO;
1165}
1166
1167// ler uma string
1168char* TProcura::NovoTexto(const char* prompt) {
1169 static char str[BUFFER_SIZE];
1170 printf("%s", prompt);
1172 return str;
1173}
1174
1175
1177 if (instancia.max != instancia.min) {
1178 int resultado;
1179 char* texto;
1180 printf("\nID atual: %d Intervalo: [%d–%d] ",
1182 printf("Prefixo atual: '%s' ", ficheiroInstancia);
1183 printf("\nNovo ID (ENTER mantém) ou novo prefixo (texto): ");
1184
1185 texto = NovoTexto("");
1186 resultado = atoi(texto);
1187 if (resultado != 0 || strlen(texto) <= 1) {
1188 if (resultado != 0)
1191 }
1192 else if (strlen(texto) < 256) {
1193 char* contexto;
1194 char* pt = compat::strtok(texto, " \n\t\r", &contexto);
1196 }
1197 }
1198 else
1200}
1201
1202
1203int TProcura::Dominio(int& variavel, int min, int max) {
1204 if (variavel < min)
1205 variavel = min;
1206 if (variavel > max)
1207 variavel = max;
1208 return variavel;
1209}
1210
1211void TProcura::InicializaMPI(int argc, char* argv[])
1212{
1213#ifdef MPI_ATIVO
1214 MPI_Init(&argc, &argv);
1217 Debug(COMPLETO, false, "\nProcesso %d de %d iniciado.", mpiID, mpiCount) &&
1218 fflush(stdout);
1219#endif
1220}
1221
1223{
1224#ifdef MPI_ATIVO
1225 Debug(COMPLETO, false, "\nProcesso %d de %d terminado.", mpiID, mpiCount) &&
1226 fflush(stdout);
1227 MPI_Finalize();
1228#endif
1229}
1230
1231void TProcura::DebugTabela(ENivelDebug nivel, TVector<int> tabela, const char* tipo)
1232{
1233 Debug(nivel, false, "\n%4s|", tipo);
1234 for (int i = 0; i < 10 && i < tabela.Count(); i++)
1235 Debug(nivel, false, "%4d|", i + 1);
1236 Debug(nivel, false, "\n----|");
1237 for (int i = 0; i < 10 && i < tabela.Count(); i++)
1238 Debug(nivel, false, "----|");
1239 for (int i = 0; i < tabela.Count(); i++) {
1240 if (i % 10 == 0)
1241 Debug(nivel, false, "\n%4d|", i);
1242 Debug(nivel, false, "%4d|", tabela[i]);
1243 }
1244}
1245
1246bool TProcura::JuntarCSV(const char* ficheiro)
1247{
1248 // ficheiros CSV com o mesmo cabeçalho, ficheiro0.csv, ficheiro1.csv, ..., ficheiroN.csv
1249 FILE* fGravar = NULL, * fLer = NULL;
1250 char nome[256], str[BUFFER_SIZE];
1251
1252 // verifica se existem os ficheiros intermédios
1253 for (int i = 0; i < mpiCount; i++) {
1254 snprintf(nome, sizeof(nome), "%s_%d.csv", ficheiro, i);
1255 if ((fLer = compat::fopen(nome, "rt")) == NULL)
1256 // não existe este ficheiro, ainda não está tudo
1257 return false;
1258 fclose(fLer);
1259 }
1260
1261 // todos os ficheiros existem, juntar
1262 snprintf(nome, sizeof(nome), "%s.csv", ficheiro);
1263 fGravar = compat::fopen(nome, "wt");
1264 if (fGravar == NULL) {
1265 printf("\nErro ao gravar ficheiro %s.", nome);
1266 return false;
1267 }
1268
1269 for (int i = 0; i < mpiCount; i++) {
1270 snprintf(nome, sizeof(nome), "%s_%d.csv", ficheiro, i);
1271 fLer = compat::fopen(nome, "rt");
1272 if (fLer == NULL) {
1273 printf("\nErro ao ler ficheiro %s.", nome);
1274 continue;
1275 }
1276 while (!feof(fLer)) {
1277 if (fgets(str, BUFFER_SIZE, fLer) != NULL) {
1278 // evitar escrever o cabeçalho mais do que uma vez
1279 if (i > 0 && strncmp(str, "Instância;", 10) == 0)
1280 continue;
1281 fputs(str, fGravar);
1282 }
1283 }
1284 fclose(fLer);
1285 remove(nome); // apagar ficheiro intermédio
1286 }
1287 fclose(fGravar);
1288 return true;
1289}
constexpr int BUFFER_SIZE
constexpr int BUFFER_SIZE
Definition TProcura.cpp:10
@ TAG_TRABALHO
Definition TProcura.h:97
@ TAG_VALORES
Definition TProcura.h:99
@ TAG_CABECALHO
Definition TProcura.h:98
@ GRAVAR
Definition TProcura.h:76
@ LER
Definition TProcura.h:76
@ IND_TEMPO
tempo em milisegundos consumidos
Definition TProcura.h:18
@ IND_ITERACOES
número de iterações consumidas
Definition TProcura.h:19
@ IND_RESULTADO
resultado do algoritmo
Definition TProcura.h:17
constexpr int NAO_LIDO
Definition TProcura.h:14
ENivelDebug
Níveis de detalhamento para debug.
Definition TProcura.h:62
@ ATIVIDADE
Apenas eventos principais.
Definition TProcura.h:64
@ COMPLETO
Mostra toda a execução detalhadamente.
Definition TProcura.h:67
@ NADA
Sem informações de debug.
Definition TProcura.h:63
@ DETALHE
Debug detalhada sobre estados e decisões.
Definition TProcura.h:66
@ CONT_TESTE
Tempo total do teste (todas as execuções)
Definition TProcura.h:85
@ CONT_REPORTE
Tempo entre mensagens durante o teste.
Definition TProcura.h:86
@ CONT_ALGORITMO
Tempo da execução do algoritmo por instância.
Definition TProcura.h:84
@ 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
@ LIMITE_TEMPO
Tempo limite em segundos.
Definition TProcura.h:45
TVector< int > _TV(const char *str)
Definition TVector.h:1154
virtual void MostrarSolucao()
definir para visualizar a solução
static bool memoriaEsgotada
Flag indicando problemas de memória esgotada.
Definition TProcura.h:501
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
virtual int ExecutaAlgoritmo()
Executa o algoritmo com os parametros atuais.
Definition TProcura.h:220
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.
Definition TProcura.h:508
static char * NovoTexto(const char *prompt)
virtual void Inicializar(void)
Coloca o objecto no estado inicial da procura.
Definition TProcura.h:209
virtual void TesteEmpiricoTrabalhador(TVector< int > instancias, char *ficheiro=NULL)
Teste empírico com modo mestre-escravo (este é o escravo)
Definition TProcura.cpp:714
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 BarraTorneio(bool nomes)
Mostra a barra de progresso ou nomes do torneio.
void ExecutaTarefa(TVector< TResultado > &resultados, int inst, int conf)
Executa uma tarefa num teste empírico.
Definition TProcura.cpp:764
void MostrarTorneio(TVector< TVector< int > > &torneio, bool jogo=false)
Mostra os resultados do torneio.
static int mpiID
MPI - rank do processo.
Definition TProcura.h:503
void MostrarConfiguracoes(int detalhe, int atual=-1)
Mostra as configurações disponíveis.
Definition TProcura.cpp:468
virtual int64_t Indicador(int id)
Retorna um indicador, após a execução do algoritmo.
Definition TProcura.cpp:80
static char * MostraTempo(double segundos)
Mostra tempo num formato humano.
Definition TProcura.cpp:281
TVector< TResultado > ExtrairConfiguracao(TVector< TResultado > &resultados, int configuracao)
Extrai resultados de uma determinada configuração.
static int iteracoes
Número total de iterações realizadas na última execução.
Definition TProcura.h:497
static void FinalizaMPI()
Finaliza o ambiente MPI, se aplicável.
virtual void TesteManual(const char *nome)
Inicializa a interação com o utilizador.
Definition TProcura.cpp:110
static char ficheiroInstancia[256]
nome do ficheiro de uma instância - editado pelo utilizador (utilizar como prefixo, concatenando com ID...
Definition TProcura.h:482
int NovaConfiguracao(TVector< int > &parametros)
Adiciona uma nova configuração se ainda não existir.
Definition TProcura.cpp:252
void InserirConfiguracoes(char *str, TVector< int > &base)
Insere configurações a partir de uma string.
Definition TProcura.cpp:394
TVector< int > SolicitaInstancias()
Solicita ao utilizador uma lista de instâncias.
Definition TProcura.cpp:335
virtual void ResetParametros()
Inicializa os parametros, indicadores e instâncias.
Definition TProcura.cpp:47
void MostraParametros(int detalhe=1, TVector< int > *idParametros=NULL)
Mostra os parâmetros atuais.
Definition TProcura.cpp:159
virtual bool Parar(void)
Verifica se a procura deve ser interrompida.
Definition TProcura.h:363
bool ParametroAtivo(int id, TVector< int > *valores=NULL) const
Definition TProcura.h:524
virtual void ExecucaoTerminada()
Chamar após a execução do algoritmo. Grava o tempo consumido.
void MostraRelatorio(TVector< TResultado > &resultados, bool ultimo=false)
Mostra um relatório dos resultados.
Definition TProcura.cpp:966
bool EditarIndicadores()
Permite ao utilizador editar os indicadores a utilizar.
Definition TProcura.cpp:193
static int mpiCount
MPI - número de processos.
Definition TProcura.h:505
static void InicializaMPI(int argc, char *argv[])
Inicializa o ambiente MPI, se aplicável.
static int NovoValor(const char *prompt)
void MostraIndicadores()
Mostra os indicadores definidos.
static TVector< TIndicador > indicador
Indicadores que podem ser calculados após a execução, quer com informação da instãncia, quer com resultado da ...
Definition TProcura.h:488
bool JuntarCSV(const char *ficheiro)
Juntar ficheiros CSV gerados por diferentes processos MPI em um único ficheiro.
virtual void main(int argc, char *argv[], const char *nome)
Inicializa a interação com o utilizador.
Definition TProcura.cpp:804
static clock_t instanteFinal
Instante final (deadline) da corrida atual.
Definition TProcura.h:499
void EditarParametros()
Permite ao utilizador editar os parâmetros.
Definition TProcura.cpp:221
bool RelatorioCSV(TVector< TResultado > &resultados, char *ficheiro)
Gera um relatório CSV com os resultados.
Definition TProcura.cpp:915
void DebugTabela(ENivelDebug nivel, TVector< int >tabela, const char *tipo="")
Mostra uma tabela de inteiros, 10 elementos por linha, apenas se o nível de debug for igual ou superior...
int MelhorResultado(TResultado base, TResultado alternativa)
Compara dois resultados para determinar o melhor.
virtual void Explorar()
definir para explorar manualmente os dados (não definido em TProcura, apenas em TProcuraConstrutiva)
Definition TProcura.h:468
void CalculaTorneio(TVector< TResultado > &resultados)
Calcula o torneio entre várias configurações.
void ConfiguracaoAtual(TVector< int > &parametros, int operacao)
Grava ou lê a configuração atual.
Definition TProcura.cpp:269
static TVector< int > indAtivo
Definition TProcura.h:489
static TParametro instancia
ID da instância atual, a ser utilizado em SolucaoVazia().
Definition TProcura.h:24
virtual TVector< int64_t > CodificarSolucao()
retorna um vetor de inteiros com a codificação da solução (esta codificação será adicionada aos indicadores,...
Definition TProcura.h:472
void InserirRegisto(TVector< TResultado > &resultados, int inst, int conf)
Insere um novo registo de resultados.
Definition TProcura.cpp:313
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
void AjudaUtilizacao(const char *programa)
Mostra ajuda de utilização do programa.
Definition TProcura.cpp:892
void EditarConfiguracoes()
Permite ao utilizador editar as configurações.
Definition TProcura.cpp:350
int64_t Registo(TResultado &resultado, int id)
Procura um registo com determinado id.
Definition TProcura.cpp:322
virtual void LimparEstatisticas()
Chapar antes da execução do algoritmo. Limpa valores estatísticos, e fixa o instante limite de tempo para...
Definition TProcura.cpp:99
virtual void TesteEmpirico(TVector< int > instancias, char *ficheiro=NULL)
Executa testes empíricos, em todas as configurações guardadas, nas instâncias selecionadas.
Definition TProcura.cpp:498
void SolicitaInstancia()
Solicita ao utilizador o ID da instância a utilizar, permitindo alterar também o prefixo do ficheiro.
static double tempo
tempo consumido na última execução.
Definition TProcura.h:495
bool TempoExcedido()
Definition TProcura.h:512
virtual void TesteEmpiricoGestor(TVector< int > instancias, char *ficheiro=NULL)
Teste empírico com modo mestre-escravo (este é o mestre)
Definition TProcura.cpp:579
Item & First()
Definition TVector.h:221
bool Empty() const
Definition TVector.h:230
Item & Last()
Definition TVector.h:224
TVector< Item > & Delete(int i)
Remove o elemento na posição i deslocando os seguintes.
Definition TVector.h:817
int Count() const
Definition TVector.h:227
void srand(unsigned int seed, int seq)
Inicializa a semente da geração pseudo-aleatória.
Definition TRand.cpp:34
FILE * fopen(const char *filename, const char *mode)
Definition compact.h:8
char * strtok(char *str, const char *delim, char **context)
Definition compact.h:18
Estrutura para registo de um parâmetro.
Definition TProcura.h:135
int valor
valor do parametro
Definition TProcura.h:139
int max
valor máximo que o parametro pode tomar
Definition TProcura.h:143
int min
valor mínimo que o parametro pode tomar
Definition TProcura.h:141