Beispiel #1
0
double
KL_V_alpha_g (const gsl_vector *v_V_alpha_g)
{
  int i = *params->i;
  int d;
  int G = *params->G, g = *params->g;
  double tmpsum = 0.0, tmp;
  int N = *params->N;
  double KL;
  double V_alpha_g = gsl_vector_get(v_V_alpha_g, 0);
  for (i = 0; i < SUBSET; i++)
    {
  tmp = 0.0;
  for (d=0; d<*params->D; d++)
    tmp += pow(params->V_z[i * *params->D + d] - params->V_eta[g * *params->D + d], 2.0);
      tmpsum +=
	params->V_lambda[*params->g * N + i] * 
	              (*params->D*gsl_sf_psi(*params->inv_sigma02*V_alpha_g) -
                       0.5* *params->inv_sigma02*V_alpha_g*(params->V_sigma2[i]+params->V_omega2[g]+tmp));
    }
  tmp = 0.0;
  for (g=0; g<G; g++)
    if (g!=*params->g)
      tmp += params->V_alpha[g];
  KL =
    fabs (tmpsum*(tmp+V_alpha_g) + lgamma(0.5*V_alpha_g) +
   0.5*(params->alpha[*params->g]-V_alpha_g)*(gsl_sf_psi(0.5*V_alpha_g)));
   //-gsl_sf_psi(params->alpha[*params->g])));
  return KL;
}
Beispiel #2
0
void fbst_loginorm(gsl_rng *r,
		   gsl_vector_uint *x,
		   gsl_vector_uint *sums,
		   double alpha,
		   double beta,
		   double *_ev,double *_err,
		   FBSTConfig *config) {

  size_t i,j;
  double mean;
  double var;
  double a,b;

  assert(x->size == sums->size);

  gsl_vector *means=gsl_vector_alloc(x->size);
  gsl_vector *sd=gsl_vector_alloc(x->size);

  
  for(i=0;i<x->size;i++) {
    a=ELT(x,i)+alpha;
    b=ELT(sums,i)+beta-a;
    mean=gsl_sf_psi(a)-gsl_sf_psi(b);
    var=gsl_sf_psi_1(a)+gsl_sf_psi_1(b);

    printf("x%i=N(%lg %lg)\n",i,mean,var);

    gsl_vector_set(means,i,mean);
    gsl_vector_set(sd,i,var);
  }

  fbst_normal(r,means,sd,_ev,_err,config);
  gsl_vector_free(means);
  gsl_vector_free(sd);  
}
Beispiel #3
0
double
KL_V_nu_g (const gsl_vector *v_V_nu_g)
{
  int i = *params->i;	
  int g, G = *params->G;
  double tmpsum = 0.0, tmp;
  int N = *params->N;
  double KL;
  double V_nu_g = gsl_vector_get(v_V_nu_g, 0);
  tmp = 0.0;
  for (g = 0; g < G; g++)
    if (g!=*params->g)
      tmp += params->V_nu[g];
  for (i = 0; i < SUBSET; i++)
    tmpsum +=
      params->V_lambda[*params->g * N +
			     i] * (gsl_sf_psi (V_nu_g) - gsl_sf_psi (tmp+V_nu_g));
  KL = tmpsum - lgamma (tmp+V_nu_g);
  tmp = 0.0;
  for (g = 0; g < G; g++)
    if (g!=*params->g)
      tmp += lgamma (params->V_nu[g]);
  KL = fabs (KL + tmp + lgamma (V_nu_g) -
	     (V_nu_g -
	      params->nu[*params->g]) *
	     (gsl_sf_psi (V_nu_g) -
	      gsl_sf_psi (params->nu[*params->g])));
  return KL;
}
Beispiel #4
0
void my_df (const gsl_vector *v, void *params, gsl_vector *df)
{

	cclda_alphaopt * alphaopt=(cclda_alphaopt *) params;
	double f = 0.0;
	double sumalpha, sumpsialpha, temp;
	int j, c;

	f = 0.0;
	c = alphaopt->c;
	sumalpha = 0.0;
	sumpsialpha = 0.0;
	for (j = 0; j < alphaopt->m; j++){
		alphaopt->alpha[j] = exp(gsl_vector_get(v, j));
		sumalpha += alphaopt->alpha[j];
		f += (alphaopt->alpha[j] - 1)*alphaopt->ss2[j][c];
		temp = gsl_sf_psi(alphaopt->alpha[j]);
		sumpsialpha += temp;

		alphaopt->grad[j] = alphaopt->ss2[j][c] -alphaopt->ss1[c]*temp;
	}
	f += alphaopt->ss1[c]*(gsl_sf_psi(sumalpha) - sumpsialpha);
	for (j = 0; j < alphaopt->m; j++){

		alphaopt->grad[j] += gsl_sf_psi(sumalpha)*alphaopt->ss1[c];
		gsl_vector_set(df, j, -alphaopt->alpha[j]*alphaopt->grad[j]);
	}
	f *= -1;

}
double lda_m_step(lda* model, lda_suff_stats* ss) {
    int k, w;
    double lhood = 0;
    for (k = 0; k < model->ntopics; k++)
    {
        gsl_vector ss_k = gsl_matrix_column(ss->topics_ss, k).vector;
        gsl_vector log_p = gsl_matrix_column(model->topics, k).vector;
        if (LDA_USE_VAR_BAYES == 0)
        {
            gsl_blas_dcopy(&ss_k, &log_p);
            normalize(&log_p);
            vct_log(&log_p);
        }
        else
        {
            double digsum = sum(&ss_k)+model->nterms*LDA_TOPIC_DIR_PARAM;
            digsum = gsl_sf_psi(digsum);
            double param_sum = 0;
            for (w = 0; w < model->nterms; w++)
            {
                double param = vget(&ss_k, w) + LDA_TOPIC_DIR_PARAM;
                param_sum += param;
                double elogprob = gsl_sf_psi(param) - digsum;
                vset(&log_p, w, elogprob);
                lhood += (LDA_TOPIC_DIR_PARAM - param) * elogprob + gsl_sf_lngamma(param);
            }
            lhood -= gsl_sf_lngamma(param_sum);
        }
    }
    return(lhood);
}
Beispiel #6
0
/* Computes psi (digamma) vector function */
int vector_psi(long n, double *a, double *x)
{
	long i;
	double tot=0, psi_tot;
	for (i=0; i<n; i++) { tot += a[i]; }
	psi_tot = gsl_sf_psi(tot);
	for (i=0; i<n; i++) { x[i] = gsl_sf_psi(a[i]) - psi_tot; }
	return 1;
}
Beispiel #7
0
void binom_transform (const double* rs, const double* fq, double* out)
{
  double r=rs[0]; double s=rs[1];
  double f=fq[0]; double q=fq[1];
  double E = gsl_sf_psi(r) - gsl_sf_psi(s);
  double V = gsl_sf_psi_1(r) + gsl_sf_psi_1(s);
  out[0] = E - f;
  out[1] = V - q;
  // Rprintf("r=%g, s=%g, f=%g, q=%g, out=%g, %g\n", r, s, f, q, out[0], out[1]);
}
static void hessian(gsl_matrix* ptHessian, const double* adLambda,
                    const struct data_t *data)
{
    const int S = data->S, N = data->N, *aanX = data->aanX;
    const double *adPi = data->adPi;

    int i = 0, j = 0;
    double adAlpha[S], adAJK[S], adCJK[S], adAJK0[S], adCJK0[S];
    double dCK0 = 0.0, dAK0;
    double dCSum, dAlphaSum = 0.0, dW = 0.0, dCK = 0.0, dAK;

    for (j = 0; j < S; j++) {
        adAlpha[j] = exp(adLambda[j]);
        dAlphaSum += adAlpha[j];
        adAJK0[j] = adAJK[j] = adCJK0[j] = adCJK[j] = 0.0;
        const double dPsiAlpha = gsl_sf_psi(adAlpha[j]);
        const double dPsi1Alpha = gsl_sf_psi_1(adAlpha[j]);
        for (i = 0; i < N; i++) {
            const int n = aanX[j * N + i];
            adCJK0[j] += adPi[i] * n ? gsl_sf_psi(adAlpha[j] + n) : dPsiAlpha;
            adAJK0[j] += adPi[i] * dPsiAlpha;
            adCJK[j] += adPi[i] * n ? gsl_sf_psi_1(adAlpha[j] + n): dPsi1Alpha;
            adAJK[j] += adPi[i] * dPsi1Alpha;
        }
    }

    for (i = 0; i < N; i++) {
        dW += adPi[i];
        dCSum = 0.0;
        for (j = 0; j < S; j++)
            dCSum += adAlpha[j] + aanX[j * N + i];
        dCK  += adPi[i]*gsl_sf_psi_1(dCSum);
        dCK0 += adPi[i]*gsl_sf_psi(dCSum);
    }

    dAK = dW * gsl_sf_psi_1(dAlphaSum);
    dAK0 = dW * gsl_sf_psi(dAlphaSum);
    for (i = 0; i < S; i++)
        for (j = 0; j < S; j++) {
            double dVal = 0.0;
            if (i == j) {
                double dG1 = -adAlpha[i] *
                    (dAK0 - dCK0 + adCJK0[i] - adAJK0[i]);
                double dG2 = -adAlpha[i] *
                    adAlpha[i]*(dAK - dCK + adCJK[i] - adAJK[i]);
                double dG3 = adAlpha[i]*GAMMA_NU;
                dVal = dG1 + dG2 + dG3;
            } else
                dVal = -adAlpha[i] * adAlpha[j] * (dAK - dCK);
            gsl_matrix_set(ptHessian, i, j, dVal);
        }
}
double compute_lda_lhood(lda_post* p) {
  int k, n;
  int K = p->model->ntopics, N = p->doc->nterms;

  double gamma_sum = sum(p->gamma);
  double lhood =
    gsl_sf_lngamma(sum(p->model->alpha)) -
    gsl_sf_lngamma(gamma_sum);
  vset(p->lhood, K, lhood);
  
  double influence_term = 0.0;
  double digsum = gsl_sf_psi(gamma_sum);
  for (k = 0; k < K; k++) {
    if (p->doc_weight != NULL) {
      //	  outlog("doc weight size: %d", p->doc_weight->size);
      assert (K == p->doc_weight->size);
      double influence_topic = gsl_vector_get(p->doc_weight, k);
      if (FLAGS_model == "dim"
	  || FLAGS_model == "fixed") {
	influence_term = - ((influence_topic * influence_topic
			     + FLAGS_sigma_l * FLAGS_sigma_l)
			    / 2.0 / (FLAGS_sigma_d * FLAGS_sigma_d));
	// Note that these cancel with the entropy.
	//     - (log(2 * PI) + log(FLAGS_sigma_d)) / 2.0);
      }
    }
    double e_log_theta_k = gsl_sf_psi(vget(p->gamma, k)) - digsum;
    double lhood_term =
      (vget(p->model->alpha, k)-vget(p->gamma, k)) * e_log_theta_k +
      gsl_sf_lngamma(vget(p->gamma, k)) -
      gsl_sf_lngamma(vget(p->model->alpha, k));
    
    for (n = 0; n < N; n++) {
      if (mget(p->phi, n, k) > 0) {
	lhood_term +=
	  p->doc->count[n]*
	  mget(p->phi, n, k) *
	  (e_log_theta_k
	   + mget(p->model->topics, p->doc->word[n], k)
	   - mget(p->log_phi, n, k));
      }
    }
    vset(p->lhood, k, lhood_term);
    lhood += lhood_term;
    lhood += influence_term;
  }
  
  return(lhood);
}
Beispiel #10
0
double NBinGlm::getfAfAdash(double k0, unsigned int id, unsigned int limit)
{
    unsigned int i, it=0;
    double sum=1, num=0, k;
    double y, m, dl, ddl, tol;
    double phi, dl_dphi, d2l_dphi2, del_phi;
    if (k0==0) {
       for (i=0; i<nRows; i++) {
           y = gsl_matrix_get(Yref, i, id);
           m = gsl_matrix_get(Mu, i, id);
           if (m>0) {
              sum = sum+(y/m-1)*(y/m-1);
              num = num+1;
           }
       }
       k = num/sum;
       if (num==0) printf("num=0\n");
    }
    else k=k0; 
    k = MAX(k, mintol);
    phi = 1/k;
    while ( it<limit ) {
        it++;
        dl=nRows*(1+log(k)-gsl_sf_psi(k));
        ddl=nRows*(gsl_sf_psi_1(k)-1/k);
        for ( i=0; i<nRows; i++ ) {
           y = gsl_matrix_get(Yref, i, id);
           m = gsl_matrix_get(Mu, i, id);
           dl  = dl + gsl_sf_psi(y+k)-log(m+k)-(y+k)/(m+k); 
           ddl = ddl - gsl_sf_psi_1(y+k)+2/(m+k)-(y+k)/((m+k)*(m+k)); 
        }   
       dl_dphi = - exp(2*log(k))*dl;
       d2l_dphi2 = 2*exp(3*log(k))*dl + exp(4*log(k))*ddl;

       if (ABS(ddl) < mintol) ddl = GSL_SIGN(ddl)*mintol;
       del_phi = dl_dphi/ABS(d2l_dphi2);
       tol = ABS(del_phi*dl_dphi);

       if (tol<eps) break;

       phi = phi + del_phi;
       if (phi<0) {k=0; break;}
       k = 1/MAX(ABS(phi),mintol);
       if (k>maxth) break;
    }

    return k;
    
}
Beispiel #11
0
double KL_V_z_i (const gsl_vector *v_V_z_i)
{
  int i = *params->i, d = *params->d;
  int D = *params->D;	
  int g;
  double tmpsum = 0.0, tmp;
  int N = *params->N;
  double KL;
  for (d=0; d<D; d++)
    params->V_z[i*D+d] = gsl_vector_get(v_V_z_i, d);
  tmpsum = loglikefunc();
  KL = tmpsum;
  tmpsum = 0;
  for (g = 0; g < *params->G; g++)
    {
      tmp = 0.0;
        for (d=0; d<D; d++)
          tmp += pow(params->V_z[i*D+d] - params->V_eta[g * D + d], 2.0);
      tmp = GSQRT(tmp + params->V_sigma2[i] + params->V_omega2[g]);
      tmpsum +=
	params->V_lambda[g * N + i] * (D * gsl_sf_psi (0.5 * *params->inv_sigma02 *
				params->V_alpha[g]) -0.5 * *params->inv_sigma02 *
				     params->V_alpha[g] * tmp);
    }
  KL = fabs (KL + tmpsum);
  return KL;
}
void update_phi(int doc_number, int time,
		lda_post* p, lda_seq* var,
		gsl_matrix* g) {
    int i, k, n, K = p->model->ntopics, N = p->doc->nterms;
    double dig[p->model->ntopics];

    for (k = 0; k < K; k++) {
      dig[k] = gsl_sf_psi(vget(p->gamma, k));
    }

    for (n = 0; n < N; n++) {
      // compute log phi up to a constant

      int w = p->doc->word[n];
      for (k = 0; k < K; k++) {
	mset(p->log_phi, n, k,
	     dig[k] + mget(p->model->topics, w, k));
      }

      // normalize in log space

      gsl_vector log_phi_row = gsl_matrix_row(p->log_phi, n).vector;
      gsl_vector phi_row = gsl_matrix_row(p->phi, n).vector;
      log_normalize(&log_phi_row);
      for (i = 0; i < K; i++) {
	vset(&phi_row, i, exp(vget(&log_phi_row, i)));
      }
    }
}
  void init(bool deserialize) {
    LOG(debug) << "global.min_gamma_shape="
               << options.get<double>("global.min_gamma_shape");
    layer_size = options.get<int>("layer.size");
    lf = get_link_function(options.get<string>("lf"));
    min_gamma_sample = options.get<double>("global.min_gamma_sample");
    wshape.set_size(layer_size, n_examples);
    wscale.set_size(layer_size, n_examples);

    ScoreFunction score_shape = [=](double z, arma::uword i, arma::uword j) {
      auto shape0 = wshape(i,j);
      auto shape = lf->f(shape0);
      auto scale = lf->f(wscale(i,j));
      return lf->g(shape0) * (- gsl_sf_psi(shape) - log(scale) + log(z));
    };
    register_param(&wshape, score_shape, deserialize);

    ScoreFunction score_scale = [=](double z, arma::uword i, arma::uword j) {
      auto shape = lf->f(wshape(i,j));
      auto scale0 = wscale(i,j);
      auto scale = lf->f(scale0);
      return lf->g(scale0) * (- shape/scale + z/scale/scale);
    };
    register_param(&wscale, score_scale, deserialize);
  }
Beispiel #14
0
double NBinGlm::thetaML(double k0, unsigned int id, unsigned int limit)
{
    // equivalent to theta.ml() in MASS
    // Note that theta here is the dispersion parameter
    // So phi = 1/theta;
    unsigned int i, it=0;
    double del=1, sum=1, num=0, k;
    double y, m, dl, ddl, tol;
    if (k0==0) {
       for (i=0; i<nRows; i++) {
           y = gsl_matrix_get(Yref, i, id);
           m = gsl_matrix_get(Mu, i, id);
           if (m>0) {
              sum = sum+(y/m-1)*(y/m-1);
              num = num+1;
           }
       }
       k = num/sum;
    }
    else k=k0;

    k = MAX(k, mintol);
    while ( it<=limit ) {
        it++;
        k = ABS(k);
        dl=nRows*(1+log(k)-gsl_sf_psi(k));
        ddl=nRows*(gsl_sf_psi_1(k)-1/k);
        for ( i=0; i<nRows; i++ ) {
           y = gsl_matrix_get(Yref, i, id);
           m = gsl_matrix_get(Mu, i, id);
           dl  = dl + gsl_sf_psi(y+k)-log(m+k)-(y+k)/(m+k); 
           ddl = ddl - gsl_sf_psi_1(y+k)+2/(m+k)-(y+k)/((m+k)*(m+k)); 
        }   
       if (ABS(ddl) < mintol) ddl = GSL_SIGN(ddl)*mintol;
       del = dl/ABS(ddl);
       tol = ABS(del*dl);
       if (tol<eps) break;
       k = k+del; // Normal Newton use - instead of + for -ddl
       if (k>maxth) break;
       if (k<0) { k = 0; break; }  
    }
   // if (k<0) k=0;

    return k;

}    
Beispiel #15
0
void vdigamma(const gsl_vector* v, gsl_vector* digamma_v) {
  for (unsigned int ii = 0; ii < v->size; ++ii) {
    // gsl_sf_psi throws an error when its argument is 0, whereas digamma
    // returns inf.
    gsl_vector_set(digamma_v, ii, gsl_sf_psi(gsl_vector_get(v, ii)));
    // gsl_vector_set(digamma_v, ii, digamma(gsl_vector_get(v, ii)));
  }
}
static void neg_log_derive_evidence_lambda_pi(const gsl_vector *ptLambda,
                                              void *params, gsl_vector* g)
{
    const struct data_t *data = (const struct data_t *) params;
    const int S = data->S, N = data->N, *aanX = data->aanX;
    const double *adPi = data->adPi;

    int i, j;
    double adDeriv[S], adStore[N], adAlpha[S];
    double dSumStore = 0.0, dStore = 0.0;
    double dWeight = 0;

    for (i = 0; i < N; i++) {
        adStore[i] = 0.0;
        dWeight += adPi[i];
    }

    for (j = 0; j < S; j++) {
        adAlpha[j] = exp(gsl_vector_get(ptLambda, j));
        dStore += adAlpha[j];
        adDeriv[j] = dWeight* gsl_sf_psi(adAlpha[j]);
        double alphaS0 = gsl_sf_psi(adAlpha[j]);
        for (i = 0; i < N; i++) {
            int dN = aanX[j * N + i];
            double dAlphaN = adAlpha[j] + dN;

            double psiAlphaN = dN ? gsl_sf_psi(dAlphaN) : alphaS0;
            adDeriv[j] -= adPi[i] * psiAlphaN;
            adStore[i] += dAlphaN;
        }
    }

    for (i = 0; i < N; i++)
        dSumStore += adPi[i] * gsl_sf_psi(adStore[i]);
    dStore = dWeight * gsl_sf_psi(dStore);

    for (j = 0; j < S; j++) {
        double value = adAlpha[j] *
            (GAMMA_NU + adDeriv[j] - dStore + dSumStore) - GAMMA_ITA;
        gsl_vector_set(g, j, value);
    }
}
Beispiel #17
0
double SPF::update_theta(int user) {
    double change = accu(abs(theta(user) - (a_theta(user) / b_theta(user))));
    double total = accu(theta(user));

    theta(user) = a_theta(user) / b_theta(user);
    for (int k = 0; k < settings->k; k++)
        logtheta(k, user) = gsl_sf_psi(a_theta(k, user));
    logtheta(user) = logtheta(user) - log(b_theta(user));

    return change / total;
}
Beispiel #18
0
inline
typename ICR::EnsembleLearning::Gamma<T>::moments_t
ICR::EnsembleLearning::Gamma<T>::CalcMoments(NP_parameter NP)
{
  const data_t shape  = NP[1]+1.0;
  const data_t iscale = -NP[0];
  BOOST_ASSERT(iscale>0);

  return moments_t(shape/iscale,
		   gsl_sf_psi(shape) - std::log(iscale) 
		   );
}
Beispiel #19
0
void SPF::update_beta(int item) {
    if (settings->svi) {
        double rho = pow(iter_count[item] + settings->delay,
                         -1 * settings->forget);
        a_beta(item) = (1 - rho) * a_beta_old(item) + rho * a_beta(item);
        a_beta_old(item) = a_beta(item);
    }
    beta(item)  = a_beta(item) / b_beta(item);
    for (int k = 0; k < settings->k; k++)
        logbeta(k, item) = gsl_sf_psi(a_beta(k, item));
    logbeta(item) = logbeta(item) - log(b_beta(item));
}
Beispiel #20
0
void gr_KL_V_nu_g (const gsl_vector *v_V_nu_g, void *null, gsl_vector *df)
{
  int i = *params->i;	//, j, d = *params->d;
  int g, G = *params->G;
  double tmpsum = 0.0, tmp;
  int N = *params->N;
  double KL;
  double V_nu_g = gsl_vector_get(v_V_nu_g, 0);
  tmp = 0.0;
  for (g = 0; g < G; g++)
    if (g!=*params->g)
      tmp += params->V_nu[g];
  for (i = 0; i < SUBSET; i++)
    tmpsum =
      tmpsum + params->V_lambda[*params->g * N + i] * (gsl_sf_psi_1 (V_nu_g) -
						    gsl_sf_psi_1 (tmp+V_nu_g));
  KL =
    tmpsum - gsl_sf_psi (tmp+V_nu_g) - gsl_sf_psi (params->nu[*params->g]) -
    V_nu_g * gsl_sf_psi_1 (V_nu_g) +
    params->nu[*params->g] * gsl_sf_psi_1 (V_nu_g);
  gsl_vector_set(df, 0, -KL);
  return;
}
Beispiel #21
0
double my_f (const gsl_vector *v, void *params)
{

	cclda_alphaopt * alphaopt=(cclda_alphaopt *) params;
	double f = 0.0;
	double sumalpha, sumpsialpha;
	int j, c;

	f = 0.0;
	c = alphaopt->c;
	sumalpha = 0.0;
	sumpsialpha = 0.0;
	for (j = 0; j < alphaopt->m; j++){
		alphaopt->alpha[j] = exp(gsl_vector_get(v, j));
		sumalpha += alphaopt->alpha[j];
		f += (alphaopt->alpha[j] - 1)*alphaopt->ss2[j][c];
		sumpsialpha += gsl_sf_psi(alphaopt->alpha[j]);
	}
	f += alphaopt->ss1[c]*(gsl_sf_psi(sumalpha) - sumpsialpha);

	f = -f;

	return(f);
}
Beispiel #22
0
inline
typename ICR::EnsembleLearning::Gamma<T>::moments_t
ICR::EnsembleLearning::Gamma<T>::CalcMoments(vector_data_param mean,
					     vector_data_param var)
{
  const data_t m = mean[0];
  const data_t p = 1.0/var[0];
  
  const data_t shape  = std::pow(m,2)*p;
  const data_t iscale = m*p;
  BOOST_ASSERT(iscale>0);

  return moments_t(shape/iscale,
		   gsl_sf_psi(shape) - std::log(iscale) 
		   );
}
Beispiel #23
0
double SPF::update_tau(int user) {
    int neighbor, n;
    double old, change, total;
    change = 0;
    total = 0;
    for (n = 0; n < data->neighbor_count(user); n++) {
        neighbor = data->get_neighbor(user, n);

        old = tau(neighbor, user);
        total += tau(neighbor, user);

        tau(neighbor, user) = a_tau(neighbor, user) / b_tau(neighbor, user);
        // fake log!
        logtau(neighbor, user) = exp(gsl_sf_psi(a_tau(neighbor, user)) - log(b_tau(neighbor, user)));

        change += abs(old - tau(neighbor, user));
    }

    return total==0 ? 0 : change / total;
}
Beispiel #24
0
double dWishartExpectLogDet(gsl_matrix *ptW, double dNu, int nD)
{
  int i = 0;
  double dRet = 0.0, dLogDet = 0.0, dD = (double) nD;
  gsl_matrix* ptTemp = gsl_matrix_alloc(nD,nD);

  gsl_matrix_memcpy(ptTemp, ptW);

  dLogDet = decomposeMatrix(ptW, nD);

  dRet = dD*log(2.0) + dLogDet;

  for(i = 0; i < nD; i++){
    dRet += gsl_sf_psi(0.5*(dNu - (double) i));
  }

  gsl_matrix_free(ptTemp);

  return dRet;
}
Beispiel #25
0
/// gsl_wrappers
double digamma(double x) {
    return gsl_sf_psi(x);
}
Beispiel #26
0
//Fitting. Allow fitting multiple q curves simultaneously to decrease the chance of converging to local minimum.
void ddm::fitting()
{
    int cnum_fit=num_fit;
    int ctimeWindow=timeWindow;
    //Find the truncation time if time window is set
    for (int itert=0; itert<num_fit; ++itert)
    {
        if (tau[itert]>ctimeWindow)
        {
            cnum_fit=itert;
            break;
        }
    }
    
    //Local variables
    int cqsize=qsize-qIncreList[num_qCurve-1];  //number of fitting result
    int cnum_qCurve=num_qCurve;
    int ctnum_fit=cnum_fit*num_qCurve;
    int cnumOfPara=numOfPara+2*num_qCurve;  //Total number of parameters
    
    fittedPara=gsl_matrix_alloc(cqsize, cnumOfPara);
    //To store the fitting result and error.
    fitErr=gsl_matrix_alloc(cqsize, cnumOfPara);
    status = new int[cqsize];		//Record the status of fitting.
    
    //Using Levenberg-Marquardt algorithm as implemented in the scaled lmder routine in minpack. Jacobian is given.
    const gsl_multifit_fdfsolver_type *solverType = gsl_multifit_fdfsolver_lmsder;
    
    int progress=0;		//Indicator of progress.
    
    //Objects to do numerical inverse Laplace transformation
#ifdef ISFRTD
    NILT NILT1(OMP_NUM_THREADS), NILT2(OMP_NUM_THREADS), NILT3(OMP_NUM_THREADS), NILT4(OMP_NUM_THREADS);
#endif
    
#ifdef ISFRTDP
    NILT NILT1(OMP_NUM_THREADS), NILT2(OMP_NUM_THREADS), NILT3(OMP_NUM_THREADS), NILT4(OMP_NUM_THREADS), NILT5(OMP_NUM_THREADS);
#endif
    
#ifdef ISFRTDPTT
    NILT NILT1(OMP_NUM_THREADS), NILT2(OMP_NUM_THREADS), NILT3(OMP_NUM_THREADS), NILT4(OMP_NUM_THREADS), NILT5(OMP_NUM_THREADS), NILT6(OMP_NUM_THREADS);
#endif
    
#ifdef ISFRTDPfix
    NILT NILT1(OMP_NUM_THREADS), NILT2(OMP_NUM_THREADS);
    
    const long double vbar=vbarGuess;
    const long double sigma=sigmaGuess;
    
    const long double vbsigma2=vbar/sigma/sigma;
    const long double vb2sigma2=vbsigma2*vbar;
    const long double logvbsigma2=log(vbsigma2);
    const long double logfactor=vb2sigma2*logvbsigma2-gsl_sf_lngamma(vb2sigma2);
    const long double cpsiz1=logvbsigma2-gsl_sf_psi(vb2sigma2);
    const long double vb2sigma3=vb2sigma2/sigma;
#endif
    
#ifdef ISFRTDPTTfix
    NILT NILT1(OMP_NUM_THREADS), NILT2(OMP_NUM_THREADS), NILT3(OMP_NUM_THREADS);
    
    const long double vbar=vbarGuess;
    const long double sigma=sigmaGuess;
    
    const long double vbsigma2=vbar/sigma/sigma;
    const long double vb2sigma2=vbsigma2*vbar;
    const long double logvbsigma2=log(vbsigma2);
    const long double logfactor=vb2sigma2*logvbsigma2-gsl_sf_lngamma(vb2sigma2);
    const long double cpsiz1=logvbsigma2-gsl_sf_psi(vb2sigma2);
    const long double vb2sigma3=vb2sigma2/sigma;
#endif
    
#pragma omp parallel for
    for (int iterq=0; iterq<cqsize; ++iterq)
    {
        //Data array which is going to present to the fitting algorithm
        double* datafit=new double[ctnum_fit];
        double* qList=new double[cnum_qCurve];
        double* time=new double[ctnum_fit];
        //Truncate the data, and put multiple curves into one array
        for (int iterqc=0; iterqc<cnum_qCurve; ++iterqc)
        {
            for (int iterf = 0; iterf < cnum_fit; ++iterf)
            {
                datafit[iterf+iterqc*cnum_fit]=(gsl_matrix_get(datag, iterq+qIncreList[iterqc], iterf));		//Fitting in log scale.
                time[iterf+iterqc*cnum_fit]=tau[iterf];
            }
            qList[iterqc]=qabs[iterq+qIncreList[iterqc]];
        }
        
        gsl_multifit_function_fdf fitfun;		//Pointer of function to fit.
        dataStruct sdata;		//GSL data structure
        
        //Data is passed to ISFfun by sdata
        sdata.data=datafit;
        sdata.tau=time;
        sdata.q=qList;
        sdata.num_fit=cnum_fit;
        sdata.num_qCurve=cnum_qCurve;
        
#ifdef ISFRTD
        sdata.ISFILT=&NILT1;
        sdata.dvISFILT=&NILT2;
        sdata.dDISFILT=&NILT3;
        sdata.dlambdaISFILT=&NILT4;
#endif
        
#ifdef ISFRTDP
        sdata.ISFILT=&NILT1;
        sdata.dvbarISFILT=&NILT2;
        sdata.dsigmaISFILT=&NILT3;
        sdata.dDISFILT=&NILT4;
        sdata.dlambdaISFILT=&NILT5;
#endif
        
#ifdef ISFRTDPTT
        sdata.ISFILT=&NILT1;
        sdata.dvbarISFILT=&NILT2;
        sdata.dsigmaISFILT=&NILT3;
        sdata.dDISFILT=&NILT4;
        sdata.dlambdaISFILT=&NILT5;
        sdata.dTTISFILT=&NILT6;
#endif
        
#ifdef ISFRTDPfix
        sdata.alpha=alphaGuess;
        sdata.D=DGuess;
        sdata.vbar=vbar;
        sdata.sigma=sigma;
        
        sdata.vbsigma2=vbsigma2;
        sdata.logfactor=logfactor;
        sdata.vb2sigma2=vb2sigma2;
        sdata.cpsiz1=cpsiz1;
        sdata.vb2sigma3=vb2sigma3;
        sdata.ISFILT=&NILT1;
        sdata.dlambdaISFILT=&NILT2;
#endif
        
#ifdef ISFRTDPTTfix
        sdata.alpha=alphaGuess;
        sdata.D=DGuess;
        sdata.vbar=vbar;
        sdata.sigma=sigma;
        
        sdata.vbsigma2=vbsigma2;
        sdata.logfactor=logfactor;
        sdata.vb2sigma2=vb2sigma2;
        sdata.cpsiz1=cpsiz1;
        sdata.vb2sigma3=vb2sigma3;
        sdata.ISFILT=&NILT1;
        sdata.dlambdaISFILT=&NILT2;
        sdata.dTTISFILT=&NILT3;
#endif
        
        //API
        fitfun.f=&ISFfun;
#ifdef NoJacobian
        fitfun.df=0;
        fitfun.fdf=0;
#else
        fitfun.df=&dISFfun;
        fitfun.fdf=&fdISFfun;
#endif
        fitfun.n=ctnum_fit;
        fitfun.p=cnumOfPara;
        fitfun.params=&sdata;
        
        //Initialization of the parameters
        double* localinipara=new double[cnumOfPara];
        for (int iterp=0; iterp<numOfPara; ++iterp)
        {
            localinipara[iterp]=inipara[iterp];
        }
        //Estimation of A(q) and B(q)
        for (int iterqc=0; iterqc<num_qCurve; ++iterqc)
        {
            localinipara[numOfPara+1+2*iterqc] = gsl_matrix_get(datag, iterq+qIncreList[iterqc], 0);
            localinipara[numOfPara+2*iterqc] = gsl_matrix_get(datag, iterq+qIncreList[iterqc], num_fit-1)-localinipara[numOfPara+1+2*iterqc];
        }
        //Initiallization of the solver
        gsl_vector_view para=gsl_vector_view_array(localinipara, cnumOfPara);
        gsl_multifit_fdfsolver* solver = gsl_multifit_fdfsolver_alloc(solverType, ctnum_fit, cnumOfPara);
        gsl_multifit_fdfsolver_set(solver, &fitfun, &para.vector);
        int iter=0;
        //gsl_vector* g=gsl_vector_alloc(numOfPara);
        
        //For debugging and monitering the iterations
//        cout << qList[0] << ' ' << qList[1] << '\n';
//        for (int iterpara=0; iterpara<cnumOfPara; ++iterpara)
//        {
//            cout << gsl_vector_get(solver->x, iterpara) << '\n';
//        }
//        cout << '\n';
        
        int cstatus=GSL_CONTINUE;   //Current status
        do
        {
            gsl_multifit_fdfsolver_iterate(solver);		//Iterate one step.
            cstatus = norm0_rel_test(solver->dx, solver->x, 1e-7, 1e-7);  //Test the exiting criteria
            
            //For debugging and monitering the iterations
//            for (int iterpara=0; iterpara<cnumOfPara; ++iterpara)
//            {
//                cout << gsl_vector_get(solver->x, iterpara) << '\n';
//            }
//            cout << '\n';
            
            //If to use other exiting criteria
            //gsl_multifit_gradient(solver->J,solver->f, g);
            //status[iterq-1]=gsl_multifit_test_gradient(g, 1e-5);
            //			status[iterq - 1] = covar_rel_test(solver->J, solver->x, 1e-4);
            
            ++iter;
            //Number of iterations exceed certain limitation
            if (iter>maxIter)
            {
                cstatus=GSL_EMAXITER;
            }
        } while (cstatus == GSL_CONTINUE);
        status[iterq]=cstatus;
        //gsl_vector_free(g);
        
        //Estimating the error.
        gsl_matrix* covar=gsl_matrix_alloc(cnumOfPara, cnumOfPara);
        gsl_multifit_covar(solver->J, 0.0, covar);
        for (int iterpara=0; iterpara<cnumOfPara; ++iterpara)	//Record result.
        {
            gsl_matrix_set(fittedPara, iterq, iterpara, gsl_vector_get(solver->x, iterpara) );
            gsl_matrix_set(fitErr, iterq, iterpara, sqrt(gsl_matrix_get(covar, iterpara, iterpara)) );    //Not presice in log scale
        }
        gsl_matrix_free(covar);
        gsl_multifit_fdfsolver_free(solver);
        
        //Output to standard I/O
        progress+=1;
        cout << "Fitted q=" << qabs[iterq] << " at iter=" << iter << ", " << 100.0*progress / qsize << "% completed from thread No." << omp_get_thread_num() << ", "<< gsl_strerror(status[iterq]) << "." << '\n';
        for (int iterpara=0; iterpara<cnumOfPara; ++iterpara)
        {
            cout << gsl_matrix_get(fittedPara, iterq, iterpara) << '\n';
        }
        cout << '\n';
        delete [] datafit;
        delete [] qList;
        delete [] localinipara;
        delete [] time;
    }
}
Beispiel #27
0
double psi(double x) { return gsl_sf_psi(x); }
//------------------------------------------------------------------------------
/// Digamma function \f$ \psi^{(0)}(x) \f$
inline double psi0(const double x)
{
   return gsl_sf_psi(x);
}
Beispiel #29
0
int main()
{
   typedef double T;
#define SC_(x) static_cast<double>(x)
#  include "digamma_data.ipp"
#  include "digamma_root_data.ipp"
#  include "digamma_small_data.ipp"
#  include "digamma_neg_data.ipp"
    static const boost::array<boost::array<T, 2>, 5> digamma_bugs = {{
       // Test cases from Rocco Romeo:
        {{ static_cast<T>(std::ldexp(1.0, -100)), SC_(-1.26765060022822940149670320537657721566490153286060651209008e30) }},
        {{ static_cast<T>(-std::ldexp(1.0, -100)), SC_(1.26765060022822940149670320537542278433509846713939348790992e30) }},
        {{ static_cast<T>(1), SC_(-0.577215664901532860606512090082402431042159335939923598805767) }},
        {{ static_cast<T>(-1) + static_cast<T>(std::ldexp(1.0, -20)), SC_(-1.04857557721314249602848739817764518743062133735858753112190e6) }},
        {{ static_cast<T>(-1) - static_cast<T>(std::ldexp(1.0, -20)), SC_(1.04857642278181269259522681939281063878220298942888100442172e6) }},
    }};
   static const boost::array<boost::array<T, 2>, 40> digamma_integers = { {
      { 1, SC_(-0.57721566490153286060651209008240243) }, { 2, SC_(0.42278433509846713939348790991759757) }, { 3, SC_(0.92278433509846713939348790991759757) }, { 4, SC_(1.2561176684318004727268212432509309) }, { 5, SC_(1.5061176684318004727268212432509309) }, { 6, SC_(1.7061176684318004727268212432509309) }, { 7, SC_(1.8727843350984671393934879099175976) }, { 8, SC_(2.0156414779556099965363450527747404) }, { 9, SC_(2.1406414779556099965363450527747404) }, { SC_(10.0), SC_(2.2517525890667211076474561638858515) }, { SC_(11.0), SC_(2.3517525890667211076474561638858515) }, { SC_(12.0), SC_(2.4426616799758120167383652547949424) }, { SC_(13.0), SC_(2.5259950133091453500716985881282758) }, { SC_(14.0), SC_(2.6029180902322222731486216650513527) }, { SC_(15.0), SC_(2.6743466616607937017200502364799241) }, { SC_(16.0), SC_(2.7410133283274603683867169031465908) }, { SC_(17.0), SC_(2.8035133283274603683867169031465908) }, { SC_(18.0), SC_(2.8623368577392250742690698443230614) }, { SC_(19.0), SC_(2.9178924132947806298246253998786169) }, { SC_(20.0), SC_(2.9705239922421490508772569788259854) }, { SC_(21.0), SC_(3.0205239922421490508772569788259854) }, { SC_(22.0), SC_(3.0681430398611966699248760264450330) }, { SC_(23.0), SC_(3.1135975853157421244703305718995784) }, { SC_(24.0), SC_(3.1570758461853073418616349197256654) }, { SC_(25.0), SC_(3.1987425128519740085283015863923321) }, { SC_(26.0), SC_(3.2387425128519740085283015863923321) }, { SC_(27.0), SC_(3.2772040513135124700667631248538705) }, { SC_(28.0), SC_(3.3142410883505495071038001618909076) }, { SC_(29.0), SC_(3.3499553740648352213895144476051933) }, { SC_(30.0), SC_(3.3844381326855248765619282407086415) }, { SC_(31.0), SC_(3.4177714660188582098952615740419749) }, { SC_(32.0), SC_(3.4500295305349872421533260901710071) }, { SC_(33.0), SC_(3.4812795305349872421533260901710071) }, { SC_(34.0), SC_(3.5115825608380175451836291204740374) }, { SC_(35.0), SC_(3.5409943255438998981248055910622727) }, { SC_(36.0), SC_(3.5695657541153284695533770196337013) }, { SC_(37.0), SC_(3.5973435318931062473311547974114791) }, { SC_(38.0), SC_(3.6243705589201332743581818244385061) }, { SC_(39.0), SC_(3.6506863483938174848844976139121903) }, { SC_(40.0), SC_(3.6763273740348431259101386395532160) }
   } };
   static const boost::array<boost::array<T, 2>, 41> digamma_half_integers = { {
      { SC_(0.5), SC_(-1.9635100260214234794409763329987556) }, { SC_(1.5), SC_(0.036489973978576520559023667001244433) }, { SC_(2.5), SC_(0.70315664064524318722569033366791110) }, { SC_(3.5), SC_(1.1031566406452431872256903336679111) }, { SC_(4.5), SC_(1.3888709263595289015114046193821968) }, { SC_(5.5), SC_(1.6110931485817511237336268416044190) }, { SC_(6.5), SC_(1.7929113303999329419154450234226009) }, { SC_(7.5), SC_(1.9467574842460867880692911772687547) }, { SC_(8.5), SC_(2.0800908175794201214026245106020880) }, { SC_(9.5), SC_(2.1977378764029495331673303929550292) }, { SC_(10.5), SC_(2.3030010342976863752725935508497661) }, { SC_(11.5), SC_(2.3982391295357816133678316460878613) }, { SC_(12.5), SC_(2.4851956512749120481504403417400352) }, { SC_(13.5), SC_(2.5651956512749120481504403417400352) }, { SC_(14.5), SC_(2.6392697253489861222245144158141093) }, { SC_(15.5), SC_(2.7082352425903654325693420020210058) }, { SC_(16.5), SC_(2.7727513716226234970854710342790703) }, { SC_(17.5), SC_(2.8333574322286841031460770948851310) }, { SC_(18.5), SC_(2.8905002893715412460032199520279881) }, { SC_(19.5), SC_(2.9445543434255953000572740060820421) }, { SC_(20.5), SC_(2.9958363947076465821085560573640934) }, { SC_(21.5), SC_(3.0446168825125246308890438622421422) }, { SC_(22.5), SC_(3.0911285104195013750750903738700492) }, { SC_(23.5), SC_(3.1355729548639458195195348183144936) }, { SC_(24.5), SC_(3.1781261463533075216471943927825787) }, { SC_(25.5), SC_(3.2189424728839197665451535764560481) }, { SC_(26.5), SC_(3.2581581591584295704667222039070285) }, { SC_(27.5), SC_(3.2958940082150333440516278642843870) }, { SC_(28.5), SC_(3.3322576445786697076879915006480234) }, { SC_(29.5), SC_(3.3673453638769153217230792199462690) }, { SC_(30.5), SC_(3.4012436689616610844349436267259300) }, { SC_(31.5), SC_(3.4340305542075627237792059218078972) }, { SC_(32.5), SC_(3.4657765859535944698109519535539290) }, { SC_(33.5), SC_(3.4965458167228252390417211843231597) }, { SC_(34.5), SC_(3.5263965629914819554596316320843538) }, { SC_(35.5), SC_(3.5553820702378587670538345306350784) }, { SC_(36.5), SC_(3.5835510843223658093073556573956418) }, { SC_(37.5), SC_(3.6109483445963384120470816847929021) }, { SC_(38.5), SC_(3.6376150112630050787137483514595687) }, { SC_(39.5), SC_(3.6635890372370310527397223774335947) }, { SC_(40.5), SC_(3.6889054929332335843852919976867593) }
   } };

   add_data(digamma_data);
   add_data(digamma_root_data);
   add_data(digamma_small_data);
   add_data(digamma_neg_data);
   add_data(digamma_bugs);
   add_data(digamma_integers);
   add_data(digamma_half_integers);

   unsigned data_total = data.size();

   screen_data([](const std::vector<double>& v){  return boost::math::digamma(v[0]);  }, [](const std::vector<double>& v){ return v[1];  });


#if defined(TEST_GSL) && !defined(COMPILER_COMPARISON_TABLES)
   screen_data([](const std::vector<double>& v){  return gsl_sf_psi(v[0]);  }, [](const std::vector<double>& v){ return v[1];  });
#endif
#if defined(TEST_RMATH) && !defined(COMPILER_COMPARISON_TABLES)
   screen_data([](const std::vector<double>& v){  return ::digamma(v[0]);  }, [](const std::vector<double>& v){ return v[1];  });
#endif

   unsigned data_used = data.size();
   std::string function = "digamma[br](" + boost::lexical_cast<std::string>(data_used) + "/" + boost::lexical_cast<std::string>(data_total) + " tests selected)";
   std::string function_short = "digamma";

   double time = exec_timed_test([](const std::vector<double>& v){  return boost::math::digamma(v[0]);  });
   std::cout << time << std::endl;
#if !defined(COMPILER_COMPARISON_TABLES) && (defined(TEST_GSL) || defined(TEST_RMATH))
   report_execution_time(time, std::string("Library Comparison with ") + std::string(compiler_name()) + std::string(" on ") + platform_name(), function, boost_name());
#endif
   report_execution_time(time, std::string("Compiler Comparison on ") + std::string(platform_name()), function_short, compiler_name() + std::string("[br]") + boost_name());
   //
   // Boost again, but with promotion to long double turned off:
   //
#if !defined(COMPILER_COMPARISON_TABLES)
   if(sizeof(long double) != sizeof(double))
   {
      double time = exec_timed_test([](const std::vector<double>& v){  return boost::math::digamma(v[0], boost::math::policies::make_policy(boost::math::policies::promote_double<false>()));  });
      std::cout << time << std::endl;
#if !defined(COMPILER_COMPARISON_TABLES) && (defined(TEST_GSL) || defined(TEST_RMATH))
      report_execution_time(time, std::string("Library Comparison with ") + std::string(compiler_name()) + std::string(" on ") + platform_name(), function, boost_name() + "[br]promote_double<false>");
#endif
      report_execution_time(time, std::string("Compiler Comparison on ") + std::string(platform_name()), function_short, compiler_name() + std::string("[br]") + boost_name() + "[br]promote_double<false>");
   }
#endif


#if defined(TEST_GSL) && !defined(COMPILER_COMPARISON_TABLES)
   time = exec_timed_test([](const std::vector<double>& v){  return gsl_sf_psi(v[0]);  });
   std::cout << time << std::endl;
   report_execution_time(time, std::string("Library Comparison with ") + std::string(compiler_name()) + std::string(" on ") + platform_name(), function, "GSL " GSL_VERSION);
#endif
#if defined(TEST_RMATH) && !defined(COMPILER_COMPARISON_TABLES)
   time = exec_timed_test([](const std::vector<double>& v){  return ::digamma(v[0]);  });
   std::cout << time << std::endl;
   report_execution_time(time, std::string("Library Comparison with ") + std::string(compiler_name()) + std::string(" on ") + platform_name(), function, "Rmath "  R_VERSION_STRING);
#endif

   return 0;
}
void update_phi_fixed(int doc_number, int time,
		      lda_post* p, lda_seq* var,
		      gsl_matrix* g3_matrix,
		      gsl_matrix* g4_matrix,
		      gsl_matrix* g5_matrix) {
    // Hate to do this, but I had problems allocating this data
    // structure.
    if (scaled_influence == NULL) {
      scaled_influence = NewScaledInfluence(FLAGS_max_number_time_points);
    }

    int i, k, n, K = p->model->ntopics, N = p->doc->nterms;
    double dig[p->model->ntopics];

    double k_sum = 0.0;
    for (k = 0; k < K; k++) {
        double gamma_k = vget(p->gamma, k);
        dig[k] = gsl_sf_psi(gamma_k);
	k_sum += gamma_k;
    }
    double dig_sum = gsl_sf_psi(k_sum);

    gsl_vector_view document_weights;
    if (var && var->influence) {
      document_weights = gsl_matrix_row(
      var->influence->doc_weights[time], doc_number);
    }

    for (n=0; n < N; ++n) {
      int w = p->doc->word[n];
      // We have info. about the topics. Use them!
      // Try two alternate approaches.  We compare results of the new
      // algorithm with the old to make sure we're not doing anything
      // silly.

      for (k = 0; k < K; ++k) {
	// Find an estimate for log_phi_nk.
	double doc_weight = 0.0;
	sslm_var* topic = var->topic[k];
	const double chain_variance = topic->chain_variance;

	// These matrices are already set up for the correct time.
	double g3 = mget(g3_matrix, w, k);
	double g4 = mget(g4_matrix, w, k);
	double g5 = mget(g5_matrix, w, k);
	double w_phi_sum = gsl_matrix_get(
	    var->topic[k]->w_phi_sum, w, time);

	// Only set these variables if we are within the correct
	// time window.
	if (time < var->nseq) {
	  doc_weight = gsl_vector_get(&document_weights.vector, k);
	}
	
	double term_weight;
	if (FLAGS_normalize_docs == "normalize") {
	  term_weight = ((double) p->doc->count[n]
			 / (double) p->doc->total);
	} else if (FLAGS_normalize_docs == "log") {
	  term_weight = log(p->doc->count[n] + 1.0);
	} else if (FLAGS_normalize_docs == "log_norm") {
	  term_weight = log(p->doc->count[n] / p->doc->total);
	} else if (FLAGS_normalize_docs == "identity") {
	  term_weight = p->doc->count[n];
	} else if (FLAGS_normalize_docs == "occurrence") {
	  term_weight = ((double) p->doc->count[n]
			 / (double) p->doc->total);
	} else {
	  assert(0);
	}

	assert(var != NULL);
	
	double total, term1, term2, term3, term4;
	double phi_last = 0.0;

	// It's unnecessary to always multiply by 1/chain_variance
	// this deep in a loop, but it's likely not a major
	// bottleneck.
	term1 = dig[k] + mget(p->model->topics, w, k);
	term2 = (g3
		 * term_weight
		 * doc_weight
		 / chain_variance);
	term3 = (term_weight
		 * doc_weight
		 * g4
		 / chain_variance);
	term4 = (term_weight * term_weight
		 * (phi_last * (doc_weight * doc_weight)
		    - (doc_weight * doc_weight
		       + FLAGS_sigma_l * FLAGS_sigma_l))
		 * g5
		 / chain_variance);

	// Note: we're ignoring term3.  sgerrish: 18 July 2010:
	// Changing term2 to have a positive coefficient (instead of
	// negative) to be consistent with parallel version.
	// sgerrish: 23 July 2010: changing term2 back to negative,
	// to try to reproduce earlier results.
	total = term1 - term2 - term3 + term4;
	mset(p->log_phi, n, k, total);
      }
      
      // Normalize in log space.
      gsl_vector log_phi_row = gsl_matrix_row(p->log_phi, n).vector;
      gsl_vector phi_row = gsl_matrix_row(p->phi, n).vector;
      log_normalize(&log_phi_row);
      
      for (i = 0; i < K; i++) {
	vset(&phi_row, i, exp(vget(&log_phi_row, i)));
      }
    }
}