Ejemplo n.º 1
0
void mexFunction(int nlhs, mxArray *plhs[], int nrhs,
                 const mxArray *prhs[])
{
  double *srww_old, *srww_new,*srwp_old,*srdp_new, *probs, *DS_NEW, *WS_NEW, *WS_OLD, *SI_NEW, *WC_OLD, *PROBA, *C, *Z;
  double ALPHA,BETA, GAMMA0, GAMMA1, DELTA;
  int *irww_old, *irww_new, *jcww_old, *jcww_new, *irwp_old, *jcwp_old, *irdp_new, *jcdp_new;
  int *z,*d,*w, *s, *c, *sc, *order, *wp_old, *dp_new, *dp_new2, *ztot_old, *wtot_new, *wc_new;
  int W_NEW, W_OLD,T_NEW, T_OLD,D_NEW,NITER,SEED,OUTPUT, nzmax_new, nzmax_old, nzmaxdp_new, ntokens_new, ntokens_old;
  int i,j,cc,nt,n,wi,wipre,di, startindex, endindex, currentrow, count;
  int NSAMPLE, updatecols;
  
  /* Check for proper number of arguments. */
  if (nrhs != 19) {
    mexErrMsgTxt("19 input arguments required");
  } else if (nlhs != 4) {
    mexErrMsgTxt("4 output arguments required");
  }

// Syntax                                       0       1          2       3       4   5    6         7      8       9      10        11      12      13      14       15       16       17     18 
//   [ DP_NEW,C,Z,PROB ] = NewDocumentsLDACOL( WS_NEW , DS_NEW , SI_NEW , WW_NEW , T , N , NSAMPLE , ALPHA , BETA , GAMMA0, GAMMA1 , DELTA , SEED , OUTPUT , WW_OLD , WP_OLD , WC_OLD , WS_OLD, UPDATECOLS );
  
  
  /* process the input arguments */
  if (mxIsDouble( prhs[ 0 ] ) != 1)
      mexErrMsgTxt("WS_NEW must be double precision"); 
  WS_NEW = mxGetPr(prhs[0]);
  ntokens_new = mxGetM( prhs[ 0 ] ) * mxGetN( prhs[ 0 ] );
  
  if (mxIsDouble( prhs[ 1 ] ) != 1)
      mexErrMsgTxt("DS_NEW must be double precision"); 
  DS_NEW = mxGetPr(prhs[1]);
  
  if (mxIsDouble( prhs[ 2 ] ) != 1)
      mexErrMsgTxt("SI_NEW must be double precision");
  SI_NEW = mxGetPr(prhs[2]);
  
  if ((mxIsSparse( prhs[ 3 ] ) != 1) || (mxIsDouble( prhs[ 3 ] ) != 1))
      mexErrMsgTxt("WW_NEW collocation matrix must be a sparse double precision matrix");

  /* dealing with sparse array WW_NEW */
  srww_new  = mxGetPr(prhs[3]);
  irww_new  = mxGetIr(prhs[3]);
  jcww_new  = mxGetJc(prhs[3]);
  nzmax_new = mxGetNzmax(prhs[3]);  
  W_NEW     = mxGetM( prhs[3] );
  
  if (mxGetN( prhs[3] ) != W_NEW) mexErrMsgTxt("WW_NEW matrix should be square");
  
  D_NEW    = 0;
  for (i=0; i<ntokens_new; i++) {
      if (DS_NEW[ i ] > D_NEW) D_NEW = (int) DS_NEW[ i ];
      if (WS_NEW[ i ] > W_NEW) mexErrMsgTxt("Some word tokens in WS_NEW stream exceed number of word types in WW_NEW matrix");
  }
   
  T_NEW    = (int) mxGetScalar(prhs[4]);
  if (T_NEW<=0) mexErrMsgTxt("Number of topics must be greater than zero");
  
  NITER    = (int) mxGetScalar(prhs[5]);
  if (NITER<0) mexErrMsgTxt("Number of iterations must be greater than zero");
  
  NSAMPLE    = (int) mxGetScalar(prhs[6]);
  if (NSAMPLE<0) mexErrMsgTxt("Number of samples must be greater than zero");
  
  ALPHA = (double) mxGetScalar(prhs[7]);
  if (ALPHA<=0) mexErrMsgTxt("ALPHA must be greater than zero");
  
  BETA = (double) mxGetScalar(prhs[8]);
  if (BETA<=0) mexErrMsgTxt("BETA must be greater than zero");
  
  GAMMA0 = (double) mxGetScalar(prhs[9]);
  if (GAMMA0<=0) mexErrMsgTxt("GAMMA0 must be greater than zero");
  
  GAMMA1 = (double) mxGetScalar(prhs[10]);
  if (GAMMA1<=0) mexErrMsgTxt("GAMMA1 must be greater than zero");
  
  DELTA = (double) mxGetScalar(prhs[11]);
  if (DELTA<=0) mexErrMsgTxt("DELTA must be greater than zero");
  
  SEED = (int) mxGetScalar(prhs[12]);
  // set the seed of the random number generator
  
  OUTPUT = (int) mxGetScalar(prhs[13]);
  
  // dealing with sparse array WW_OLD 
  if ((mxIsSparse( prhs[ 14 ] ) != 1) || (mxIsDouble( prhs[ 14 ] ) != 1))
      mexErrMsgTxt("WW_OLD collocation frequency matrix must be a sparse double precision matrix");  
  srww_old  = mxGetPr(prhs[14]);
  irww_old  = mxGetIr(prhs[14]);
  jcww_old  = mxGetJc(prhs[14]);
  nzmax_old = mxGetNzmax(prhs[14]);
  W_OLD     = mxGetM( prhs[14] );
  if (W_OLD != W_NEW) mexErrMsgTxt("WW_OLD and WW_NEW matrices have different dimensions");
  if (mxGetN( prhs[14] ) != W_NEW) mexErrMsgTxt("WW_OLD matrix should be square");
  
  // dealing with sparse array WP_OLD 
  if ((mxIsSparse( prhs[ 15 ] ) != 1) || (mxIsDouble( prhs[ 15 ] ) != 1))
      mexErrMsgTxt("WP_OLD topic-word matrix must be a sparse double precision matrix");  
  srwp_old  = mxGetPr(prhs[15]);
  irwp_old  = mxGetIr(prhs[15]);
  jcwp_old  = mxGetJc(prhs[15]);
  if (mxGetM( prhs[15] ) != W_NEW) mexErrMsgTxt("Number of words in WP_OLD matrix does not match WW_NEW number of words");
  if (mxGetN( prhs[15] ) != T_NEW) mexErrMsgTxt("Number of topics in WP_OLD matrix does not match given number of topics");
 
  WC_OLD = mxGetPr( prhs[ 16 ]);
  if ((mxGetM( prhs[16] ) * mxGetN( prhs[16] )) != W_NEW ) mexErrMsgTxt("Number of words in WC_OLD matrix does not match WW_NEW number of words");   
  
  if (mxIsDouble( prhs[ 17 ] ) != 1) mexErrMsgTxt("WS_OLD must be double precision"); 
  WS_OLD = mxGetPr(prhs[ 17 ]);
  ntokens_old = mxGetM( prhs[ 17 ] ) * mxGetN( prhs[ 17 ] );
  
  updatecols = (int) mxGetScalar(prhs[18]);
  
  // seeding
  seedMT( 1 + SEED * 2 ); // seeding only works on uneven numbers
  
  /* allocate memory */
  z  = (int *) mxCalloc( ntokens_new , sizeof( int ));
  d  = (int *) mxCalloc( ntokens_new , sizeof( int ));
  w  = (int *) mxCalloc( ntokens_new , sizeof( int ));
  s  = (int *) mxCalloc( ntokens_new , sizeof( int ));
  c  = (int *) mxCalloc( ntokens_new , sizeof( int ));
  sc  = (int *) mxCalloc( ntokens_new , sizeof( int ));
 
  for (i=0; i<ntokens_new; i++) w[ i ] = (int) (WS_NEW[ i ] - 1); // Matlab indexing not zero based
  for (i=0; i<ntokens_new; i++) d[ i ] = (int) (DS_NEW[ i ] - 1); // Matlab indexing not zero based
  for (i=0; i<ntokens_new; i++) s[ i ] = (int) SI_NEW[ i ];
  
  order   = (int *) mxCalloc( ntokens_new , sizeof( int ));
  wp_old  = (int *) mxCalloc( T_NEW*W_NEW , sizeof( int ));
  dp_new  = (int *) mxCalloc( T_NEW*D_NEW , sizeof( int ));
  dp_new2  = (int *) mxCalloc( T_NEW*D_NEW , sizeof( int ));
  wc_new  = (int *) mxCalloc( W_NEW , sizeof( int ));
  ztot_old  = (int *) mxCalloc( T_NEW , sizeof( int ));
  wtot_new  = (int *) mxCalloc( W_NEW , sizeof( int ));
  probs  = (double *) mxCalloc( T_NEW , sizeof( double ));
  
  // FILL IN WTOT_NEW with OLD COUNTS
  for (i=0; i<ntokens_old; i++) {
     j = (int) WS_OLD[ i ] - 1;
     wtot_new[ j ]++; // calculate number of words of each type
  }
  
  // FILL IN WTOT_NEW with NEW COUNTS
  if (updatecols==1)
  for (i=0; i<ntokens_new; i++) {
     j = w[ i ];
     wtot_new[ j ]++; // calculate number of words of each type
  }
  
  // FILL IN WC WITH COUNTS FROM OLD SET
  for (i=0; i<W_NEW; i++) {
     wc_new[ i ] = (int) WC_OLD[ i ];   
  }
  
  // FILL IN wp_old and ztot_old
  for (j=0; j<T_NEW; j++) {
      startindex = *( jcwp_old + j );
      endindex   = *( jcwp_old + j + 1 ) - 1;
      
      for (i=startindex; i<=endindex; i++) {
          currentrow = *( irwp_old + i );
          count      = (int) *( srwp_old + i );
          wp_old[ j + currentrow*T_NEW ] = count;
          ztot_old[ j ] += count;
      }    
  }
  
  // FILL IN SC COUNTS 
  for (i=1; i<ntokens_new; i++) // start with second item
  {
      wi = w[ i ]; // word index
      
      count = 0;
      
      // what is the previous word?
      wipre = w[ i-1 ];
      
      // calculate how many times the current word follows the previous word IN THE OLD DOCUMENT SET    
      startindex = *( jcww_old + wipre ); // look up start and end index for column wipre in WW_OLD matrix
      endindex   = *( jcww_old + wipre + 1 ) - 1;   
      for (j=startindex; j<=endindex; j++) {
          currentrow = *( irww_old + j );
          if (currentrow == wi) count = (int) *( srww_old + j );
      }
      
      // calculate how many times the current word follows the previous word IN THE NEW DOCUMENT SET
      if (updatecols==1) {
          startindex = *( jcww_new + wipre ); // look up start and end index for column wipre in WW_NEW matrix
          endindex   = *( jcww_new + wipre + 1 ) - 1;
          for (j=startindex; j<=endindex; j++) {
              currentrow = *( irww_new + j );
              if (currentrow == wi) count += (int) *( srww_new + j ); // add the count to what was there previously !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
          }
      }
      
      sc[ i ] = count;
  }
  
  
  
  /*for (i=0; i<10; i++) {
     mexPrintf( "i=%4d w[i]=%3d d[i]=%d z[i]=%d s[i]=%d\n" , i , w[i] , d[i] , z[i] , s[i] );    
  }*/
  
  if (OUTPUT==2) {
      mexPrintf( "Running NEW DOCUMENT LDA COL Gibbs Sampler Version 1.0\n" );
      mexPrintf( "Arguments:\n" );
      mexPrintf( "\tNumber of words      W = %d\n" , W_NEW );
      mexPrintf( "\tNumber of docs       D = %d\n" , D_NEW );
      mexPrintf( "\tNumber of topics     T = %d\n" , T_NEW );
      mexPrintf( "\tNumber of iterations N = %d\n" , NITER );
      mexPrintf( "\tNumber of samples    S = %d\n" , NSAMPLE );
      mexPrintf( "\tHyperparameter   ALPHA = %4.4f\n" , ALPHA );
      mexPrintf( "\tHyperparameter    BETA = %4.4f\n" , BETA );
      mexPrintf( "\tHyperparameter  GAMMA0 = %4.4f\n" , GAMMA0 );
      mexPrintf( "\tHyperparameter  GAMMA1 = %4.4f\n" , GAMMA1 );
      mexPrintf( "\tHyperparameter  DELTA  = %4.4f\n" , DELTA );
      mexPrintf( "\tSeed number            = %d\n" , SEED );
      mexPrintf( "\tNumber of tokens       = %d\n" , ntokens_new );
      mexPrintf( "\tUpdating collocation counts with new documents? = %d\n" , updatecols );
  }
  
  /* ---------------------------------------------
     create the PROB vector
   -----------------------------------------------*/
  plhs[ 3 ] = mxCreateDoubleMatrix( ntokens_new , 1 , mxREAL );
  PROBA = mxGetPr( plhs[ 3 ] );
  
  /* run the model */  
  GibbsSamplerLDACOL( ALPHA, BETA, GAMMA0,GAMMA1,DELTA, W_NEW, T_NEW, D_NEW, NITER, NSAMPLE , OUTPUT, ntokens_new, z, d, w, s, c, sc, wp_old, dp_new, dp_new2, ztot_old, wtot_new, order, probs, wc_new , PROBA , updatecols );
  

  /* ---------------------------------------------
   convert the full DP matrix into a sparse matrix 
   -----------------------------------------------*/
  nzmaxdp_new = 0;
  for (i=0; i<D_NEW; i++) {
      for (j=0; j<T_NEW; j++)
          nzmaxdp_new += (int) ( *( dp_new2 + j + i*T_NEW )) > 0; // !!!!!!!!!!!!!!!!!! copy from dp_new2
  }
  
  if (OUTPUT==2) {
      mexPrintf( "Constructing sparse output matrix dp_new\n" );
      mexPrintf( "Number of nonzero entries for DP = %d\n" , nzmaxdp_new );
  }
  
  plhs[0] = mxCreateSparse( D_NEW,T_NEW,nzmaxdp_new,mxREAL);
  srdp_new  = mxGetPr(plhs[0]);
  irdp_new = mxGetIr(plhs[0]);
  jcdp_new = mxGetJc(plhs[0]);
  n = 0;
  for (j=0; j<T_NEW; j++) {
      *( jcdp_new + j ) = n;
      for (i=0; i<D_NEW; i++) {
          cc = (int) *( dp_new2 + i*T_NEW + j ); // !!!!!!!!!!!!!!!!!! copy from dp_new2
          if (cc >0) {
              *( srdp_new + n ) = cc;
              *( irdp_new + n ) = i;
              n++;
          }
      }
  } 
  *( jcdp_new + T_NEW ) = n;
  
  /* ---------------------------------------------
     create the C route vector
   -----------------------------------------------*/
  plhs[ 1 ] = mxCreateDoubleMatrix( ntokens_new , 1 , mxREAL );
  C = mxGetPr( plhs[ 1 ] );
  for (i=0; i<ntokens_new; i++) C[ i ] = (double) c[ i ];
  
  /* ---------------------------------------------
     create the topic assignment vector
   -----------------------------------------------*/
  plhs[ 2 ] = mxCreateDoubleMatrix( ntokens_new , 1 , mxREAL );
  Z = mxGetPr( plhs[ 2 ] );
  for (i=0; i<ntokens_new; i++) Z[ i ] = (double) z[ i ] + 1;

}
Ejemplo n.º 2
0
void mexFunction(int nlhs, mxArray *plhs[], int nrhs,
                 const mxArray *prhs[])
{
    char *CIN;
    int *DS, *WS, *SI, *ZIN;
    double *srww,*srwp,*srdp, *probs, *WC, *WWC, *ZZ;
    double ALPHA,BETA, GAMMA0, GAMMA1, DELTA;
    mwIndex *irww, *jcww, *irwp, *jcwp, *irdp, *jcdp;
    int *z,*d,*w, *s, *c, *sc, *order, *wp, *dp, *ztot, *wtot, *wc;
    int W,T,D,NN,SEED,OUTPUT, nzmax, nzmaxwp, nzmaxdp, ntokens;
    int i,j,cc,n,nt,wi,di;
    int startcond;

    mexPrintf( "GibbsSamplerLDACOL: entering...\n" );
    mexEvalString("drawnow;");

    /* Check for proper number of arguments. */
    if (nrhs < 13) {
        mexErrMsgTxt("At least 13 input arguments required");
    } else if (nlhs != 5) {
        mexErrMsgTxt("5 output arguments required");
    }

    //[ WP,DP,WC,C,Z ] = GibbsSamplerLDACOL( WS , DS , SI , WW , T , N , ALPHA , BETA , GAMMA0, GAMMA1 , DELTA , SEED , OUTPUT , CIN , ZIN );

    /* process the input arguments */
    if (mxIsInt32( prhs[ 0 ] ) != 1)
        mexErrMsgTxt("WS must be int32");
    WS = (int *)mxGetData(prhs[0]);

    if (mxIsInt32( prhs[ 1 ] ) != 1)
        mexErrMsgTxt("DS must be int32");
    DS = (int *)mxGetData(prhs[1]);

    if (mxIsInt32( prhs[ 2 ] ) != 1)
        mexErrMsgTxt("SI must be int32");
    SI = (int *)mxGetData(prhs[2]);

    //for (int yy=0;yy<20;yy++)
    //  printf("%2d: WS=%4u, DS=%4u, SI=%4u\n",yy,WS[yy],DS[yy],SI[yy]);

    if ((mxIsSparse( prhs[ 3 ] ) != 1) || (mxIsDouble( prhs[ 3 ] ) != 1))
        mexErrMsgTxt("WW collocation matrix must be a sparse double precision matrix");

    /* dealing with sparse array WW */
    srww = mxGetPr(prhs[3]);
    irww  = mxGetIr(prhs[3]);
    jcww  = mxGetJc(prhs[3]);
    nzmax= mxGetNzmax(prhs[3]);

    W    = mxGetM( prhs[3] );
    ntokens = mxGetM( prhs[ 0 ] ) * mxGetN( prhs[ 0 ] );

    D    = 0;
    for (i=0; i<ntokens; i++) {
        if (DS[ i ] > D) D = (int) DS[ i ];
    }

    T    = (int) mxGetScalar(prhs[4]);
    if (T<=0) mexErrMsgTxt("Number of topics must be greater than zero");

    NN    = (int) mxGetScalar(prhs[5]);
    if (NN<0) mexErrMsgTxt("Number of iterations must be greater than zero");

    ALPHA = (double) mxGetScalar(prhs[6]);
    if (ALPHA<=0) mexErrMsgTxt("ALPHA must be greater than zero");

    BETA = (double) mxGetScalar(prhs[7]);
    if (BETA<=0) mexErrMsgTxt("BETA must be greater than zero");

    GAMMA0 = (double) mxGetScalar(prhs[8]);
    if (GAMMA0<=0) mexErrMsgTxt("GAMMA0 must be greater than zero");

    GAMMA1 = (double) mxGetScalar(prhs[9]);
    if (GAMMA1<=0) mexErrMsgTxt("GAMMA1 must be greater than zero");

    DELTA = (double) mxGetScalar(prhs[10]);
    if (DELTA<=0) mexErrMsgTxt("DELTA must be greater than zero");

    SEED = (int) mxGetScalar(prhs[11]);
    // set the seed of the random number generator

    OUTPUT = (int) mxGetScalar(prhs[12]);

    // assume that we start a new chain
    startcond = 0;

    if (nrhs > 13) {
        startcond = 1;

        if (mxIsInt8( prhs[ 13 ] ) != 1)
            mexErrMsgTxt("C must be int8");
        CIN =  (char*)mxGetData(prhs[13]);

        if (mxIsInt32( prhs[ 14 ] ) != 1)
            mexErrMsgTxt("Z must be int32");
        ZIN =  (int*)mxGetData(prhs[14]);

        //for (int yy=0;yy<20;yy++)
        //   printf("%2d: Z=%4u, C=%4u\n",yy,ZIN[yy],CIN[yy]);

    }

    // seeding
    seedMT( 1 + SEED * 2 ); // seeding only works on uneven numbers

    /* allocate memory */
    if (OUTPUT==2) {
        mexPrintf( "GibbsSamplerLDACOL: Allocating z,d,w,s,c,sc\n" );
        mexEvalString("drawnow;");
    }
    z  = (int *) mxCalloc( ntokens , sizeof( int ));
    d  = (int *) mxCalloc( ntokens , sizeof( int ));
    w  = (int *) mxCalloc( ntokens , sizeof( int ));
    s  = (int *) mxCalloc( ntokens , sizeof( int ));
    c  = (int *) mxCalloc( ntokens , sizeof( int ));
    sc  = (int *) mxCalloc( ntokens , sizeof( int ));

    if (startcond==1) {
        if (OUTPUT==2) {
            mexPrintf( "GibbsSamplerLDACOL: Preparing c,z\n" );
        }
        for (i=0; i<ntokens; i++) c[ i ] = (int) CIN[ i ];
        for (i=0; i<ntokens; i++) z[ i ] = (int) ZIN[ i ] - (int) 1;
    }

    if (OUTPUT==2) {
        mexPrintf( "GibbsSamplerLDACOL: Preparing w,d,s\n" );
        mexEvalString("drawnow;");
    }
    for (i=0; i<ntokens; i++) w[ i ] = (int) (WS[ i ] - 1); // Matlab indexing not zero based
    for (i=0; i<ntokens; i++) d[ i ] = (int) (DS[ i ] - 1); // Matlab indexing not zero based
    for (i=0; i<ntokens; i++) s[ i ] = (int) SI[ i ];

    if (OUTPUT==2) {
        mexPrintf( "GibbsSamplerLDACOL: Allocating order,wp,dp,wc,ztot,wtot,probs\n" );
        mexEvalString("drawnow;");
    }
    order  = (int *) mxCalloc( ntokens , sizeof( int ));
    wp  = (int *) mxCalloc( T*W , sizeof( int ));
    dp  = (int *) mxCalloc( T*D , sizeof( int ));
    wc  = (int *) mxCalloc( W , sizeof( int ));
    ztot  = (int *) mxCalloc( T , sizeof( int ));
    wtot  = (int *) mxCalloc( W , sizeof( int ));
    probs  = (double *) mxCalloc( T , sizeof( double ));

    n = ntokens;

    /*for (i=0; i<10; i++) {
       mexPrintf( "i=%4d w[i]=%3d d[i]=%d z[i]=%d s[i]=%d\n" , i , w[i] , d[i] , z[i] , s[i] );
    }*/

    if (OUTPUT==2) {
        mexPrintf( "Running LDA COL Gibbs Sampler Version 1.0\n" );
        if (startcond==1) mexPrintf( "Starting with C and Z vector given as input\n" );
        mexPrintf( "Arguments:\n" );
        mexPrintf( "\tNumber of words      W = %d\n" , W );
        mexPrintf( "\tNumber of docs       D = %d\n" , D );
        mexPrintf( "\tNumber of topics     T = %d\n" , T );
        mexPrintf( "\tNumber of iterations N = %d\n" , NN );
        mexPrintf( "\tHyperparameter   ALPHA = %4.4f\n" , ALPHA );
        mexPrintf( "\tHyperparameter    BETA = %4.4f\n" , BETA );
        mexPrintf( "\tHyperparameter  GAMMA0 = %4.4f\n" , GAMMA0 );
        mexPrintf( "\tHyperparameter  GAMMA1 = %4.4f\n" , GAMMA1 );
        mexPrintf( "\tHyperparameter  DELTA  = %4.4f\n" , DELTA );
        mexPrintf( "\tSeed number            = %d\n" , SEED );
        mexPrintf( "\tNumber of tokens       = %d\n" , ntokens );
        mexPrintf( "Internal Memory Allocation\n" );
        mexPrintf( "\tw,d,z,s,c,sc,order indices combined = %d bytes\n" , 7 * sizeof( int) * ntokens );
        mexPrintf( "\twp (full) matrix (%dx%d) = %d bytes\n" , W,T,sizeof( int ) * W * T  );
        mexPrintf( "\tdp (full) matrix (%dx%d) = %d bytes\n" , D,T,sizeof( int ) * D * T  );
        mexPrintf( "Checking: sizeof(char)=%d sizeof(int)=%d sizeof(long)=%d sizeof(double)=%d\n" , sizeof(char),sizeof(int) , sizeof(long) , sizeof(double));
        mexEvalString("drawnow;");
    }

    /* run the model */
    GibbsSamplerLDACOL( ALPHA, BETA, GAMMA0,GAMMA1,DELTA, W, T, D, NN, OUTPUT, n, z, d, w, s, c, sc, wp, dp, ztot, wtot, order, probs , srww, irww, jcww, wc, startcond );

    /* ---------------------------------------------
     Erasing variables to free memory
     -----------------------------------------------*/
    if (OUTPUT==2) {
        mexPrintf( "Freeing internal memory from d,w,s,sc,ztot,wtot,probs\n");
        mexEvalString("drawnow;");
        mxFree(d);
        mxFree(w);
        mxFree(s);
        mxFree(sc);
        mxFree(ztot);
        mxFree(wtot);
        mxFree(probs);
    }

    /* ---------------------------------------------
     convert the full wp matrix into a sparse matrix
     -----------------------------------------------*/
    nzmaxwp = 0;
    for (i=0; i<W; i++) {
        for (j=0; j<T; j++)
            nzmaxwp += (int) ( *( wp + j + i*T )) > 0;
    }

    if (OUTPUT==2) {
        mexPrintf( "Constructing sparse output matrix wp\n" );
        mexPrintf( "Number of nonzero entries for WP = %d\n" , nzmaxwp );
        mexEvalString("drawnow;");
    }

    plhs[0] = mxCreateSparse( W,T,nzmaxwp,mxREAL);
    srwp  = mxGetPr(plhs[0]);
    irwp = mxGetIr(plhs[0]);
    jcwp = mxGetJc(plhs[0]);

    n = 0;
    for (j=0; j<T; j++) {
        *( jcwp + j ) = n;
        for (i=0; i<W; i++) {
            cc = (int) *( wp + i*T + j );
            if (cc >0) {
                *( srwp + n ) = cc;
                *( irwp + n ) = i;
                n++;
            }
        }
    }

    *( jcwp + T ) = n;

    if (OUTPUT==2) {
        mexPrintf( "Freeing internal memory from matrix 'wp'\n");
        mexEvalString("drawnow;");
        mxFree(wp);
    }

    /* ---------------------------------------------
     convert the full DP matrix into a sparse matrix
     -----------------------------------------------*/
    nzmaxdp = 0;
    for (i=0; i<D; i++) {
        for (j=0; j<T; j++)
            nzmaxdp += (int) ( *( dp + j + i*T )) > 0;
    }
    if (OUTPUT==2) {
        mexPrintf( "Constructing sparse output matrix dp\n" );
        mexPrintf( "Number of nonzero entries for DP = %d\n" , nzmaxdp );
        mexEvalString("drawnow;");
    }

    plhs[1] = mxCreateSparse( D,T,nzmaxdp,mxREAL);
    srdp  = mxGetPr(plhs[1]);
    irdp = mxGetIr(plhs[1]);
    jcdp = mxGetJc(plhs[1]);

    n = 0;
    for (j=0; j<T; j++) {
        *( jcdp + j ) = n;
        for (i=0; i<D; i++) {
            cc = (int) *( dp + i*T + j );
            if (cc >0) {
                *( srdp + n ) = cc;
                *( irdp + n ) = i;
                n++;
            }
        }
    }

    *( jcdp + T ) = n;

    if (OUTPUT==2) {
        mexPrintf( "Freeing internal memory from matrix 'dp'\n");
        mexEvalString("drawnow;");
        mxFree(dp);
    }

    /* ---------------------------------------------
       create the WC count matrix
     -----------------------------------------------*/
    plhs[ 2 ] = mxCreateDoubleMatrix( W , 1 , mxREAL );
    WC = mxGetPr( plhs[ 2 ] );
    for (i=0; i<W; i++) WC[ i ] = (double) wc[ i ];

    if (OUTPUT==2) {
        mexPrintf( "Freeing internal memory from matrix 'wc'\n");
        mexEvalString("drawnow;");
        mxFree(wc);
    }

    /* ---------------------------------------------
       create the C route vector
     -----------------------------------------------*/
    plhs[ 3 ] = mxCreateDoubleMatrix( ntokens , 1 , mxREAL );
    WWC = mxGetPr( plhs[ 3 ] );
    for (i=0; i<ntokens; i++) WWC[ i ] = (double) c[ i ];

    if (OUTPUT==2) {
        mexPrintf( "Freeing internal memory from matrix 'c'\n");
        mexEvalString("drawnow;");
        mxFree(c);
    }

    /* ---------------------------------------------
       create the topic assignment vector
     -----------------------------------------------*/
    plhs[ 4 ] = mxCreateDoubleMatrix( ntokens , 1 , mxREAL );
    ZZ = mxGetPr( plhs[ 4 ] );
    for (i=0; i<ntokens; i++) ZZ[ i ] = (double) z[ i ] + 1;

    if (OUTPUT==2) {
        mexPrintf( "Freeing internal memory from matrix 'z'\n");
        mexEvalString("drawnow;");
        mxFree(z);
    }

}