00001
00007
00008
00009
00010
00011
00012
00013
00014
00120 #include "aib.h"
00121 #include <stdio.h>
00122 #include <stdlib.h>
00123 #include <float.h>
00124 #include <math.h>
00125
00126
00127 #define BETA_MAX DBL_MAX
00128
00139 void vl_aib_normalize_P (double * P, vl_uint nelem)
00140 {
00141 vl_uint i;
00142 double sum = 0;
00143 for(i=0; i<nelem; i++)
00144 sum += P[i];
00145 for(i=0; i<nelem; i++)
00146 P[i] /= sum;
00147 }
00148
00158 vl_uint *vl_aib_new_nodelist (vl_uint nentries)
00159 {
00160 vl_uint * nodelist = vl_malloc(sizeof(vl_uint)*nentries);
00161 vl_uint n;
00162 for(n=0; n<nentries; n++)
00163 nodelist[n] = n;
00164
00165 return nodelist;
00166 }
00167
00180 double * vl_aib_new_Px(double * Pcx, vl_uint nvalues, vl_uint nlabels)
00181 {
00182 double * Px = vl_malloc(sizeof(double)*nvalues);
00183 vl_uint r,c;
00184 for(r=0; r<nvalues; r++)
00185 {
00186 double sum = 0;
00187 for(c=0; c<nlabels; c++)
00188 sum += Pcx[r*nlabels+c];
00189 Px[r] = sum;
00190 }
00191 return Px;
00192 }
00193
00205 double * vl_aib_new_Pc(double * Pcx, vl_uint nvalues, vl_uint nlabels)
00206 {
00207 double * Pc = vl_malloc(sizeof(double)*nlabels);
00208 vl_uint r, c;
00209 for(c=0; c<nlabels; c++)
00210 {
00211 double sum = 0;
00212 for(r=0; r<nvalues; r++)
00213 sum += Pcx[r*nlabels+c];
00214 Pc[c] = sum;
00215 }
00216 return Pc;
00217 }
00218
00232 void vl_aib_min_beta
00233 (VlAIB * aib, vl_uint * besti, vl_uint * bestj, double * minbeta)
00234 {
00235 vl_uint i;
00236 *minbeta = aib->beta[0];
00237 *besti = 0;
00238 *bestj = aib->bidx[0];
00239
00240 for(i=0; i<aib->nentries; i++)
00241 {
00242 if(aib->beta[i] < *minbeta)
00243 {
00244 *minbeta = aib->beta[i];
00245 *besti = i;
00246 *bestj = aib->bidx[i];
00247 }
00248 }
00249 }
00250
00271 void
00272 vl_aib_merge_nodes (VlAIB * aib, vl_uint i, vl_uint j, vl_uint new)
00273 {
00274 vl_uint last_entry = aib->nentries - 1 ;
00275 vl_uint c, n ;
00276
00277
00278 aib->nwhich = 0;
00279
00280
00281 if(i > j) { vl_uint tmp = j; j = i; i = tmp; }
00282
00283
00284
00285
00286
00287 aib-> Px [i] += aib->Px[j] ;
00288 aib-> beta [i] = BETA_MAX ;
00289 aib-> nodes[i] = new ;
00290
00291 for (c = 0; c < aib->nlabels; c++)
00292 aib-> Pcx [i*aib->nlabels + c] += aib-> Pcx [j*aib->nlabels + c] ;
00293
00294
00295
00296
00297
00298 aib-> Px [j] = aib-> Px [last_entry];
00299 aib-> beta [j] = aib-> beta [last_entry];
00300 aib-> bidx [j] = aib-> bidx [last_entry];
00301 aib-> nodes [j] = aib-> nodes [last_entry];
00302
00303 for (c = 0 ; c < aib->nlabels ; c++)
00304 aib-> Pcx[j*aib->nlabels + c] = aib-> Pcx [last_entry*aib->nlabels + c] ;
00305
00306
00307 aib-> nentries -- ;
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323 for (n = 0 ; n < aib->nentries; n++) {
00324 if(aib->bidx[n] == i || aib->bidx[n] == j) {
00325 aib->bidx [n] = 0;
00326 aib->beta [n] = BETA_MAX;
00327 aib->which [aib->nwhich++] = n ;
00328 }
00329 else if(aib->bidx[n] == last_entry) {
00330 aib->bidx[n] = j ;
00331 }
00332 }
00333 }
00334
00350 void
00351 vl_aib_update_beta (VlAIB * aib)
00352 {
00353
00354 #define PLOGP(x) ((x)*log((x)))
00355
00356 vl_uint i;
00357 double * Px = aib->Px;
00358 double * Pcx = aib->Pcx;
00359 double * tmp = vl_malloc(sizeof(double)*aib->nentries);
00360 vl_uint a, b, c ;
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375 for (a = 0; a < aib->nentries; a++) {
00376 tmp[a] = 0;
00377 for (c = 0; c < aib->nlabels; c++) {
00378 double Pac = Pcx [a*aib->nlabels + c] ;
00379 if(Pac != 0) tmp[a] += Pac * log (Pac / Px[a]) ;
00380 }
00381 }
00382
00383
00384 for (i = 0 ; i < aib->nwhich; i++) {
00385 a = aib->which[i];
00386
00387
00388 for(b = 0 ; b < aib->nentries ; b++) {
00389 double T1 = 0 ;
00390
00391 if (a == b || Px [a] == 0 || Px [b] == 0) continue ;
00392
00393
00394 T1 = PLOGP ((Px[a] + Px[b])) ;
00395 T1 += tmp[a] + tmp[b] ;
00396
00397 for (c = 0 ; c < aib->nlabels; ++ c) {
00398 double Pac = Pcx [a*aib->nlabels + c] ;
00399 double Pbc = Pcx [b*aib->nlabels + c] ;
00400 if (Pac == 0 && Pbc == 0) continue;
00401 T1 += - PLOGP ((Pac + Pbc)) ;
00402 }
00403
00404
00405
00406
00407
00408 {
00409 double beta = T1 ;
00410
00411 if (beta < aib->beta[a])
00412 {
00413 aib->beta[a] = beta;
00414 aib->bidx[a] = b;
00415 }
00416 if (beta < aib->beta[b])
00417 {
00418 aib->beta[b] = beta;
00419 aib->bidx[b] = a;
00420 }
00421 }
00422 }
00423 }
00424 vl_free(tmp);
00425 }
00426
00437 void vl_aib_calculate_information(VlAIB * aib, double * I, double * H)
00438 {
00439 vl_uint r, c;
00440 *H = 0;
00441 *I = 0;
00442
00443
00444
00445
00446
00447
00448
00449 for(r = 0 ; r< aib->nentries ; r++) {
00450
00451 if (aib->Px[r] == 0) continue ;
00452 *H += -log(aib->Px[r]) * aib->Px[r] ;
00453
00454 for(c=0; c<aib->nlabels; c++) {
00455 if (aib->Pcx[r*aib->nlabels+c] == 0) continue;
00456 *I += aib->Pcx[r*aib->nlabels+c] *
00457 log (aib->Pcx[r*aib->nlabels+c] / (aib->Px[r]*aib->Pc[c])) ;
00458 }
00459 }
00460 }
00461
00489 VlAIB * vl_aib_new(double * Pcx, vl_uint nvalues, vl_uint nlabels)
00490 {
00491 VlAIB * aib = vl_malloc(sizeof(VlAIB));
00492 vl_uint i ;
00493
00494 aib->verbosity = 0 ;
00495 aib->Pcx = Pcx ;
00496 aib->nvalues = nvalues ;
00497 aib->nlabels = nlabels ;
00498
00499 vl_aib_normalize_P (aib->Pcx, aib->nvalues * aib->nlabels) ;
00500
00501 aib->Px = vl_aib_new_Px (aib->Pcx, aib->nvalues, aib->nlabels) ;
00502 aib->Pc = vl_aib_new_Pc (aib->Pcx, aib->nvalues, aib->nlabels) ;
00503
00504 aib->nentries = aib->nvalues ;
00505 aib->nodes = vl_aib_new_nodelist(aib->nentries) ;
00506 aib->beta = vl_malloc(sizeof(double) * aib->nentries) ;
00507 aib->bidx = vl_malloc(sizeof(vl_uint) * aib->nentries) ;
00508
00509 for(i = 0 ; i < aib->nentries ; i++)
00510 aib->beta [i] = BETA_MAX ;
00511
00512
00513 aib->nwhich = aib->nvalues;
00514 aib->which = vl_aib_new_nodelist (aib->nwhich) ;
00515
00516 aib->parents = vl_malloc(sizeof(vl_uint)*(aib->nvalues*2-1));
00517
00518 for (i = 0 ; i < 2 * aib->nvalues - 1 ; i++)
00519 aib->parents [i] = 2 * aib->nvalues ;
00520
00521
00522 aib->costs = vl_malloc (sizeof(double) * (aib->nvalues - 1 + 1)) ;
00523
00524
00525 return aib ;
00526 }
00527
00533 void
00534 vl_aib_delete (VlAIB * aib)
00535 {
00536 if (aib) {
00537 if (aib-> nodes) vl_free (aib-> nodes);
00538 if (aib-> beta) vl_free (aib-> beta);
00539 if (aib-> bidx) vl_free (aib-> bidx);
00540 if (aib-> which) vl_free (aib-> which);
00541 if (aib-> Px) vl_free (aib-> Px);
00542 if (aib-> Pc) vl_free (aib-> Pc);
00543 if (aib-> parents) vl_free (aib-> parents);
00544 if (aib-> costs) vl_free (aib-> costs);
00545
00546 vl_free (aib) ;
00547 }
00548 }
00549
00587 VL_EXPORT
00588 void vl_aib_process(VlAIB *aib)
00589 {
00590 vl_uint i, besti, bestj, newnode, nodei, nodej;
00591 double I, H;
00592 double minbeta;
00593
00594
00595 vl_aib_calculate_information (aib, &I, &H) ;
00596 aib->costs[0] = I;
00597
00598
00599
00600
00601 for(i = 0 ; i < aib->nvalues - 1 ; i++) {
00602
00603
00604 vl_aib_update_beta(aib);
00605
00606
00607 vl_aib_min_beta (aib, &besti, &bestj, &minbeta);
00608
00609 if(minbeta == BETA_MAX)
00610
00611 break;
00612
00613
00614 newnode = aib->nvalues + i ;
00615 nodei = aib->nodes[besti];
00616 nodej = aib->nodes[bestj];
00617
00618 aib->parents [nodei] = newnode ;
00619 aib->parents [nodej] = newnode ;
00620 aib->parents [newnode] = 0 ;
00621
00622
00623 vl_aib_merge_nodes (aib, besti, bestj, newnode) ;
00624 vl_aib_calculate_information (aib, &I, &H) ;
00625
00626 aib->costs[i+1] = I;
00627
00628 if (aib->verbosity > 0) {
00629 VL_PRINTF ("aib: (%5d,%5d)=%5d dE: %10.3g I: %6.4g H: %6.4g updt: %5d\n",
00630 nodei,
00631 nodej,
00632 newnode,
00633 minbeta,
00634 I,
00635 H,
00636 aib->nwhich) ;
00637 }
00638 }
00639
00640
00641 for(; i < aib->nvalues - 1 ; i++)
00642 aib->costs[i+1] = VL_NAN_D ;
00643 }