void slice_sample_branch_length(owned_ptr<Probability_Model>& P,MoveStats& Stats,int b)
{
  Parameters& PP = *P.as<Parameters>();
  PP.select_root(b);
  
  const double L = PP.T->directed_branch(b).length();
  const double mu = PP.branch_mean();


  MCMC::Result result(3);
  
  //------------- Find new length --------------//
  
  double sigma = loadvalue(P->keys,"slice_branch_sigma",1.5);
  // NOTE - it is OK to depend on L below -- IF AND ONLY IF the likelihood is unimodal.
  double w = sigma*(PP.branch_mean()+L);
  branch_length_slice_function logp(PP,b);
  double L2 = slice_sample(L,logp,w,100);

  //---------- Record Statistics - -------------//
  result.totals[0] = std::abs(L2 - L);
  result.totals[1] = std::abs(log(L2/L));
  result.totals[2] = logp.count;

  Stats.inc("branch-length (slice) *",result);
  if (L < mu/2.0)
    Stats.inc("branch-length (slice) 1",result);
  else if (L < mu)
    Stats.inc("branch-length (slice) 2",result);
  else if (L < mu*2)
    Stats.inc("branch-length (slice) 3",result);
  else 
    Stats.inc("branch-length (slice) 4",result);
}
void slide_node(owned_ptr<Probability_Model>& P, MoveStats& Stats,int b0)
{
  Parameters* PP = P.as<Parameters>();

  vector<const_branchview> b;
  b.push_back( PP->T->directed_branch(b0) );

  // choose branches to alter
  if (uniform() < 0.5)
    b[0] = b[0].reverse();
  if (b[0].target().is_leaf_node())
    b[0] = b[0].reverse();
  append(b[0].branches_after(),b);

  b0 = b[0].name();
  int b1 = b[1].undirected_name();
  int b2 = b[2].undirected_name();
  double L1a = PP->T->branch(b1).length();
  double L2a = PP->T->branch(b2).length();

  PP->set_root(b[0].target());

  double p = loadvalue(P->keys,"branch_slice_fraction",0.9);
  if (uniform() < p)
  {
    slide_node_slice_function logp(*PP,b0);
    double w = logp.total * loadvalue(P->keys,"slide_branch_slice_window",0.3);
    double L1b = slice_sample(logp,w,100);
    
    MCMC::Result result(2);
    result.totals[0] = 2.0*std::abs(L1b-L1a);
    result.totals[1] = logp.count;
    Stats.inc("slide_node_slice",result);
  }
  else {
    bool success; string name;
    if (uniform() < 0.5) {
      success = slide_node(P, b, slide_node_no_expand_branch);
      name = "slide_node";
    }
    else {
      success = slide_node(P, b, slide_node_expand_branch);
      name = "slide_node_expand_branch";
    }
    PP = P.as<Parameters>();
    double L1b = PP->T->branch(b1).length();
    double L2b = PP->T->branch(b2).length();

    MCMC::Result result(2);
    result.totals[0] = success?1:0;
    result.totals[1] = std::abs(L1b-L1a) + std::abs(L2b-L2a);
    Stats.inc(name,result);
  }
}
Beispiel #3
0
void SPR_inc(MoveStats& Stats, MCMC::Result result,const string& name,double L)
{
  Stats.inc(name, result);

  if (L < 0.5)
    Stats.inc(name+"-0.5", result);
  else if (L < 1)
    Stats.inc(name+"-1.0", result);
  else if (L < 2.0)
    Stats.inc(name+"-2.0", result);
  else 
    Stats.inc(name+"-2.0+", result);
}
Beispiel #4
0
void sample_tri_branch_one(Parameters& P, MoveStats& Stats,int b) 
{
  if (not P.smodel_full_tree and b>=P.T->n_leaves())
    return;

  MCMC::Result result(2);

  assert(P.n_imodels() > 0); 

  const SequenceTree& T = *P.T;

  int node1 = T.branch(b).target();
  int node2 = T.branch(b).source();

  if (myrandomf() < 0.5)
    std::swap(node1,node2);

  if (node1 < T.n_leaves())
    std::swap(node1,node2);
    
  const double sigma = 0.3/2;
  double length1 = T.branch(b).length();
  double length2 = length1 + gaussian(0,sigma);
  if (length2 < 0) length2 = -length2;

  if (tri_sample_alignment_branch(P,node1,node2,b,1,length2)) {
    result.totals[0] = 1;
    result.totals[1] = std::abs(length2 - length1);
  }

  Stats.inc("sample_tri_branch",result);
}
Beispiel #5
0
void sample_tri_branch_type_one(Parameters& P, MoveStats& Stats,int b) 
{
  if (not P.smodel_full_tree and b>=P.T->n_leaves())
    return;

  MCMC::Result result(1);

  assert(P.n_imodels() > 0); 

  const SequenceTree& T = *P.T;

  int node1 = T.branch(b).target();
  int node2 = T.branch(b).source();

  if (myrandomf() < 0.5)
    std::swap(node1,node2);

  if (node1 < T.n_leaves())
    std::swap(node1,node2);
    
  if (tri_sample_alignment_branch_model(P,node1,node2)) {
    result.totals[0] = 1;
  }

  Stats.inc("sample_tri_branch_type",result);
}
void change_branch_length_flat(owned_ptr<Probability_Model>& P,
			       MoveStats& Stats,int b,double sigma)
{
  Parameters& PP = *P.as<Parameters>();

  const double L = PP.T->directed_branch(b).length();
  const double mu = PP.branch_mean();

  MCMC::Result result = change_branch_length_(P, b, sigma*PP.branch_mean(), branch_twiddle_positive);

  Stats.inc("branch-length *",result);
  if (L < mu/2.0)
    Stats.inc("branch-length 1",result);
  else if (L < mu)
    Stats.inc("branch-length 2",result);
  else if (L < mu*2)
    Stats.inc("branch-length 3",result);
  else 
    Stats.inc("branch-length 4",result);
}
void change_branch_length_log_scale(owned_ptr<Probability_Model>& P,
				    MoveStats& Stats,
				    int b,
				    double sigma)
{
  const double L = P.as<Parameters>()->T->directed_branch(b).length();
  const double mu = P.as<Parameters>()->branch_mean();

  MCMC::Result result = change_branch_length_(P, b, sigma, scale_gaussian );

  Stats.inc("branch-length (log) *",result);
  if (L < mu/2.0)
    Stats.inc("branch-length (log) 1",result);
  else if (L < mu)
    Stats.inc("branch-length (log) 2",result);
  else if (L < mu*2)
    Stats.inc("branch-length (log) 3",result);
  else 
    Stats.inc("branch-length (log) 4",result);
}
void sample_SPR_nodes(Parameters& P,MoveStats& Stats)
{
    double f = loadvalue(P.keys,"SPR_amount",0.1);
    int n = poisson(P.T->n_branches()*f);

    double p = loadvalue(P.keys,"SPR_slice_fraction",-0.25);

    for(int i=0; i<n; i++) {

        int b1=-1, b2=-1;
        choose_subtree_branch_nodes(*P.T, b1, b2);

        if (P.n_imodels() == 0 and uniform()< p) {
            MCMC::Result result = sample_SPR(P,b1,b2,true);
            Stats.inc("SPR (path/slice)", result);
        }
        else {
            MCMC::Result result = sample_SPR(P,b1,b2);
            Stats.inc("SPR (path)", result);
        }
    }
}
Beispiel #9
0
    void Parameter_Slice_Move::iterate(owned_ptr<Model>& P,MoveStats& Stats,int)
    {
	double v1 = P->get_parameter_value(index).as_double();

	parameter_slice_function logp(*P,index,transform,inverse);

	double v2 = sample(*P,logp,v1);

	//---------- Record Statistics - -------------//
	Result result(2);
	result.totals[0] = std::abs(v2-v1);
	result.totals[1] = logp.count;
    
	Stats.inc(name,result);
    }
Beispiel #10
0
/// Update statistics counters for an NNI move.
void NNI_inc(MoveStats& Stats, const string& name, MCMC::Result result,double L)
{
  Stats.inc(name, result);

  if (L < 0.0325)
    Stats.inc(name+"-0.0325", result);
  else if (L < 0.065)
    Stats.inc(name+"-0.065", result);
  else if (L < 0.125)
    Stats.inc(name+"-0.125", result);
  else if (L < 0.25)
    Stats.inc(name+"-0.25", result);
  else if (L < 0.5)
    Stats.inc(name+"-0.5", result);
  else if (L < 1)
    Stats.inc(name+"-1.0", result);
  else if (L < 2.0)
    Stats.inc(name+"-2.0", result);
  else
    Stats.inc(name+"-2.0+", result);
}
Beispiel #11
0
    void Modifiable_Slice_Move::iterate(owned_ptr<Model>& P,MoveStats& Stats,int)
    {
#ifndef NDEBUG
	clog<<" [modifiable slice] move = "<<m_index<<endl;
#endif

	double v1 = P->get_modifiable_value(m_index).as_double();

	modifiable_slice_function logp(*P, m_index, bounds, transform, inverse);

	double v2 = sample(*P,logp,v1);

	//---------- Record Statistics --------------//
	Result result(2);
	result.totals[0] = std::abs(v2-v1);
	result.totals[1] = logp.count;
    
	Stats.inc(name,result);
    }
Beispiel #12
0
    void Dirichlet_Modifiable_Slice_Move::iterate(owned_ptr<Model>& P,MoveStats& Stats,int)
    {
#ifndef NDEBUG
	clog<<" [dirichlet modifiable slice] move"<<endl;
#endif
	double v1 = P->get_modifiable_value(indices[n]).as_double();
	constant_sum_modifiable_slice_function slice_levels_function(*P,indices,n);

	double v2 = sample(*P,slice_levels_function,v1);

	//---------- Record Statistics - -------------//
	Result result(2);
	vector<double> x = vec_to_double(P->get_modifiable_values(indices));
	double total = sum(x);
	double factor = (total - v2)/(total-v1);
	result.totals[0] = std::abs(log(v2/v1)) + (indices.size()-1)*(std::abs(log(factor)));
	result.totals[1] = slice_levels_function.count;

	Stats.inc(name,result);
    }
Beispiel #13
0
    void Scale_Means_Only_Slice_Move::iterate(owned_ptr<Model>& P, MoveStats& Stats,int)
    {
#ifndef NDEBUG
	clog<<" [scale means only slice] move"<<endl;
#endif
	Parameters& PP = *P.as<Parameters>();
	// If any of the branch means are fixed, this won't work.

	double v1 = 0;
	try
	{
	    scale_means_only_slice_function slice_levels_function(PP);

	    double v2 = sample(PP,slice_levels_function, v1);

	    //---------- Record Statistics --------------//
	    Result result(2);
	    result.totals[0] = std::abs(v2);
	    result.totals[1] = slice_levels_function.count;

	    Stats.inc(name,result);
	}
	catch (...) {}
    }
/// Propose three neighboring branch lengths all anti-correlated
void change_3_branch_lengths(owned_ptr<Probability_Model>& P,MoveStats& Stats,int n) 
{
  Parameters* PP = P.as<Parameters>();
  MCMC::Result result(2);

  const Tree& T = *PP->T;
  if (not T[n].is_internal_node()) return;

  //-------------- Find branches ------------------//
  vector<const_branchview> branches;
  append(T[n].branches_out(),branches);
  int b1 = branches[0].undirected_name();
  int b2 = branches[1].undirected_name();
  int b3 = branches[2].undirected_name();

  //------------ Change coordinates ---------------//
  double T1 = T.branch(b1).length();
  double T2 = T.branch(b2).length();
  double T3 = T.branch(b3).length();

  double S12 = T1 + T2;
  double S23 = T2 + T3;
  double S31 = T3 + T1;

  //----------- Propose new distances -------------//
  double sigma = loadvalue(P->keys,"log_branch_sigma",0.6)/2.0;
  double ratio = 1.0;

  double T1_ = T1;
  double T2_ = T2;
  double T3_ = T3;

  for(int i=0;i<20;i++) 
  {
    double R12 = exp(gaussian(0,sigma));
    double R23 = exp(gaussian(0,sigma));
    double R31 = exp(gaussian(0,sigma));

    double S12_ = S12 * R12;
    double S23_ = S23 * R23;
    double S31_ = S31 * R31;

    //---------------- Change back ------------------//
    T1_ = (S12_ + S31_ - S23_)/2.0;
    T2_ = (S12_ + S23_ - S31_)/2.0;
    T3_ = (S23_ + S31_ - S12_)/2.0;

    ratio = R12 * R23 * R31;

    if (T1_ > 0.0 and T2_ > 0.0 and T3_ > 0.0) break;
  }
  if (T1_ <= 0.0 or T2_ <= 0.0 or T3_ <= 0.0) return;

  //----------- Construct proposed Tree -----------//
  PP->set_root(n);
  
  owned_ptr<Probability_Model> P2 = P;
  P2.as<Parameters>()->setlength(b1,T1_);
  P2.as<Parameters>()->setlength(b2,T2_);
  P2.as<Parameters>()->setlength(b3,T3_);
  
  //--------- Do the M-H step if OK--------------//
  if (do_MH_move(P,P2,ratio)) {
    result.totals[0] = 1;
    result.totals[1] = abs(T1_-T1) + abs(T2_-T2) + abs(T3_-T3);
  }

  Stats.inc("3-branch-lengths",result);
}
void scale_means_only(owned_ptr<Probability_Model>& P,MoveStats& Stats)
{
  Parameters* PP = P.as<Parameters>();
  // If any of the partition rates are fixed, then we're out of luck
  // FIXME - techincally, we could recompute likelihoods in just THOSE partitions :P
  //       - also, I suppose, if they are fixed, then there is no mixing problem.
  for(int i=0;i<PP->n_branch_means();i++)
    if (PP->is_fixed(PP->branch_mean_index(i)))
      return;

  MCMC::Result result(2);

  //------------ Propose scaling ratio ------------//
  const double sigma = loadvalue(P->keys,"log_branch_mean_sigma",0.6);

  Bounds<double> b;
  for(int i=0; i<PP->n_branch_means(); i++)
  {
    Bounds<double> b2 = PP->get_bounds(PP->branch_mean_index(i));
    double mu = PP->get_parameter_value_as<Double>(PP->branch_mean_index(i));

    if (b2.has_lower_bound and b2.lower_bound > 0)
    {
      b2.has_lower_bound = true;
      b2.lower_bound = log(b2.lower_bound) - log(mu);
    }
    else
      b2.has_lower_bound = false;

    if (b2.has_upper_bound)
      b2.upper_bound = log(b2.upper_bound) - log(mu);

    b = b and b2;
  }

  double scale = gaussian(0,sigma);
  scale = wrap(scale, b);
  scale = exp(scale);

  //-------- Change branch lengths and mean -------//
  owned_ptr<Parameters> P2 = PP;

#ifndef NDEBUG
  {
    owned_ptr<Parameters> P3 = P2;
    check_caching(*PP,*P3);
  }
#endif

  SequenceTree& T2 = *P2->T;
  for(int b=0;b<T2.n_branches();b++) {
    const double length = T2.branch(b).length();
    T2.branch(b).set_length(length/scale);
  }
  P2->tree_propagate();

  for(int i=0;i<PP->n_branch_means();i++) 
    P2->branch_mean_tricky(i, P2->get_parameter_value_as<Double>(P2->branch_mean_index(i)) * scale);
  
#ifndef NDEBUG
  owned_ptr<Parameters> P3 = P2;
  P3->recalc_imodels();
  P3->recalc_smodels();
  efloat_t L1 = PP->likelihood();
  efloat_t L2 = P3->likelihood();
  double diff = std::abs(log(L1)-log(L2));
  if (diff > 1.0e-9) {
    std::cerr<<"scale_mean_only: likelihood diff = "<<diff<<std::endl;
    std::abort();
  }
#endif

  //--------- Compute proposal ratio ---------//
  efloat_t p_ratio = pow(efloat_t(scale),P2->n_data_partitions()-T2.n_branches());
  efloat_t a_ratio = P2->prior_no_alignment()/PP->prior_no_alignment()*p_ratio;

#ifndef NDEBUG
  efloat_t a_ratio2 = P2->probability()/PP->probability()*p_ratio;
  double diff2 = std::abs(log(a_ratio2)-log(a_ratio));
  if (diff2 > 1.0e-9) {
    std::cerr<<"scale_mean_only: a_ratio diff = "<<diff2<<std::endl;
    std::cerr<<"probability ratio = "<<log(P2->probability()/PP->probability())<<std::endl;
    std::cerr<<"likelihood ratio = "<<log(P2->likelihood()/PP->likelihood())<<std::endl;
    std::cerr<<"prior ratio       = "<<log(P2->prior()/PP->prior())<<std::endl;
    std::cerr<<"prior ratio (no A)= "<<log(P2->prior_no_alignment()/PP->prior_no_alignment())<<std::endl;
    std::cerr<<"prior ratio (   A)= "<<log(P2->prior_alignment()/PP->prior_alignment())<<std::endl;
    std::cerr<<"    a ratio = "<<log(a_ratio)<<std::endl;
    std::abort();
  }
#endif
  
  if (uniform() < double(a_ratio)) 
  {
    P=P2;
    result.totals[0] = 1;
    result.totals[1] = std::abs(log(scale));
  }

  Stats.inc("branch-means-only",result);
}
void change_branch_length_and_T(owned_ptr<Probability_Model>& P,MoveStats& Stats,int b) 
{
  Parameters& PP = *P.as<Parameters>();
  MCMC::Result result(5,0);

  result.counts[0] = 1;

  //------------- Propose new length --------------//
  const double length = PP.T->directed_branch(b).length();
  double newlength = length;
  double ratio = branch_twiddle(newlength,PP.branch_mean()*0.6);

  //----- positive  =>  propose length change -----//
  if (newlength >= 0) 
  {
    result.counts[1] = 1;
    result.counts[3] = 1;

    //---------- Construct proposed Tree ----------//
    PP.select_root(b);

    owned_ptr<Probability_Model> P2 = P;

    P2.as<Parameters>()->setlength(b,newlength);

    //--------- Do the M-H step if OK--------------//
    if (do_MH_move(P,P2,ratio)) {
      result.totals[0] = 1;
      result.totals[1] = 1;
      result.totals[3] = std::abs(newlength - length);
    }
  }

  //----- negative  => propose topology ---------//
  else 
  {
    result.counts[2] = 1;
    result.counts[4] = 1;

    //----- Generate the Different Topologies ------//
    vector<Parameters> p(2,PP);
    
    SequenceTree& T2 = *p[1].T;
    
    vector<int> nodes = A5::get_nodes_random(T2,b);
    int b1 = T2.directed_branch(nodes[4],nodes[1]);
    int b2 = T2.directed_branch(nodes[5],nodes[2]);
    exchange_subtrees(T2,b1,b2);

    p[1].invalidate_subA_index_branch(b);

    vector<efloat_t> rho(2,1);
    rho[1] = ratio;

    //------ Sample the Different Topologies ------//
    int C = two_way_topology_sample(p,rho,b);

    if (C != -1) {
      PP = p[C];
    }

    if (C > 0) {
      result.totals[0] = 1;
      result.totals[2] = 1;
      result.totals[4] = std::abs(length - newlength);
    }
  }

  Stats.inc("change_branch_length_and_T",result);
}
Beispiel #17
0
    void MH_Move::iterate(owned_ptr<Model>& P,MoveStats& Stats,int) 
    {
#ifndef NDEBUG
	clog<<" [MH] move = "<<name<<endl;
#endif

	iterations++;

	owned_ptr<Model> P2 = P;

	double ratio = 1;
	try {
	    ratio = (*proposal)(*P2);
	}
	catch (myexception& e)
	{
	    std::ostringstream o;
	    o<<" [MH] move = "<<name<<"  (during proposal)\n";
	    e.prepend(o.str());
	    throw e;
	}
    

	int n = 1;
	Proposal2* p2 = dynamic_cast<Proposal2*>(&(*proposal));
	int n_indices = -1;
	if (p2) {
	    n_indices = p2->get_indices().size();
	    n = 2;
	}
	Result result(n);

#ifndef NDEBUG
	show_parameters(std::cerr,*P);
	std::cerr<<P->probability()<<" = "<<P->likelihood()<<" + "<<P->prior()<<endl;
	std::cerr<<endl;

	show_parameters(std::cerr,*P2);
	std::cerr<<P2->probability()<<" = "<<P2->likelihood()<<" + "<<P2->prior();
	std::cerr<<endl<<endl;
#endif

#ifndef NDEBUG
	// Check that we have not strayed outside the bounds.
	for(int i=0;i<P->n_parameters();i++)
	{
	    if (not P->parameter_is_modifiable(i)) continue;

	    if (not P->get_parameter_value(i).is_double()) continue;

	    if (not P->has_bounds(i)) continue;
	
	    Bounds<double> range = P->get_bounds(i);
	    if (not range.in_range(P->get_parameter_value(i).as_double()))
		throw myexception()<<"Parameter "<<P->parameter_name(i)<<" = "<<P->get_parameter_value(i).as_double()<<" is NOT in range "<<range;
	    if (not range.in_range(P2->get_parameter_value(i).as_double()))
		throw myexception()<<"Parameter "<<P->parameter_name(i)<<" = "<<P->get_parameter_value(i).as_double()<<" is NOT in range "<<range;
	}
#endif

	// Accept or Reject
	if (accept_MH(*P,*P2,ratio)) {
	    result.totals[0] = 1;
	    if (n == 2) {
		int first_index = p2->get_indices()[0];
		if (n_indices == 1 and P->get_parameter_value(first_index).is_double()) 
		{
		    double v1 = P->get_parameter_value(first_index).as_double();
		    double v2 = P2->get_parameter_value(first_index).as_double();
		    //      cerr<<"v1 = "<<v1<<"   v2 = "<<v2<<"\n";
		    result.totals[1] = std::abs(v2-v1);
		}
		else if (n_indices > 1 and P->get_parameter_value(first_index).is_double()) //currently this can only be a dirichlet proposal
		{
		    double total = 0;
		    for(int i=0;i<n_indices;i++) 
		    {
			int j = p2->get_indices()[i];
			double v1 = P->get_parameter_value(j).as_double();
			double v2 = P2->get_parameter_value(j).as_double();
			total += std::abs(log(v1/v2));
		    }
		    result.totals[1] = total;
		}
	    }
	    P = P2;
	}

	Stats.inc(name,result);
    }