/** Perform the move */ double AdmixtureShiftNodeAgeAndRate::performSimpleMove( void ) { failed = false; //std::cout << "\nAge-Rate Shift\n"; // clear old rates storedRates.clear(); // Get random number generator RandomNumberGenerator* rng = GLOBAL_RNG; AdmixtureTree& tau = variable->getValue(); AdmixtureNode* node = &tau.getNode(nodeIndex); AdmixtureNode& 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 ( node->getNumberOfChildren() > 1 && child_Age < node->getChild( 1 ).getAge()) { child_Age = node->getChild( 1 ).getAge(); } // admixture node ages are further constrained by their partner's time if (&node->getAdmixtureChild() != NULL) { AdmixtureNode& admixtureChild = node->getAdmixtureChild(); double other_parent_age = admixtureChild.getParent().getAge(); if (parent_age > other_parent_age) parent_age = other_parent_age; double other_child_age = admixtureChild.getChild(0).getAge(); if (child_Age < other_child_age) child_Age = other_child_age; } else if (&node->getAdmixtureParent() != NULL) { AdmixtureNode& admixtureParent = node->getAdmixtureParent(); double other_parent_age = admixtureParent.getParent().getAge(); if (parent_age > other_parent_age) parent_age = other_parent_age; double other_child_age = admixtureParent.getChild(0).getAge(); if (child_Age < other_child_age) child_Age = other_child_age; } // now we store all necessary values storedNode = node; storedAge = my_age; // draw new age double ageRange = parent_age - child_Age; double unitAge = (storedAge - child_Age) / ageRange; double a = delta * unitAge + 1.0; double b = delta * (1.0 - unitAge) + 1.0; double newUnitAge = RbStatistics::Beta::rv(a, b, *rng); double fwdProposal = RbStatistics::Beta::lnPdf(a, b, newUnitAge); double my_new_age = newUnitAge * ageRange + child_Age; double new_a = delta * newUnitAge + 1.0; double new_b = delta * (1.0 - newUnitAge) + 1.0; double bwdProposal = RbStatistics::Beta::lnPdf(new_a, new_b, unitAge); // double get branch length double old_brlen = node->getTopologyParent().getAge() - my_age; double new_brlen = node->getTopologyParent().getAge() - my_new_age; double brlen_ratio = old_brlen / new_brlen; // update branch rate leading to node double node_rate = branchRates[node->getIndex()]->getValue(); //branchRates[node->getIndex()]->touch(); //std::cout << "br_name" << branchRates[node->getIndex()]->getName() << "\n"; storedRates[node] = node_rate; //std::cout << "brlen\t" << old_brlen << " -> " << new_brlen << " " << brlen_ratio << "\n"; //std::cout << "node_rate " << node_rate << " -> " << node_rate * brlen_ratio <<"\n"; node_rate = node_rate * brlen_ratio; branchRates[node->getIndex()]->setValue(new double(node_rate)); // update branch rates following from node for (size_t i = 0; i < storedNode->getNumberOfChildren(); i++) { AdmixtureNode* ch = &storedNode->getTopologyChild(i); //AdmixtureNode* ch = &storedNode->getChild(i); //double ch_ratio = (storedAge - ch->getAge()) / (my_new_age - ch->getAge()); double ch_ratio = (storedAge - ch->getAge()) / (my_new_age - ch->getAge()); double ch_rate = branchRates[ch->getIndex()]->getValue(); // branchRates[ch->getIndex()]->touch(); storedRates[ch] = ch_rate; //branchRates[node->getIndex()]->setValue(new double(ch_rate * ch_ratio)); //std::cout << "ch_brlen " << i << " " << (storedAge - ch->getAge()) << " -> " << (my_new_age - ch->getAge()) << " " << ch_ratio << "\n"; //std::cout << "ch_rate " << i << " " << ch_rate << " -> " << ch_rate * ch_ratio << "\n"; ch_rate = ch_rate * ch_ratio; branchRates[ch->getIndex()]->setValue(new double(ch_rate)); } // set the age node->setAge( my_new_age ); // set age of admixture partner if (&node->getAdmixtureParent() != NULL) node->getAdmixtureParent().setAge( my_new_age ); else if (&node->getAdmixtureChild() != NULL) node->getAdmixtureChild().setAge( my_new_age ); return bwdProposal - fwdProposal; }
/** Perform the move */ double AdmixtureNearestNeighborInterchangeAndRateShift::performSimpleMove( void ) { //std::cout << "\nDiv Node NNI & Rate Rescale\n"; failed = false; // Get random number generator RandomNumberGenerator* rng = GLOBAL_RNG; AdmixtureTree& tau = variable->getValue(); // pick a random node which is not the root and neithor the direct descendant of the root AdmixtureNode* node; do { double u = rng->uniform01(); size_t index = std::floor(tau.getNumberOfNodes() * u); node = &tau.getNode(index); } while ( node->isRoot() || node->getTopologyParent().isRoot() || node->getNumberOfChildren() != 2); int nodeChildMoveIdx = (int)std::floor(rng->uniform01() * 2.0); int nodeBrotherIdx = 0; //std::cout << "nodeChildeMoveIdx " << nodeChildMoveIdx << "\n"; // divergence location AdmixtureNode* childMove = &node->getChild(nodeChildMoveIdx); AdmixtureNode* parent = &node->getTopologyParent(); AdmixtureNode* brother = &parent->getTopologyChild( nodeBrotherIdx ); // check if we got the correct child lineage if ( brother == node ) { if (nodeBrotherIdx == 0) nodeBrotherIdx = 1; else nodeBrotherIdx = 0; } // get brother of node (not divergence child node) brother = &parent->getChild(nodeBrotherIdx); if (brother->getAge() > node->getAge()) { //std::cout << "failed, bro > node\n"; failed = true; return RbConstants::Double::neginf; } else if (childMove->getAge() > parent->getAge()) { //std::cout << "failed, child > parent\n"; failed = true; return RbConstants::Double::neginf; } else if (childMove->isOutgroup() != brother->isOutgroup()) { //std::cout << "failed, outgroup mismatch\n"; failed = true; return RbConstants::Double::neginf; } // update parent clade storedNodeParent = parent; storedNodeChildMove = childMove; storedBrother = brother; storedNode = node; // swap storedNode->removeChild(storedNodeChildMove); storedNodeParent->removeChild(storedBrother); storedNode->addChild(storedBrother); storedNodeParent->addChild(storedNodeChildMove); storedBrother->setParent(storedNode); storedNodeChildMove->setParent(storedNodeParent); // get branch rate index storedChildRateIndex = (int)node->getTopologyChild(nodeChildMoveIdx).getIndex(); storedBrotherRateIndex = (int)parent->getTopologyChild(nodeBrotherIdx).getIndex(); // storedNodeRateIndex = node->getIndex(); // store branch rate values storedChildRate = branchRates[storedChildRateIndex]->getValue(); // storedNodeRate = branchRates[storedNodeRateIndex]->getValue(); storedBrotherRate = branchRates[storedBrotherRateIndex]->getValue(); // update //double cnr = 0.0; //double snr = 0.0; //double sbr = 0.0; double scaleChildRate = exp(delta*(rng->uniform01() - 0.5)); // double scaleNodeRate = exp(delta*(rng->uniform01() - 0.5)); double scaleBrotherRate = exp(delta*(rng->uniform01() - 0.5)); branchRates[storedChildRateIndex]->setValue(new double(storedChildRate*scaleChildRate)); // branchRates[storedNodeRateIndex]->setValue(new double(storedNodeRate * scaleNodeRate)); branchRates[storedBrotherRateIndex]->setValue(new double(storedBrotherRate * scaleBrotherRate)); //branchRates[storedChildRateIndex]->touch(); //std::cout << "chld rate " << storedChildRate << " -> " << storedChildRate*scaleChildRate << "\n"; // std::cout << "node rate " << storedNodeRate << " -> " << storedNodeRate*scaleNodeRate << "\n"; //std::cout << "bro rate " << storedBrotherRate << " -> " << storedBrotherRate*scaleBrotherRate << "\n"; if (storedChildRate * scaleChildRate == 0.0) { ;//std::cout << "new scaledChildRate == 0.0\n"; } //if (storedNodeRate * scaleNodeRate == 0.0) //{ // std::cout << "new scaledNodeRate == 0.0\n"; //} if (storedBrotherRate * scaleBrotherRate == 0.0) { ;//std::cout << "new scaledBrotherRate == 0.0\n"; } //std::cout << scaleChildRate*scaleBrotherRate << " " << log(scaleChildRate*scaleBrotherRate) << "\n"; // MH // return 0.0; return log(scaleChildRate*scaleBrotherRate); }