/*---------------------------------------------------------------------------------------------------------------------- | Computes the joint log working prior over all edges in the associated tree. */ double TreeScalerMove::recalcWorkingPriorForMove( bool using_tree_length_prior, /*< true if using the Ranalla-Yang tree length prior */ bool using_vartopol_prior) const /*< true if using the Holder et al. variable topology reference distribution */ { double ln_ref_dist = 0.0; if (using_tree_length_prior) { ln_ref_dist = likelihood->getTreeLengthRefDist()->GetLnPDF(tree); } else if (using_vartopol_prior) { // Computes the log of the probability of the tree under Mark Holder's variable tree topology reference distribution PHYCAS_ASSERT(topo_prob_calc); std::pair<double, double> treeprobs = topo_prob_calc->CalcTopologyLnProb(*tree, true); const double ln_ref_topo = treeprobs.first; const double ln_ref_edges = treeprobs.second; ln_ref_dist = ln_ref_topo + ln_ref_edges; } else { // Loop through all EdgeLenMasterParam objects and call the recalcWorkingPrior function of each. // Each EdgeLenMasterParam object knows how to compute the working prior for the edge lengths it controls. ChainManagerShPtr p = chain_mgr.lock(); const MCMCUpdaterVect & edge_length_params = p->getEdgeLenParams(); for (MCMCUpdaterVect::const_iterator it = edge_length_params.begin(); it != edge_length_params.end(); ++it) { if (!(*it)->isFixed()) ln_ref_dist += (*it)->recalcWorkingPrior(); } } return ln_ref_dist; }
/*---------------------------------------------------------------------------------------------------------------------- | Reverses move made in proposeNewState. */ void TreeScalerMove::revert() { MCMCUpdater::revert(); tree->ScaleAllEdgeLens(reverse_scaler); likelihood->useAsLikelihoodRoot(NULL); likelihood->storeAllCLAs(tree); // force CLAs to be recalculated ChainManagerShPtr p = chain_mgr.lock(); PHYCAS_ASSERT(p); JointPriorManagerShPtr jpm = p->getJointPriorManager(); jpm->allEdgeLensModified(tree); curr_ln_prior = jpm->getLogJointPrior(); }
/*---------------------------------------------------------------------------------------------------------------------- | 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); }
/*---------------------------------------------------------------------------------------------------------------------- | OmegaParam is a functor whose operator() returns a value proportional to the full-conditional posterior probability | density for a particular value of omega, the nonsynonymous/synonymous rate ratio. If the supplied omega value `w' is | out of bounds (i.e. <= 0.0), the return value is -DBL_MAX (closest we can come to a log posterior equal to negative | infinity). */ double OmegaParam::operator()( double w) /**< is a new value for the parameter omega */ { curr_ln_like = ln_zero; curr_ln_prior = 0.0; if (w > 0.0) { PHYCAS_ASSERT(codon); sendCurrValueToModel(w); likelihood->useAsLikelihoodRoot(NULL); // invalidates all CLAs curr_ln_like = (heating_power > 0.0 ? likelihood->calcLnL(tree) : 0.0); ChainManagerShPtr p = chain_mgr.lock(); PHYCAS_ASSERT(p); p->setLastLnLike(curr_ln_like); JointPriorManagerShPtr jpm = p->getJointPriorManager(); jpm->univariateModified(name, w); curr_ln_prior = jpm->getLogJointPrior(); if (is_standard_heating) if (use_ref_dist) { PHYCAS_ASSERT(ref_dist); double curr_ln_ref_dist = ref_dist->GetLnPDF(w); return heating_power*(curr_ln_like + curr_ln_prior) + (1.0 - heating_power)*curr_ln_ref_dist; } else return heating_power*(curr_ln_like + curr_ln_prior); else return heating_power*curr_ln_like + curr_ln_prior; } else return ln_zero; }
/*---------------------------------------------------------------------------------------------------------------------- | 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(); }
/*---------------------------------------------------------------------------------------------------------------------- | Performs a local perturbation using a generalization of the algorithm "LOCAL Without a Molecular Clock" described by | Larget and Simon (1999. Mol. Biol. Evol. 16(6): 750-759). This version allows polytomies (except the case of the | star tree, for which the required three-contiguous-edge segment cannot be identified). | | X c d | \ | / | \|/ | a b Y | \ | / | \|/ | u | | | Z <-- may or may not be the tip at which tree is rooted | | Pick a random interior node Y whose parent is not the root (i.e. avoid the subroot node directly connected to the | tip node at which the tree is rooted. Let u be the parent of y. Let Z be a randomly-chosen child of u (note that in | this case u's parent is considered a "child" of u). In the figure above, we (by chance) chose the parent of u to be | Z, but we could have chosen any of u's real children (except Y). a and b are the other "children" of u, not | including Y. Let X be a randomly chosen child of Y (and here a "child" is really a child). c and d are the other | children of Y. | | a b c d | \ / \ / | Z ===== u ===== Y ===== X | | The path represented by the double line above is either contracted or expanded by a factor m*, where | | m* = m*exp(lambda*(r.Uniform() - 0.5)) | | Then, one of {u, Y} is chosen at random to move. Let's say for illustration that u was chosen. u is moved (along | with a and c) to a random point along the main path from Z to X. If this makes the node u cross over node Y, then | the equivalent of an NNI rearrangement is effected: | | X c d X a b | \ | / \ | / In this case, invalidate CLAs away from u and | \|/ \|/ make u the likelihood root | a b Y c d u | \ | / --> \ | / | \|/ \|/ | u Y | | | | Z Z | | If there is no NNI rearrangement, the move will only require adjusting edge lengths. In this case, invalidate CLAs | away from Y and make Y the likelihood root. */ void LargetSimonMove::defaultProposeNewState() { double xstar, ystar, zstar; ChainManagerShPtr p = chain_mgr.lock(); PHYCAS_ASSERT(p); JointPriorManagerShPtr jpm = p->getJointPriorManager(); // Make sure all the necessary shared pointers have been set to something meaningful PHYCAS_ASSERT(rng); PHYCAS_ASSERT(tree); PHYCAS_ASSERT(model); PHYCAS_ASSERT(likelihood); // Begin by resetting all the data members involved with reverting a move reset(); // Select an internal node whose parent is not the root node to serve as ndY, // whose branch will form the middle segment in the path of three contiguous // segments to be modified. ndY = randomInternalAboveSubroot(); y = ndY->GetEdgeLen(); // Set ndX equal to a randomly-chosen child of ndY ndX = randomChild(ndY); x = ndX->GetEdgeLen(); // Set ndZ randomly to either the parent of ndY or one of ndY's sibs ndZ = chooseZ(ndY); z = ndZ->GetEdgeLen(); // Set ndBase to the deepest affected node //ndBase = ndZ->GetParent(); // Set node U to the other node (besides ndY) that could slide. // Note that U may or may not be equal to ndZ. TreeNode * ndU = ndY->GetParent(); m = x + y + z; expand_contract_factor = exp(lambda*(rng->Uniform() - 0.5)); mstar = m*expand_contract_factor; xstar = x*expand_contract_factor; ndX->SetEdgeLen(xstar); ystar = y*expand_contract_factor; ndY->SetEdgeLen(ystar); zstar = z*expand_contract_factor; ndZ->SetEdgeLen(zstar); double d = rng->Uniform()*mstar; // Decide whether to move ndY a distance d from the top, or // move ndU a distance d from the bottom bool moving_Y = true; if (rng->Uniform() < 0.5) moving_Y = false; bool moving_U = !moving_Y; // Determine whether proposed move will change the topology topol_changed = false; if (moving_Y && d >= xstar + ystar) topol_changed = true; if (moving_U && d >= ystar + zstar) topol_changed = true; if (topol_changed) { jpm->allEdgeLensModified(tree); jpm->topologyModified("tree_topology", tree); //jpm->externalEdgeLensModified("external_edgelen", tree); //jpm->internalEdgeLensModified("internal_edgelen", tree); if (moving_Y) { double f = (d - xstar - ystar)/zstar; if (ndU == ndZ) { which_case = 6; //ndX->SelectNode(); //ndY->SelectNode(); //ndZ->SelectNode(); //std::string titlestr = str(boost::format("%s, %s: f = %.8f, d = %.8f, r = %.8f, x = %.8f, y = %.8f, z = %.8f") % (moving_Y ? "Y" : "U") % (topol_changed ? "nni" : "nul") % f % d % expand_contract_factor % x % y % z); //likelihood->startTreeViewer(tree, titlestr); likelihood->slideNode(-1.0, ndY, ndX); // move all of Y's edge to base of X //titlestr = str(boost::format("Before NNISwapSpecial: x = %.8f, y = %.8f, z = %.8f") % ndX->GetEdgeLen() % ndY->GetEdgeLen() % ndZ->GetEdgeLen()); //likelihood->startTreeViewer(tree, titlestr); swap1 = ndX; swap2 = ndZ->GetParent(); tree_manipulator.NNISwapSpecial(swap1); // moves Y below Z likelihood->swapInternalDataAndEdgeLen(ndY, ndZ); //titlestr = str(boost::format("After NNISwapSpecial: x = %.8f, y = %.8f, z = %.8f") % ndX->GetEdgeLen() % ndY->GetEdgeLen() % ndZ->GetEdgeLen()); //likelihood->startTreeViewer(tree, titlestr); likelihood->slideNode(1.0 - f, ndZ, ndY); //titlestr = str(boost::format("After final slideNode: x = %.8f, y = %.8f, z = %.8f") % ndX->GetEdgeLen() % ndY->GetEdgeLen() % ndZ->GetEdgeLen()); //likelihood->startTreeViewer(tree, titlestr); } else { which_case = 3; likelihood->slideNode(-1.0, ndY, ndX); // move all of Y's edge to base of X swap1 = ndX; swap2 = ndZ; tree_manipulator.NNISwap(swap1, swap2); // nearest-neighbor interchange likelihood->slideNode(f, ndY, ndZ); // move a fraction f of the basal part of Z's edge onto Y } } else { double f = (d - zstar - ystar)/xstar; // positive f means slide ndU up past ndY toward ndX if (ndU == ndZ) { which_case = 12; //ndX->SelectNode(); //ndY->SelectNode(); //ndZ->SelectNode(); //std::string titlestr = str(boost::format("%s, %s: f = %.8f, d = %.8f, r = %.8f, x = %.8f, y = %.8f, z = %.8f") % (moving_Y ? "Y" : "U") % (topol_changed ? "nni" : "nul") % f % d % expand_contract_factor % x % y % z); //likelihood->startTreeViewer(tree, titlestr); likelihood->slideNode(-1.0, ndZ, ndY); // move all of Z's edge to base of Y swap1 = ndX; swap2 = ndZ->GetParent(); tree_manipulator.NNISwapSpecial(swap1); // moves Y below Z likelihood->swapInternalDataAndEdgeLen(ndY, ndZ); //titlestr = str(boost::format("After NNISwapSpecial: x = %.8f, y = %.8f, z = %.8f") % ndX->GetEdgeLen() % ndY->GetEdgeLen() % ndZ->GetEdgeLen()); //likelihood->startTreeViewer(tree, titlestr); likelihood->slideNode(f, ndY, ndX); // move a fraction f of the basal part of X's edge onto Y //titlestr = str(boost::format("After slideNode: x = %.8f, y = %.8f, z = %.8f") % ndX->GetEdgeLen() % ndY->GetEdgeLen() % ndZ->GetEdgeLen()); //likelihood->startTreeViewer(tree, titlestr); } else { which_case = 9; likelihood->slideNode(-1.0, ndY, ndZ); // move all of Y's edge to base of Z likelihood->slideNode(f, ndY, ndX); // move a fraction f of the basal part of X's edge onto Y swap1 = ndX; swap2 = ndZ; tree_manipulator.NNISwap(swap1, swap2); // nearest-neighbor interchange } } } else // topol_changed { jpm->allEdgeLensModified(tree); //jpm->externalEdgeLensModified("external_edgelen", tree); //jpm->internalEdgeLensModified("internal_edgelen", tree); if (moving_Y) { if (d < xstar) { // sliding Y up if (ndU == ndZ) which_case = 4; else which_case = 1; double f = (xstar - d)/xstar; // positive f means slide ndY up likelihood->slideNode(f, ndY, ndX); // slide ndY up a fraction f into ndX's edge } else { // sliding Y down if (ndU == ndZ) which_case = 5; else which_case = 2; double f = -(d - xstar)/ystar; // negative f means slide ndY down likelihood->slideNode(f, ndY, ndX); // slide ndY down a fraction f into its own edge } } else // moving U { if (d < zstar) { // sliding U down if (ndU == ndZ) { which_case = 11; double f = -(zstar - d)/zstar; // negative f means slide ndZ down likelihood->slideNode(f, ndZ, ndY); // slide ndZ down a fraction f into its own edge } else { which_case = 8; double f = -(zstar - d)/zstar; // negative f means slide ndU down likelihood->slideNode(f, ndZ, ndY); // slide ndU "down" a fraction f into ndZ's edge } } else { // sliding U up if (ndU == ndZ) { which_case = 10; double f = (d - zstar)/ystar; // positive f means slide ndZ up likelihood->slideNode(f, ndZ, ndY); // slide ndZ up a fraction f into ndY's edge } else { which_case = 7; double f = (d - zstar)/ystar; // positive f means slide ndU up //ndX->SelectNode(); //ndY->SelectNode(); //ndZ->SelectNode(); //std::string titlestr = str(boost::format("Before slideNode: %s, %s: f = %.8f, d = %.8f, r = %.8f, x = %.8f, y = %.8f, z = %.8f") % (moving_Y ? "Y" : "U") % (topol_changed ? "nni" : "nul") % f % d % expand_contract_factor % ndX->GetEdgeLen() % ndY->GetEdgeLen() % ndZ->GetEdgeLen()); //likelihood->startTreeViewer(tree, titlestr); likelihood->slideNode(f, ndZ, ndY); // slide ndU up a fraction f into ndY's edge //titlestr = str(boost::format("After slideNode: %s, %s: f = %.8f, d = %.8f, r = %.8f, x = %.8f, y = %.8f, z = %.8f") % (moving_Y ? "Y" : "U") % (topol_changed ? "nni" : "nul") % f % d % expand_contract_factor % ndX->GetEdgeLen() % ndY->GetEdgeLen() % ndZ->GetEdgeLen()); //likelihood->startTreeViewer(tree, titlestr); } } } } ndX->SelectNode(); ndY->SelectNode(); ndZ->SelectNode(); PHYCAS_ASSERT(ndY->IsInternal()); if (!likelihood->getNoData()) { likelihood->useAsLikelihoodRoot(ndY); likelihood->invalidateAwayFromNode(*ndY); likelihood->invalidateBothEnds(ndY); //@POL temp //likelihood->invalidateBothEnds(ndZ); } }
/*---------------------------------------------------------------------------------------------------------------------- | Calls proposeNewState(), then decides whether to accept or reject the proposed new state, calling accept() or | revert(), whichever is appropriate. */ bool LargetSimonMove::update() { // The only case in which is_fixed is true occurs when the user decides to fix the edge lengths. // A proposed LargetSimonMove cannot be accepted without changing edge lengths, so it is best to bail out now. if (is_fixed) return false; tree->renumberInternalNodes(tree->GetNTips()); //@POL this should be somewhere else tree->RecalcAllSplits(tree->GetNTips()); ChainManagerShPtr p = chain_mgr.lock(); PHYCAS_ASSERT(p); JointPriorManagerShPtr jpm = p->getJointPriorManager(); // compute the likelihood before proposing a new state double prev_ln_like = p->getLastLnLike(); double prev_ln_prior = jpm->getLogJointPrior(); TreeNode * prev_likelihood_root = likelihood->getLikelihoodRoot(); double prev_ln_ref_dist = 0.0; if (use_ref_dist) { prev_ln_ref_dist = recalcWorkingPrior(); } //likelihood->startTreeViewer(tree, boost::str(boost::format("LS move BEFORE: %.5f") % prev_ln_like)); proposeNewState(); curr_ln_like = (heating_power > 0.0 ? likelihood->calcLnL(tree) : 0.0); //likelihood->startTreeViewer(tree, boost::str(boost::format("LS move AFTER: %.5f") % curr_ln_like)); curr_ln_prior = jpm->getLogJointPrior(); double curr_ln_ref_dist = 0.0; if (likelihood->getTreeLengthPrior()) { PHYCAS_ASSERT(!use_ref_dist); // not ready for this yet curr_ln_prior = likelihood->getTreeLengthPrior()->GetLnPDF(tree); } else { if (use_ref_dist) { curr_ln_ref_dist = recalcWorkingPrior(); } } double prev_posterior = 0.0; double curr_posterior = 0.0; if (is_standard_heating) { prev_posterior = heating_power*(prev_ln_like + prev_ln_prior); curr_posterior = heating_power*(curr_ln_like + curr_ln_prior); if (use_ref_dist) { prev_posterior += (1.0 - heating_power)*prev_ln_ref_dist; curr_posterior += (1.0 - heating_power)*curr_ln_ref_dist; } } else { prev_posterior = heating_power*prev_ln_like + prev_ln_prior; curr_posterior = heating_power*curr_ln_like + curr_ln_prior; } double ln_accept_ratio = curr_posterior - prev_posterior + getLnHastingsRatio() + getLnJacobian(); double lnu = DBL_MAX; bool accepted = (ln_accept_ratio >= 0.0); if (!accepted) { double u = rng->Uniform(); lnu = std::log(u); accepted = (lnu <= ln_accept_ratio); } if (save_debug_info) { if (star_tree_proposal) { debug_info = str(boost::format("LS: %.5f -> %.5f (%s)") % orig_edge_len % orig_node->GetEdgeLen() % (accepted ? "accepted" : "rejected")); } else { debug_info = boost::str(boost::format("%s, prev_ln_like = %.5f, getLastLnLike() = %.5f, curr_ln_like = %.5f, topology %s, case = %d, x=%f, y=%f, z=%f, newX=%f, newY=%f, newZ=%f, lnu = %.5f, lnr = %.5f, curr = %.5f, prev = %.5f") % (accepted ? "ACCEPT" : "REJECT") % prev_ln_like % p->getLastLnLike() % curr_ln_like % (topol_changed ? "changed" : "unchanged") % which_case % x % y % z % (ndX->GetEdgeLen()) % (ndY->GetEdgeLen()) % (ndZ->GetEdgeLen()) % (lnu == DBL_MAX ? -1.0 : lnu) % ln_accept_ratio % curr_posterior % prev_posterior); if (is_standard_heating) { if (use_ref_dist) { debug_info += boost::str(boost::format("\n prev_posterior = %g = %g*(%g + %g) + (1.0 - %g)*%g") % prev_posterior % heating_power % prev_ln_like % prev_ln_prior % heating_power % prev_ln_ref_dist ); debug_info += boost::str(boost::format("\n curr_posterior = %g = %g*(%g + %g) + (1.0 - %g)*%g") % curr_posterior % heating_power % curr_ln_like % curr_ln_prior % heating_power % curr_ln_ref_dist ); } else { debug_info += boost::str(boost::format("\n prev_posterior = %g = %g*(%g + %g)") % prev_posterior % heating_power % prev_ln_like % prev_ln_prior ); debug_info += boost::str(boost::format("\n curr_posterior = %g = %g*(%g + %g)") % curr_posterior % heating_power % curr_ln_like % curr_ln_prior ); } } else { debug_info += boost::str(boost::format("\n prev_posterior = %g = %g*%g + %g") % prev_posterior % heating_power % prev_ln_like % prev_ln_prior ); debug_info += boost::str(boost::format("\n curr_posterior = %g = %g*%g + %g") % curr_posterior % heating_power % curr_ln_like % curr_ln_prior ); } if (!prev_likelihood_root) debug_info += "\n prev_likelihood_root = NULL"; else debug_info += boost::str(boost::format("\n prev_likelihood_root = %g") % prev_likelihood_root->GetNodeNumber()); TreeNode * tmp_curr_likelihood_root = likelihood->getLikelihoodRoot(); if (!tmp_curr_likelihood_root) debug_info += "\n curr_likelihood_root = NULL"; else debug_info += boost::str(boost::format("\n curr_likelihood_root = %g") % tmp_curr_likelihood_root->GetNodeNumber()); } } if (accepted) { p->setLastLnLike(curr_ln_like); accept(); } else { curr_ln_like = p->getLastLnLike(); revert(); PHYCAS_ASSERT(!prev_likelihood_root || prev_likelihood_root->IsInternal()); likelihood->useAsLikelihoodRoot(prev_likelihood_root); } //POLTMP lambda = p->adaptUpdater(lambda, nattempts, accepted); //std::cerr << boost::str(boost::format("~~~> log(lambda) = %.5f <~~~") % log(lambda)) << std::endl; return accepted; }
/*---------------------------------------------------------------------------------------------------------------------- | Calls the sample() member function of the `slice_sampler' data member. */ bool TreeScalerMove::update() { if (is_fixed) return false; ChainManagerShPtr p = chain_mgr.lock(); PHYCAS_ASSERT(p); JointPriorManagerShPtr jpm = p->getJointPriorManager(); bool using_tree_length_prior = jpm->isTreeLengthPrior(); // If first edge length master param returns false for useWorkingPrior(), then we are using // Mark Holder's variable tree topology reference distribution (see _provideRefDistToUpdaters in MCMCImpl.py) MCMCUpdaterVect::const_iterator it = p->getEdgeLenParams().begin(); bool using_vartopol_prior = !(*it)->useWorkingPrior(); double prev_ln_prior = jpm->getLogJointPrior(); double prev_ln_like = p->getLastLnLike(); double prev_ln_ref_dist = (use_ref_dist ? recalcWorkingPriorForMove(using_tree_length_prior, using_vartopol_prior) : 0.0); proposeNewState(); if (jpm->isTreeLengthPrior()) jpm->treeLengthModified("tree_length", tree); else jpm->allEdgeLensModified(tree); curr_ln_prior = jpm->getLogJointPrior(); likelihood->useAsLikelihoodRoot(NULL); // invalidates all CLAs double curr_ln_like = (heating_power > 0.0 ? likelihood->calcLnL(tree) : 0.0); double curr_ln_ref_dist = (use_ref_dist ? recalcWorkingPriorForMove(using_tree_length_prior, using_vartopol_prior) : 0.0); double prev_posterior = 0.0; double curr_posterior = 0.0; if (is_standard_heating) { prev_posterior = heating_power*(prev_ln_like + prev_ln_prior); curr_posterior = heating_power*(curr_ln_like + curr_ln_prior); if (use_ref_dist) { prev_posterior += (1.0 - heating_power)*prev_ln_ref_dist; curr_posterior += (1.0 - heating_power)*curr_ln_ref_dist; } } else { prev_posterior = heating_power*prev_ln_like + prev_ln_prior; curr_posterior = heating_power*curr_ln_like + curr_ln_prior; } double ln_hastings = getLnHastingsRatio(); double ln_accept_ratio = curr_posterior - prev_posterior + ln_hastings; double lnu = std::log(rng->Uniform()); bool accepted = false; if (ln_accept_ratio >= 0.0 || lnu <= ln_accept_ratio) { if (save_debug_info) { debug_info = boost::str(boost::format("ACCEPT, forward_scaler = %.5f, prev_ln_prior = %.5f, curr_ln_prior = %.5f, prev_ln_like = %.5f, curr_ln_like = %.5f, lnu = %.5f, ln_accept_ratio = %.5f") % forward_scaler % prev_ln_prior % curr_ln_prior % prev_ln_like % curr_ln_like % lnu % ln_accept_ratio); } p->setLastLnLike(curr_ln_like); accept(); accepted = true; } else { if (save_debug_info) { debug_info = boost::str(boost::format("REJECT, forward_scaler = %.5f, prev_ln_prior = %.5f, curr_ln_prior = %.5f, prev_ln_like = %.5f, curr_ln_like = %.5f, lnu = %.5f, ln_accept_ratio = %.5f") % forward_scaler % prev_ln_prior % curr_ln_prior % prev_ln_like % curr_ln_like % lnu % ln_accept_ratio); } curr_ln_like = p->getLastLnLike(); revert(); accepted = false; } //POLTMP lambda = p->adaptUpdater(lambda, nattempts, accepted); return accepted; }
/*---------------------------------------------------------------------------------------------------------------------- | Calls proposeNewState(), then decides whether to accept or reject the proposed new state, calling accept() or | revert(), whichever is appropriate. | | We actually generate a new mapping all the time (in proposeNewState). Then we change the branch length. The branch length | change might be rejected. */ bool UnimapEdgeMove::update() { #if 1 || DISABLED_UNTIL_UNIMAP_WORKING_WITH_PARTITIONING // The only case in which is_fixed is true occurs when the user decides to fix the edge lengths. // A proposed UnimapEdgeMove cannot be accepted without changing edge lengths, so it is best to just bail out now. if (is_fixed) return false; // std::cerr << "****** UnimapEdgeMove::update" << std::endl; ChainManagerShPtr p = chain_mgr.lock(); PHYCAS_ASSERT(p); //likelihood->fullRemapping(tree, rng, true); ///@TEMP!!!! proposeNewState(); PartitionModelShPtr partModel = likelihood->getPartitionModel(); const unsigned nSubsets = partModel->getNumSubsets(); std::vector<double> uniformization_lambda(nSubsets); for (unsigned i = 0; i < nSubsets; ++i) { ModelShPtr subMod = partModel->getModel(i); uniformization_lambda[i] = subMod->calcUniformizationLambda(); } bool is_internal_edge = origNode->IsInternal(); double prev_ln_prior = (is_internal_edge ? p->calcInternalEdgeLenPriorUnnorm(origEdgelen) : p->calcExternalEdgeLenPriorUnnorm(origEdgelen)); double curr_edgelen = r*origEdgelen; double curr_ln_prior = (is_internal_edge ? p->calcInternalEdgeLenPriorUnnorm(curr_edgelen) : p->calcExternalEdgeLenPriorUnnorm(curr_edgelen)); double log_posterior_ratio = 0.0; const double log_prior_ratio = curr_ln_prior - prev_ln_prior; double log_likelihood_ratio = (double)mdot*log(r); const double edgeLenDiff = (curr_edgelen - origEdgelen); for (unsigned i = 0; i < nSubsets; ++i) { const unsigned numSites = partModel->getNumSites(i); const double ul = uniformization_lambda[i]; PHYCAS_ASSERT(ul > 0.0); log_likelihood_ratio -= numSites*ul*edgeLenDiff; } likelihood->incrementNumLikelihoodEvals(); if (is_standard_heating) log_posterior_ratio = heating_power*(log_likelihood_ratio + log_prior_ratio); else log_posterior_ratio = heating_power*log_likelihood_ratio + log_prior_ratio; double ln_accept_ratio = log_posterior_ratio + getLnHastingsRatio(); double lnu = std::log(rng->Uniform(FILE_AND_LINE)); /* std::cerr << " log_likelihood_ratio = " << log_likelihood_ratio << '\n'; std::cerr << " log_posterior_ratio = " << log_posterior_ratio << '\n'; std::cerr << " ln_accept_ratio = " << ln_accept_ratio << '\n'; */ if (ln_accept_ratio >= 0.0 || lnu <= ln_accept_ratio) { p->setLastLnPrior(p->getLastLnPrior() + log_prior_ratio); p->setLastLnLike(p->getLastLnLike() + log_likelihood_ratio); accept(); return true; } else { curr_ln_like = p->getLastLnLike(); curr_ln_prior = p->getLastLnPrior(); revert(); return false; } #else return true; #endif }
/*---------------------------------------------------------------------------------------------------------------------- | Calls proposeNewState(), then decides whether to accept or reject the proposed new state, calling accept() or | revert(), whichever is appropriate. */ bool EdgeMove::update() { // The only case in which is_fixed is true occurs when the user decides to fix the edge lengths. // A proposed EdgeMove cannot be accepted without changing edge lengths, so it is best to just bail out now. if (is_fixed) return false; ChainManagerShPtr p = chain_mgr.lock(); PHYCAS_ASSERT(p); double prev_ln_like = p->getLastLnLike(); PHYCAS_ASSERT(!likelihood->getTreeLengthPrior()); // not ready for this yet proposeNewState(); bool is_internal_edge = origNode->IsInternal(); double prev_ln_prior = (is_internal_edge ? p->calcInternalEdgeLenPriorUnnorm(origEdgelen) : p->calcExternalEdgeLenPriorUnnorm(origEdgelen)); double prev_ln_ref_dist = 0.0; double curr_ln_like = (heating_power > 0.0 ? likelihood->calcLnL(tree) : 0.0); double curr_edgelen = origNode->GetEdgeLen(); double curr_ln_prior = (is_internal_edge ? p->calcInternalEdgeLenPriorUnnorm(curr_edgelen) : p->calcExternalEdgeLenPriorUnnorm(curr_edgelen)); double curr_ln_ref_dist = 0.0; double prev_posterior = 0.0; double curr_posterior = 0.0; if (is_standard_heating) { prev_posterior = heating_power*(prev_ln_like + prev_ln_prior); curr_posterior = heating_power*(curr_ln_like + curr_ln_prior); if (use_ref_dist) { prev_posterior += (1.0 - heating_power)*prev_ln_ref_dist; curr_posterior += (1.0 - heating_power)*curr_ln_ref_dist; } } else { prev_posterior = heating_power*prev_ln_like + prev_ln_prior; curr_posterior = heating_power*curr_ln_like + curr_ln_prior; } double ln_hastings = getLnHastingsRatio(); double ln_accept_ratio = curr_posterior - prev_posterior + ln_hastings; double lnu = std::log(rng->Uniform()); bool accepted = false; if (ln_accept_ratio >= 0.0 || lnu <= ln_accept_ratio) { p->setLastLnLike(curr_ln_like); accept(); accepted = true; } else { curr_ln_like = p->getLastLnLike(); revert(); accepted = false; } //POLTMP lambda = p->adaptUpdater(lambda, nattempts, accepted); return accepted; }