vl_aib.c
Go to the documentation of this file.
00001 
00008 /*
00009 Copyright (C) 2007-12 Andrea Vedaldi and Brian Fulkerson.
00010 All rights reserved.
00011 
00012 This file is part of the VLFeat library and is made available under
00013 the terms of the BSD license (see the COPYING file).
00014 */
00015 
00016 #include <mexutils.h>
00017 #include <vl/mathop.h>
00018 #include <vl/aib.h>
00019 
00020 #include <assert.h>
00021 #include <string.h>
00022 
00023 /* option codes */
00024 enum {
00025   opt_cluster_null = 0,
00026   opt_verbose
00027 } ;
00028 
00029 /* options */
00030 vlmxOption  options [] = {
00031   {"ClusterNull",0,   opt_cluster_null},
00032   {"Verbose",    0,   opt_verbose    },
00033   {0,            0,   0              }
00034 } ;
00035 
00036 #define CLUSTER_NULL_NODES 1
00037 
00051 static void
00052 cluster_null_nodes (vl_uint32* parents, vl_uint32 nvalues, double *cost, int verbosity)
00053 {
00054   vl_uint32 nnull = 0 ;
00055   vl_uint32 n ;
00056   vl_uint32 first ;
00057   vl_uint32 last_intermed ;
00058 
00059   vl_uint32 a, b, c, d, e ;
00060   vl_uint32 dp, ep ;
00061 
00062   /* count null nodes so far */
00063   for (n = 0 ; n < nvalues ; ++ n) {
00064     if (parents[n] >= 2 * nvalues - 1) {
00065       ++ nnull ;
00066     }
00067   }
00068 
00069   if (nnull == 0) return ;
00070 
00071   /* = : leaves
00072    * 0 : null leaves
00073    * i : internal node
00074    * * : padding
00075    * x : intermediate nodes to link null nodes
00076    *
00077    * Input:
00078    *
00079    * ====== 0000 ======= iiiiiii ****
00080    * |                   |     |
00081    * 0                   dp    ep
00082    *
00083    *
00084    * Output:
00085    *
00086    * ====== ==== ======= xxxx iiiiiii
00087    * |                   | || |     |
00088    * 0                   a bc d     e
00089    */
00090 
00091   a = nvalues ;
00092   b = nvalues + nnull - 1 - 1 ;
00093   c = b + 1 ;
00094   d = c + 1 ;
00095   e = 2 * nvalues - 2 ;
00096 
00097   dp = nvalues ;
00098   ep = 2 * nvalues - 2 - nnull ;
00099 
00100   if (verbosity > 1) {
00101     mexPrintf("vl_aib: a:%u b:%u c:%u d:%u e:%u dp:%u ep:%u\n",
00102               a,b,c,d,e,dp,ep) ;
00103   }
00104 
00105   /* search first leaf that has been merged */
00106   {
00107     vl_uint32 first_parent = e ;
00108     first = 0 ;
00109     for (n = 0 ; n < nvalues ; ++ n) {
00110       if ((parents[n] <= e) & (parents[n] != 1)) {
00111         if (first_parent >= parents [n]) {
00112           first_parent = parents [n] ;
00113           first = n ;
00114         }
00115       }
00116     }
00117   }
00118 
00119   if (verbosity > 1) {
00120     mexPrintf("vl_aib: nnull:%u, nvalues:%u, first: %u\n",
00121               nnull,nvalues,first) ;
00122   }
00123 
00124   /* move internal node block [dp:ep] to [d:e] */
00125   for (n = 0 ; n < e ; ++ n) {
00126     if ((parents [n] <= e) & (parents [n] != 0)) {
00127       parents [n] += (e - ep) ;
00128     }
00129   }
00130   for (n = e ; n >= d ; -- n) {
00131     parents [n] = parents [n - (e - ep)] ;
00132   }
00133 
00134   /* find first null node and connect it to a */
00135   last_intermed = a ;
00136   for (n = 0 ; n < a ; ++ n) {
00137     if (parents[n] > e) {
00138       parents [n] = last_intermed ;
00139       break ;
00140     }
00141   }
00142 
00143   if (verbosity > 1) {
00144     mexPrintf("vl_aib:first null %u parent seto to last_intermed:%u\n",
00145               n,
00146               last_intermed)  ;
00147   }
00148 
00149   /* chain rest of intermediate nodes */
00150   for (; n < a ; ++ n) {
00151     if (parents[n] > e) {
00152       parents [n] = last_intermed ;
00153       parents [last_intermed] = last_intermed + 1 ;
00154       ++ last_intermed ;
00155     }
00156   }
00157 
00158   if (verbosity > 1) {
00159     mexPrintf("vl_aib: after chaining other nulls last_intermed:%u\n", last_intermed)  ;
00160   }
00161 
00162   /* make last_intermed point to d */
00163   parents [last_intermed] = d ;
00164 
00165   /* change parent of first to be last_intermed */
00166   if (verbosity > 1) {
00167     mexPrintf("vl_aib: parent of %u (first) was %u\n", first, parents[first]) ;
00168   }
00169   parents [first] = last_intermed ;
00170   if (verbosity > 1) {
00171     mexPrintf("vl_aib: parent of %u (first) is now %u\n", first, parents[first]) ;
00172   }
00173 
00174   /* fix cost too (reall that the fist entry is the cost before
00175    any merge) */
00176   if (cost) {
00177     cost -= nvalues - 1 ;
00178     for (n = e ; n >= d ; --n) {
00179       cost [n] = cost [n - (e - ep)] ;
00180     }
00181     for (n = c ; n >= a ; --n) {
00182       cost [n] = cost [d] ;
00183     }
00184   }
00185 }
00186 
00191 void
00192 mexFunction(int nout, mxArray *out[],
00193             int nin, const mxArray *in[])
00194 {
00195   enum {IN_PCX = 0, IN_END} ;
00196   enum {OUT_PARENTS = 0, OUT_COST} ;
00197   enum {INFORMATION, EC} ;
00198 
00199   int            verbose = 0 ;
00200   int            opt ;
00201   int            next = IN_END ;
00202   mxArray const *optarg ;
00203   int            cluster_null = 0 ;
00204 
00205   double   *Pcx     ;
00206   vl_uint32    nlabels ;
00207   vl_uint32    nvalues ;
00208 
00209   mxArray *Pcx_cpy ;
00210 
00211   VL_USE_MATLAB_ENV ;
00212 
00213   /* -----------------------------------------------------------------
00214    *                                               Check the arguments
00215    * -------------------------------------------------------------- */
00216 
00217   if (nin < 1) {
00218     mexErrMsgTxt("One argument required.") ;
00219   } else if (nout > 2) {
00220     mexErrMsgTxt("Too many output arguments.");
00221   }
00222 
00223   if (!vlmxIsMatrix(in[IN_PCX], -1, -1)) {
00224     mexErrMsgTxt("PCX must be a real matrix.") ;
00225   }
00226 
00227   Pcx_cpy = mxDuplicateArray(in[IN_PCX]);
00228   Pcx     = mxGetPr (Pcx_cpy) ;
00229   nlabels = mxGetM  (in[IN_PCX]) ;
00230   nvalues = mxGetN  (in[IN_PCX]) ;
00231 
00232   while ((opt = vlmxNextOption (in, nin, options, &next, &optarg)) >= 0) {
00233 
00234     switch (opt) {
00235 
00236     case opt_verbose :
00237       ++ verbose ;
00238       break ;
00239 
00240     case opt_cluster_null :
00241       cluster_null = 1 ;
00242       break ;
00243 
00244     }
00245   }
00246 
00247   if (verbose) {
00248     mexPrintf("vl_aib: clustering null probability variables: %s\n", VL_YESNO(cluster_null)) ;
00249   }
00250 
00251   /* -----------------------------------------------------------------
00252    *                                                            Do job
00253    * -------------------------------------------------------------- */
00254 
00255   {
00256     VlAIB   *aib;
00257     double* acost = 0, *cost = 0 ;
00258     vl_uint32 *aparents = 0, *parents = 0 ;
00259     vl_uint32 n ;
00260 
00261     out[OUT_PARENTS] = mxCreateNumericMatrix(1, 2*nvalues - 1, mxUINT32_CLASS, mxREAL);
00262     parents = mxGetData(out[OUT_PARENTS]);
00263 
00264     if (nout > 1) {
00265       out[OUT_COST] = mxCreateNumericMatrix(1, nvalues, mxDOUBLE_CLASS, mxREAL);
00266       cost = mxGetPr(out[OUT_COST]);
00267     }
00268 
00269     aib = vl_aib_new (Pcx, nvalues, nlabels) ;
00270     vl_aib_set_verbosity (aib, verbose) ;
00271     vl_aib_process (aib);
00272 
00273     aparents = vl_aib_get_parents (aib);
00274     acost    = vl_aib_get_costs (aib);
00275     memcpy(parents, aparents, sizeof(vl_uint32)*(2*nvalues-1));
00276     if (nout > 1)
00277       memcpy(cost, acost, sizeof(double)*nvalues);
00278 
00279     vl_aib_delete(aib);
00280 
00281     if (cluster_null) {
00282       cluster_null_nodes (parents, nvalues, (nout == 0) ? 0 : cost, verbose) ;
00283     }
00284 
00285     /* save back parents */
00286     for (n = 0 ; n < 2 * nvalues - 1 ; ++n) {
00287       if (parents [n] > 2 * nvalues - 1) {
00288         /* map ingored nodes to zero */
00289         parents [n] = 0 ;
00290       } else {
00291         /* MATLAB starts counting from 1 */
00292         ++ parents [n]  ;
00293       }
00294     }
00295 
00296   }
00297   mxDestroyArray(Pcx_cpy);
00298 }


libvlfeat
Author(s): Andrea Vedaldi
autogenerated on Thu Jun 6 2019 20:25:51