/** * Constructor * * Here we simply allocate and initialize the move object. * * \param[in] w The weight how often the proposal will be used (per iteration). * \param[in] t If auto tuning should be used. */ MetropolisHastingsMove::MetropolisHastingsMove( Proposal *p, double w, bool t ) : AbstractMove(w,t), affectedNodes(), nodes(), numAccepted( 0 ), proposal( p ) { nodes = proposal->getNodes(); for (std::set<DagNode*>::iterator it = nodes.begin(); it != nodes.end(); ++it) { // get the pointer to the current node DagNode* theNode = *it; // add myself to the set of moves theNode->addMove( this ); // increase the DAG node reference count because we also have a pointer to it theNode->incrementReferenceCount(); // get the affected nodes if we would update this node // then we don't need to get the affected nodes every time again theNode->getAffectedNodes( affectedNodes ); } // remove all "core" nodes from affectedNodes so their probabilities are not double-counted for (size_t i = 0; i < affectedNodes.size(); ++i) { std::set<DagNode*>::iterator it = affectedNodes.begin(); std::advance(it, i); if ( nodes.find(*it) != nodes.end() ) { affectedNodes.erase(*it); --i; } } }
/** * Swap the current variable for a new one. * * \param[in] oldN The old variable that needs to be replaced. * \param[in] newN The new variable. */ void AbstractMove::swapNode(DagNode *oldN, DagNode *newN) { // find the old node for (size_t i = 0; i < nodes.size(); ++i) { // get the pointer to the current node DagNode* theNode = nodes[i]; if ( theNode == oldN ) { nodes[i] = newN; } } // remove myself from the old node and add myself to the new node oldN->removeMove( this ); newN->addMove( this ); // increment and decrement the reference counts newN->incrementReferenceCount(); if ( oldN->decrementReferenceCount() == 0 ) { throw RbException("Memory leak in Metropolis-Hastings move. Please report this bug to Sebastian."); } affectedNodes.clear(); for (std::vector<DagNode*>::iterator it = nodes.begin(); it != nodes.end(); ++it) { // get the pointer to the current node DagNode* theNode = *it; // get the affected nodes if we would update this node // then we don't need to get the affected nodes every time again theNode->getAffectedNodes( affectedNodes ); } // remove all "core" nodes from affectedNodes so their probabilities are not double-counted for (size_t i = 0; i < affectedNodes.size(); ++i) { RbOrderedSet<DagNode*>::iterator it = affectedNodes.begin(); std::advance(it, i); for (size_t j = 0; j < nodes.size(); ++j) { if ( nodes[j] == *it ) { affectedNodes.erase(*it); --i; break; } } } swapNodeInternal(oldN, newN); }