/*-------------------------------------------------------------------------------------------------------------------------- | Called if the move is accepted. */ void LargetSimonMove::accept() { MCMCUpdater::accept(); if (star_tree_proposal) { TreeNode * nd = orig_node->IsTip() ? orig_node->GetParent() : orig_node; PHYCAS_ASSERT(nd->IsInternal()); if (!likelihood->getNoData()) { likelihood->useAsLikelihoodRoot(nd); likelihood->discardCacheAwayFromNode(*orig_node); likelihood->discardCacheBothEnds(orig_node); } orig_node->UnselectNode(); } else { PHYCAS_ASSERT(ndY->IsInternal()); if (!likelihood->getNoData()) { likelihood->useAsLikelihoodRoot(ndY); likelihood->discardCacheAwayFromNode(*ndY); likelihood->discardCacheBothEnds(ndY); } ndX->UnselectNode(); ndY->UnselectNode(); ndZ->UnselectNode(); } reset(); }
/*---------------------------------------------------------------------------------------------------------------------- | Chooses a random edge and changes its current length m to a new length m* using the following formula, where `lambda' is | a tuning parameter. |> | m* = m*exp(lambda*(r.Uniform() - 0.5)) |> */ void LargetSimonMove::starTreeProposeNewState() { // Choose edge randomly. // unsigned numEdges = tree->GetNNodes() - 1; unsigned k = rng->SampleUInt(numEdges); unsigned i = 0; //@POL this loop is crying out for the for_each algorithm for (orig_node = tree->GetFirstPreorder(); orig_node != NULL; orig_node = orig_node->GetNextPreorder()) { // All nodes have an edge associated with them except for the root // if (!orig_node->IsTipRoot()) { if (i == k) { orig_edge_len = orig_node->GetEdgeLen(); break; } ++i; } } // Modify the edge // double m = orig_node->GetEdgeLen(); double mstar = m*std::exp(lambda*(rng->Uniform() - 0.5)); orig_node->SetEdgeLen(mstar); // Invalidate CLAs to ensure next likelihood calculation will be correct orig_node->SelectNode(); TreeNode * nd = orig_node->IsTip() ? orig_node->GetParent() : orig_node; PHYCAS_ASSERT(nd->IsInternal()); likelihood->useAsLikelihoodRoot(nd); likelihood->invalidateAwayFromNode(*orig_node); likelihood->invalidateBothEnds(orig_node); ChainManagerShPtr p = chain_mgr.lock(); PHYCAS_ASSERT(p); JointPriorManagerShPtr jpm = p->getJointPriorManager(); jpm->allEdgeLensModified(tree); //jpm->externalEdgeLensModified("external_edgelen", tree); }
/*---------------------------------------------------------------------------------------------------------------------- | Selects an internal node at random from a discrete uniform distribution with the constraint that the returned node | is not equal to the subroot (the sole child of the tip node serving as the root). */ TreeNode * LargetSimonMove::randomInternalAboveSubroot() { // Avoiding the "subroot" node (only child of the tip serving as the root), so the number of // acceptable nodes is one fewer than the number of internal nodes unsigned numAcceptableNodes = tree->GetNInternals() - 1; unsigned ypos = rng->SampleUInt(numAcceptableNodes); unsigned i = 0; TreeNode * nd = tree->GetFirstPreorder(); for (; nd != NULL; nd = nd->GetNextPreorder()) { if (nd->IsInternal() && !nd->GetParentConst()->IsTipRoot()) { if (i == ypos) break; ++i; } } PHYCAS_ASSERT(nd->GetLeftChild() != NULL); PHYCAS_ASSERT(nd->GetParentConst() != NULL); PHYCAS_ASSERT(!nd->GetParent()->IsTipRoot()); return nd; }
/*---------------------------------------------------------------------------------------------------------------------- | Reverses move made in proposeNewState. Assumes ndX, ndY, and ndZ are non-NULL, which will be true if proposeNewState | was just called. */ void LargetSimonMove::revert() { ChainManagerShPtr p = chain_mgr.lock(); PHYCAS_ASSERT(p); JointPriorManagerShPtr jpm = p->getJointPriorManager(); MCMCUpdater::revert(); if (star_tree_proposal) { orig_node->SetEdgeLen(orig_edge_len); TreeNode * nd = orig_node->IsTip() ? orig_node->GetParent() : orig_node; PHYCAS_ASSERT(nd->IsInternal()); likelihood->useAsLikelihoodRoot(nd); likelihood->restoreFromCacheAwayFromNode(*orig_node); likelihood->restoreFromCacheParentalOnly(orig_node); orig_node->UnselectNode(); jpm->allEdgeLensModified(tree); //jpm->externalEdgeLensModified("external_edgelen", tree); } else { PHYCAS_ASSERT(ndX != NULL); PHYCAS_ASSERT(ndY != NULL); PHYCAS_ASSERT(ndZ != NULL); PHYCAS_ASSERT(topol_changed ? (swap1 != NULL && swap2 != NULL) : (swap1 == NULL && swap2 == NULL)); if (topol_changed) { if (swap2 == ndZ) { // If swap2 equals ndZ, then swap2 was a child of ndBase and we were able to use // the standard NNISwap function to swap the two nodes // tree_manipulator.NNISwap(swap1, swap2); } else { // If swap2 is ndZ's parent, then swap2 is ndBase (i.e. it is the "child" node below the // lower of the two adjacent internal nodes involved in the swap) and we had to use the // NNISwapSpecial function to perform the rearrangment // tree_manipulator.NNISwapSpecial(swap1); likelihood->swapInternalDataAndEdgeLen(ndY, ndZ); } } ndX->SetEdgeLen(x); ndY->SetEdgeLen(y); ndZ->SetEdgeLen(z); PHYCAS_ASSERT(ndY->IsInternal()); if (!likelihood->getNoData()) { likelihood->useAsLikelihoodRoot(ndY); likelihood->restoreFromCacheAwayFromNode(*ndY); likelihood->restoreFromCacheParentalOnly(ndY); } ndX->UnselectNode(); ndY->UnselectNode(); ndZ->UnselectNode(); jpm->allEdgeLensModified(tree); if (topol_changed) jpm->topologyModified("tree_topology", tree); } curr_ln_prior = jpm->getLogJointPrior(); reset(); }