00001
00008
00009
00010
00011
00012
00013
00014
00114 #include "aib.h"
00115
00116 #include <stdio.h>
00117 #include <stdlib.h>
00118 #include <float.h>
00119 #include <math.h>
00120
00122 #define BETA_MAX DBL_MAX
00123
00134 void vl_aib_normalize_P (double * P, vl_uint nelem)
00135 {
00136 vl_uint i;
00137 double sum = 0;
00138 for(i=0; i<nelem; i++)
00139 sum += P[i];
00140 for(i=0; i<nelem; i++)
00141 P[i] /= sum;
00142 }
00143
00153 vl_uint *vl_aib_new_nodelist (vl_uint nentries)
00154 {
00155 vl_uint * nodelist = vl_malloc(sizeof(vl_uint)*nentries);
00156 vl_uint n;
00157 for(n=0; n<nentries; n++)
00158 nodelist[n] = n;
00159
00160 return nodelist;
00161 }
00162
00175 double * vl_aib_new_Px(double * Pcx, vl_uint nvalues, vl_uint nlabels)
00176 {
00177 double * Px = vl_malloc(sizeof(double)*nvalues);
00178 vl_uint r,c;
00179 for(r=0; r<nvalues; r++)
00180 {
00181 double sum = 0;
00182 for(c=0; c<nlabels; c++)
00183 sum += Pcx[r*nlabels+c];
00184 Px[r] = sum;
00185 }
00186 return Px;
00187 }
00188
00200 double * vl_aib_new_Pc(double * Pcx, vl_uint nvalues, vl_uint nlabels)
00201 {
00202 double * Pc = vl_malloc(sizeof(double)*nlabels);
00203 vl_uint r, c;
00204 for(c=0; c<nlabels; c++)
00205 {
00206 double sum = 0;
00207 for(r=0; r<nvalues; r++)
00208 sum += Pcx[r*nlabels+c];
00209 Pc[c] = sum;
00210 }
00211 return Pc;
00212 }
00213
00227 void vl_aib_min_beta
00228 (VlAIB * aib, vl_uint * besti, vl_uint * bestj, double * minbeta)
00229 {
00230 vl_uint i;
00231 *minbeta = aib->beta[0];
00232 *besti = 0;
00233 *bestj = aib->bidx[0];
00234
00235 for(i=0; i<aib->nentries; i++)
00236 {
00237 if(aib->beta[i] < *minbeta)
00238 {
00239 *minbeta = aib->beta[i];
00240 *besti = i;
00241 *bestj = aib->bidx[i];
00242 }
00243 }
00244 }
00245
00266 void
00267 vl_aib_merge_nodes (VlAIB * aib, vl_uint i, vl_uint j, vl_uint new)
00268 {
00269 vl_uint last_entry = aib->nentries - 1 ;
00270 vl_uint c, n ;
00271
00272
00273 aib->nwhich = 0;
00274
00275
00276 if(i > j) { vl_uint tmp = j; j = i; i = tmp; }
00277
00278
00279
00280
00281
00282 aib-> Px [i] += aib->Px[j] ;
00283 aib-> beta [i] = BETA_MAX ;
00284 aib-> nodes[i] = new ;
00285
00286 for (c = 0; c < aib->nlabels; c++)
00287 aib-> Pcx [i*aib->nlabels + c] += aib-> Pcx [j*aib->nlabels + c] ;
00288
00289
00290
00291
00292
00293 aib-> Px [j] = aib-> Px [last_entry];
00294 aib-> beta [j] = aib-> beta [last_entry];
00295 aib-> bidx [j] = aib-> bidx [last_entry];
00296 aib-> nodes [j] = aib-> nodes [last_entry];
00297
00298 for (c = 0 ; c < aib->nlabels ; c++)
00299 aib-> Pcx[j*aib->nlabels + c] = aib-> Pcx [last_entry*aib->nlabels + c] ;
00300
00301
00302 aib-> nentries -- ;
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318 for (n = 0 ; n < aib->nentries; n++) {
00319 if(aib->bidx[n] == i || aib->bidx[n] == j) {
00320 aib->bidx [n] = 0;
00321 aib->beta [n] = BETA_MAX;
00322 aib->which [aib->nwhich++] = n ;
00323 }
00324 else if(aib->bidx[n] == last_entry) {
00325 aib->bidx[n] = j ;
00326 }
00327 }
00328 }
00329
00345 void
00346 vl_aib_update_beta (VlAIB * aib)
00347 {
00348
00349 #define PLOGP(x) ((x)*log((x)))
00350
00351 vl_uint i;
00352 double * Px = aib->Px;
00353 double * Pcx = aib->Pcx;
00354 double * tmp = vl_malloc(sizeof(double)*aib->nentries);
00355 vl_uint a, b, c ;
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370 for (a = 0; a < aib->nentries; a++) {
00371 tmp[a] = 0;
00372 for (c = 0; c < aib->nlabels; c++) {
00373 double Pac = Pcx [a*aib->nlabels + c] ;
00374 if(Pac != 0) tmp[a] += Pac * log (Pac / Px[a]) ;
00375 }
00376 }
00377
00378
00379 for (i = 0 ; i < aib->nwhich; i++) {
00380 a = aib->which[i];
00381
00382
00383 for(b = 0 ; b < aib->nentries ; b++) {
00384 double T1 = 0 ;
00385
00386 if (a == b || Px [a] == 0 || Px [b] == 0) continue ;
00387
00388
00389 T1 = PLOGP ((Px[a] + Px[b])) ;
00390 T1 += tmp[a] + tmp[b] ;
00391
00392 for (c = 0 ; c < aib->nlabels; ++ c) {
00393 double Pac = Pcx [a*aib->nlabels + c] ;
00394 double Pbc = Pcx [b*aib->nlabels + c] ;
00395 if (Pac == 0 && Pbc == 0) continue;
00396 T1 += - PLOGP ((Pac + Pbc)) ;
00397 }
00398
00399
00400
00401
00402
00403 {
00404 double beta = T1 ;
00405
00406 if (beta < aib->beta[a])
00407 {
00408 aib->beta[a] = beta;
00409 aib->bidx[a] = b;
00410 }
00411 if (beta < aib->beta[b])
00412 {
00413 aib->beta[b] = beta;
00414 aib->bidx[b] = a;
00415 }
00416 }
00417 }
00418 }
00419 vl_free(tmp);
00420 }
00421
00432 void vl_aib_calculate_information(VlAIB * aib, double * I, double * H)
00433 {
00434 vl_uint r, c;
00435 *H = 0;
00436 *I = 0;
00437
00438
00439
00440
00441
00442
00443
00444 for(r = 0 ; r< aib->nentries ; r++) {
00445
00446 if (aib->Px[r] == 0) continue ;
00447 *H += -log(aib->Px[r]) * aib->Px[r] ;
00448
00449 for(c=0; c<aib->nlabels; c++) {
00450 if (aib->Pcx[r*aib->nlabels+c] == 0) continue;
00451 *I += aib->Pcx[r*aib->nlabels+c] *
00452 log (aib->Pcx[r*aib->nlabels+c] / (aib->Px[r]*aib->Pc[c])) ;
00453 }
00454 }
00455 }
00456
00484 VlAIB * vl_aib_new(double * Pcx, vl_uint nvalues, vl_uint nlabels)
00485 {
00486 VlAIB * aib = vl_malloc(sizeof(VlAIB));
00487 vl_uint i ;
00488
00489 aib->Pcx = Pcx ;
00490 aib->nvalues = nvalues ;
00491 aib->nlabels = nlabels ;
00492
00493 vl_aib_normalize_P (aib->Pcx, aib->nvalues * aib->nlabels) ;
00494
00495 aib->Px = vl_aib_new_Px (aib->Pcx, aib->nvalues, aib->nlabels) ;
00496 aib->Pc = vl_aib_new_Pc (aib->Pcx, aib->nvalues, aib->nlabels) ;
00497
00498 aib->nentries = aib->nvalues ;
00499 aib->nodes = vl_aib_new_nodelist(aib->nentries) ;
00500 aib->beta = vl_malloc(sizeof(double) * aib->nentries) ;
00501 aib->bidx = vl_malloc(sizeof(vl_uint) * aib->nentries) ;
00502
00503 for(i = 0 ; i < aib->nentries ; i++)
00504 aib->beta [i] = BETA_MAX ;
00505
00506
00507 aib->nwhich = aib->nvalues;
00508 aib->which = vl_aib_new_nodelist (aib->nwhich) ;
00509
00510 aib->parents = vl_malloc(sizeof(vl_uint)*(aib->nvalues*2-1));
00511
00512 for (i = 0 ; i < 2 * aib->nvalues - 1 ; i++)
00513 aib->parents [i] = 2 * aib->nvalues ;
00514
00515
00516 aib->costs = vl_malloc (sizeof(double) * (aib->nvalues - 1 + 1)) ;
00517
00518
00519 return aib ;
00520 }
00521
00527 void
00528 vl_aib_delete (VlAIB * aib)
00529 {
00530 if (aib) {
00531 if (aib-> nodes) vl_free (aib-> nodes);
00532 if (aib-> beta) vl_free (aib-> beta);
00533 if (aib-> bidx) vl_free (aib-> bidx);
00534 if (aib-> which) vl_free (aib-> which);
00535 if (aib-> Px) vl_free (aib-> Px);
00536 if (aib-> Pc) vl_free (aib-> Pc);
00537 if (aib-> parents) vl_free (aib-> parents);
00538 if (aib-> costs) vl_free (aib-> costs);
00539 }
00540 vl_free (aib) ;
00541 }
00542
00580 VL_EXPORT
00581 void vl_aib_process(VlAIB *aib)
00582 {
00583 vl_uint i, besti, bestj, newnode, nodei, nodej;
00584 double I, H;
00585 double minbeta;
00586
00587
00588 vl_aib_calculate_information (aib, &I, &H) ;
00589 aib->costs[0] = I;
00590
00591
00592
00593
00594 for(i = 0 ; i < aib->nvalues - 1 ; i++) {
00595
00596
00597 vl_aib_update_beta(aib);
00598
00599
00600 vl_aib_min_beta (aib, &besti, &bestj, &minbeta);
00601
00602 if(minbeta == BETA_MAX)
00603
00604 break;
00605
00606
00607 newnode = aib->nvalues + i ;
00608 nodei = aib->nodes[besti];
00609 nodej = aib->nodes[bestj];
00610
00611 aib->parents [nodei] = newnode ;
00612 aib->parents [nodej] = newnode ;
00613 aib->parents [newnode] = 0 ;
00614
00615
00616 vl_aib_merge_nodes (aib, besti, bestj, newnode) ;
00617 vl_aib_calculate_information (aib, &I, &H) ;
00618
00619 aib->costs[i+1] = I;
00620
00621 VL_PRINTF ("aib: (%5d,%5d)=%5d dE: %10.3g I: %6.4g H: %6.4g updt: %5d\n",
00622 nodei,
00623 nodej,
00624 newnode,
00625 minbeta,
00626 I,
00627 H,
00628 aib->nwhich) ;
00629 }
00630
00631
00632 for(; i < aib->nvalues - 1 ; i++)
00633 aib->costs[i+1] = VL_NAN_D ;
00634 }