VLFeat.org

API docs

  • Home
    • Download and Install
    • API docs
    • Matlab docs
    • About VLFeat
  • Tutorials
    • SIFT
    • MSER
    • IKM
    • HIKM
    • AIB
    • Utils
  • Main Page
  • Related Pages
  • Data Structures
  • Files
  • Examples

aib.c

Go to the documentation of this file.
00001 
00008 /* AUTORIGHTS
00009 Copyright 2007 (c) Andrea Vedaldi and Brian Fulkerson
00010 
00011 This file is part of VLFeat, available in the terms of the GNU
00012 General Public License version 2.
00013 */
00014 
00114 #include "aib.h"
00115 
00116 #include <stdio.h>
00117 #include <stdlib.h>
00118 #include <float.h> /* DBL_MAX */
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   /* clear the list of nodes to update */
00273   aib->nwhich = 0;
00274   
00275   /* make sure that i is smaller than j */
00276   if(i > j) { vl_uint tmp = j; j = i; i = tmp; }
00277   
00278   /* -----------------------------------------------------------------
00279    *                    Merge entries i and j, storing the result in i
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    *                                              Move last entry to j
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   /* delete last entry */
00302   aib-> nentries -- ;
00303   
00304   /* -----------------------------------------------------------------
00305    *                                        Scan for entries to update
00306    * -------------------------------------------------------------- */
00307 
00308   /*
00309    * After mergin entries i and j, we need to update all other entries
00310    * that had one of these two as closest match. We also need to
00311    * update the renewend entry i. This is added by the loop below
00312    * since bidx [i] = j exactly because i was merged.
00313    *
00314    * Additionaly, since we moved the last entry back to the entry j,
00315    * we need to adjust the valeus of bidx to reflect this.
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    * T1 = I(x,c) - I([x]_ij) = A + B - C
00359    *
00360    * A  = \sum_c p(xa,c)           \log ( p(xa,c)          /  p(xa)       ) 
00361    * B  = \sum_c p(xb,c)           \log ( p(xb,c)          /  p(xb)       ) 
00362    * C  = \sum_c (p(xa,c)+p(xb,c)) \log ((p(xa,c)+p(xb,c)) / (p(xa)+p(xb)))
00363    *
00364    * C  = C1 + C2
00365    * C1 = \sum_c (p(xa,c)+p(xb,c)) \log (p(xa,c)+p(xb,c))
00366    * C2 = - (p(xa)+p(xb) \log (p(xa)+p(xb))
00367    */
00368  
00369   /* precalculate A and B */
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   /* for each entry listed in which */
00379   for (i = 0 ; i < aib->nwhich; i++) {    
00380     a = aib->which[i];
00381 
00382     /* for each other entry */
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])) ;                  /* - C2 */
00390       T1 += tmp[a] + tmp[b] ;                         /* + A + 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)) ;                 /* - C1 */
00397       }
00398       
00399       /* 
00400        * Now we have beta(a,b). We check wether this is the best beta
00401        * for entries a and b.
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      * H(x)   = - sum_x p(x)    \ log p(x)
00440      * I(x,c) =   sum_xc p(x,c) \ log (p(x,c) / p(x)p(c))
00441      */
00442     
00443     /* for each entry */
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     /* Initially we must consider all nodes */
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     /* Initially, all parents point to a nonexistent node */
00512     for (i = 0 ; i < 2 * aib->nvalues - 1 ; i++)
00513       aib->parents [i] = 2 * aib->nvalues ; 
00514 
00515     /* Allocate cost output vector */
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     /* Calculate initial value of cost function */
00588     vl_aib_calculate_information (aib, &I, &H) ;
00589     aib->costs[0] = I;
00590     
00591     /* Initially which = all */
00592     
00593     /* For each merge */
00594     for(i = 0 ; i < aib->nvalues - 1 ; i++) {
00595       
00596       /* update entries in aib-> which */
00597       vl_aib_update_beta(aib);
00598       
00599       /* find best pair of nodes to merge */
00600       vl_aib_min_beta (aib, &besti, &bestj, &minbeta);
00601 
00602       if(minbeta == BETA_MAX)
00603         /* only null-probability entries remain */
00604         break;
00605       
00606       /* Add the parent pointers for the new node */
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       /* Merge the nodes which produced the minimum beta */
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     /* fill ignored entries with NaNs */
00632     for(; i < aib->nvalues - 1 ; i++)
00633         aib->costs[i+1] = VL_NAN_D ;
00634 } 
Copyright © 2008 Andrea Vedaldi and Brian Fulkerson