示例#1
0
/**
 * 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;
}
示例#2
0
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;
}