/** * Perform the proposal. * * An element swap simplex proposal simply selects two random elements of a simplex * and swaps them. * * \return The hastings ratio. */ double ElementSwapSimplexProposal::propose( RbVector<double> &value ) { // Get random number generator RandomNumberGenerator* rng = GLOBAL_RNG; // store the value storedValue = value; // we need to know the number of categories size_t cats = value.size(); // randomly draw two indices size_t chosen_index_1 = size_t( floor(rng->uniform01()*double(cats)) ); size_t chosen_index_2 = size_t( floor(rng->uniform01()*double(cats)) ); while (chosen_index_1 == chosen_index_2) { chosen_index_2 = size_t( floor(rng->uniform01()*double(cats)) ); } // swap the values double value_1 = value[chosen_index_1]; double value_2 = value[chosen_index_2]; value[chosen_index_1] = value_2; value[chosen_index_2] = value_1; double ln_Hastins_ratio = 0; return ln_Hastins_ratio; }
StitchTreeFunction::StitchTreeFunction(const TypedDagNode<Tree> *bt, const TypedDagNode<RbVector<Tree> >* pc, RbVector<RbVector<Taxon> > pt) : TypedFunction<Tree>( new Tree() ), backboneTree( bt ), patchClades( pc ), patchTaxa( pt ), numPatches( pt.size() ), haveIndex(false) { // add the lambda parameter as a parent addParameter( bt ); addParameter( pc ); initTaxonGroups(); value = new Tree(); update(); }
void MonteCarloAnalysis::runPriorSampler( size_t kIterations , RbVector<StoppingRule> rules ) { // Let user know what we are doing std::stringstream ss; if ( runs[0]->getCurrentGeneration() == 0 ) { ss << "\n"; ss << "Running prior MCMC simulation\n"; } else { ss << "Appending to previous MCMC simulation of " << runs[0]->getCurrentGeneration() << " iterations\n"; } ss << "This simulation runs " << replicates << " independent replicate" << (replicates > 1 ? "s" : "") << ".\n"; ss << runs[0]->getStrategyDescription(); RBOUT( ss.str() ); // Initialize objects needed by chain for (size_t i=0; i<replicates; ++i) { runs[i]->initializeSampler(true); } if ( runs[0]->getCurrentGeneration() == 0 ) { // Monitor for (size_t i=0; i<replicates; ++i) { runs[i]->startMonitors( kIterations ); runs[i]->monitor(0); } } // reset the counters for the move schedules for (size_t i=0; i<replicates; ++i) { runs[i]->reset(); } // reset the stopping rules for (size_t i=0; i<rules.size(); ++i) { rules[i].runStarted(); } // Run the chain bool finished = false; bool converged = false; size_t gen = runs[0]->getCurrentGeneration(); do { ++gen; for (size_t i=0; i<replicates; ++i) { runs[i]->nextCycle(true); // Monitor runs[i]->monitor(gen); } converged = true; size_t numConvergenceRules = 0; // do the stopping test for (size_t i=0; i<rules.size(); ++i) { if ( rules[i].isConvergenceRule() ) { converged &= rules[i].checkAtIteration(gen) && rules[i].stop( gen ); ++numConvergenceRules; } else { if ( rules[i].checkAtIteration(gen) && rules[i].stop( gen ) ) { finished = true; break; } } } converged &= numConvergenceRules > 0; } while ( finished == false && converged == false); }
/** * Perform the proposal. * * A Dirichlet-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 ~ Dirichlet(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 DirichletSimplexProposal::doProposal( void ) { // Get random number generator RandomNumberGenerator* rng = GLOBAL_RNG; // store the value storedValue = variable->getValue(); const RbVector<double>& curVal = variable->getValue(); RbVector<double> newVal = curVal; size_t n = curVal.size(); /* We update the simplex values by proposing new values from a Dirichlet centered on the current values. The i-th parameter of the Dirichlet is the i-th value in the simplex multiplied by a parameter (alpha0, AKA tuning) that controls the variance of the Dirichlet. We implement two cases of this general move. In one case, all of the elements of the simplex are targeted for update (n == k). In the other, more complicated, case a subset of the elements of the simplex are updated (k < n). Here, we construct a smaller simplex with k+1 elements. The first k of the elements are the values from the full simplex that were targeted for update. The last element of the smaller simplex accumulates the probabilities of all of the simplex values in the full simplex that were not targeted for update. We then update the small simplex by centering a Dirichlet on the small simplex. The values for those elements in the full simplex that were not targeted for update are all changed proportionally. This means that we need to calculate the Jacobian for the Hastings ratio in this case. */ double lnProposalRatio = 0.0; if ( nCategories > n ) { // we can't update more elements than there are elements in the simplex throw RbException( "Attempting to update too many simplex variables" ); } else if ( nCategories < 1 ) { // we also can't update 0 or a negative number of elements throw RbException( "Attempting to update too few simplex variables" ); } else if ( nCategories < n ) { // we update a subset of the elements in the full simplex // pick k values at random, producing a map from the index in the full vector (curVal) to // the index in the reduced vector (x, alpha, and z) std::vector<size_t> indicesToUpdate; std::vector<size_t> tmpV; for (size_t i=0; i<n; i++) { tmpV.push_back(i); } RbStatistics::Helper::randomlySelectFromVectorWithoutReplacement<size_t>(tmpV, indicesToUpdate, nCategories, *rng); std::map<size_t,size_t> mapper; for (size_t i=0; i<indicesToUpdate.size(); i++) { mapper.insert( std::make_pair(indicesToUpdate[i], i) ); } // set up the vectors std::vector<double> x(indicesToUpdate.size()+1, 0.0); std::vector<double> kappaV(indicesToUpdate.size()+1, 0.0); std::vector<double> alphaForward(indicesToUpdate.size()+1, 0.0); std::vector<double> alphaReverse(indicesToUpdate.size()+1, 0.0); std::vector<double> z(indicesToUpdate.size()+1, 0.0); for (size_t i=0; i<n; i++) { std::map<size_t,size_t>::iterator it = mapper.find(i); if (it != mapper.end()) { x[it->second] += curVal[it->first]; kappaV[it->second] += kappa; } else { x[x.size()-1] += curVal[i]; kappaV[kappaV.size()-1] += kappa; } } for (size_t i=0; i<x.size(); i++) { alphaForward[i] = (x[i]+offset) * alpha + kappaV[i]; } // draw a new value for the reduced vector z = RbStatistics::Dirichlet::rv( alphaForward, *rng ); // fill in the Dirichlet parameters for the reverse probability calculations for (size_t i=0; i<z.size(); i++) { alphaReverse[i] = (z[i]+offset) * alpha + kappaV[i]; } // fill in the full vector double factor = z[z.size()-1] / x[x.size()-1]; for (size_t i=0; i<n; i++) { std::map<size_t,size_t>::iterator it = mapper.find(i); if (it != mapper.end()) { newVal[i] = z[it->second]; } else { newVal[i] = curVal[i] * factor; } // test for 0-values if ( newVal[i] < 1E-100) { return RbConstants::Double::neginf; } } try { // Hastings ratio lnProposalRatio = RbStatistics::Dirichlet::lnPdf(alphaReverse, x) - RbStatistics::Dirichlet::lnPdf(alphaForward, z); // Hastings Ratio lnProposalRatio += (n - nCategories) * log(factor); // Jacobian } catch (RbException e) { lnProposalRatio = RbConstants::Double::neginf; } } else { // we update all of the elements in the vector // first, we get the parameters of the Dirichlet for the forward move std::vector<double> alphaForward(curVal.size()); for (size_t i=0; i<curVal.size(); i++) { alphaForward[i] = (curVal[i]+offset) * alpha + kappa; // we need to check for 0 values if (alphaForward[i] < 1E-100) { // very low proposal probability which will hopefully result into a rejected proposal return RbConstants::Double::neginf; } } // then, we propose new values newVal = RbStatistics::Dirichlet::rv( alphaForward, *rng ); // and calculate the Dirichlet parameters for the (imagined) reverse move std::vector<double> alphaReverse(newVal.size()); for (size_t i=0; i<curVal.size(); i++) { alphaReverse[i] = (newVal[i]+offset) * alpha + kappa; // we need to check for 0 values if (alphaReverse[i] < 1E-100) { // very low proposal probability which will hopefully result into a rejected proposal return RbConstants::Double::neginf; } } try { // finally, we calculate the log of the Hastings ratio lnProposalRatio = RbStatistics::Dirichlet::lnPdf(alphaReverse, curVal) - RbStatistics::Dirichlet::lnPdf(alphaForward, newVal); } catch (RbException e) { lnProposalRatio = RbConstants::Double::neginf; } } variable->setValue( new RbVector<double>(newVal), false ); return lnProposalRatio; }