<commit_before>/** @internal
 ** @file     aib.c
 ** @author   <NAME>
 ** @author   <NAME>
 ** @brief    AIB MEX driver
 **/

/* AUTORIGHTS
Copyright 2007 (c) <NAME> and <NAME>

This file is part of VLFeat, available in the terms of the GNU
General Public License version 2.
*/

#include "mexutils.h"
#include <vl/mathop.h>
#include <vl/aib.h>

#include <assert.h>
#include <string.h>

/* option codes */
enum {
  opt_cost = 0,
  opt_cluster_null,
  opt_verbose 
} ;

/* options */
uMexOption options [] = {
  {"Cost",       1,   opt_cost       },
  {"ClusterNull",0,   opt_cluster_null}, 
  {"Verbose",    0,   opt_verbose    },
  {0,            0,   0              }
} ;

#define CLUSTER_NULL_NODES 1

/** ------------------------------------------------------------------
 **
 ** Null nodes are nodes with null probability and are not merged by AIB.
 ** It is convenient, however, to treat them as follows:
 ** 
 ** - we pretend that AIB merged those nodes at the very beginning into a
 **   single cluster (as they, after hall, yield zero information drop).
 **
 ** - we attach this cluster to the root as the very last step (as we
 **   do not want to change other nodes.
 **
 ** In this way, 
 **/

static void
cluster_null_nodes (vl_uint32* parents, int nvalues, double *cost)
{
  int nnull = 0 ;
  int n ;
  int first ;
  int last_intermed ;

  int a, b, c, d, e ;
  int dp, ep ;

  /* count null nodes so far */
  for (n = 0 ; n < nvalues ; ++ n) {
    if (parents[n] >= 2 * nvalues - 1) {
      ++ nnull ;
    }
  }
  
  if (nnull == 0) return ;
  
  /* = : leaves
   * 0 : null leaves
   * i : internal node
   * * : padding
   * x : intermediate nodes to link null nodes
   *
   * Input:
   *
   * ====== 0000 ======= iiiiiii ****
   * |                   |     |
   * 0                   dp    ep
   *
   *
   * Output:
   *
   * ====== ==== ======= xxxx iiiiiii
   * |                   | || |     |
   * 0                   a bc d     e
   */
  
  a = nvalues ;
  b = nvalues + nnull - 1 - 1 ;
  c = b + 1 ;
  d = c + 1 ;
  e = 2 * nvalues - 2 ;

  dp = nvalues ;
  ep = 2 * nvalues - 2 - nnull ; 

  mexPrintf("a:%d b:%d c:%d d:%d e:%d dp:%d ep:%d\n",
            a,b,c,d,e,dp,ep) ;

  /* search first leaf that has been merged */
  {
    int first_parent = 0 ;
    first = 0 ;
    for (n = 0 ; n < nvalues ; ++ n) {
      if (parents[n] <= e) {
        if (first_parent < parents [n]) {
          first_parent = parents [n] ;
          first = n ;
        }
      }
    }
  }

  mexPrintf("nnull:%d\n",nnull) ;
  mexPrintf("nvalues:%d\n",nvalues) ;
  mexPrintf("first:%d\n",first) ;
    
  /* move internal node block [dp:ep] to [d:e] */
  for (n = 0 ; n < e ; ++ n) {
    if ((parents [n] <= e) & (parents [n] != 0)) {
      parents [n] += (e - ep) ;
    }
  }
  for (n = e ; n >= d ; -- n) {
    parents [n] = parents [n - (e - ep)] ;
  }
 
  /* find first null node and connect it to a */
  last_intermed = a ;
  for (n = 0 ; n < a ; ++ n) {
    if (parents[n] > e) {
      parents [n] = last_intermed ;
      break ;
    }
  }
  
  mexPrintf("last_intermed:%d\n", last_intermed)  ;

  /* chain rest of intermediate nodes */
  for (; n < a ; ++ n) {
    if (parents[n] > e) {
      parents [n] = last_intermed ;
      parents [last_intermed] = last_intermed + 1 ;
      ++ last_intermed ;
    }
  }

  mexPrintf("last_intermed:%d\n", last_intermed)  ;

  /* make last_intermed point to d */
  parents [last_intermed] = d ;
  
  /* change parent of first to be last_intermed */
  parents [first] = last_intermed ;

  /* fix cost too (reall that the fist entry is the cost before
   any merge) */
  if (cost) {
    cost -= nvalues - 1 ;
    for (n = e ; n >= d ; --n) {
      cost [n] = cost [n - (e - ep)] ;
    }
    for (n = c ; n >= a ; --n) {
      cost [n] = cost [d] ;
    }
  }
}

/** ------------------------------------------------------------------
 ** @brief MEX entry point
 **/

void
mexFunction(int nout, mxArray *out[], 
            int nin, const mxArray *in[])
{
  enum {IN_PCX = 0, IN_END} ;
  enum {OUT_PARENTS = 0, OUT_COST} ;
  enum {INFORMATION, EC} ;

  int            verbose = 0 ;
  int            opt ;
  int            next = IN_END ;<commit_msg>another bug removed in aib.c in the formation of the cluster of null nodes<commit_after>/** @internal
 ** @file     aib.c
 ** @author   <NAME>
 ** @author   <NAME>
 ** @brief    AIB MEX driver
 **/

/* AUTORIGHTS
Copyright 2007 (c) <NAME> and <NAME>

This file is part of VLFeat, available in the terms of the GNU
General Public License version 2.
*/

#include "mexutils.h"
#include <vl/mathop.h>
#include <vl/aib.h>

#include <assert.h>
#include <string.h>

/* option codes */
enum {
  opt_cost = 0,
  opt_cluster_null,
  opt_verbose 
} ;

/* options */
uMexOption options [] = {
  {"Cost",       1,   opt_cost       },
  {"ClusterNull",0,   opt_cluster_null}, 
  {"Verbose",    0,   opt_verbose    },
  {0,            0,   0              }
} ;

#define CLUSTER_NULL_NODES 1

/** ------------------------------------------------------------------
 **
 ** Null nodes are nodes with null probability and are not merged by AIB.
 ** It is convenient, however, to treat them as follows:
 ** 
 ** - we pretend that AIB merged those nodes at the very beginning into a
 **   single cluster (as they, after hall, yield zero information drop).
 **
 ** - we attach this cluster to the root as the very last step (as we
 **   do not want to change other nodes.
 **
 ** In this way, 
 **/

static void
cluster_null_nodes (vl_uint32* parents, int nvalues, double *cost)
{
  int nnull = 0 ;
  int n ;
  int first ;
  int last_intermed ;

  int a, b, c, d, e ;
  int dp, ep ;

  /* count null nodes so far */
  for (n = 0 ; n < nvalues ; ++ n) {
    if (parents[n] >= 2 * nvalues - 1) {
      ++ nnull ;
    }
  }
  
  if (nnull == 0) return ;
  
  /* = : leaves
   * 0 : null leaves
   * i : internal node
   * * : padding
   * x : intermediate nodes to link null nodes
   *
   * Input:
   *
   * ====== 0000 ======= iiiiiii ****
   * |                   |     |
   * 0                   dp    ep
   *
   *
   * Output:
   *
   * ====== ==== ======= xxxx iiiiiii
   * |                   | || |     |
   * 0                   a bc d     e
   */
  
  a = nvalues ;
  b = nvalues + nnull - 1 - 1 ;
  c = b + 1 ;
  d = c + 1 ;
  e = 2 * nvalues - 2 ;

  dp = nvalues ;
  ep = 2 * nvalues - 2 - nnull ; 

  mexPrintf("a:%d b:%d c:%d d:%d e:%d dp:%d ep:%d\n",
            a,b,c,d,e,dp,ep) ;

  /* search first leaf that has been merged */
  {
    int first_parent = e ;
    first = 0 ;
    for (n = 0 ; n < nvalues ; ++ n) {
      if (parents[n] <= e & parents[n] != 1) {
        if (first_parent >= parents [n]) {
          first_parent = parents [n] ;
          first = n ;
        }
      }
    }
  }

  mexPrintf("nnull:%d\n",nnull) ;
  mexPrintf("nvalues:%d\n",nvalues) ;
  mexPrintf("first:%d\n",first) ;
    
  /* move internal node block [dp:ep] to [d:e] */
  for (n = 0 ; n < e ; ++ n) {
    if ((parents [n] <= e) & (parents [n] != 0)) {
      parents [n] += (e - ep) ;
    }
  }
  for (n = e ; n >= d ; -- n) {
    parents [n] = parents [n - (e - ep)] ;
  }
 
  /* find first null node and connect it to a */
  last_intermed = a ;
  for (n = 0 ; n < a ; ++ n) {
    if (parents[n] > e) {
      parents [n] = last_intermed ;
      break ;
    }
  }
  
  mexPrintf("first null %d parent seto to last_intermed:%d\n", 
            n,
            last_intermed)  ;

  /* chain rest of intermediate nodes */
  for (; n < a ; ++ n) {
    if (parents[n] > e) {
      parents [n] = last_intermed ;
      parents [last_intermed] = last_intermed + 1 ;
      ++ last_intermed ;
    }
  }

  mexPrintf("after chaining other nulls last_intermed:%d\n", last_intermed)  ;

  /* make last_intermed point to d */
  parents [last_intermed] = d ;
  
  /* change parent of first to be last_intermed */
  mexPrintf("parent of %d (first) was %d\n", first, parents[first]) ;
  parents [first] = last_intermed ;
  mexPrintf("parent of %d (first) is now %d\n", first, parents[first]) ;

  /* fix cost too (reall that the fist entry is the cost before
   any merge) */
  if (cost) {
    cost -= nvalues - 1 ;
    for (n = e ; n >= d ; --n) {
      cost [n] = cost [n - (e - ep)] ;
    }
    for (n = c ; n >= a ; --n) {
      cost [n] = cost [d] ;
    }
  }
}

/** ------------------------------------------------------------------
 ** @brief MEX entry point
 **/

void
mexFunction(int nout, mxArray *out[], 
            int nin, const mxArray *in[])
{
  enum {IN_PCX = 0, IN_END} ;
  enum {OUT_PARENTS = 0, OUT_COST} ;
  enum {INFORMATION, EC} ;

  int            verbose = 0 ;
  int            opt ;
  int            next = IN_END ;
{'fraction_non_alphanumeric': 0.18306293867218962, 'fraction_numerical': 0.010585663329881487, 'mean_word_length': 1.7179487179487178, 'pattern_counts': {'":': 0, '<': 34, '<?xml version=': 0, '>': 32, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 4, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6459350', 'n_tokens_mistral': 3249, 'n_tokens_neox': 3120, 'n_words': 959}