/* Last edited on 2009-12-14 17:43:07 by stolfilocal */ #include #include #include #include #define True 1 #define False 0 // PROTOTIPOS INTERNOS void plotaFila( Plotter_t *plt, filaCandidatos_t *fila, QFILA_t qual, int iteracao, int nBoxes, int res_max, float Dmin, float Dmax ); void acumulaEstatisticas(int k, float odLo, float odHi, float dLo, float dHi, float dMd, double estLo[], double estHi[], double estMd[], int estNum[]); void imprimeEstatisticas(int res_max, double estLo[], double estHi[], double estMd[], int estNum[]); candidato_t *escolheCandidatoAuto(filaCandidatos_t *fila, int num_resultados); // Escolhe o proximo candidato da fila {QFILA_Ex} a refinar. candidato_t *escolheCandidatoManual(filaCandidatos_t *fila); // Pede para o usuario escolher o proximo candidato da fila {QFILA_Ex} a refinar. int comparaCandidatosDMd(candidato_t *x,candidato_t *y); int comparaCandidatosDLoEsperadoDepois(candidato_t *x,candidato_t *y); int comparaCandidatosNivelDLoEsperadoDepois(candidato_t *x,candidato_t *y); int comparaCandidatosFracaoDentroDaFaixa(candidato_t *x,candidato_t *y, float dAstLo, float dAstHi); void refinaIntervaloDist ( char *bandir, char *ext, float_image_t *Alo, float_image_t *Ahi, float_image_t *AmdLo, float_image_t *AmdHi, float_image_t *AsdLo, float_image_t *AsdHi, int res, int res_max, int fator, char *cand_nome, int bgZero, int usa_IA, int usa_MD_SD, QDIST_t qualDist, float *distAcc, int cumul, double lambda[], float dist[], Interval *distEstIA, int *ndistExP, int *ndistIAP ); // IMPLEMENTACOES void buscaMuSIS ( char *bandir, char *model_name, char *ext, int res_max, int fator, int num_imagens, char *nome_imagem[], int num_resultados, int distsExPorNivel[], int distsIAPorNivel[], int bgZero, int criteriosEscolha, int usa_IA, int usa_MD_SD, QDIST_t qualDist, int cumul, double base, int opcaoPlot ) { int debug = 0; int plotar = (opcaoPlot > 0); int manual = 0; int online = (opcaoPlot == 1); float dAstLo = 0.0; // Limite inferior para a minima distancia. float dAstHi = 1.0; // Limite superior para a distancia do ultimo resultado desejado. auto int comparaEscolha(candidato_t *x, candidato_t *y); // Funcao que determina a ordem de escolha para refinamento (fila {QFILA_Ex}). // Piramide da imagem modelo float_image_t *modeloHi[res_max+1]; float_image_t *modeloLo[res_max+1]; float_image_t *modeloMdlo[res_max+1]; float_image_t *modeloMdhi[res_max+1]; float_image_t *modeloSdlo[res_max+1]; float_image_t *modeloSdhi[res_max+1]; int i; float_image_t *ALo=NULL; float_image_t *AHi=NULL; float_image_t *AMdlo=NULL; float_image_t *AMdhi=NULL; float_image_t *ASdlo=NULL; float_image_t *ASdhi=NULL; for (i=0; i <= res_max; i++) { leImagens(bandir,model_name,i,ext,&ALo,&AHi,&AMdlo,&AMdhi,&ASdlo,&ASdhi); modeloLo[i]=ALo; modeloHi[i]=AHi; modeloMdlo[i]=AMdlo; modeloMdhi[i]=AMdhi; modeloSdlo[i]=ASdlo; modeloSdhi[i]=ASdhi; } // Inicializa fila de candidatos: filaCandidatos_t fila = criaFila(); for (i=0; i 100) { num_plotar = 100; } plt = openPlotter(bandir, model_name, online); } while (num_resultados > 0) { assert(fila.n >= num_resultados); // Atualiza dAstLo, dAstHi: dAstLo = indexaCand(&fila,0,QFILA_Lo)->distLo; dAstHi = indexaCand(&fila,num_resultados-1,QFILA_Hi)->distHi; if (debug) { fprintf(stderr, "dAstLo = %8.6f dAstHi = %8.6f\n", dAstLo, dAstHi); } assert(dAstLo <= dAstHi); // Reordena a fila {QFILA_Ex} se necessario: reordenaFila(&fila,&comparaEscolha); // Gera um arquivo com as informações atuais if (plotar) { plotaFila(plt, &fila, qPl, iteracao, num_plotar, res_max, dAstLo, dAstHi); iteracao++; } // Escolhe candidato para refinar e tira da fila: candidato_t *cand; if (manual) { cand = escolheCandidatoManual(&fila); } else { cand = escolheCandidatoAuto(&fila,num_resultados); } assert(cand != NULL); if (debug) { fprintf(stderr, "Retirado: "); exibeCand(cand); } char *cand_nome = cand->nome; int cand_k = cand->k; float old_distLo = cand->distLo; float old_distHi = cand->distHi; float old_distMd = cand->distMd; float distAcc = cand->distAcc; Interval distEstIA = cand->distEstIA; assert(old_distLo <= old_distMd); assert(old_distMd <= old_distHi); retiraCandidato(&fila,cand); cand = NULL; // Refina o candidato: int res = cand_k - 1; assert(res >= 0); float dist[3]; refinaIntervaloDist ( bandir, ext, modeloLo[res], modeloHi[res], modeloMdlo[res], modeloMdhi[res], modeloSdlo[res], modeloSdhi[res], res, res_max, fator, cand_nome, bgZero, usa_IA, usa_MD_SD, qualDist, &distAcc, cumul, lambda, dist, &distEstIA, &(distsExPorNivel[res]), &(distsIAPorNivel[res]) ); if (debug) { fprintf(stderr, "Calculado: dist = [ %8.6f _ %8.6f ] ~ %8.6f \n", dist[0], dist[1], dist[2]); fprintf(stderr, "Iteracao: %d\n", iteracao); } if (res == 0) { // Exige que o intervalo seja exato e dentro da estimativa intervalar: assert(dist[0] == dist[1]); assert(dist[0] >= old_distLo); assert(dist[1] <= old_distHi); } else { //corrige erro arredondamento dist[0]-=0.0001; dist[1]+=0.0001; // Combina estimativa intervalar anterior com esta: if (dist[0] < old_distLo) { dist[0] = old_distLo; } if (dist[1] > old_distHi) { dist[1] = old_distHi; } } if (dist[2] < dist[0]) { dist[2] = dist[0]; } if (dist[2] > dist[1]) { dist[2] = dist[1]; } if (debug) { fprintf(stderr, "Calculado2: dist = [ %8.6f _ %8.6f ] ~ %8.6f \n", dist[0], dist[1], dist[2]); } assert(dist[0] <= dist[1]); if (debug) { fprintf(stderr, "Acumulando estatisticas (k = %d)\n", cand_k); } acumulaEstatisticas(cand_k, old_distLo, old_distHi, dist[0], dist[1], dist[2], estLo, estHi, estMd, estNum); if (debug) { fprintf(stderr, "Re-inserindo na fila:\n"); } cand = insereCandidato(&fila,cand_nome,res,dist[0],dist[1],dist[2],distAcc,distEstIA,&comparaEscolha); if (debug) { fprintf(stderr, "Inserido: "); exibeCand(cand); } if (debug) { fprintf(stderr, "Antes da limpeza n = %d\n", fila.n); } limpaRuins(&fila,&num_resultados); if (debug) { fprintf(stderr, "Limpou ruins n = %d\n", fila.n); } limpaBons(&fila,&num_resultados,arq_resultados); if (debug) { fprintf(stderr, "Limpou bons n = %d\n", fila.n); } if (debug) { fprintf(stderr, "\n"); } } if (plotar) { plotaFila(plt, &fila, qPl, iteracao, num_plotar, res_max, 1, 0); } // Limpeza final for (i=0; i <= res_max; i++) { ALo=modeloLo[i]; AHi=modeloHi[i]; AMdlo=modeloMdlo[i]; AMdhi=modeloMdhi[i]; ASdlo=modeloSdlo[i]; ASdhi=modeloSdhi[i]; liberaImagens(&ALo,&AHi,&AMdlo,&AMdhi,&ASdlo,&ASdhi); } if (plotar) { closePlotter(plt); } if (debug) { imprimeEstatisticas(res_max, estLo, estHi, estMd, estNum); } return; // Definicao do criterio de escolha: int comparaEscolha(candidato_t *x, candidato_t *y) { if (criteriosEscolha==0) //ordena pelo menor distLo com k>0 { return comparaLo(x,y); } else if (criteriosEscolha==1) //ordena pelo maior disthi { return comparaHi(x,y); } else if (criteriosEscolha==2) //ordena pelo menor distMd com k>0 { return comparaCandidatosDMd(x,y); } else if (criteriosEscolha==3) //ordena pelo valor esperado de dLo depois do refinamento { return comparaCandidatosDLoEsperadoDepois(x,y); } else if (criteriosEscolha==4) //ordena pelo nivel decrescente, depois pelo distLo esperado depois da divisao crescente { return comparaCandidatosNivelDLoEsperadoDepois(x,y); } else //ordena pela fração decrescente do intervalo que esta dentro da faixa {dAstLo, dAstHi} { return comparaCandidatosFracaoDentroDaFaixa(x,y,dAstLo,dAstHi); } } } void gravaCand(candidato_t *cand,FILE *arq) { fprintf(arq,"%s %02d %8.6f %8.6f %8.6f %8.6f %8.6f\n",cand->nome,cand->k,cand->distLo,cand->distHi,cand->distMd,0.0,0.0); fflush(arq); } void refinaIntervaloDist ( char *bandir, char *ext, float_image_t *ALo, float_image_t *AHi, float_image_t *AMdLo, float_image_t *AMdHi, float_image_t *ASdLo, float_image_t *ASdHi, int res, int res_max, int fator, char *cand_nome, int bgZero, int usa_IA, int usa_MD_SD, QDIST_t qualDist, float *distAcc, int cumul, double lambda[], float dist[], Interval *distEstIA, int *ndistExP, int *ndistIAP ) { float_image_t *BLo=NULL; float_image_t *BHi=NULL; float_image_t *BMdLo=NULL; float_image_t *BMdHi=NULL; float_image_t *BSdLo=NULL; float_image_t *BSdHi=NULL; leImagens(bandir,cand_nome,res,ext,&BLo,&BHi,&BMdLo,&BMdHi,&BSdLo,&BSdHi); if (cumul) { estima_dist_Multiescala ( ALo, AHi, AMdLo, AMdHi, ASdLo, ASdHi, BLo, BHi, BMdLo, BMdHi, BSdLo, BSdHi, res, res_max, bgZero, usa_IA, usa_MD_SD, qualDist, distAcc, lambda, dist, distEstIA, ndistExP, ndistIAP ); } else { estima_dist_Monoescala ( ALo, AHi, AMdLo, AMdHi, ASdLo, ASdHi, BLo, BHi, BMdLo, BMdHi, BSdLo, BSdHi, res, res_max, bgZero, usa_IA, usa_MD_SD, qualDist, dist, ndistExP, ndistIAP ); } liberaImagens(&BLo,&BHi,&BMdLo,&BMdHi,&BSdLo,&BSdHi); } void limpaRuins(filaCandidatos_t *fila,int *m) { if ((*m) > fila->n) { (*m) = fila->n; } if ((*m) >= fila->n) { return; } assert((*m) > 0); // Determina o corte - m-esimo Hi: candidato_t *aux = indexaCand(fila,(*m) - 1, QFILA_Hi); assert(aux != NULL); float corte = aux->distHi; // Elimina todo mundo acima do corte: candidato_t *ele = fila->prim[QFILA_Lo]; // Primeiro em ordem de Lo // procura o primeiro ruim: while ((ele != NULL) && (ele->distLo <= corte)) { ele = ele->prox[QFILA_Lo]; } // Elimina todos dali para a frente: while (ele != NULL) { assert(ele->distLo > corte); candidato_t *pro = ele->prox[QFILA_Lo]; // Salva o proximo da lista retiraCandidato(fila,ele); ele = pro; } assert(fila->n >= (*m)); } void limpaBons(filaCandidatos_t *fila,int *m,FILE *arq) { if ((*m) > fila->n) { (*m) = fila->n; } while ((*m) > 0) { assert(fila->n > 0); candidato_t *cmin = indexaCand(fila,0,QFILA_Lo); // candidato com menor Lo assert(cmin != NULL); candidato_t *cseg = indexaCand(fila,1,QFILA_Lo); // candidato com segundo menor Lo, ou NULL if ((cseg != NULL) && (cmin->distHi > cseg->distLo)) break; gravaCand(cmin,arq); retiraCandidato(fila,cmin); (*m)--; } } void acumulaEstatisticas(int k, float odLo, float odHi, float dLo, float dHi, float dMd, double estLo[], double estHi[], double estMd[], int estNum[]) { estNum[k]++; double rLo, rHi, rMd; if (odLo == odHi) { // Nao deveria acontecer, mas... rLo = rHi = rMd = 0.5; } else { rLo = ((double) dLo - odLo)/((double) odHi - odLo); rHi = ((double) dHi - odLo)/((double) odHi - odLo); rMd = ((double) dMd - odLo)/((double) odHi - odLo); } estLo[k] += rLo; estHi[k] += rHi; estMd[k] += rMd; } void imprimeEstatisticas(int res_max, double estLo[], double estHi[], double estMd[], int estNum[]) { assert(estNum[0] == 0); int k; fprintf(stderr, "efeito medio do refinamento por escala:\n"); for (k = 0; k <= res_max+1; k++) { if (estNum[k] != 0) { double rLo = estLo[k]/estNum[k]; double rHi = estHi[k]/estNum[k]; double rMd = estMd[k]/estNum[k]; fprintf(stderr, "nivel %2d rLo = %6.4f rHi = %6.4f rMd = %6.4f\n", k, rLo, rHi, rMd); } } } candidato_t *escolheCandidatoAuto(filaCandidatos_t *fila, int num_resultados) { candidato_t *cand0 = indexaCand(fila,0,QFILA_Ex); assert(cand0!=NULL); candidato_t *cand1 = NULL; int cont = 0; while ((cand0 != NULL) && ((cand1 == NULL) || (cont < num_resultados))) { if (cand0->k != 0) { cand1 = cand0; } cand0=cand0->prox[QFILA_Ex]; cont++; } assert(cand1!=NULL); return cand1; } candidato_t *escolheCandidatoManual(filaCandidatos_t *fila) { //a escolha da de quem sai é do usuário int pos=-1; candidato_t *cand0 = NULL; do{ fprintf(stderr, "\nDigite a posição na fila do intervalo que deseja retirar\n"); scanf("%d", &pos); if (pos >= 0) { cand0 = indexaCand(fila,pos,QFILA_Ex); } } while ((cand0 == NULL) || (cand0->k == 0)); return cand0; } void plotaFila( Plotter_t *plt, filaCandidatos_t *fila, QFILA_t qual, int iteracao, int nBoxes, int res_max, float Dmin, float Dmax ) { beginPlot(plt, nBoxes, iteracao); drawQueue(plt, fila->prim[qual], qual, res_max, Dmin, Dmax); endPlot(plt); } int comparaCandidatosDMd(candidato_t *x,candidato_t *y) { // Ordena pelo valor de distMd, desempata por k: float xMd = x->distMd; float yMd = y->distMd; if (xMd < yMd) { return -1; } else if (xMd > yMd) { return +1; } else if (x->k > y->k) { return -1; } else if (x->k < y->k) { return +1; } else {return 0; } } int comparaCandidatosDLoEsperadoDepois(candidato_t *x,candidato_t *y) { // Ordena pelo valor esperado de dLo depois do refinamento: double xrLo = pow(2.0, -(x->k)); double yrLo = pow(2.0, -(y->k)); float xeLo = ((1-xrLo)*x->distLo + xrLo*x->distHi); float yeLo = ((1-yrLo)*y->distLo + yrLo*y->distHi); if (xeLo < yeLo) { return -1; } else if (xeLo > yeLo) { return +1; } else if (x->k > y->k) { return -1; } else if (x->k < y->k) { return +1; } else {return 0; } } int comparaCandidatosNivelDLoEsperadoDepois(candidato_t *x,candidato_t *y) { // Ordena pelo nivel decrescente, depois pelo distLo esperado depois da divisao crescente: if (x->k > y->k) { return -1; } else if (x->k < y->k + 1.0e-10) { return +1; } else { double xrLo = pow(2.0, -(x->k)); double yrLo = pow(2.0, -(y->k)); float xeLo = ((1-xrLo)*x->distLo + xrLo*x->distHi); float yeLo = ((1-yrLo)*y->distLo + yrLo*y->distHi); if (xeLo < yeLo) { return -1; } else if (xeLo > yeLo) { return +1; } else { return 0; } } } int comparaCandidatosFracaoDentroDaFaixa(candidato_t *x,candidato_t *y, float dAstLo, float dAstHi) { // Ordena pela fracao decrescente do intervalo que esta dentro da faixa {dAstLo, dAstHi} assert(x->distLo >= dAstLo); assert(y->distLo >= dAstLo); double xf = (x->distLo > dAstHi ? 0 : (dAstHi - x->distLo)/(x->distHi - x->distLo + 1.0e-10)); double yf = (y->distLo > dAstHi ? 0 : (dAstHi - y->distLo)/(y->distHi - y->distLo + 1.0e-10)); int debug = 0; if (debug) { fprintf(stderr, "d* = [ %8.6f _ %8.6f ]\n", dAstLo, dAstHi); fprintf(stderr, "x = [ %8.6f _ %8.6f ] xf = %22.6f\n", x->distLo, x->distHi, xf); fprintf(stderr, "y = [ %8.6f _ %8.6f ] yf = %22.6f\n", y->distLo, y->distHi, yf); fprintf(stderr, "\n"); } if (xf > yf) { return -1; } else if (xf < yf) { return +1; } else if (x->k > y->k) { return -1; } else if (x->k < y->k) { return +1; } else { return 0; } }