Exemple #1
0
t_max_err poki_recLevel_set(t_poki *x, void *attr, long ac, t_atom *av)
{
  if (ac && av)
  {
    const double target = atom_getfloat(av);
    if (absDif(target, x->p_recLevelTarget) > 0.0001)
    {
      x->p_recLevelTarget = target;
      if (absDif(target, x->p_recLevel) > 0.0001)
      {
        x->p_recFadeInc = (x->p_recLevelTarget - x->p_recLevel) / x->p_fadeSamps;
        x->p_recFadeFlag = 1;
      }
      else
      {
        x->p_recFadeFlag = 0;
      }
    }
    else
    {
      x->p_recLevelTarget = target;
      x->p_recLevel = target;
      x->p_recFadeInc = 0.0;
      x->p_recFadeFlag = 0;
    }
  }
  return MAX_ERR_NONE;
}
Exemple #2
0
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) {
    /* Variables */
    int n, s, e, e2, n1, n2, neigh, Vind, Vind2, s1, s2,
            nNodes, nEdges, maxState,
            iter, maxIter, 
            *edgeEnds, *nStates, *V, *E, *y;
    
    double *nodePot, *edgePot, *nodeBel,
            z, *prodMsgs, *oldMsgs, *newMsgs, *tmp, *tmp1, *tmp2, *mu,nNbrs;
    
    /* Input */
    
    nodePot = mxGetPr(prhs[0]);
    edgePot = mxGetPr(prhs[1]);
    edgeEnds = (int*)mxGetPr(prhs[2]);
    nStates = (int*)mxGetPr(prhs[3]);
    V = (int*)mxGetPr(prhs[4]);
    E = (int*)mxGetPr(prhs[5]);
    maxIter = ((int*)mxGetPr(prhs[6]))[0];
    mu = mxGetPr(prhs[7]);
    
	if (!mxIsClass(prhs[2],"int32")||!mxIsClass(prhs[3],"int32")||!mxIsClass(prhs[4],"int32")||!mxIsClass(prhs[5],"int32")||!mxIsClass(prhs[6],"int32"))
		mexErrMsgTxt("edgeEnds, nStates, V, E, maxIter must be int32");
	
    /* Compute Sizes */
    
    nNodes = mxGetDimensions(prhs[0])[0];
    maxState = mxGetDimensions(prhs[0])[1];
    nEdges = mxGetDimensions(prhs[2])[0];    
    
    /* Output */
    plhs[0] = mxCreateDoubleMatrix(nNodes,maxState,mxREAL);
    nodeBel = mxGetPr(plhs[0]);    
    
    prodMsgs = mxCalloc(maxState*nNodes, sizeof(double));
    oldMsgs = mxCalloc(maxState*nEdges*2, sizeof(double));
    newMsgs = mxCalloc(maxState*nEdges*2, sizeof(double));
    tmp = mxCalloc(maxState, sizeof(double));
    tmp1 = mxCalloc(maxState, sizeof(double));
    tmp2 = mxCalloc(maxState, sizeof(double));
    
    /* Initialize */
    for(e = 0; e < nEdges; e++) {
        n1 = edgeEnds[e]-1;
        n2 = edgeEnds[e+nEdges]-1;
        for(s = 0; s < nStates[n2]; s++)
            newMsgs[s+maxState*e] = 1./nStates[n2];
        for(s = 0; s < nStates[n1]; s++)
            newMsgs[s+maxState*(e+nEdges)] = 1./nStates[n1];
    }
    
    
    
    for(iter = 0; iter < maxIter; iter++) {
        
        for(n=0;n<nNodes;n++) {
            
            /* Update Messages */
            for(Vind = V[n]-1; Vind < V[n+1]-1; Vind++) {
                e = E[Vind]-1;
                n1 = edgeEnds[e]-1;
                n2 = edgeEnds[e+nEdges]-1;
                
                /* First part of message is nodePot*/
                for(s = 0; s < nStates[n]; s++)
                    tmp[s] = nodePot[n + nNodes*s];
                
                /* Multiply by messages from neighbors except j */
                for(Vind2 = V[n]-1; Vind2 < V[n+1]-1; Vind2++) {
                    e2 = E[Vind2]-1;
                    if (e != e2) {
                        if (n == edgeEnds[e2+nEdges]-1) {
                            for(s = 0; s < nStates[n]; s++) {
                                tmp[s] *= pow(newMsgs[s+maxState*e2], mu[e2]);
                            }
                        }
                        else {
                            for(s = 0; s < nStates[n]; s++) {
                                tmp[s] *= pow(newMsgs[s+maxState*(e2+nEdges)], mu[e2]);
                            }
                        }
                    }
                    else {
                        if (n == edgeEnds[e2+nEdges]-1) {
                            for(s = 0; s < nStates[n]; s++) {
                                tmp[s] /= pow(newMsgs[s+maxState*e2], 1.-mu[e2]);
                            }
                        }
                        else {
                            for(s = 0; s < nStates[n]; s++) {
                                tmp[s] /= pow(newMsgs[s+maxState*(e2+nEdges)], 1.-mu[e2]);
                            }
                        }
                    }
                }
                
                /* Now multiply by edge potential to get new message */
                
                if (n == n2) {
                    for(s1 = 0; s1 < nStates[n1]; s1++) {
                        newMsgs[s1+maxState*(e+nEdges)] = tmp[0]*pow(edgePot[s1+maxState*(0+maxState*e)], 1./mu[e]);
                        for(s2 = 1; s2 < nStates[n2]; s2++) {
							if(tmp[s2]*pow(edgePot[s1+maxState*(s2+maxState*e)], 1./mu[e]) > newMsgs[s1+maxState*(e+nEdges)])
								newMsgs[s1+maxState*(e+nEdges)] = tmp[s2]*pow(edgePot[s1+maxState*(s2+maxState*e)], 1./mu[e]);
                        }
						/* Might get NaN or Inf values due to 0*log(0) */
						newMsgs[s1+maxState*(e+nEdges)] = zeroIfNaN(newMsgs[s1+maxState*(e+nEdges)]);
                    }
                    
					/* Safe normalize */
					z = 0.0;
					for(s = 0; s < nStates[n1]; s++)
						z += newMsgs[s+maxState*(e+nEdges)];
					if (z > 0.0) {
						for(s = 0; s < nStates[n1]; s++)
							newMsgs[s+maxState*(e+nEdges)] /= z;
					}
                }
                else {
                    for(s2 = 0; s2 < nStates[n2]; s2++) {
                        newMsgs[s2+maxState*e] = tmp[0]*pow(edgePot[0+maxState*(s2+maxState*e)], 1./mu[e]);
                        for(s1 = 1; s1 < nStates[n1]; s1++) {
							if(tmp[s1]*pow(edgePot[s1+maxState*(s2+maxState*e)], 1./mu[e]) > newMsgs[s2+maxState*e])
								newMsgs[s2+maxState*e] = tmp[s1]*pow(edgePot[s1+maxState*(s2+maxState*e)], 1./mu[e]);
                        }
 						/* Might get NaN or Inf values due to 0*log(0) */
						newMsgs[s2+maxState*e] = zeroIfNaN(newMsgs[s2+maxState*e]);
                   }
                    
					/* Safe normalize */
					z = 0.0;
					for(s = 0; s < nStates[n2]; s++)
						z += newMsgs[s+maxState*e];
					if (z > 0.0) {
						for(s = 0; s < nStates[n2]; s++)
							newMsgs[s+maxState*e] /= z;
					}
                }
                
            }
            
            
            
            
        }
        
        /* Print out messages */
        /*
         * printf("\n\nIter = %d\n", iter);
         * for(s=0;s<maxState;s++) {
         * for(e=0;e<nEdges*2;e++) {
         * printf("newMsgs(%d,%d) = %f\n", s, e, newMsgs[s+maxState*e]);
         * }
         * }
         */
        

        /* oldMsgs = newMsgs */
        z = 0;
        for(s=0;s<maxState;s++) {
            for(e=0;e<nEdges*2;e++) {
                z += absDif(newMsgs[s+maxState*e], oldMsgs[s+maxState*e]);
                oldMsgs[s+maxState*e] = newMsgs[s+maxState*e];
            }
        }
        
        /* if sum(abs(newMsgs(:)-oldMsgs(:))) < 1e-4; break; */
        if(z < 1e-4) {
            break;
        }
        
    }
    
    /* ******************* DONE MESSAGE PASSING ********************** */
    
    /*if(iter == maxIter)
     * {
     * printf("LBP reached maxIter of %d iterations\n",maxIter);
     * }
     * printf("Stopped after %d iterations\n",iter); */
    
    /* compute nodeBel */
    for(n = 0; n < nNodes; n++) {
		/* Init to nodePot */
        for(s = 0; s < nStates[n]; s++)
            prodMsgs[s+maxState*n] = nodePot[n+nNodes*s];
        /* Multiply by product of messages */
        for(Vind = V[n]-1; Vind < V[n+1]-1; Vind++) {
            e = E[Vind]-1;
            n1 = edgeEnds[e]-1;
            n2 = edgeEnds[e+nEdges]-1;
            if (n == n2) {
                for(s = 0; s < nStates[n]; s++) {
                    prodMsgs[s+maxState*n] *= pow(newMsgs[s+maxState*e], mu[e]);
                }
            }
            else {
                for(s = 0; s < nStates[n]; s++) {
                    prodMsgs[s+maxState*n] *= pow(newMsgs[s+maxState*(e+nEdges)], mu[e]);
                }
            }
        }
        /* Normalize */
		z = 0.0;
		for(s = 0; s < nStates[n]; s++)
			z += prodMsgs[s+maxState*n];
		for(s = 0; s < nStates[n]; s++) {
			/* Note: unsafe normalize! */
			nodeBel[n+nNodes*s] = prodMsgs[s+maxState*n] / z;
			/* Clamp to [0,1] (just in case) */
			if (nodeBel[n+nNodes*s] < 0.0)
				nodeBel[n+nNodes*s] = 0.0;
			else if (nodeBel[n+nNodes*s] > 1.0)
				nodeBel[n+nNodes*s] = 1.0;
		}
    }
    
    
    /* Free memory */
    mxFree(prodMsgs);
    mxFree(oldMsgs);
    mxFree(newMsgs);
    mxFree(tmp);
    mxFree(tmp1);
    mxFree(tmp2);
}
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
   /* Variables */
    int n, s,e,e2,n1,n2,neigh,Vind,Vind2,s1,s2,
    nNodes, nEdges, maxState,
    iter,maxIter,nNbrs,
    *edgeEnds, *nStates, *V, *E,*y;
    
    double *nodePot, *edgePot, *nodeBel,
    z,*prodMsgs,*oldMsgs,*newMsgs,*tmp;
    
   /* Input */
    
    nodePot = mxGetPr(prhs[0]);
    edgePot = mxGetPr(prhs[1]);
    edgeEnds = (int*)mxGetPr(prhs[2]);
    nStates = (int*)mxGetPr(prhs[3]);
    V = (int*)mxGetPr(prhs[4]);
    E = (int*)mxGetPr(prhs[5]);
    maxIter = ((int*)mxGetPr(prhs[6]))[0];
    
	if (!mxIsClass(prhs[2],"int32")||!mxIsClass(prhs[3],"int32")||!mxIsClass(prhs[4],"int32")||!mxIsClass(prhs[5],"int32")||!mxIsClass(prhs[6],"int32"))
		mexErrMsgTxt("edgeEnds, nStates, V, E, maxIter must be int32");
	
   /* Compute Sizes */
    
    nNodes = mxGetDimensions(prhs[0])[0];
    maxState = mxGetDimensions(prhs[0])[1];
    nEdges = mxGetDimensions(prhs[2])[0];    
    
   /* Output */
    plhs[0] = mxCreateDoubleMatrix(nNodes,maxState,mxREAL);
    nodeBel = mxGetPr(plhs[0]);
        
    prodMsgs = mxCalloc(maxState*nNodes,sizeof(double));
    oldMsgs = mxCalloc(maxState*nEdges*2,sizeof(double));
    newMsgs = mxCalloc(maxState*nEdges*2,sizeof(double));
    tmp = mxCalloc(maxState,sizeof(double));
    
    /* Initialize */
    for(e = 0; e < nEdges; e++)
    {
        n1 = edgeEnds[e]-1;
        n2 = edgeEnds[e+nEdges]-1;
        for(s = 0; s < nStates[n2]; s++)
            newMsgs[s+maxState*e] = 1./nStates[n2];
        for(s = 0; s < nStates[n1]; s++)
            newMsgs[s+maxState*(e+nEdges)] = 1./nStates[n1];
    }
    
    
    for(iter = 0; iter < maxIter; iter++)
    {
        
        for(n=0;n<nNodes;n++)
        {
            
            /* Update Messages */
            for(Vind = V[n]-1; Vind < V[n+1]-1; Vind++)
            {
                e = E[Vind]-1;
                n1 = edgeEnds[e]-1;
                n2 = edgeEnds[e+nEdges]-1;
                
                /* First part of message is nodePot*/
                for(s = 0; s < nStates[n]; s++)
                    tmp[s] = nodePot[n + nNodes*s];
                
                /* Multiply by messages from neighbors except j */
                for(Vind2 = V[n]-1; Vind2 < V[n+1]-1; Vind2++)
                {
                    e2 = E[Vind2]-1;
                    if (e != e2)
                    {
                        if (n == edgeEnds[e2+nEdges]-1)
                        {
                            for(s = 0; s < nStates[n]; s++)
                            {
                                tmp[s] *= newMsgs[s+maxState*e2];
                            }
                        }
                        else
                        {
                            for(s = 0; s < nStates[n]; s++)
                            {
                                tmp[s] *= newMsgs[s+maxState*(e2+nEdges)];
                            }
                        }
                    }
                }
                
                /* Now multiply by edge potential to get new message */
                
                if (n == n2)
                {
                    for(s1 = 0; s1 < nStates[n1]; s1++)
                    {
                        newMsgs[s1+maxState*(e+nEdges)] = tmp[0]*edgePot[s1+maxState*(0+maxState*e)];
                        for(s2 = 1; s2 < nStates[n2]; s2++)
                        {
							if(tmp[s2]*edgePot[s1+maxState*(s2+maxState*e)] > newMsgs[s1+maxState*(e+nEdges)])
									newMsgs[s1+maxState*(e+nEdges)] = tmp[s2]*edgePot[s1+maxState*(s2+maxState*e)];
                        }
                    }
                    
                    z = 0.0;
                    for(s = 0; s < nStates[n1]; s++)
                        z += newMsgs[s+maxState*(e+nEdges)];
                    for(s = 0; s < nStates[n1]; s++)
                        newMsgs[s+maxState*(e+nEdges)] /= z;
                }
                else
                {
                    for(s2 = 0; s2 < nStates[n2]; s2++)
                    {
						newMsgs[s2+maxState*e] = tmp[0]*edgePot[0+maxState*(s2+maxState*e)];
                        for(s1 = 1; s1 < nStates[n1]; s1++)
                        {
							if(tmp[s1]*edgePot[s1+maxState*(s2+maxState*e)] > newMsgs[s2+maxState*e])
									newMsgs[s2+maxState*e] = tmp[s1]*edgePot[s1+maxState*(s2+maxState*e)];
                        }
                    }
                    
                    z = 0.0;
                    for(s = 0; s < nStates[n2]; s++)
                        z += newMsgs[s+maxState*e];
                    for(s = 0; s < nStates[n2]; s++)
                        newMsgs[s+maxState*e] /= z;
                }
            }
            
            
            
            
        }
        
        
        /* oldMsgs = newMsgs */
        z = 0;
        for(s=0;s<maxState;s++)
        {
            for(e=0;e<nEdges*2;e++)
            {
                z += absDif(newMsgs[s+maxState*e],oldMsgs[s+maxState*e]);
                oldMsgs[s+maxState*e] = newMsgs[s+maxState*e];
            }
        }
        
        /* if sum(abs(newMsgs(:)-oldMsgs(:))) < 1e-4; break; */
		/*printf("z = %f\n",z);*/
        if(z < 1e-4)
        {
            break;
        }
        
    }
    
    /*if(iter == maxIter)
    {
        printf("LBP reached maxIter of %d iterations\n",maxIter);
    }
     printf("Stopped after %d iterations\n",iter); */
    
    /* compute nodeBel */
    for(n = 0; n < nNodes; n++)
    {
        for(s = 0; s < nStates[n]; s++)
            prodMsgs[s+maxState*n] = nodePot[n+nNodes*s];
        
        for(Vind = V[n]-1; Vind < V[n+1]-1; Vind++)
        {
            e = E[Vind]-1;
            n1 = edgeEnds[e]-1;
            n2 = edgeEnds[e+nEdges]-1;
            
            if (n == n2)
            {
                for(s = 0; s < nStates[n]; s++)
                {
                    prodMsgs[s+maxState*n] *= newMsgs[s+maxState*e];
                }
            }
            else
            {
                for(s = 0; s < nStates[n]; s++)
                {
                    prodMsgs[s+maxState*n] *= newMsgs[s+maxState*(e+nEdges)];
                }
            }
        }
        
        z = 0;
        for(s = 0; s < nStates[n]; s++)
        {
            nodeBel[n + nNodes*s] = prodMsgs[s+maxState*n];
            z = z + nodeBel[n+nNodes*s];
        }
        for(s = 0; s < nStates[n]; s++)
            nodeBel[n + nNodes*s] /= z;
    }
    
    
   /* Free memory */
    mxFree(prodMsgs);
    mxFree(oldMsgs);
    mxFree(newMsgs);
    mxFree(tmp);
}
Exemple #4
0
t_int *poki_perform(t_int *w)
  {
  t_float * in = (t_float *)(w[1]);
  t_float * out = (t_float *)(w[2]);
  t_poki * x = (t_poki *)(w[3]);
  t_float * index = x->p_connected ? (t_float *)(w[4]) : NULL;
	int n = (int)(w[5]);
	
	if (index == NULL)
    goto out;
	
	t_buffer *b = x->p_buf;
	float *tab;
  long frames,nc;
	
	if (x->p_obj.z_disabled)
		goto out;
  
	if (!b)
		goto out;
  
  // buffer data structure exists
	ATOMIC_INCREMENT(&b->b_inuse);
	if (!b->b_valid) {
		ATOMIC_DECREMENT(&b->b_inuse);
		goto out;
	}
  
	tab = b->b_samples;
	frames = b->b_frames;
	nc = b->b_nchans;
	if (nc != 1)
	{
    ATOMIC_DECREMENT(&b->b_inuse);
    goto zero;
	}
	else
	{
		while (n--)
    {
			const long idx = (long)(*index + 0.5f) % frames;
        
			const int step = (idx - x->p_idx0) % frames;
			int interpCount = step-1;
      float input = *in;

			if (x->p_preFadeFlag)
      {
        x->p_preLevel += x->p_preFadeInc;
        if (absDif(x->p_preLevel, x->p_preLevelTarget) < 0.001)
        {
          x->p_preLevel = x->p_preLevelTarget;
          x->p_preFadeFlag = 0;
        }
      }

      if (x->p_recFadeFlag)
      {
        x->p_recLevel += x->p_recFadeInc;
        if (absDif(x->p_recLevel, x->p_recLevelTarget) < 0.001)
        {
          x->p_recLevel = x->p_recLevelTarget;
          x->p_recFadeFlag = 0;
        }
      }
      // these macros are weirdly undefined in deployment builds for some target architectures
      //if (FIX_DENORM_DOUBLE(x->p_recLevel) > 0.00001)
      if (absDif(x->p_recLevel, 0.0) > 1e-6) // -120dB
      { // recording level is non-zero
        input *= x->p_recLevel;
        //if (FIX_DENORM_DOUBLE(x->p_preLevel) > 0.0)
        if (absDif(x->p_preLevel, 0.0) > 1e-6)
        {
          if (absDif(x->p_preLevel, 1.0) < 0.001)
          {
            input += tab[idx];
          }
          else
          { // pre-level is non-unity
            input += (tab[idx] * x->p_preLevel);
          }
        }
      }
      else
      { 
        /* // FIXME: this behavior is potentially useful, should be an option
        // no recording, use overdub level only
        input = 0.0;
        if (absDif(x->p_preLevel, 1.0) < 0.001)
        { // pre level is unity
          input = tab[idx]; // TODO: should just skip this sample
        }
        else
        { // pre level is non-unity
          input = tab[idx] * FIX_DENORM_DOUBLE(x->p_preLevel);
        }
         */
        // with no recording, we don't change the buffer
        input = tab[idx];
        interpCount =  x->p_interpThresholdSamps + 1; // this should cause the interp steps to be skipped
      }
      
      // perform interpolation
			if (interpCount <= x->p_interpThresholdSamps)
			{
				// FIXME: get higher-order interpolation working and add option to switch.
				// usually there is not really an audible improvement.
				// but i can imaginge someone wanting it for some extreme purpose. -emb
        /*
				const float y3 = x->p_y0;
				const float y2 = tab[(x->p_idx0 - step) % frames];
				const float y1 = tab[(idx - (step*2)) % frames];
				const float y0 = tab[(idx - (step*3)) % frames];		
         */
				const float phaseInc = 1.f / ((float)step);
				float phase=phaseInc;
				int interpIdx = (x->p_idx0 + 1) % frames;
				
				while (interpCount > 0)
				{
					// 3rd-order:
					// tab[interpIdx] = hermite_interp(phase, y0, y1, y2, y3);
					// linear:
					tab[interpIdx] = x->p_y0 + (phase * (input - x->p_y0));
					phase += phaseInc;
					interpIdx = ((interpIdx + 1) % frames);
					interpCount--;
				}
			} // interp count < thresh
      
			// no interpolation
			//*out = tab[idx];
      
      // location and float offset 
      const long iIdx = (long)(*index);
      const float fIdx = *index - (long)(*index);
      
      // 3rd-order:
      // *out = hermite_interp(fIdx,
      //                      tab[(iIdx+1) % frames],
      //                      tab[(iIdx+2) % frames], 
      //                      tab[(iIdx+3) % frames],
      //                      tab[(iIdx+4) % frames]
      //                      );
      
      // linear:
      const float tab0 = tab[(iIdx+1) % frames];
      *out =  tab0 + fIdx * (tab[(iIdx + 2) % frames] - tab0);
    
			tab[idx] = input;
			x->p_y0 = input;
      x->p_idx0 = idx;
			out++;
			in++;
			index++;
		} // sample loop
    object_method(b, gensym("dirty"));
    ATOMIC_DECREMENT(&b->b_inuse);
	} // test for mono
	return w + 6;
zero:
  while(n--) *out++ = 0.0;
out:
	return w + 6;
}
Exemple #5
0
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) {
    /* Variables */
    int n, s, e, e2, n1, n2, neigh, Vind, Vind2, s1, s2,
            nNodes, nEdges, maxState, dims[3],
            iter, maxIter, 
            *edgeEnds, *nStates, *V, *E, *y;
    
    double *nodePot, *edgePot, *nodeBel, *edgeBel, *logZ,
            z, energy1, energy2, entropy1, entropy2, *prodMsgs, *oldMsgs, *newMsgs, *tmp, *tmp1, *tmp2, *mu,nNbrs;
    
    /* Input */
    
    nodePot = mxGetPr(prhs[0]);
    edgePot = mxGetPr(prhs[1]);
    edgeEnds = (int*)mxGetPr(prhs[2]);
    nStates = (int*)mxGetPr(prhs[3]);
    V = (int*)mxGetPr(prhs[4]);
    E = (int*)mxGetPr(prhs[5]);
    maxIter = ((int*)mxGetPr(prhs[6]))[0];
    mu = mxGetPr(prhs[7]);
    
	if (!mxIsClass(prhs[2],"int32")||!mxIsClass(prhs[3],"int32")||!mxIsClass(prhs[4],"int32")||!mxIsClass(prhs[5],"int32")||!mxIsClass(prhs[6],"int32"))
		mexErrMsgTxt("edgeEnds, nStates, V, E, maxIter must be int32");
	
    /* Compute Sizes */
    
    nNodes = mxGetDimensions(prhs[0])[0];
    maxState = mxGetDimensions(prhs[0])[1];
    nEdges = mxGetDimensions(prhs[2])[0];    
    
    /* Output */
    plhs[0] = mxCreateDoubleMatrix(nNodes,maxState,mxREAL);
    dims[0] = maxState;
    dims[1] = maxState;
    dims[2] = nEdges;
    plhs[1] = mxCreateNumericArray(3,dims,mxDOUBLE_CLASS,mxREAL);
    plhs[2] = mxCreateDoubleMatrix(1,1,mxREAL);
    nodeBel = mxGetPr(plhs[0]);
    edgeBel = mxGetPr(plhs[1]);
    logZ = mxGetPr(plhs[2]);
    
    prodMsgs = mxCalloc(maxState*nNodes, sizeof(double));
    oldMsgs = mxCalloc(maxState*nEdges*2, sizeof(double));
    newMsgs = mxCalloc(maxState*nEdges*2, sizeof(double));
    tmp = mxCalloc(maxState, sizeof(double));
    tmp1 = mxCalloc(maxState, sizeof(double));
    tmp2 = mxCalloc(maxState, sizeof(double));
    
    /* Initialize */
    for(e = 0; e < nEdges; e++) {
        n1 = edgeEnds[e]-1;
        n2 = edgeEnds[e+nEdges]-1;
        for(s = 0; s < nStates[n2]; s++)
            newMsgs[s+maxState*e] = 1./nStates[n2];
        for(s = 0; s < nStates[n1]; s++)
            newMsgs[s+maxState*(e+nEdges)] = 1./nStates[n1];
    }
    
    
    
    for(iter = 0; iter < maxIter; iter++) {
        
        for(n=0;n<nNodes;n++) {
            
            /* Update Messages */
            for(Vind = V[n]-1; Vind < V[n+1]-1; Vind++) {
                e = E[Vind]-1;
                n1 = edgeEnds[e]-1;
                n2 = edgeEnds[e+nEdges]-1;
                
                /* First part of message is nodePot*/
                for(s = 0; s < nStates[n]; s++)
                    tmp[s] = nodePot[n + nNodes*s];
                
                /* Multiply by messages from neighbors except j */
                for(Vind2 = V[n]-1; Vind2 < V[n+1]-1; Vind2++) {
                    e2 = E[Vind2]-1;
                    if (e != e2) {
                        if (n == edgeEnds[e2+nEdges]-1) {
                            for(s = 0; s < nStates[n]; s++) {
                                tmp[s] *= pow(newMsgs[s+maxState*e2], mu[e2]);
                            }
                        }
                        else {
                            for(s = 0; s < nStates[n]; s++) {
                                tmp[s] *= pow(newMsgs[s+maxState*(e2+nEdges)], mu[e2]);
                            }
                        }
                    }
                    else {
                        if (n == edgeEnds[e2+nEdges]-1) {
                            for(s = 0; s < nStates[n]; s++) {
                                tmp[s] /= pow(newMsgs[s+maxState*e2], 1.-mu[e2]);
                            }
                        }
                        else {
                            for(s = 0; s < nStates[n]; s++) {
                                tmp[s] /= pow(newMsgs[s+maxState*(e2+nEdges)], 1.-mu[e2]);
                            }
                        }
                    }
                }
                
                /* Now multiply by edge potential to get new message */
                
                if (n == n2) {
                    for(s1 = 0; s1 < nStates[n1]; s1++) {
                        newMsgs[s1+maxState*(e+nEdges)] = 0.0;
                        for(s2 = 0; s2 < nStates[n2]; s2++) {
                            newMsgs[s1+maxState*(e+nEdges)] += tmp[s2]*pow(edgePot[s1+maxState*(s2+maxState*e)], 1./mu[e]);
                        }
                        
                    }
                    
                    /* Normalize */
                    z = 0.0;
                    for(s = 0; s < nStates[n1]; s++)
                        z += newMsgs[s+maxState*(e+nEdges)];
                    for(s = 0; s < nStates[n1]; s++)
                        newMsgs[s+maxState*(e+nEdges)] /= z;
                }
                else {
                    for(s2 = 0; s2 < nStates[n2]; s2++) {
                        newMsgs[s2+maxState*e] = 0.0;
                        for(s1 = 0; s1 < nStates[n1]; s1++) {
                            newMsgs[s2+maxState*e] += tmp[s1]*pow(edgePot[s1+maxState*(s2+maxState*e)], 1./mu[e]);
                        }
                        
                    }
                    
                    /* Normalize */
                    z = 0.0;
                    for(s = 0; s < nStates[n2]; s++)
                        z += newMsgs[s+maxState*e];
                    for(s = 0; s < nStates[n2]; s++)
                        newMsgs[s+maxState*e] /= z;
                }
                
            }
            
            
            
            
        }
        
        /* Print out messages */
        /*
         * printf("\n\nIter = %d\n", iter);
         * for(s=0;s<maxState;s++) {
         * for(e=0;e<nEdges*2;e++) {
         * printf("newMsgs(%d,%d) = %f\n", s, e, newMsgs[s+maxState*e]);
         * }
         * }
         */
        

        /* oldMsgs = newMsgs */
        z = 0;
        for(s=0;s<maxState;s++) {
            for(e=0;e<nEdges*2;e++) {
                z += absDif(newMsgs[s+maxState*e], oldMsgs[s+maxState*e]);
                oldMsgs[s+maxState*e] = newMsgs[s+maxState*e];
            }
        }
        
        /* if sum(abs(newMsgs(:)-oldMsgs(:))) < 1e-4; break; */
        if(z < 1e-4) {
            break;
        }
        
    }
    
    /* ******************* DONE MESSAGE PASSING ********************** */
    
    /*if(iter == maxIter)
     * {
     * printf("LBP reached maxIter of %d iterations\n",maxIter);
     * }
     * printf("Stopped after %d iterations\n",iter); */
    
    /* compute nodeBel */
    for(n = 0; n < nNodes; n++) {
        for(s = 0; s < nStates[n]; s++)
            prodMsgs[s+maxState*n] = nodePot[n+nNodes*s];
        
        for(Vind = V[n]-1; Vind < V[n+1]-1; Vind++) {
            e = E[Vind]-1;
            n1 = edgeEnds[e]-1;
            n2 = edgeEnds[e+nEdges]-1;
            
            if (n == n2) {
                for(s = 0; s < nStates[n]; s++) {
                    prodMsgs[s+maxState*n] *= pow(newMsgs[s+maxState*e], mu[e]);
                }
            }
            else {
                for(s = 0; s < nStates[n]; s++) {
                    prodMsgs[s+maxState*n] *= pow(newMsgs[s+maxState*(e+nEdges)], mu[e]);
                }
            }
        }
        
        z = 0;
        for(s = 0; s < nStates[n]; s++) {
            nodeBel[n + nNodes*s] = prodMsgs[s+maxState*n];
            z = z + nodeBel[n+nNodes*s];
        }
        for(s = 0; s < nStates[n]; s++)
            nodeBel[n + nNodes*s] /= z;
    }
    
    /* Compute edgeBel */
    for(e = 0; e < nEdges; e++) {
        n1 = edgeEnds[e]-1;
        n2 = edgeEnds[e+nEdges]-1;
        
        /* temp1 = nodePot by all messages to n1 except from n2 */
        for(s = 0; s < nStates[n1]; s++)
            tmp1[s] = nodePot[n1 + nNodes*s];
        for(Vind = V[n1]-1; Vind < V[n1+1]-1; Vind++) {
            e2 = E[Vind]-1;
            if (e != e2) {
                if (n1 == edgeEnds[e2+nEdges]-1) {
                    for(s = 0; s < nStates[n1]; s++) {
                        tmp1[s] *= pow(newMsgs[s+maxState*e2],mu[e2]);
                    }
                }
                else {
                    for(s = 0; s < nStates[n1]; s++) {
                        tmp1[s] *= pow(newMsgs[s+maxState*(e2+nEdges)],mu[e2]);
                    }
                }
            }
            else {
                if (n1 == edgeEnds[e2+nEdges]-1) {
                    for(s = 0; s < nStates[n1]; s++) {
                        tmp1[s] /= pow(newMsgs[s+maxState*e2],1.-mu[e2]);
                    }
                }
                else {
                    for(s = 0; s < nStates[n1]; s++) {
                        tmp1[s] /= pow(newMsgs[s+maxState*(e2+nEdges)],1.-mu[e2]);
                    }
                }
            }
        }
        /* temp2 = nodePot by all messages to n2 except from n1 */
        for(s = 0; s < nStates[n2]; s++)
            tmp2[s] = nodePot[n2 + nNodes*s];
        for(Vind = V[n2]-1; Vind < V[n2+1]-1; Vind++) {
            e2 = E[Vind]-1;
            if (e != e2) {
                if (n2 == edgeEnds[e2+nEdges]-1) {
                    for(s = 0; s < nStates[n2]; s++) {
                        tmp2[s] *= pow(newMsgs[s+maxState*e2],mu[e2]);
                    }
                }
                else {
                    for(s = 0; s < nStates[n2]; s++) {
                        tmp2[s] *= pow(newMsgs[s+maxState*(e2+nEdges)],mu[e2]);
                    }
                }
            }
            else {
                if (n2 == edgeEnds[e2+nEdges]-1) {
                    for(s = 0; s < nStates[n2]; s++) {
                        tmp2[s] /= pow(newMsgs[s+maxState*e2],1.-mu[e2]);
                    }
                }
                else {
                    for(s = 0; s < nStates[n2]; s++) {
                        tmp2[s] /= pow(newMsgs[s+maxState*(e2+nEdges)],1.-mu[e2]);
                    }
                }
            }
        }
        
        z = 0;
        for(s1 = 0; s1 < nStates[n1]; s1++) {
            for(s2 = 0; s2 < nStates[n2]; s2++) {
                edgeBel[s1 + maxState*(s2 + maxState*e)] = tmp1[s1]*tmp2[s2]*pow(edgePot[s1+maxState*(s2+maxState*e)],1./mu[e]);
                z += edgeBel[s1+maxState*(s2+maxState*e)];
            }
        }
        for(s1 = 0; s1 < nStates[n1]; s1++) {
            for(s2 = 0; s2 < nStates[n2]; s2++)
                edgeBel[s1+maxState*(s2+maxState*e)] /= z;
        }
    }
    
    /* Compute Bethe Free Energy */
    energy1 = 0;
    energy2 = 0;
    entropy1 = 0;
    entropy2 = 0;
    for(n = 0; n < nNodes; n++) {
        nNbrs = 0;
        for(Vind = V[n]-1; Vind < V[n+1]-1; Vind++)
            nNbrs += mu[E[Vind]-1];
        /*printf("%f\n",nNbrs);*/
        
        for(s = 0; s < nStates[n]; s++) {
            if(nodeBel[n+nNodes*s] > 1e-10)
                entropy1 += (nNbrs-1)*nodeBel[n+nNodes*s]*log(nodeBel[n+nNodes*s]);
            
            energy1 -= nodeBel[n+nNodes*s]*log(nodePot[n+nNodes*s]);
        }
    }
    for(e = 0; e < nEdges; e++) {
        n1 = edgeEnds[e]-1;
        n2 = edgeEnds[e+nEdges]-1;
        
        for(s1 = 0; s1 < nStates[n1];s1++) {
            for(s2 = 0; s2 < nStates[n2]; s2++) {
                if(edgeBel[s1+maxState*(s2+maxState*e)] > 1e-10) {
                    entropy2 -= mu[e]*edgeBel[s1+maxState*(s2+maxState*e)]*log(edgeBel[s1+maxState*(s2+maxState*e)]);
                }
                energy2 -= edgeBel[s1+maxState*(s2+maxState*e)]*log(edgePot[s1+maxState*(s2+maxState*e)]);
            }
        }
    }
    /*printf("%f,%f,%f,%f\n",energy1,energy2,entropy1,entropy2);*/
    logZ[0] = -energy1-energy2+entropy1+entropy2;
    
    
    
    
    /* Free memory */
    mxFree(prodMsgs);
    mxFree(oldMsgs);
    mxFree(newMsgs);
    mxFree(tmp);
    mxFree(tmp1);
    mxFree(tmp2);
}
Exemple #6
0
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
   /* Variables */
    int n, s, e, e2, n1, n2, neigh, Vind, Vind2, s1, s2, di, L, foundIt, 
        nNodes, nEdges, maxState, dims[3],
        iter,maxIter,nNbrs,
        *edgeEnds, *nStates, *V, *E,*y,
        calcMargs, useDamping, *nNeighbors;
    
    double *msgFromNode, *edgePot, *nodeBel, *edgeBel, *logZ,
           z,energy1,energy2,entropy1,entropy2,*prodMsgs,*oldMsgs,*newMsgs,*tmp,
           *updatedMsg, *nodeBelUptree, *msgFromNodeForUptree, *prodMsgForUptree, *prodMsgForFactorMargs, z1, z2, z3, *nodePot, *msgDownTree, *factorMarginals,
           nodeTerm, factorTerm, zf, *messagesFromLastLBP, alpha, M1, temp;
    
   /* Input */
    msgFromNode = mxGetPr(prhs[0]);
    msgFromNodeForUptree = mxGetPr(prhs[1]);
    nodePot = mxGetPr(prhs[2]);
    msgDownTree = mxGetPr(prhs[3]);
    nNeighbors = (int*)mxGetPr(prhs[4]);
    edgePot = mxGetPr(prhs[5]);
    edgeEnds = (int*)mxGetPr(prhs[6]);
    nStates = (int*)mxGetPr(prhs[7]);
    V = (int*)mxGetPr(prhs[8]);
    E = (int*)mxGetPr(prhs[9]);
    maxIter = ((int*)mxGetPr(prhs[10]))[0];
    calcMargs = ((int*)mxGetPr(prhs[11]))[0];
    useDamping = ((int*)mxGetPr(prhs[12]))[0];
    messagesFromLastLBP = mxGetPr(prhs[13]);
    alpha = ((double*)mxGetPr(prhs[14]))[0];
   
    if (!mxIsClass(prhs[6],"int32")||!mxIsClass(prhs[7],"int32")||!mxIsClass(prhs[8],"int32")||!mxIsClass(prhs[9],"int32")||!mxIsClass(prhs[10],"int32"))
		mexErrMsgTxt("edgeEnds, nStates, V, E, maxIter must be int32");
	
    /* Compute Sizes */

    nNodes = mxGetDimensions(prhs[0])[0];
    maxState = mxGetDimensions(prhs[0])[1];
    nEdges = mxGetDimensions(prhs[6])[0];
    
    /* Output */
    plhs[0] = mxCreateDoubleMatrix(nNodes,maxState,mxREAL);
    dims[0] = maxState;
    dims[1] = maxState;
    dims[2] = nEdges;
    plhs[1] = mxCreateNumericArray(3,dims,mxDOUBLE_CLASS,mxREAL);
    plhs[2] = mxCreateDoubleMatrix(1,1,mxREAL);
    plhs[3] = mxCreateDoubleMatrix(nEdges*maxState*2,1,mxREAL);
    plhs[4] = mxCreateDoubleMatrix(nNodes, maxState, mxREAL);
    
    nodeBel = mxGetPr(plhs[0]);
    edgeBel = mxGetPr(plhs[1]);
    logZ = mxGetPr(plhs[2]);
    updatedMsg = mxGetPr(plhs[3]);
    nodeBelUptree = mxGetPr(plhs[4]);
    
    prodMsgs = mxCalloc(maxState*nNodes,sizeof(double));
    prodMsgForUptree = mxCalloc(maxState*nNodes,sizeof(double));
    prodMsgForFactorMargs = mxCalloc(maxState*nNodes,sizeof(double)); 
    oldMsgs = mxCalloc(maxState*nEdges*2,sizeof(double));
    newMsgs = mxCalloc(maxState*nEdges*2,sizeof(double));
    tmp = mxCalloc(maxState,sizeof(double));
    factorMarginals = mxCalloc(maxState*nNodes,sizeof(double));
    
    /* Initialize */
    for(e = 0; e < nEdges; e++)
    {
        n1 = edgeEnds[e]-1;
        n2 = edgeEnds[e+nEdges]-1;
        for(s = 0; s < nStates[n2]; s++)
            newMsgs[s+maxState*e] = myLog(1./nStates[n2]);
        for(s = 0; s < nStates[n1]; s++)
            newMsgs[s+maxState*(e+nEdges)] = myLog(1./nStates[n1]);
    }
    
    for(iter = 0; iter < maxIter; iter++)
    {        
        for(n = 0; n < nNodes; n++)
        {            
            /* Update Messages */
            for(Vind = V[n]-1; Vind < V[n+1]-1; Vind++)
            {
                e = E[Vind]-1;
                n1 = edgeEnds[e]-1;
                n2 = edgeEnds[e+nEdges]-1;
                
                /* First part of message is msgFromNode*/
                for(s = 0; s < nStates[n]; s++)
                    tmp[s] = msgFromNode[n + nNodes*s];
                
                /* Multiply by messages from neighbors except j */
                for(Vind2 = V[n]-1; Vind2 < V[n+1]-1; Vind2++)
                {
                    e2 = E[Vind2]-1;
                    if (e != e2)
                    {
                        if (n == edgeEnds[e2+nEdges]-1)
                        {
                            for(s = 0; s < nStates[n]; s++)
                            {
                                tmp[s] += newMsgs[s+maxState*e2];
                            }
                        }
                        else
                        {
                            for(s = 0; s < nStates[n]; s++)
                            {
                                tmp[s] += newMsgs[s+maxState*(e2+nEdges)];
                            }
                        }
                    }
                }
               
                /* Now multiply by edge potential to get new message */
                
                if (n == n2)
                {
                    for(s1 = 0; s1 < nStates[n1]; s1++)
                    {
                        temp = 0.0;
                        M1 = tmp[0] + edgePot[s1+maxState*(0+maxState*e)];

                        for(s2 = 0; s2 < nStates[n2]; s2++)
                        {
                            if ((tmp[s2] + edgePot[s1+maxState*(s2+maxState*e)]) > M1)
                                M1 = tmp[s2] + edgePot[s1+maxState*(s2+maxState*e)];
                        }
                        
                        for(s2 = 0; s2 < nStates[n2]; s2++)
                        {
                            temp += exp(tmp[s2] + edgePot[s1+maxState*(s2+maxState*e)] - M1);
                        }
                        newMsgs[s1+maxState*(e+nEdges)] = M1 + myLog(temp);
                    }
                    
                    /* Normalize */
                    M1 = newMsgs[0+maxState*(e+nEdges)];
                    for(s = 0; s < nStates[n1]; s++)
                        if (newMsgs[s+maxState*(e+nEdges)] > M1)
                            M1 = newMsgs[s+maxState*(e+nEdges)];
                    temp = 0.0;

                    z = M1;
                    for(s = 0; s < nStates[n1]; s++)
                    {
                        temp += exp(newMsgs[s+maxState*(e+nEdges)] - M1);
                    }
                    z += myLog(temp);
                        
                    for(s = 0; s < nStates[n1]; s++)
                    {
                        newMsgs[s+maxState*(e+nEdges)] -= z;
                    }
                        
                    if(useDamping == 1)
                    {
                        for(s = 0; s < nStates[n1]; s++)
                        {
                            newMsgs[s+maxState*(e+nEdges)] = myLog(alpha*exp(newMsgs[s+maxState*(e+nEdges)]) + (1-alpha)*exp(messagesFromLastLBP[s+maxState*(e+nEdges)]));
                        }
                    }
                }
                else
                {
                    for(s2 = 0; s2 < nStates[n2]; s2++)
                    {
                        temp = 0.0;
                        M1 = tmp[0] + edgePot[0+maxState*(s2+maxState*e)];
                        for(s1 = 0; s1 < nStates[n1]; s1++)
                            if ((tmp[s1] + edgePot[s1+maxState*(s2+maxState*e)]) > M1)
                                M1 = tmp[s1] + edgePot[s1+maxState*(s2+maxState*e)];

                        for(s1 = 0; s1 < nStates[n1]; s1++)
                            temp += exp(tmp[s1] + edgePot[s1+maxState*(s2+maxState*e)] - M1);
                        newMsgs[s2+maxState*e] = M1 + myLog(temp);
                    }

                    /* Normalize */
                    M1 = newMsgs[0+maxState*e];
                    for (s = 0; s < nStates[n2]; s++)
                        if (newMsgs[s+maxState*e] > M1)
                            M1 = newMsgs[s+maxState*e];

                    z = M1;
                    temp = 0.0;
                    for (s = 0; s < nStates[n2]; s++)
                        temp += exp(newMsgs[s+maxState*e] - M1);
                    z += myLog(temp);
                    
                    for (s = 0; s < nStates[n2]; s++)
                        newMsgs[s+maxState*e] -= z;
                        
                    if(useDamping == 1)
                    {
                        for(s = 0; s < nStates[n2]; s++)
                        {
                            newMsgs[s+maxState*e] = myLog(alpha*exp(newMsgs[s+maxState*e]) + (1-alpha)*exp(messagesFromLastLBP[s+maxState*e]));
                        }
                    }
                }   
            }            
        }
        

        /* oldMsgs = newMsgs */
        z = 0;
        for(s=0;s<maxState;s++)
        {
            for(e=0;e<nEdges*2;e++)
            {
                z += absDif(newMsgs[s+maxState*e],oldMsgs[s+maxState*e]);
                oldMsgs[s+maxState*e] = newMsgs[s+maxState*e];
                updatedMsg[s+maxState*e] = newMsgs[s+maxState*e];
            }
        }
        
        /* if sum(abs(newMsgs(:)-oldMsgs(:))) < 1e-4; break; */
        if(z < 1e-3)
        {
            break;
        }   
    }
        
    /* compute nodeBel */
    for(n = 0; n < nNodes; n++)
    {
        for(s = 0; s < nStates[n]; s++)
        {
            prodMsgs[s+maxState*n] = msgFromNode[n+nNodes*s];
            prodMsgForUptree[s+maxState*n] = msgFromNodeForUptree[n+nNodes*s];
            prodMsgForFactorMargs[s+maxState*n] = msgDownTree[n+nNodes*s];
        }
        
        for(Vind = V[n]-1; Vind < V[n+1]-1; Vind++)
        {
            e = E[Vind]-1;
            n1 = edgeEnds[e]-1;
            n2 = edgeEnds[e+nEdges]-1;
            
            if (n == n2)
            {
                for(s = 0; s < nStates[n]; s++)
                {
                    prodMsgs[s+maxState*n] += newMsgs[s+maxState*e];
                    prodMsgForUptree[s+maxState*n] += newMsgs[s+maxState*e];
                    prodMsgForFactorMargs[s+maxState*n] += newMsgs[s+maxState*e];
                }
            }
            else
            {
                for(s = 0; s < nStates[n]; s++)
                {
                    prodMsgs[s+maxState*n] += newMsgs[s+maxState*(e+nEdges)];
                    prodMsgForUptree[s+maxState*n] += newMsgs[s+maxState*(e+nEdges)];
                    prodMsgForFactorMargs[s+maxState*n] += newMsgs[s+maxState*(e+nEdges)];
                }
            }
        }
        
        /* normalize */
        M1 = prodMsgs[0+maxState*n];
        for (s = 0; s < nStates[n]; s++)
        {
            nodeBel[n+nNodes*s] = prodMsgs[s+maxState*n];
            if (prodMsgs[s+maxState*n] > M1)
                M1 = prodMsgs[s+maxState*n];
        }
        z = M1;
        temp = 0.0;
        for (s = 0; s < nStates[n]; s++)
            temp += exp(nodeBel[n+nNodes*s] - M1);
        z += myLog(temp);
        for (s = 0; s < nStates[n]; s++)
            nodeBel[n+nNodes*s] -= z;
            
        M1 = prodMsgForUptree[0+maxState*n];
        for (s = 0; s < nStates[n]; s++)
        {
            nodeBelUptree[n+nNodes*s] = prodMsgForUptree[s+maxState*n];
            if (prodMsgForUptree[s+maxState*n] > M1)
                M1 = prodMsgForUptree[s+maxState*n];
        }
        z = M1;
        temp = 0.0;
        for (s = 0; s < nStates[n]; s++)
            temp += exp(nodeBelUptree[n+nNodes*s] - M1);
        z += myLog(temp);
        for (s = 0; s < nStates[n]; s++)
            nodeBelUptree[n+nNodes*s] -= z;
                
        M1 = prodMsgForFactorMargs[0+maxState*n];
        for (s = 0; s < nStates[n]; s++)
        {
            if (prodMsgForFactorMargs[s+maxState*n] > M1)
                M1 = prodMsgForFactorMargs[s+maxState*n];
        }
        z = M1;
        temp = 0.0;
        for (s = 0; s < nStates[n]; s++)
            temp += exp(prodMsgForFactorMargs[s+maxState*n] - M1);
        z += myLog(temp);
        for (s = 0; s < nStates[n]; s++)
        {
            prodMsgForFactorMargs[s+maxState*n] -= z;
        }
        
    }        
    

    /* Compute edgeBel */
    for(e = 0; e < nEdges; e++)
    {
        n1 = edgeEnds[e]-1;
        n2 = edgeEnds[e+nEdges]-1;
        for(s1 = 0; s1 < nStates[n1]; s1++)
        {
            for(s2 = 0; s2 < nStates[n2]; s2++)
            {
                edgeBel[s1+maxState*(s2+maxState*e)] = nodeBel[n1+nNodes*s1] - newMsgs[s1+maxState*(e+nEdges)];
                edgeBel[s1+maxState*(s2+maxState*e)] += nodeBel[n2+nNodes*s2] - newMsgs[s2+maxState*e];
                edgeBel[s1+maxState*(s2+maxState*e)] += edgePot[s1+maxState*(s2+maxState*e)];
            }
        }
       
        M1 = edgeBel[maxState*(maxState*e)];
        for(s1 = 0; s1 < nStates[n1]; s1++)
            for(s2 = 0; s2 < nStates[n2]; s2++)
                if (edgeBel[s1+maxState*(s2+maxState*e)] > M1)
                    M1 = edgeBel[s1+maxState*(s2+maxState*e)];

        z = M1;
        temp = 0.0;
        for(s1 = 0; s1 < nStates[n1]; s1++)
            for(s2 = 0; s2 < nStates[n2]; s2++)
                    temp += exp(edgeBel[s1+maxState*(s2+maxState*e)] - M1);
        z += myLog(temp);
        
        for(s1 = 0; s1 < nStates[n1]; s1++)
            for(s2 = 0; s2 < nStates[n2]; s2++)
                edgeBel[s1+maxState*(s2+maxState*e)] -= z;
    }



    /* Compute Bethe Free Energy */  
    nodeTerm = 0.0;
    factorTerm = 0.0;
    
    for(n = 0; n < nNodes; n++)
    {
        nNbrs = V[n+1]-V[n];
        
       M1 = nodePot[n] + prodMsgForFactorMargs[maxState*n];
        for(s = 0; s < nStates[n]; s++)
        {
            nodeTerm += (nNbrs+nNeighbors[n]+1)*exp(nodeBel[n+nNodes*s])*nodeBel[n+nNodes*s];
            factorMarginals[s+maxState*n] = nodePot[n+nNodes*s] + prodMsgForFactorMargs[s+maxState*n];
            
            if (factorMarginals[s+maxState*n] > M1)
                M1 = factorMarginals[s+maxState*n];

        }
        zf = M1;
        temp = 0.0;
        for (s = 0; s < nStates[n]; s++)
            temp += exp(factorMarginals[s+maxState*n] - M1);
        zf += myLog(temp);
        

        for(s = 0; s < nStates[n]; s++)

        {
            factorMarginals[s+maxState*n] -= zf;
            temp = exp(factorMarginals[s+maxState*n]) * (-nodePot[n+nNodes*s] + factorMarginals[s+maxState*n]);

            factorTerm += temp;
        }
    }
    
    for(e = 0; e < nEdges; e++)
    {
        n1 = edgeEnds[e]-1;
        n2 = edgeEnds[e+nEdges]-1;
        
        for(s1 = 0; s1 < nStates[n1];s1++)
        {
            for(s2 = 0; s2 < nStates[n2]; s2++)
            {
                factorTerm += exp(edgeBel[s1+maxState*(s2+maxState*e)]) * (-edgePot[s1+maxState*(s2+maxState*e)] + edgeBel[s1+maxState*(s2+maxState*e)]);
            }
        }
    }
    logZ[0] = nodeTerm - factorTerm;
    
   /* Free memory */
    mxFree(prodMsgs);
    mxFree(oldMsgs);
    mxFree(newMsgs);
    mxFree(tmp);
    mxFree(prodMsgForUptree);
    mxFree(prodMsgForFactorMargs);
    mxFree(factorMarginals);    
}