void GibbsPruneAndRegraft::findNewBrothers(std::vector<TopologyNode *> &b, TopologyNode &p, TopologyNode *n) { // security check that I'm not a tip if (!n->isTip() && &p != n) { // check the first child TopologyNode* child = &n->getChild( 0 ); if ( child->getAge() < p.getAge() ) { b.push_back( child ); } else { findNewBrothers(b, p, child); } // check the second child child = &n->getChild( 1 ); if ( child->getAge() < p.getAge() ) { b.push_back( child ); } else { findNewBrothers(b, p, child); } } }
void RateAgeACLNMixingMove::rejectCompoundMove( void ) { // undo the proposal TimeTree& tau = tree->getValue(); std::vector<double>& nrates = rates->getValue(); double &rootR = rootRate->getValue(); size_t nn = tau.getNumberOfNodes(); double c = storedC; for(size_t i=0; i<nn; i++){ TopologyNode* node = &tau.getNode(i); if(node->isTip() == false){ double curAge = node->getAge(); double undoAge = curAge / c; tau.setAge( node->getIndex(), undoAge ); } } size_t nr = nrates.size(); rootR = rootR * c; for(size_t i=0; i<nr; i++){ double curRt = nrates[i]; double undoRt = curRt * c; nrates[i] = undoRt; } #ifdef ASSERTIONS_TREE if ( fabs(storedRootAge - tau.getRoot().getAge()) > 1E-8 ) { throw RbException("Error while rejecting RateAgeACLNMixingMove proposal: Node ages were not correctly restored!"); } #endif }
/** * Perform the proposal. * * A Uniform-simplex proposal randomly changes some values of a simplex, although the other values * change too because of the renormalization. * First, some random indices are drawn. Then, the proposal draws a new somplex * u ~ Uniform(val[index] * alpha) * where alpha is the tuning parameter.The new value is set to u. * The simplex is then renormalized. * * \return The hastings ratio. */ double RootTimeSlideUniformProposal::doProposal( void ) { // Get random number generator RandomNumberGenerator* rng = GLOBAL_RNG; Tree& tau = variable->getValue(); // pick a random node which is not the root and neithor the direct descendant of the root TopologyNode* node = &tau.getRoot(); // we need to work with the times double my_age = node->getAge(); double child_Age = node->getChild( 0 ).getAge(); if ( child_Age < node->getChild( 1 ).getAge()) { child_Age = node->getChild( 1 ).getAge(); } // now we store all necessary values storedAge = my_age; // draw new ages and compute the hastings ratio at the same time double my_new_age = (origin->getValue() - child_Age) * rng->uniform01() + child_Age; // set the age node->setAge( my_new_age ); return 0.0; }
/** * Perform the proposal. * * A Beta-simplex proposal randomly changes some values of a simplex, although the other values * change too because of the renormalization. * First, some random indices are drawn. Then, the proposal draws a new somplex * u ~ Beta(val[index] * alpha) * where alpha is the tuning parameter.The new value is set to u. * The simplex is then renormalized. * * \return The hastings ratio. */ double SubtreeScaleProposal::doProposal( void ) { // Get random number generator RandomNumberGenerator* rng = GLOBAL_RNG; TimeTree& tau = variable->getValue(); // pick a random node which is not the root and neither the direct descendant of the root TopologyNode* node; do { double u = rng->uniform01(); size_t index = size_t( std::floor(tau.getNumberOfNodes() * u) ); node = &tau.getNode(index); } while ( node->isRoot() || node->isTip() ); TopologyNode& parent = node->getParent(); // we need to work with the times double parent_age = parent.getAge(); double my_age = node->getAge(); // now we store all necessary values storedNode = node; storedAge = my_age; // lower bound double min_age = 0.0; TreeUtilities::getOldestTip(&tau, node, min_age); // draw new ages and compute the hastings ratio at the same time double my_new_age = min_age + (parent_age - min_age) * rng->uniform01(); double scalingFactor = my_new_age / my_age; size_t nNodes = node->getNumberOfNodesInSubtree(false); // rescale the subtrees TreeUtilities::rescaleSubtree(&tau, node, scalingFactor ); if (min_age != 0.0) { for (size_t i = 0; i < tau.getNumberOfTips(); i++) { if (tau.getNode(i).getAge() < 0.0) { return RbConstants::Double::neginf; } } } // compute the Hastings ratio double lnHastingsratio = (nNodes > 1 ? log( scalingFactor ) * (nNodes-1) : 0.0 ); return lnHastingsratio; }
/** * Compute the diversity of the tree at time t. * * \param[in] t time at which we want to know the diversity. * * \return The diversity (number of species in the reconstructed tree). */ int PiecewiseConstantSerialSampledBirthDeathProcess::survivors(double t) const { const std::vector<TopologyNode*>& nodes = value->getNodes(); int survivors = 0; for (std::vector<TopologyNode*>::const_iterator it = nodes.begin(); it != nodes.end(); ++it) { TopologyNode* n = *it; if ( n->getAge() < t ) { if ( n->isRoot() || n->getParent().getAge() > t ) { survivors++; } } } return survivors; }
/** Perform the move */ double SubtreeScale::performSimpleMove( void ) { // Get random number generator RandomNumberGenerator* rng = GLOBAL_RNG; TimeTree& tau = variable->getValue(); // pick a random node which is not the root and neither the direct descendant of the root TopologyNode* node; do { double u = rng->uniform01(); size_t index = size_t( std::floor(tau.getNumberOfNodes() * u) ); node = &tau.getNode(index); } while ( node->isRoot() || node->isTip() ); TopologyNode& parent = node->getParent(); // we need to work with the times double parent_age = parent.getAge(); double my_age = node->getAge(); // now we store all necessary values storedNode = node; storedAge = my_age; // draw new ages and compute the hastings ratio at the same time double my_new_age = parent_age * rng->uniform01(); double scalingFactor = my_new_age / my_age; size_t nNodes = node->getNumberOfNodesInSubtree(false); // rescale the subtrees TreeUtilities::rescaleSubtree(&tau, node, scalingFactor ); // compute the Hastings ratio double lnHastingsratio = (nNodes > 1 ? log( scalingFactor ) * (nNodes-1) : 0.0 ); return lnHastingsratio; }
/** * Perform the proposal. * * A Uniform-simplex proposal randomly changes some values of a simplex, although the other values * change too because of the renormalization. * First, some random indices are drawn. Then, the proposal draws a new somplex * u ~ Uniform(val[index] * alpha) * where alpha is the tuning parameter.The new value is set to u. * The simplex is then renormalized. * * \return The hastings ratio. */ double NodeTimeSlideUniformProposal::doProposal( void ) { // Get random number generator RandomNumberGenerator* rng = GLOBAL_RNG; Tree& tau = variable->getValue(); // pick a random node which is not the root and neithor the direct descendant of the root TopologyNode* node; do { double u = rng->uniform01(); size_t index = size_t( std::floor(tau.getNumberOfNodes() * u) ); node = &tau.getNode(index); } while ( node->isRoot() || node->isTip() ); TopologyNode& parent = node->getParent(); // we need to work with the times double parent_age = parent.getAge(); double my_age = node->getAge(); double child_Age = node->getChild( 0 ).getAge(); if ( child_Age < node->getChild( 1 ).getAge()) { child_Age = node->getChild( 1 ).getAge(); } // now we store all necessary values storedNode = node; storedAge = my_age; // draw new ages and compute the hastings ratio at the same time double my_new_age = (parent_age-child_Age) * rng->uniform01() + child_Age; // set the age tau.getNode(node->getIndex()).setAge( my_new_age ); return 0.0; }
/** Perform the move */ double RateAgeACLNMixingMove::performCompoundMove( void ) { // Get random number generator RandomNumberGenerator* rng = GLOBAL_RNG; TimeTree& tau = tree->getValue(); std::vector<double>& nrates = rates->getValue(); double &rootR = rootRate->getValue(); size_t nn = tau.getNumberOfNodes(); double u = rng->uniform01(); double c = exp( epsilon * (u - 0.5) ); for(size_t i=0; i<nn; i++){ TopologyNode* node = &tau.getNode(i); if(node->isTip() == false){ double curAge = node->getAge(); double newAge = curAge * c; tau.setAge( node->getIndex(), newAge ); if(node->isRoot()){ storedRootAge = curAge; } } } size_t nr = nrates.size(); rootR = rootR / c; for(size_t i=0; i<nrates.size(); i++){ double curRt = nrates[i]; double newRt = curRt / c; nrates[i] = newRt; } storedC = c; double pr = (((double)nn) - (double)nr) * log(c); return pr; }
std::vector<TopologyNode*> TreeNodeAgeUpdateProposal::getNodesInPopulation( Tree &tau, TopologyNode &n ) { // I need all the oldest nodes/subtrees that have the same tips. // Those nodes need to be scaled too. // get the beginning and ending age of the population double max_age = -1.0; if ( n.isRoot() == false ) { max_age = n.getParent().getAge(); } // get all the taxa from the species tree that are descendants of node i double min_age_left = n.getChild(0).getAge(); std::vector<TopologyNode*> speciesTaxa_left; TreeUtilities::getTaxaInSubtree( &n.getChild(0), speciesTaxa_left ); // get all the individuals std::set<TopologyNode*> individualTaxa_left; for (size_t i = 0; i < speciesTaxa_left.size(); ++i) { const std::string &name = speciesTaxa_left[i]->getName(); std::vector<TopologyNode*> ind = tau.getTipNodesWithSpeciesName( name ); for (size_t j = 0; j < ind.size(); ++j) { individualTaxa_left.insert( ind[j] ); } } // create the set of the nodes within this population std::set<TopologyNode*> nodesInPopulationSet; // now go through all nodes in the gene while ( individualTaxa_left.empty() == false ) { // get the first element std::set<TopologyNode*>::iterator it = individualTaxa_left.begin(); // store the pointer TopologyNode *geneNode = *it; // and now remove the element from the list individualTaxa_left.erase( it ); // add this node to our list of node we need to scale, if: // a) this is the root node // b) this is not the root and the age of the parent node is larger than the parent's age of the species node if ( geneNode->getAge() > min_age_left && geneNode->getAge() < max_age && geneNode->isTip() == false ) { // add this node if it is within the age of our population nodesInPopulationSet.insert( geneNode ); } if ( geneNode->isRoot() == false && ( max_age == -1.0 || max_age > geneNode->getParent().getAge() ) ) { // push the parent to our current list individualTaxa_left.insert( &geneNode->getParent() ); } } // get all the taxa from the species tree that are descendants of node i double min_age_right = n.getChild(1).getAge(); std::vector<TopologyNode*> speciesTaxa_right; TreeUtilities::getTaxaInSubtree( &n.getChild(1), speciesTaxa_right ); // get all the individuals std::set<TopologyNode*> individualTaxa_right; for (size_t i = 0; i < speciesTaxa_right.size(); ++i) { const std::string &name = speciesTaxa_right[i]->getName(); std::vector<TopologyNode*> ind = tau.getTipNodesWithSpeciesName( name ); for (size_t j = 0; j < ind.size(); ++j) { individualTaxa_right.insert( ind[j] ); } } // now go through all nodes in the gene while ( individualTaxa_right.empty() == false ) { // get the first element std::set<TopologyNode*>::iterator it = individualTaxa_right.begin(); // store the pointer TopologyNode *geneNode = *it; // and now remove the element from the list individualTaxa_right.erase( it ); // add this node to our list of node we need to scale, if: // a) this is the root node // b) this is not the root and the age of the parent node is larger than the parent's age of the species node if ( geneNode->getAge() > min_age_right && geneNode->getAge() < max_age && geneNode->isTip() == false ) { // add this node if it is within the age of our population nodesInPopulationSet.insert( geneNode ); } if ( geneNode->isRoot() == false && ( max_age == -1.0 || max_age > geneNode->getParent().getAge() ) ) { // push the parent to our current list individualTaxa_right.insert( &geneNode->getParent() ); } } // convert the set into a vector std::vector<TopologyNode*> nodesInPopulation; for (std::set<TopologyNode*>::iterator it = nodesInPopulationSet.begin(); it != nodesInPopulationSet.end(); ++it) { nodesInPopulation.push_back( *it ); } return nodesInPopulation; }
/** * Perform the proposal. * * \return The hastings ratio. */ double TreeNodeAgeUpdateProposal::doProposal( void ) { // Get random number generator RandomNumberGenerator* rng = GLOBAL_RNG; Tree& tau = speciesTree->getValue(); // pick a random node which is not the root and neither the direct descendant of the root TopologyNode* node; do { double u = rng->uniform01(); size_t index = size_t( std::floor(tau.getNumberOfNodes() * u) ); node = &tau.getNode(index); } while ( node->isRoot() || node->isTip() ); TopologyNode& parent = node->getParent(); // we need to work with the times double parent_age = parent.getAge(); double my_age = node->getAge(); double child_Age = node->getChild( 0 ).getAge(); if ( child_Age < node->getChild( 1 ).getAge()) { child_Age = node->getChild( 1 ).getAge(); } // now we store all necessary values storedNode = node; storedAge = my_age; // draw new ages and compute the hastings ratio at the same time double my_new_age = (parent_age-child_Age) * rng->uniform01() + child_Age; // Sebastian: This is for debugging to test if the proposal's acceptance rate is 1.0 as it should be! // my_new_age = my_age; int upslideNodes = 0; int downslideNodes = 0; for ( size_t i=0; i<geneTrees.size(); ++i ) { // get the i-th gene tree Tree& geneTree = geneTrees[i]->getValue(); std::vector<TopologyNode*> nodes = getNodesInPopulation(geneTree, *node ); for (size_t j=0; j<nodes.size(); ++j) { double a = nodes[j]->getAge(); double new_a = a; if ( a > my_age ) { ++upslideNodes; new_a = parent_age - (parent_age - my_new_age)/(parent_age - my_age) * (parent_age - a); } else { ++downslideNodes; new_a = child_Age + (my_new_age - child_Age)/(my_age - child_Age) * (a - child_Age); } // set the new age of this gene tree node geneTree.getNode( nodes[j]->getIndex() ).setAge( new_a ); } // Sebastian: This is only for debugging. It makes the code slower. Hopefully it is not necessary anymore. // geneTrees[i]->touch( true ); } // Sebastian: We need to work on a mechanism to make these proposal safe for non-ultrametric trees! // if (min_age != 0.0) // { // for (size_t i = 0; i < tau.getNumberOfTips(); i++) // { // if (tau.getNode(i).getAge() < 0.0) // { // return RbConstants::Double::neginf; // } // } // } // set the age of the species tree node tau.getNode( node->getIndex() ).setAge( my_new_age ); // compute the Hastings ratio double lnHastingsratio = upslideNodes * log( (parent_age - my_new_age)/(parent_age - my_age) ) + downslideNodes * log( (my_new_age - child_Age)/(my_age - child_Age) ); return lnHastingsratio; }
/** Perform the move */ void RateAgeBetaShift::performMcmcMove( double lHeat, double pHeat ) { // Get random number generator RandomNumberGenerator* rng = GLOBAL_RNG; Tree& tau = tree->getValue(); RbOrderedSet<DagNode*> affected; tree->getAffectedNodes( affected ); double oldLnLike = 0.0; bool checkLikelihoodShortcuts = rng->uniform01() < 0.001; if ( checkLikelihoodShortcuts == true ) { for (RbOrderedSet<DagNode*>::iterator it = affected.begin(); it != affected.end(); ++it) { (*it)->touch(); oldLnLike += (*it)->getLnProbability(); } } // pick a random node which is not the root and neithor the direct descendant of the root TopologyNode* node; size_t nodeIdx = 0; do { double u = rng->uniform01(); nodeIdx = size_t( std::floor(tau.getNumberOfNodes() * u) ); node = &tau.getNode(nodeIdx); } while ( node->isRoot() || node->isTip() ); TopologyNode& parent = node->getParent(); // we need to work with the times double parent_age = parent.getAge(); double my_age = node->getAge(); double child_Age = node->getChild( 0 ).getAge(); if ( child_Age < node->getChild( 1 ).getAge()) { child_Age = node->getChild( 1 ).getAge(); } // now we store all necessary values storedNode = node; storedAge = my_age; storedRates[nodeIdx] = rates[nodeIdx]->getValue(); for (size_t i = 0; i < node->getNumberOfChildren(); i++) { size_t childIdx = node->getChild(i).getIndex(); storedRates[childIdx] = rates[childIdx]->getValue(); } // draw new ages and compute the hastings ratio at the same time double m = (my_age-child_Age) / (parent_age-child_Age); double a = delta * m + 1.0; double b = delta * (1.0-m) + 1.0; double new_m = RbStatistics::Beta::rv(a, b, *rng); double my_new_age = (parent_age-child_Age) * new_m + child_Age; // compute the Hastings ratio double forward = RbStatistics::Beta::lnPdf(a, b, new_m); double new_a = delta * new_m + 1.0; double new_b = delta * (1.0-new_m) + 1.0; double backward = RbStatistics::Beta::lnPdf(new_a, new_b, m); // set the age tau.getNode(nodeIdx).setAge( my_new_age ); // touch the tree so that the likelihoods are getting stored tree->touch(); // get the probability ratio of the tree double treeProbRatio = tree->getLnProbabilityRatio(); // set the rates double pa = node->getParent().getAge(); double my_new_rate =(pa - my_age) * storedRates[nodeIdx] / (pa - my_new_age); // now we set the new value // this will automcatically call a touch rates[nodeIdx]->setValue( new double( my_new_rate ) ); // get the probability ratio of the new rate double ratesProbRatio = rates[nodeIdx]->getLnProbabilityRatio(); for (size_t i = 0; i < node->getNumberOfChildren(); i++) { size_t childIdx = node->getChild(i).getIndex(); double a = node->getChild(i).getAge(); double child_new_rate = (my_age - a) * storedRates[childIdx] / (my_new_age - a); // now we set the new value // this will automcatically call a touch rates[childIdx]->setValue( new double( child_new_rate ) ); // get the probability ratio of the new rate ratesProbRatio += rates[childIdx]->getLnProbabilityRatio(); } if ( checkLikelihoodShortcuts == true ) { double lnProbRatio = 0; double newLnLike = 0; for (RbOrderedSet<DagNode*>::iterator it = affected.begin(); it != affected.end(); ++it) { double tmp = (*it)->getLnProbabilityRatio(); lnProbRatio += tmp; newLnLike += (*it)->getLnProbability(); } if ( fabs(lnProbRatio) > 1E-8 ) { double lnProbRatio2 = 0; double newLnLike2 = 0; for (RbOrderedSet<DagNode*>::iterator it = affected.begin(); it != affected.end(); ++it) { double tmp2 = (*it)->getLnProbabilityRatio(); lnProbRatio2 += tmp2; newLnLike2 += (*it)->getLnProbability(); } throw RbException("Likelihood shortcut computation failed in rate-age-proposal."); } } double hastingsRatio = backward - forward; double ln_acceptance_ratio = lHeat * pHeat * (treeProbRatio + ratesProbRatio) + hastingsRatio; if (ln_acceptance_ratio >= 0.0) { numAccepted++; tree->keep(); rates[nodeIdx]->keep(); for (size_t i = 0; i < node->getNumberOfChildren(); i++) { size_t childIdx = node->getChild(i).getIndex(); rates[childIdx]->keep(); } } else if (ln_acceptance_ratio < -300.0) { reject(); tree->restore(); rates[nodeIdx]->restore(); for (size_t i = 0; i < node->getNumberOfChildren(); i++) { size_t childIdx = node->getChild(i).getIndex(); rates[childIdx]->restore(); } } else { double r = exp(ln_acceptance_ratio); // Accept or reject the move double u = GLOBAL_RNG->uniform01(); if (u < r) { numAccepted++; //keep tree->keep(); rates[nodeIdx]->keep(); for (size_t i = 0; i < node->getNumberOfChildren(); i++) { size_t childIdx = node->getChild(i).getIndex(); rates[childIdx]->keep(); } } else { reject(); tree->restore(); rates[nodeIdx]->restore(); for (size_t i = 0; i < node->getNumberOfChildren(); i++) { size_t childIdx = node->getChild(i).getIndex(); rates[childIdx]->restore(); } } } }
/** * Perform the proposal. * * \return The hastings ratio. */ double SpeciesNarrowExchangeProposal::doProposal( void ) { // empty the previous vectors storedGeneTreeNodes.clear(); storedOldBrothers.clear(); // Get random number generator RandomNumberGenerator* rng = GLOBAL_RNG; Tree& tau = speciesTree->getValue(); // pick a random node which is not the root and neithor a direct descendant of the root TopologyNode* node; do { double u = rng->uniform01(); size_t index = size_t( std::floor(tau.getNumberOfNodes() * u) ); node = &tau.getNode(index); } while ( node->isRoot() || node->getParent().isRoot() ); TopologyNode& parent = node->getParent(); TopologyNode& grandparent = parent.getParent(); TopologyNode* uncle = &grandparent.getChild( 0 ); // check if we got the correct child if ( uncle == &parent ) { uncle = &grandparent.getChild( 1 ); } TopologyNode* brother = &parent.getChild( 0 ); // check if we got the correct child if ( brother == node ) { brother = &parent.getChild( 1 ); } // we need to work with the times double parent_age = parent.getAge(); double uncles_age = uncle->getAge(); if( uncles_age < parent_age ) { failed = false; double lnHastingsRatio = 0.0; // now we store all necessary values storedChoosenNode = node; storedUncle = uncle; // now we need to find for each gene tree the nodes that need to be moved as well // only nodes that have a coalescent event within the lifetime of the parents populations // from lineages belonging to the chosen node with lineages belonging to the brother population // need to be changed for ( size_t i=0; i<geneTrees.size(); ++i ) { // get the i-th gene tree Tree& geneTree = geneTrees[i]->getValue(); std::vector<TopologyNode*> nodes = getNodesToChange(geneTree, *node, *brother ); // get the set of nodes in my uncles populations // these are the nodes that are possible re-attachment points std::set<TopologyNode*> new_siblings = getOldestSubtreesNodesInPopulation(geneTree, *uncle); std::set<TopologyNode*> old_siblings = getOldestSubtreesNodesInPopulation(geneTree, *brother); for (size_t j=0; j<nodes.size(); ++j) { TopologyNode *the_gene_node = nodes[i]; // first we need to compute the backward probability std::set<TopologyNode*> old_candidate_siblings = getPossibleSiblings(the_gene_node, old_siblings); // add the backward probability to the hastings ratio lnHastingsRatio += log( old_siblings.size() ); // then we need to compute the forward probability std::set<TopologyNode*> new_candidate_siblings = getPossibleSiblings(the_gene_node, new_siblings); // add the forward probability to the hastings ratio lnHastingsRatio += log( new_candidate_siblings.size() ); // actually pick a new sibling size_t new_index = size_t( floor(rng->uniform01() * new_candidate_siblings.size() ) ); std::set<TopologyNode*>::iterator it = new_candidate_siblings.begin(); std::advance(it,new_index); TopologyNode *new_child = *it; // store nodes storedGeneTreeNodes.push_back( the_gene_node ); TopologyNode &the_parent = the_gene_node->getParent(); TopologyNode *old_brother = &the_parent.getChild( 0 ); if ( old_brother == the_gene_node ) { old_brother = &the_parent.getChild( 1 ); } storedOldBrothers.push_back( old_brother ); // perform a prune and regraft move prune( &the_parent, the_gene_node ); regraft( the_gene_node, new_child ); } // Sebastian: This is only for debugging. It makes the code slower. Hopefully it is not necessary anymore. // geneTrees[i]->touch( true ); } // now exchange the two nodes grandparent.removeChild( uncle ); parent.removeChild( node ); grandparent.addChild( node ); parent.addChild( uncle ); node->setParent( &grandparent ); uncle->setParent( &parent ); return 0.0; } else { failed = true; return RbConstants::Double::neginf; } }
std::set<TopologyNode*> SpeciesNarrowExchangeProposal::getNodesInPopulation( Tree &tau, TopologyNode &n ) { // I need all the oldest nodes/subtrees that have the same tips. // Those nodes need to be scaled too. // get the beginning and ending age of the population double max_age = -1.0; if ( n.isRoot() == false ) { max_age = n.getParent().getAge(); } // get all the taxa from the species tree that are descendants of the node double min_age = n.getAge(); std::vector<TopologyNode*> species_taxa; TreeUtilities::getTaxaInSubtree( &n, species_taxa ); // get all the individuals std::set<TopologyNode*> individual_taxa; for (size_t i = 0; i < species_taxa.size(); ++i) { const std::string &name = species_taxa[i]->getName(); std::vector<TopologyNode*> ind = tau.getTipNodesWithSpeciesName( name ); for (size_t j = 0; j < ind.size(); ++j) { individual_taxa.insert( ind[j] ); } } // create the set of the nodes within this population std::set<TopologyNode*> nodesInPopulationSet; // now go through all nodes in the gene while ( individual_taxa.empty() == false ) { std::set<TopologyNode*>::iterator it = individual_taxa.begin(); individual_taxa.erase( it ); TopologyNode *gene_node = *it; if ( gene_node->getAge() < min_age ) { // the age of the node is younger than the populations start age // -> add the node to the current working set individual_taxa.insert( &gene_node->getParent() ); } else if ( gene_node->getAge() < max_age || max_age == -1.0 ) { // the age of the node is within the population // -> add the node to the current return set nodesInPopulationSet.insert( gene_node ); // if this is not the root then we need to add the parent node to the working set if ( gene_node->isRoot() == false ) { individual_taxa.insert( &gene_node->getParent() ); } } } return nodesInPopulationSet; }
void AbstractRootedTreeDistribution::simulateTree( void ) { // the time tree object (topology & times) Tree *psi = new Tree(); // internally we treat unrooted topologies the same as rooted psi->setRooted( true ); // create the tip nodes std::vector<TopologyNode*> nodes; for (size_t i=0; i<num_taxa; ++i) { // create the i-th taxon TopologyNode* node = new TopologyNode( taxa[i], i ); // set the age of this tip node node->setAge( taxa[i].getAge() ); if (node->getAge() > 0) { node->setFossil(true); } // add the new node to the list nodes.push_back( node ); } double ra = root_age->getValue(); double present = ra; // we need a sorted vector of constraints, starting with the smallest std::vector<Clade> sorted_clades; std::vector<Clade> constraints; for (size_t i = 0; i < constraints.size(); ++i) { if (constraints[i].getAge() > ra) { throw RbException("Cannot simulate tree: clade constraints are older than the root age."); } // set the ages of each of the taxa in the constraint for (size_t j = 0; j < constraints[i].size(); ++j) { for (size_t k = 0; k < num_taxa; k++) { if ( taxa[k].getName() == constraints[i].getTaxonName(j) ) { constraints[i].setTaxonAge(j, taxa[k].getAge()); break; } } } if ( constraints[i].size() > 1 && constraints[i].size() < num_taxa ) { sorted_clades.push_back( constraints[i] ); } } // create a clade that contains all species Clade all_species = Clade(taxa); all_species.setAge( ra ); sorted_clades.push_back(all_species); // next sort the clades std::sort(sorted_clades.begin(),sorted_clades.end()); // remove duplicates std::vector<Clade> tmp; tmp.push_back( sorted_clades[0] ); for (size_t i = 1; i < sorted_clades.size(); ++i) { Clade &a = tmp[tmp.size()-1]; Clade &b = sorted_clades[i]; if ( a.size() != b.size() ) { tmp.push_back( sorted_clades[i] ); } else { bool equal = true; for (size_t j = 0; j < a.size(); ++j) { if ( a.getTaxon(j) != b.getTaxon(j) ) { equal = false; break; } } if ( equal == false ) { tmp.push_back( sorted_clades[i] ); } } } sorted_clades = tmp; std::vector<Clade> virtual_taxa; for (size_t i = 0; i < sorted_clades.size(); ++i) { Clade &c = sorted_clades[i]; std::vector<Taxon> taxa = c.getTaxa(); std::vector<Clade> clades; for (int j = int(i)-1; j >= 0; --j) { const Clade &c_nested = sorted_clades[j]; const std::vector<Taxon> &taxa_nested = c_nested.getTaxa(); bool found_all = true; bool found_some = false; for (size_t k = 0; k < taxa_nested.size(); ++k) { std::vector<Taxon>::iterator it = std::find(taxa.begin(), taxa.end(), taxa_nested[k]); if ( it != taxa.end() ) { taxa.erase( it ); found_some = true; } else { found_all = false; } } if ( found_all == true ) { // c.addTaxon( virtual_taxa[j] ); // taxa.push_back( virtual_taxa[j] ); clades.push_back( virtual_taxa[j] ); } if ( found_all == false && found_some == true ) { throw RbException("Cannot simulate tree: conflicting monophyletic clade constraints. Check that all clade constraints are properly nested."); } } std::vector<TopologyNode*> nodes_in_clade; for (size_t k = 0; k < taxa.size(); ++k) { Clade c = Clade( taxa[k] ); c.setAge( taxa[k].getAge() ); clades.push_back( c ); } for (size_t k = 0; k < clades.size(); ++k) { for (size_t j = 0; j < nodes.size(); ++j) { if (nodes[j]->getClade() == clades[k]) { nodes_in_clade.push_back( nodes[j] ); nodes.erase( nodes.begin()+j ); break; } } } double clade_age = c.getAge(); double max_node_age = 0; for (size_t j = 0; j < nodes_in_clade.size(); ++j) { if ( nodes_in_clade[j]->getAge() > max_node_age ) { max_node_age = nodes_in_clade[j]->getAge(); } } if ( clade_age <= max_node_age ) { // Get the rng RandomNumberGenerator* rng = GLOBAL_RNG; clade_age = rng->uniform01() * ( ra - max_node_age ) + max_node_age; } simulateClade(nodes_in_clade, clade_age, present); nodes.push_back( nodes_in_clade[0] ); std::vector<Taxon> v_taxa; nodes_in_clade[0]->getTaxa(v_taxa); Clade new_clade = Clade(v_taxa); new_clade.setAge( nodes_in_clade[0]->getAge() ); virtual_taxa.push_back( new_clade ); } TopologyNode *root = nodes[0]; // initialize the topology by setting the root psi->setRoot(root); // finally store the new value delete value; value = psi; }
/** * Perform the proposal. * * \return The hastings ratio. */ double SpeciesTreeNodeSlideProposal::doProposal( void ) { // double factor = 0.0; // Get random number generator RandomNumberGenerator* rng = GLOBAL_RNG; Tree &species_tree = speciesTree->getValue(); size_t num_taxa = species_tree.getNumberOfTips(); size_t num_internal_nodes = num_taxa - 1; size_t num_nodes = num_taxa + num_internal_nodes; std::vector<TopologyNode*> order = std::vector<TopologyNode*>(num_nodes, NULL); std::vector<bool> swapped = std::vector<bool>(num_internal_nodes, false); mauCanonical(species_tree, order, swapped); // pick an internal node to change int which = int( num_internal_nodes * rng->uniform01() ); std::vector<bool> left = std::vector<bool>(num_taxa, false); std::vector<bool> right = std::vector<bool>(num_taxa, false); for(int k = 0; k < 2*which+1; k += 2) { left[(order[k])->getIndex()] = true; } for(int k = 2*(which+1); k < num_nodes; k += 2) { right[(order[k])->getIndex()] = true; } // get the node that for which we are going to change the age TopologyNode *node = order[2 * which + 1]; // store the values so that we can undo the proposal storedAge = node->getAge(); storedNode = node; // fillPreorderIndices(species_tree, preOrderIndexBefore); swappedNodes = swapped; orderedNodes = order; // now we propose a new age double new_height = 0.0; // if( factor > 0 ) // { // newHeight = (order[2*which+1])->getAge() * factor; // } // else // { // double limit = species.speciationUpperBound(left, right); double limit = node->getParent().getAge(); new_height = rng->uniform01() * limit; // new_height = RbStatistics::Normal::rv(node->getAge(), delta, *rng); // reflect if ( new_height < 0 ) { new_height = -new_height; } // } // set the new age species_tree.getNode(node->getIndex()).setAge(new_height); // reconstruct the new tree mauReconstruct(species_tree, order, swapped); // this is a symmetric proposal (I think, maybe we should check) double ln_hastings_ratio = 0.0; return ln_hastings_ratio; }
void StateDependentSpeciationExtinctionProcess::recursivelyDrawJointConditionalAncestralStates(const TopologyNode &node, std::vector<size_t>& startStates, std::vector<size_t>& endStates) { size_t node_index = node.getIndex(); if ( node.isTip() == true ) { const AbstractHomologousDiscreteCharacterData& data = static_cast<TreeDiscreteCharacterData*>(this->value)->getCharacterData(); const AbstractDiscreteTaxonData& taxon_data = data.getTaxonData( node.getName() ); const DiscreteCharacterState &char_state = taxon_data.getCharacter(0); // we need to treat ambiguous state differently if ( char_state.isAmbiguous() == false ) { endStates[node_index] = char_state.getStateIndex(); } else { // initialize the conditional likelihoods for this branch state_type branch_conditional_probs = std::vector<double>(2 * num_states, 0); size_t start_state = startStates[node_index]; branch_conditional_probs[ num_states + start_state ] = 1.0; // first calculate extinction likelihoods via a backward time pass double end_age = node.getParent().getAge(); numericallyIntegrateProcess(branch_conditional_probs, 0, end_age, true, true); // now calculate conditional likelihoods along branch in forward time end_age = node.getParent().getAge() - node.getAge(); numericallyIntegrateProcess(branch_conditional_probs, 0, end_age, false, false); double total_prob = 0.0; for (size_t i = 0; i < num_states; ++i) { if ( char_state.isMissingState() == true || char_state.isGapState() == true || char_state.isStateSet(i) == true ) { total_prob += branch_conditional_probs[i]; } } RandomNumberGenerator* rng = GLOBAL_RNG; size_t u = rng->uniform01() * total_prob; for (size_t i = 0; i < num_states; ++i) { if ( char_state.isMissingState() == true || char_state.isGapState() == true || char_state.isStateSet(i) == true ) { u -= branch_conditional_probs[i]; if ( u <= 0.0 ) { endStates[node_index] = i; break; } } } } } else { // sample characters by their probability conditioned on the branch's start state going to end states // initialize the conditional likelihoods for this branch state_type branch_conditional_probs = std::vector<double>(2 * num_states, 0); size_t start_state = startStates[node_index]; branch_conditional_probs[ num_states + start_state ] = 1.0; // first calculate extinction likelihoods via a backward time pass double end_age = node.getParent().getAge(); numericallyIntegrateProcess(branch_conditional_probs, 0, end_age, true, true); // now calculate conditional likelihoods along branch in forward time end_age = node.getParent().getAge() - node.getAge(); numericallyIntegrateProcess(branch_conditional_probs, 0, end_age, false, false); // TODO: if character mapping compute likelihoods for each time slice.... // double current_time_slice = floor(begin_age / dt); // bool computed_at_least_one = false; // // // first iterate forward along the branch subtending this node to get the // // probabilities of the end states conditioned on the start state // while (current_time_slice * dt >= end_age || !computed_at_least_one) // { // double begin_age_slice = current_time_slice * dt; // double end_age_slice = (current_time_slice + 1) * dt; // numericallyIntegrateProcess(branch_conditional_probs, begin_age_slice, end_age_slice, false); // // computed_at_least_one = true; // current_time_slice--; // } std::map<std::vector<unsigned>, double> event_map; std::vector<double> speciation_rates; if ( use_cladogenetic_events == true ) { // get cladogenesis event map (sparse speciation rate matrix) const DeterministicNode<MatrixReal>* cpn = static_cast<const DeterministicNode<MatrixReal>* >( cladogenesis_matrix ); const TypedFunction<MatrixReal>& tf = cpn->getFunction(); const AbstractCladogenicStateFunction* csf = dynamic_cast<const AbstractCladogenicStateFunction*>( &tf ); event_map = csf->getEventMap(); } else { speciation_rates = lambda->getValue(); } // get likelihoods of descendant nodes const TopologyNode &left = node.getChild(0); size_t left_index = left.getIndex(); state_type left_likelihoods = partial_likelihoods[left_index][active_likelihood[left_index]]; const TopologyNode &right = node.getChild(1); size_t right_index = right.getIndex(); state_type right_likelihoods = partial_likelihoods[right_index][active_likelihood[right_index]]; std::map<std::vector<unsigned>, double> sample_probs; double sample_probs_sum = 0.0; std::map<std::vector<unsigned>, double>::iterator it; // calculate probabilities for each state if ( use_cladogenetic_events == true ) { // iterate over each cladogenetic event possible // and initialize probabilities for each clado event for (it = event_map.begin(); it != event_map.end(); it++) { const std::vector<unsigned>& states = it->first; double speciation_rate = it->second; // we need to sample from the ancestor, left, and right states jointly, // so keep track of the probability of each clado event double prob = left_likelihoods[num_states + states[1]] * right_likelihoods[num_states + states[2]]; prob *= speciation_rate * branch_conditional_probs[num_states + states[0]]; sample_probs[ states ] = prob; sample_probs_sum += prob; } } else { for (size_t i = 0; i < num_states; i++) { double prob = left_likelihoods[num_states + i] * right_likelihoods[num_states + i] * speciation_rates[i]; prob *= branch_conditional_probs[num_states + i]; std::vector<unsigned> states = boost::assign::list_of(i)(i)(i); sample_probs[ states ] = prob; sample_probs_sum += prob; } } // finally, sample ancestor, left, and right character states from probs size_t a, l, r; if (sample_probs_sum == 0) { RandomNumberGenerator* rng = GLOBAL_RNG; size_t u = rng->uniform01() * sample_probs.size(); size_t v = 0; for (it = sample_probs.begin(); it != sample_probs.end(); it++) { if (u < v) { const std::vector<unsigned>& states = it->first; a = states[0]; l = states[1]; r = states[2]; endStates[node_index] = a; startStates[left_index] = l; startStates[right_index] = r; break; } v++; } } else { RandomNumberGenerator* rng = GLOBAL_RNG; double u = rng->uniform01() * sample_probs_sum; for (it = sample_probs.begin(); it != sample_probs.end(); it++) { u -= it->second; if (u < 0.0) { const std::vector<unsigned>& states = it->first; a = states[0]; l = states[1]; r = states[2]; endStates[node_index] = a; startStates[left_index] = l; startStates[right_index] = r; break; } } } // recurse towards tips recursivelyDrawJointConditionalAncestralStates(left, startStates, endStates); recursivelyDrawJointConditionalAncestralStates(right, startStates, endStates); } }
/** Perform the move */ void RateAgeBetaShift::performMove( double heat, bool raiseLikelihoodOnly ) { // Get random number generator RandomNumberGenerator* rng = GLOBAL_RNG; TimeTree& tau = tree->getValue(); // pick a random node which is not the root and neithor the direct descendant of the root TopologyNode* node; size_t nodeIdx = 0; do { double u = rng->uniform01(); nodeIdx = size_t( std::floor(tau.getNumberOfNodes() * u) ); node = &tau.getNode(nodeIdx); } while ( node->isRoot() || node->isTip() ); TopologyNode& parent = node->getParent(); // we need to work with the times double parent_age = parent.getAge(); double my_age = node->getAge(); double child_Age = node->getChild( 0 ).getAge(); if ( child_Age < node->getChild( 1 ).getAge()) { child_Age = node->getChild( 1 ).getAge(); } // now we store all necessary values storedNode = node; storedAge = my_age; storedRates[nodeIdx] = rates[nodeIdx]->getValue(); for (size_t i = 0; i < node->getNumberOfChildren(); i++) { size_t childIdx = node->getChild(i).getIndex(); storedRates[childIdx] = rates[childIdx]->getValue(); } // draw new ages and compute the hastings ratio at the same time double m = (my_age-child_Age) / (parent_age-child_Age); double a = delta * m + 1.0; double b = delta * (1.0-m) + 1.0; double new_m = RbStatistics::Beta::rv(a, b, *rng); double my_new_age = (parent_age-child_Age) * new_m + child_Age; // compute the Hastings ratio double forward = RbStatistics::Beta::lnPdf(a, b, new_m); double new_a = delta * new_m + 1.0; double new_b = delta * (1.0-new_m) + 1.0; double backward = RbStatistics::Beta::lnPdf(new_a, new_b, m); // set the age tau.setAge( node->getIndex(), my_new_age ); tree->touch(); double treeProbRatio = tree->getLnProbabilityRatio(); // set the rates rates[nodeIdx]->setValue( new double((node->getParent().getAge() - my_age) * storedRates[nodeIdx] / (node->getParent().getAge() - my_new_age))); double ratesProbRatio = rates[nodeIdx]->getLnProbabilityRatio(); for (size_t i = 0; i < node->getNumberOfChildren(); i++) { size_t childIdx = node->getChild(i).getIndex(); rates[childIdx]->setValue( new double((my_age - node->getChild(i).getAge()) * storedRates[childIdx] / (my_new_age - node->getChild(i).getAge()))); ratesProbRatio += rates[childIdx]->getLnProbabilityRatio(); } std::set<DagNode*> affected; tree->getAffectedNodes( affected ); double lnProbRatio = 0; for (std::set<DagNode*>::iterator it = affected.begin(); it != affected.end(); ++it) { (*it)->touch(); lnProbRatio += (*it)->getLnProbabilityRatio(); } if ( fabs(lnProbRatio) > 1E-6 ) { // throw RbException("Likelihood shortcut computation failed in rate-age-proposal."); std::cout << "Likelihood shortcut computation failed in rate-age-proposal." << std::endl; } double hastingsRatio = backward - forward; double lnAcceptanceRatio = treeProbRatio + ratesProbRatio + hastingsRatio; if (lnAcceptanceRatio >= 0.0) { numAccepted++; tree->keep(); rates[nodeIdx]->keep(); for (size_t i = 0; i < node->getNumberOfChildren(); i++) { size_t childIdx = node->getChild(i).getIndex(); rates[childIdx]->keep(); } } else if (lnAcceptanceRatio < -300.0) { reject(); tree->restore(); rates[nodeIdx]->restore(); for (size_t i = 0; i < node->getNumberOfChildren(); i++) { size_t childIdx = node->getChild(i).getIndex(); rates[childIdx]->restore(); } } else { double r = exp(lnAcceptanceRatio); // Accept or reject the move double u = GLOBAL_RNG->uniform01(); if (u < r) { numAccepted++; //keep tree->keep(); rates[nodeIdx]->keep(); for (size_t i = 0; i < node->getNumberOfChildren(); i++) { size_t childIdx = node->getChild(i).getIndex(); rates[childIdx]->keep(); } } else { reject(); tree->restore(); rates[nodeIdx]->restore(); for (size_t i = 0; i < node->getNumberOfChildren(); i++) { size_t childIdx = node->getChild(i).getIndex(); rates[childIdx]->restore(); } } } }
void RateMap_Biogeography::calculateTransitionProbabilities(const TopologyNode& node, TransitionProbabilityMatrix &P, size_t charIdx) const { double startAge = ( node.isRoot() ? 1e10 : node.getParent().getAge() ); double endAge = node.getAge(); double currAge = startAge; double r = ( branchHeterogeneousClockRates ? heterogeneousClockRates[node.getIndex()] : homogeneousClockRate ); const std::vector<double>& glr = ( branchHeterogeneousGainLossRates ? heterogeneousGainLossRates[node.getIndex()] : homogeneousGainLossRates ); // start at earliest epoch int epochIdx = getEpochIndex(startAge); // initialize P = I P[0][0] = 1.0; P[0][1] = 0.0; P[1][0] = 0.0; P[1][1] = 1.0; bool stop = false; while (!stop) { // get dispersal and extinction rates for site size_t idx = this->numCharacters * epochIdx + charIdx; double dispersalRate = ( (availableAreaVector[ idx ] > 0) ? 1.0 : 0.0); double extinctionRate = ( (availableAreaVector[ idx ] > 0) ? 1.0 : 1e10); // get age of start of next oldest epoch double epochAge = epochs[ epochIdx ]; // get next oldest age boundary (node or epoch) double incrAge = epochAge; // no more epochs, exit loop after computation if (endAge >= epochAge) { incrAge = endAge; stop = true; } // get branch length double diffAge = currAge - incrAge; // transition probabilities w/ sum-product double glr0 = glr[0] * extinctionRate; double glr1 = glr[1] * dispersalRate; double expPart = exp( -(glr0 + glr1) * r * diffAge); double p = glr0 / (glr0 + glr1); double q = 1.0 - p; double p00 = (p + q * expPart); double p01 = (q - q * expPart); double p10 = (p - p * expPart); double p11 = (q + p * expPart); double q00 = P[0][0]; double q01 = P[0][1]; double q10 = P[1][0]; double q11 = P[1][1]; P[0][0] = p00 * q00 + p01 * q10; P[0][1] = p00 * q01 + p01 * q11; P[1][0] = p10 * q00 + p11 * q10; P[1][1] = p10 * q01 + p11 * q11; // std::cout << P[0][0] << "," << P[0][1] << ";" << P[1][0] << "," << P[1][1] << "\n"; if (!stop) { epochIdx += 1; currAge = epochAge; } } }
void CharacterDependentCladoBirthDeathProcess::recursivelyDrawJointConditionalAncestralStates(const TopologyNode &node, std::vector<size_t>& startStates, std::vector<size_t>& endStates) { size_t node_index = node.getIndex(); if ( node.isTip() == true ) { const AbstractHomologousDiscreteCharacterData& data = static_cast<TreeDiscreteCharacterData*>(this->value)->getCharacterData(); const AbstractDiscreteTaxonData& taxon_data = data.getTaxonData( node.getName() ); endStates[node_index] = taxon_data.getCharacter(0).getStateIndex(); } else { const TopologyNode &left = node.getChild(0); size_t left_index = left.getIndex(); state_type left_likelihoods = partial_likelihoods[left_index]; const TopologyNode &right = node.getChild(1); size_t right_index = right.getIndex(); state_type right_likelihoods = partial_likelihoods[right_index]; // sample characters by their probability conditioned on the branch's start state going to end states state_type branch_conditional_probs = std::vector<double>(2 * num_states, 0); size_t start_state = startStates[node_index]; branch_conditional_probs[ num_states + start_state ] = 1.0; double dt = root_age->getValue() / NUM_TIME_SLICES; double endAge = node.getAge(); double beginAge = node.getParent().getAge(); double current_time_slice = floor(beginAge / dt); bool computed_at_least_one = false; // get cladogenesis event map (sparse speciation rate matrix) const DeterministicNode<MatrixReal>* cpn = static_cast<const DeterministicNode<MatrixReal>* >( cladogenesis_matrix ); const TypedFunction<MatrixReal>& tf = cpn->getFunction(); const AbstractCladogenicStateFunction* csf = dynamic_cast<const AbstractCladogenicStateFunction*>( &tf ); std::map<std::vector<unsigned>, double> eventMap = csf->getEventMap(); // first iterate forward along the branch subtending this node to get the // probabilities of the end states conditioned on the start state while (current_time_slice * dt >= endAge || !computed_at_least_one) { // populate pre-computed extinction probs into branch_conditional_probs if (current_time_slice > 0) { for (size_t i = 0; i < num_states; i++) { branch_conditional_probs[i] = extinction_probabilities[current_time_slice - 1][i]; } } CDCladoSEObserved ode = CDCladoSEObserved(extinction_rates, &Q->getValue(), eventMap, rate->getValue()); boost::numeric::odeint::bulirsch_stoer< state_type > stepper(1E-8, 0.0, 0.0, 0.0); boost::numeric::odeint::integrate_adaptive( stepper, ode , branch_conditional_probs , current_time_slice * dt , (current_time_slice + 1) * dt, dt ); computed_at_least_one = true; current_time_slice--; } std::map<std::vector<unsigned>, double> sample_probs; double sample_probs_sum = 0.0; std::map<std::vector<unsigned>, double>::iterator it; // iterate over each cladogenetic event possible for (it = eventMap.begin(); it != eventMap.end(); it++) { const std::vector<unsigned>& states = it->first; double speciation_rate = it->second; sample_probs[ states ] = 0.0; // we need to sample from the ancestor, left, and right states jointly, // so keep track of the probability of each clado event double prob = left_likelihoods[num_states + states[1]] * right_likelihoods[num_states + states[2]]; prob *= speciation_rate * branch_conditional_probs[num_states + states[0]]; sample_probs[ states ] += prob; sample_probs_sum += prob; } // finally, sample ancestor, left, and right character states from probs size_t a, l, r; RandomNumberGenerator* rng = GLOBAL_RNG; double u = rng->uniform01() * sample_probs_sum; for (it = sample_probs.begin(); it != sample_probs.end(); it++) { u -= it->second; if (u < 0.0) { const std::vector<unsigned>& states = it->first; a = states[0]; l = states[1]; r = states[2]; endStates[node_index] = a; startStates[left_index] = l; startStates[right_index] = r; break; } } // recurse towards tips recursivelyDrawJointConditionalAncestralStates(left, startStates, endStates); recursivelyDrawJointConditionalAncestralStates(right, startStates, endStates); } }
/** * Perform the proposal. * * \return The hastings ratio. */ double SpeciesSubtreeScaleBetaProposal::doProposal( void ) { // Get random number generator RandomNumberGenerator* rng = GLOBAL_RNG; Tree& tau = speciesTree->getValue(); // pick a random node which is not the root and neither the direct descendant of the root TopologyNode* node; do { double u = rng->uniform01(); size_t index = size_t( std::floor(tau.getNumberOfNodes() * u) ); node = &tau.getNode(index); } while ( node->isRoot() || node->isTip() ); TopologyNode& parent = node->getParent(); // we need to work with the times double parent_age = parent.getAge(); double my_age = node->getAge(); // now we store all necessary values storedNode = node; storedAge = my_age; // lower bound double min_age = 0.0; TreeUtilities::getOldestTip(&tau, node, min_age); // draw new ages double current_value = my_age / (parent_age - min_age); double a = alpha + 1.0; double b = (a-1.0) / current_value - a + 2.0; double new_value = RbStatistics::Beta::rv(a, b, *rng); // Sebastian: This is for debugging to test if the proposal's acceptance rate is 1.0 as it should be! // new_value = current_value; double my_new_age = new_value * (parent_age - min_age); double scaling_factor = my_new_age / my_age; size_t num_nodes = node->getNumberOfNodesInSubtree( false ); for ( size_t i=0; i<geneTrees.size(); ++i ) { // get the i-th gene tree Tree& gene_tree = geneTrees[i]->getValue(); std::vector<TopologyNode*> nodes = getOldestNodesInPopulation(gene_tree, *node ); for (size_t j=0; j<nodes.size(); ++j) { // add the number of nodes that we are going to scale in the subtree num_nodes += nodes[j]->getNumberOfNodesInSubtree( false ); if ( nodes[j]->isTip() == true ) { std::cerr << "Trying to scale a tip\n"; } if ( nodes[j]->isRoot() == true ) { std::cerr << "Trying to scale the root\n"; } // rescale the subtree of this gene tree TreeUtilities::rescaleSubtree(&gene_tree, nodes[j], scaling_factor ); } // Sebastian: This is only for debugging. It makes the code slower. Hopefully it is not necessary anymore. // geneTrees[i]->touch( true ); } // Sebastian: We need to work on a mechanism to make these proposal safe for non-ultrametric trees! // if (min_age != 0.0) // { // for (size_t i = 0; i < tau.getNumberOfTips(); i++) // { // if (tau.getNode(i).getAge() < 0.0) // { // return RbConstants::Double::neginf; // } // } // } // rescale the subtree of the species tree TreeUtilities::rescaleSubtree(&tau, node, scaling_factor ); // compute the Hastings ratio double forward = RbStatistics::Beta::lnPdf(a, b, new_value); double new_a = alpha + 1.0; double new_b = (a-1.0) / new_value - a + 2.0; double backward = RbStatistics::Beta::lnPdf(new_a, new_b, current_value); double lnHastingsratio = (backward - forward) * (num_nodes-1); return lnHastingsratio; }