/** * 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; }
/** * Perform the proposal. * * A scaling Proposal draws a random uniform number u ~ unif(-0.5,0.5) * and scales the current vale by a scaling factor * sf = exp( lambda * u ) * where lambda is the tuning parameter of the Proposal to influence the size of the proposals. * * \return The hastings ratio. */ double VectorSingleElementScaleProposal::doProposal( void ) { // Get random number generator RandomNumberGenerator* rng = GLOBAL_RNG; RbVector<double> &val = variable->getValue(); // choose an index index = size_t(rng->uniform01() * val.size()); // copy value storedValue = val[index]; // Generate new value (no reflection, so we simply abort later if we propose value here outside of support) double u = rng->uniform01(); double scalingFactor = std::exp( lambda * ( u - 0.5 ) ); val[index] *= scalingFactor; variable->addTouchedElementIndex(index); // compute the Hastings ratio double lnHastingsratio = log( scalingFactor ); return lnHastingsratio; }
double MatrixRealSymmetricSlideMove::performSimpleMove( void ) { // Get random number generator RandomNumberGenerator* rng = GLOBAL_RNG; MatrixReal& mymat = variable->getValue(); size_t dim = mymat.getDim(); size_t indexa = size_t( rng->uniform01() * dim ); size_t indexb = size_t( rng->uniform01() * dim ); stored_i = indexa; stored_j = indexb; storedValue = mymat[stored_i][stored_j]; double u = rng->uniform01(); double m = lambda * (u - 0.5); mymat[indexa][indexb] += m; if ( indexa != indexb ) { mymat[indexb][indexa] = mymat[indexa][indexb]; } return 0; }
/*! * This function is used when generating gamma-distributed random variables. * * \brief Subfunction for gamma random variables. * \param s is the shape parameter of the gamma. * \return Returns a gamma-distributed random variable. * \throws Does not throw an error. */ double RbStatistics::Helper::rndGamma1(double s, RandomNumberGenerator& rng) { double r, x = 0.0, small = 1e-37, w; static double a, p, uf, ss = 10.0, d; if (s != ss) { a = 1.0 - s; p = a / (a + s * exp(-a)); uf = p * pow(small / a, s); d = a * log(a); ss = s; } for (;;) { r = rng.uniform01(); if (r > p) x = a - log((1.0 - r) / (1.0 - p)), w = a * log(x) - d; else if (r>uf) x = a * pow(r / p, 1.0 / s), w = x; else return (0.0); r = rng.uniform01(); if (1.0 - r <= w && r > 0.0) if (r*(w + 1.0) >= 1.0 || -log(r) <= w) continue; break; } return (x); }
/*! * This function is used when generating gamma-distributed random variables. * * \brief Subfunction for gamma random variables. * \param s is the shape parameter of the gamma. * \return Returns a gamma-distributed random variable. * \throws Does not throw an error. */ double RbStatistics::Helper::rndGamma2(double s, RandomNumberGenerator& rng) { double r, d, f, g, x; static double b, h, ss = 0.0; if (s != ss) { b = s - 1.0; h = sqrt(3.0 * s - 0.75); ss = s; } for (;;) { r = rng.uniform01(); g = r - r * r; f = (r - 0.5) * h / sqrt(g); x = b + f; if (x <= 0.0) continue; r = rng.uniform01(); d = 64.0 * r * r * g * g * g; if (d * x < x - 2.0 * f * f || log(d) < 2.0 * (b * log(x / b) - f)) break; } return (x); }
void RevBayesCore::DPPScaleCatAllocateAuxGibbs::doScaleTablesMove( void ) { // Get random number generator RandomNumberGenerator* rng = GLOBAL_RNG; DirichletProcessPriorDistribution<double>& dist = static_cast<DirichletProcessPriorDistribution<double> &>( variable->getDistribution() ); dist.createRestaurantVectors(); int numTables = dist.getNumberOfCategories(); int numElements = dist.getNumberOfElements(); std::vector<double> tableVals = dist.getTableParameters(); std::vector<int> allocVec = dist.getElementAllocationVec(); std::vector<double>& elementVals = variable->getValue(); TypedDistribution<double>* g0 = dist.getBaseDistribution(); double storedValue; variable->touch(); for(int i=0; i<numTables; i++){ // get old lnL double oldLnl = getCurrentLnProbabilityForMove(); storedValue = tableVals[i]; double u = rng->uniform01(); double scalingFactor = std::exp( lambda * ( u - 0.5 ) ); double newValue = storedValue * scalingFactor; tableVals[i] = newValue; // Assign new value to elements for(int j=0; j<numElements; j++){ if(allocVec[j] == i) elementVals[j] = tableVals[i]; } g0->getValue() = tableVals[i]; // new double priorRatio = g0->computeLnProbability(); g0->getValue() = storedValue; // old priorRatio -= g0->computeLnProbability(); variable->touch(); double newLnl = getCurrentLnProbabilityForMove(); double lnProbRatio = newLnl - oldLnl; double r = safeExponentiation(priorRatio + lnProbRatio + log(scalingFactor)); u = rng->uniform01(); if ( u < r ) //accept variable->keep(); else{ // reject for(int j=0; j<numElements; j++){ if(allocVec[j] == i) elementVals[j] = storedValue; } tableVals[i] = storedValue; variable->touch(); variable->keep(); } } dist.createRestaurantVectors(); }
/** * Perform the proposal. * * A Beta-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 ~ Beta(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 SubtreeScaleProposal::doProposal( void ) { // Get random number generator RandomNumberGenerator* rng = GLOBAL_RNG; TimeTree& tau = variable->getValue(); // pick a random node which is not the root and neither the direct descendant of the root TopologyNode* node; do { double u = rng->uniform01(); size_t index = size_t( std::floor(tau.getNumberOfNodes() * u) ); node = &tau.getNode(index); } while ( node->isRoot() || node->isTip() ); TopologyNode& parent = node->getParent(); // we need to work with the times double parent_age = parent.getAge(); double my_age = node->getAge(); // now we store all necessary values storedNode = node; storedAge = my_age; // lower bound double min_age = 0.0; TreeUtilities::getOldestTip(&tau, node, min_age); // draw new ages and compute the hastings ratio at the same time double my_new_age = min_age + (parent_age - min_age) * rng->uniform01(); double scalingFactor = my_new_age / my_age; size_t nNodes = node->getNumberOfNodesInSubtree(false); // rescale the subtrees TreeUtilities::rescaleSubtree(&tau, node, scalingFactor ); if (min_age != 0.0) { for (size_t i = 0; i < tau.getNumberOfTips(); i++) { if (tau.getNode(i).getAge() < 0.0) { return RbConstants::Double::neginf; } } } // compute the Hastings ratio double lnHastingsratio = (nNodes > 1 ? log( scalingFactor ) * (nNodes-1) : 0.0 ); return lnHastingsratio; }
/*! * This function generates a Poisson-distributed random variable for * small values of lambda. The method is a simple calculation of the * probabilities of x = 1 and x = 2. Larger values are ignored. * * \brief Poisson random variables for small lambda. * \param lambda is the rate parameter of the Poisson. * \return Returns a Poisson-distributed random variable. * \throws Does not throw an error. */ int RbStatistics::Helper::poissonLow(double lambda, RandomNumberGenerator& rng) { double d = sqrt(lambda); if (rng.uniform01() >= d) return 0; double r = rng.uniform01() * d; if (r > lambda * (1.0 - lambda)) return 0; if (r > 0.5 * lambda * lambda * (1.0 - lambda)) return 1; return 2; }
/** * Simulate new speciation times. */ double ConstantRateFossilizedBirthDeathProcess::simulateDivergenceTime(double orig, double present) const { // incorrect placeholder for constant FBDP // previous simSpeciations did not generate trees with defined likelihoods // Get the rng RandomNumberGenerator* rng = GLOBAL_RNG; // get the parameters double age = present - orig; double b = lambda->getValue(); double d = mu->getValue(); double r = rho->getValue(); // get a random draw double u = rng->uniform01(); // compute the time for this draw double t = 0.0; if ( b > d ) { t = ( log( ( (b-d) / (1 - (u)*(1-((b-d)*exp((d-b)*age))/(r*b+(b*(1-r)-d)*exp((d-b)*age) ) ) ) - (b*(1-r)-d) ) / (r * b) ) + (d-b)*age ) / (d-b); } else { t = ( log( ( (b-d) / (1 - (u)*(1-(b-d)/(r*b*exp((b-d)*age)+(b*(1-r)-d) ) ) ) - (b*(1-r)-d) ) / (r * b) ) + (d-b)*age ) / (d-b); } // return present - t; return orig + t; }
/** Perform the move */ double OriginTimeSlide::performSimpleMove( void ) { // Get random number generator RandomNumberGenerator* rng = GLOBAL_RNG; TimeTree& tau = tree->getValue(); TopologyNode& root = tau.getRoot(); // we need to work with the times double my_age = variable->getValue(); // now we store all necessary values storedAge = my_age; // get the minimum age double child_Age = root.getAge(); // draw new ages and compute the hastings ratio at the same time // Note: the Hastings ratio needs to be there because one of the nodes might be a tip and hence not scaled! double u = rng->uniform01(); double my_new_age = my_age + ( delta * ( u - 0.5 ) ); // check if the new age is lower than the minimum if ( my_new_age < child_Age ) { my_new_age = child_Age - (my_new_age - child_Age); } variable->setValue( new double(my_new_age) ); return 0.0; }
/** * Perform the proposal. * * * * \return The hastings ratio. */ double TreeScaleProposal::doProposal( void ) { // Get random number generator RandomNumberGenerator* rng = GLOBAL_RNG; Tree& tau = tree->getValue(); TopologyNode& node = tau.getRoot(); // we need to work with the times double my_age = node.getAge(); // now we store all necessary values storedAge = my_age; // draw new ages double u = rng->uniform01(); double scalingFactor = std::exp( delta * ( u - 0.5 ) ); // rescale the subtrees TreeUtilities::rescaleSubtree(&tau, &node, scalingFactor ); if ( rootAge != NULL ) { rootAge->setValue( new double(my_age * scalingFactor) ); } // compute the Hastings ratio double lnHastingsratio = log( scalingFactor ) * tau.getNumberOfInteriorNodes(); return lnHastingsratio; }
/*! * This function generates a Poisson-distributed random variable using * inversion by the chop down method. * * \brief Poisson random variables using the chop down method. * \param lambda is the rate parameter of the Poisson. * \return Returns a Poisson-distributed random variable. * \throws Does not throw an error. */ int RbStatistics::Helper::poissonInver(double lambda, RandomNumberGenerator& rng) { const int bound = 130; static double p_L_last = -1.0; static double p_f0; int x; if (lambda != p_L_last) { p_L_last = lambda; p_f0 = exp(-lambda); } while (1) { double r = rng.uniform01(); x = 0; double f = p_f0; do { r -= f; if (r <= 0.0) return x; x++; f *= lambda; r *= x; } while (x <= bound); } }
double EpisodicBirthDeathProcess::simulateDivergenceTime(double origin, double present, double rho) const { // Get the rng RandomNumberGenerator* rng = GLOBAL_RNG; // get the parameters double age = present - origin; double b = lambda_rates->getValue()[0]; double d = mu_rates->getValue()[0]; // get a random draw double u = rng->uniform01(); // compute the time for this draw double t = 0.0; if ( b > d ) { t = ( log( ( (b-d) / (1 - (u)*(1-((b-d)*exp((d-b)*age))/(rho*b+(b*(1-rho)-d)*exp((d-b)*age) ) ) ) - (b*(1-rho)-d) ) / (rho * b) ) + (d-b)*age ) / (d-b); } else { t = ( log( ( (b-d) / (1 - (u)*(1-(b-d)/(rho*b*exp((b-d)*age)+(b*(1-rho)-d) ) ) ) - (b*(1-rho)-d) ) / (rho * b) ) + (d-b)*age ) / (d-b); } return present - t; }
/** Perform the move */ double SlidingMove::performSimpleMove( void ) { // Get random number generator RandomNumberGenerator* rng = GLOBAL_RNG; double &val = variable->getValue(); // copy all value storedValue = val; double min = variable->getMin(); double max = variable->getMax(); double u = rng->uniform01(); double newVal = val + ( delta * ( u - 0.5 ) ); /* reflect the new value */ do { if ( newVal < min ) newVal = 2.0 * min - newVal; else if ( newVal > max ) newVal = 2.0 * max - newVal; } while ( newVal < min || newVal > max ); // FIXME: not the most efficient way of handling multiple reflections :-P val = newVal; return 0.0; }
/** * Perform the proposal. * * A Uniform-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 ~ Uniform(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 RootTimeSlideUniformProposal::doProposal( void ) { // Get random number generator RandomNumberGenerator* rng = GLOBAL_RNG; Tree& tau = variable->getValue(); // pick a random node which is not the root and neithor the direct descendant of the root TopologyNode* node = &tau.getRoot(); // we need to work with the times double my_age = node->getAge(); double child_Age = node->getChild( 0 ).getAge(); if ( child_Age < node->getChild( 1 ).getAge()) { child_Age = node->getChild( 1 ).getAge(); } // now we store all necessary values storedAge = my_age; // draw new ages and compute the hastings ratio at the same time double my_new_age = (origin->getValue() - child_Age) * rng->uniform01() + child_Age; // set the age node->setAge( my_new_age ); return 0.0; }
/** Build random binary tree to size num_taxa. The result is a draw from the uniform distribution on histories. */ void HeterogeneousRateBirthDeath::buildRandomBinaryHistory(std::vector<TopologyNode*> &tips) { if (tips.size() < num_taxa) { // Get the rng RandomNumberGenerator* rng = GLOBAL_RNG; // Randomly draw one node from the list of tips size_t index = static_cast<size_t>( floor(rng->uniform01()*tips.size()) ); // Get the node from the list TopologyNode* parent = tips.at(index); // Remove the randomly drawn node from the list tips.erase(tips.begin()+long(index)); // Add a left child TopologyNode* leftChild = new TopologyNode(0); parent->addChild(leftChild); leftChild->setParent(parent); tips.push_back(leftChild); // Add a right child TopologyNode* rightChild = new TopologyNode(0); parent->addChild(rightChild); rightChild->setParent(parent); tips.push_back(rightChild); // Recursive call to this function buildRandomBinaryHistory(tips); } }
void AutocorrelatedBranchMatrixDistribution::recursiveSimulate(const TopologyNode& node, RbVector< RateMatrix > *values, const std::vector< double > &scaledParent) { // get the index size_t nodeIndex = node.getIndex(); // first we simulate our value RandomNumberGenerator* rng = GLOBAL_RNG; // do we keep our parents values? double u = rng->uniform01(); if ( u < changeProbability->getValue() ) { // change // draw a new value for the base frequencies std::vector<double> newParent = RbStatistics::Dirichlet::rv(scaledParent, *rng); std::vector<double> newScaledParent = newParent; // compute the new scaled parent std::vector<double>::iterator end = newScaledParent.end(); for (std::vector<double>::iterator it = newScaledParent.begin(); it != end; ++it) { (*it) *= alpha->getValue(); } RateMatrix_GTR rm = RateMatrix_GTR( newParent.size() ); RbPhylogenetics::Gtr::computeRateMatrix( exchangeabilityRates->getValue(), newParent, &rm ); uniqueBaseFrequencies.push_back( newParent ); uniqueMatrices.push_back( rm ); matrixIndex[nodeIndex] = uniqueMatrices.size()-1; values->insert(nodeIndex, rm); size_t numChildren = node.getNumberOfChildren(); if ( numChildren > 0 ) { for (size_t i = 0; i < numChildren; ++i) { const TopologyNode& child = node.getChild(i); recursiveSimulate(child,values,newScaledParent); } } } else { // no change size_t parentIndex = node.getParent().getIndex(); values->insert(nodeIndex, uniqueMatrices[ matrixIndex[ parentIndex ] ]); size_t numChildren = node.getNumberOfChildren(); if ( numChildren > 0 ) { for (size_t i = 0; i < numChildren; ++i) { const TopologyNode& child = node.getChild(i); recursiveSimulate(child,values,scaledParent); } } } }
/*! * This function generates a Poisson-distributed random variable using * the ratio-of-uniforms rejectin method. * * \brief Poisson random variables using the ratio-of-uniforms method. * \param lambda is the rate parameter of the Poisson. * \return Returns a Poisson-distributed random variable. * \throws Does not throw an error. * \see Stadlober, E. 1990. The ratio of uniforms approach for generating * discrete random variates. Journal of Computational and Applied * Mathematics 31:181-189. */ int RbStatistics::Helper::poissonRatioUniforms(double lambda, RandomNumberGenerator& rng) { static double p_L_last = -1.0; /* previous L */ static double p_a; /* hat center */ static double p_h; /* hat width */ static double p_g; /* ln(L) */ static double p_q; /* value at mode */ static int p_bound; /* upper bound */ int mode; /* mode */ double u; /* uniform random */ double lf; /* ln(f(x)) */ double x; /* real sample */ int k; /* integer sample */ if (p_L_last != lambda) { p_L_last = lambda; p_a = lambda + 0.5; mode = (int)lambda; p_g = log(lambda); p_q = mode * p_g - RbMath::lnFactorial(mode); p_h = sqrt(2.943035529371538573 * (lambda + 0.5)) + 0.8989161620588987408; p_bound = (int)(p_a + 6.0 * p_h); } while(1) { u = rng.uniform01(); if (u == 0.0) continue; x = p_a + p_h * (rng.uniform01() - 0.5) / u; if (x < 0 || x >= p_bound) continue; k = (int)(x); lf = k * p_g - RbMath::lnFactorial(k) - p_q; if (lf >= u * (4.0 - u) - 3.0) break; if (u * (u - lf) > 1.0) continue; if (2.0 * log(u) <= lf) break; } return(k); }
double RbStatistics::Logistic::rv(double location, double scale, RandomNumberGenerator& rng) { if (scale == 0){ return (location); } else{ double u = rng.uniform01(); return location + scale * log(u / (1. - u)); } }
/** * Perform the proposal. * * A Uniform-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 ~ Uniform(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 NodeTimeSlideUniformProposal::doProposal( void ) { // Get random number generator RandomNumberGenerator* rng = GLOBAL_RNG; Tree& tau = variable->getValue(); // pick a random node which is not the root and neithor the direct descendant of the root TopologyNode* node; do { double u = rng->uniform01(); size_t index = size_t( std::floor(tau.getNumberOfNodes() * u) ); node = &tau.getNode(index); } while ( node->isRoot() || node->isTip() ); TopologyNode& parent = node->getParent(); // we need to work with the times double parent_age = parent.getAge(); double my_age = node->getAge(); double child_Age = node->getChild( 0 ).getAge(); if ( child_Age < node->getChild( 1 ).getAge()) { child_Age = node->getChild( 1 ).getAge(); } // now we store all necessary values storedNode = node; storedAge = my_age; // draw new ages and compute the hastings ratio at the same time double my_new_age = (parent_age-child_Age) * rng->uniform01() + child_Age; // set the age tau.getNode(node->getIndex()).setAge( my_new_age ); return 0.0; }
/** Perform the move */ double SubtreeScale::performSimpleMove( void ) { // Get random number generator RandomNumberGenerator* rng = GLOBAL_RNG; TimeTree& tau = variable->getValue(); // pick a random node which is not the root and neither the direct descendant of the root TopologyNode* node; do { double u = rng->uniform01(); size_t index = size_t( std::floor(tau.getNumberOfNodes() * u) ); node = &tau.getNode(index); } while ( node->isRoot() || node->isTip() ); TopologyNode& parent = node->getParent(); // we need to work with the times double parent_age = parent.getAge(); double my_age = node->getAge(); // now we store all necessary values storedNode = node; storedAge = my_age; // draw new ages and compute the hastings ratio at the same time double my_new_age = parent_age * rng->uniform01(); double scalingFactor = my_new_age / my_age; size_t nNodes = node->getNumberOfNodesInSubtree(false); // rescale the subtrees TreeUtilities::rescaleSubtree(&tau, node, scalingFactor ); // compute the Hastings ratio double lnHastingsratio = (nNodes > 1 ? log( scalingFactor ) * (nNodes-1) : 0.0 ); return lnHastingsratio; }
Move& SingleRandomMoveSchedule::nextMove( unsigned long gen ) { RandomNumberGenerator* rng = GLOBAL_RNG; double u = sumOfWeights * rng->uniform01(); size_t index = 0; while ( weights[index] < u || !(*moves)[index].isActive( gen ) ) { u -= weights[index]; ++index; } return (*moves)[index]; }
/** Perform the move */ double SliderUpDownMove::performCompoundMove( void ) { // Get random number generator RandomNumberGenerator* rng = GLOBAL_RNG; double sv1 = sliderVal1->getValue(); double sv2 = sliderVal2->getValue(); storedSV1 = sv1; storedSV2 = sv2; double min1 = sliderVal1->getMin(); double min2 = sliderVal2->getMin(); double max1 = sliderVal1->getMax(); double max2 = sliderVal2->getMax(); double size = max1 - min1; double u = rng->uniform01(); double delta = ( slideFactor * ( u - 0.5 ) ); if ( fabs(delta) > 2.0*size ) { delta -= floor(delta / (2.0*size)) * (2.0*size); } double nv1 = sv1 + delta; double nv2 = sv2 - delta; /* reflect the new value */ do { if ( nv1 < min1 ) { nv1 = 2.0 * min1 - nv1; nv2 = sv2 - (nv1 - sv1); } else if ( nv1 > max1 ) { nv1 = 2.0 * max1 - nv1; nv2 = sv2 - (nv1 - sv1); } } while ( nv1 < min1 || nv1 > max1 || nv2 < min2 || nv2 > max2); sliderVal1->setValue( new double(nv1) ); sliderVal2->setValue( new double(nv2) ); return 0.0; }
DistributionSample RefractiveMaterial::sampleBxDF( RandomNumberGenerator & rng, const RayIntersection & intersection ) const { // Perfect Fresnel refractor DistributionSample sample; const float index_in = intersection.ray.index_of_refraction; const float index_out = index_of_refraction; const Vector4 from_dir = intersection.fromDirection(); // FIXME: HACK - This assumes that if we hit the surface of an object with the same // index of refraction as the material we're in, then we are moving back into // free space. This might not be true if there are numerical errors tracing // abutting objects of the same material type, or for objects that are intersecting. if( index_out == index_in ) { sample.new_index_of_refraction = 1.0f; } Vector4 refracted = refract( from_dir, intersection.normal, index_in, index_out ); float fresnel = 1.0f; // default to total internal reflection if refract() returns // a zero length vector if( refracted.magnitude() > 0.0001 ) { fresnel = Fresnel::Dialectric::Unpolarized( dot( from_dir, intersection.normal ), dot( refracted, intersection.normal.negated() ), index_in, index_out ); } const float draw = rng.uniform01(); // Use RNG to choose whether to reflect or refract based on Fresnel coefficient. // Random selection accounts for fresnel or 1-fresnel scale factor. if( fresnel == 1.0f || draw < fresnel ) { // Trace reflection (mirror ray scaled by fresnel or 1 for total internal reflection) sample.direction = mirror( from_dir, intersection.normal ); // FIXME - How do we determine pdf_sample for total internal reflection? sample.pdf_sample = fresnel; sample.new_index_of_refraction = index_in; } else { // Trace refraction (refracted ray scaled by 1-fresnel) sample.direction = refracted; sample.pdf_sample = 1.0 - fresnel; sample.new_index_of_refraction = index_out; } return sample; }
/** * Perform the proposal. * * A scaling Proposal draws a random uniform number u ~ unif(-0.5,0.5) * and Slides the current vale by a scaling factor * sf = exp( lambda * u ) * where lambda is the tuning parameter of the Proposal to influence the size of the proposals. * * \return The hastings ratio. */ double VectorSingleElementSlideProposal::doProposal( void ) { // Get random number generator RandomNumberGenerator* rng = GLOBAL_RNG; RbVector<double> &val = variable->getValue(); // choose an index index = size_t(rng->uniform01() * val.size()); // copy value storedValue = val[index]; // Generate new value (no reflection, so we simply abort later if we propose value here outside of support) double u = rng->uniform01(); double delta = ( lambda * ( u - 0.5 ) ); val[index] += delta; variable->addTouchedElementIndex(index); return 0.0; }
double FossilSafeScaleMove::doMove( void ) { // Get random number generator RandomNumberGenerator* rng = GLOBAL_RNG; double val = scaler->getValue(); storedValue = val; // double min = scaler->getMin(); // double max = scaler->getMax(); // double size = max - min; double u = std::exp( lambda * (rng->uniform01() - 0.5)); double newVal = val * u; val = newVal; scaler->setValue( new double(val) ); TimeTree& t = tree->getValue(); // double rescale = storedValue / val; bool failed = false; std::vector<TopologyNode*> nodes = t.getNodes(); for (size_t i = 0; i < fossilIdx.size(); i++) { const size_t nodeIdx = nodes[ fossilIdx[i] ]->getIndex(); storedTipAges[nodeIdx] = t.getAge(nodeIdx); t.setAge( nodeIdx, tipAges[nodeIdx] / val ); if ( tipAges[ nodeIdx ] > nodes[ nodeIdx ]->getParent().getAge() * val ) { // reject: rescaled tree has negative branch lengths! // std::cout << "reject, negative brlen\n"; failed = true; } } if (failed) return RbConstants::Double::neginf; return log(u); }
/** Perform the move */ double SimplexSingleElementScale::performSimpleMove( void ) { // Get random number generator RandomNumberGenerator* rng = GLOBAL_RNG; // get the current value std::vector<double>& value = variable->getValue(); // store the value storedValue = value; // we need to know the number of categories size_t cats = value.size(); // randomly draw a new index size_t chosenIndex = size_t( floor(rng->uniform01()*double(cats)) ); double currentValue = value[chosenIndex]; // draw new rates and compute the hastings ratio at the same time double a = alpha * currentValue + 1.0; double b = alpha * (1.0-currentValue) + 1.0; double new_value = RbStatistics::Beta::rv(a, b, *rng); // set the value value[chosenIndex] = new_value; // rescale double sum = 0; for(size_t i=0; i<cats; i++) { sum += value[i]; } for(size_t i=0; i<cats; i++) value[i] /= sum; // compute the Hastings ratio double forward = RbStatistics::Beta::lnPdf(a, b, new_value); double new_a = alpha * value[chosenIndex] + 1.0; double new_b = alpha * (1.0-value[chosenIndex]) + 1.0; double backward = RbStatistics::Beta::lnPdf(new_a, new_b, currentValue); return backward - forward; }
/*! * This function generates a Multinomially-distributed random variable. * * \brief Multinomially random variable. * \param p is a reference to a vector of doubles containing the parameters of the Multinomial. * \param n is an integer with the number of draws from the multinomial * \param rng is a pointer to a random number object. * \return Returns a vector of integers containing the random variable. * \throws Does not throw an error. */ std::vector<int> RbStatistics::Multinomial::rv(const std::vector<double> &p, size_t n, RandomNumberGenerator& rng) { std::vector<int> x(n,0); for (size_t i=0; i<n; i++) { double u = rng.uniform01(); double sum = 0.0; for (size_t j=0; j<p.size(); j++) { sum += p[j]; if (u < sum) { break; x[i]++; } else { x[i]++; } } } return x; }
size_t SpeciesTreeNodeSlideProposal::mauCanonicalSub(Tree &tree, TopologyNode *node, size_t loc, std::vector<TopologyNode*> &order, std::vector<bool>& wasSwaped) { if( node->isTip() ) { order[loc] = node; return loc + 1; } // Get random number generator RandomNumberGenerator* rng = GLOBAL_RNG; bool swap = (rng->uniform01() > 0.5); size_t l = mauCanonicalSub(tree, &node->getChild( swap ? 1 : 0), loc, order, wasSwaped); order[l] = node; wasSwaped[(l-1)/2] = swap; l = mauCanonicalSub(tree, &node->getChild( swap ? 0 : 1), l+1, order, wasSwaped); return l; }
/** Perform the move */ double RateAgeACLNMixingMove::performCompoundMove( void ) { // Get random number generator RandomNumberGenerator* rng = GLOBAL_RNG; TimeTree& tau = tree->getValue(); std::vector<double>& nrates = rates->getValue(); double &rootR = rootRate->getValue(); size_t nn = tau.getNumberOfNodes(); double u = rng->uniform01(); double c = exp( epsilon * (u - 0.5) ); for(size_t i=0; i<nn; i++){ TopologyNode* node = &tau.getNode(i); if(node->isTip() == false){ double curAge = node->getAge(); double newAge = curAge * c; tau.setAge( node->getIndex(), newAge ); if(node->isRoot()){ storedRootAge = curAge; } } } size_t nr = nrates.size(); rootR = rootR / c; for(size_t i=0; i<nrates.size(); i++){ double curRt = nrates[i]; double newRt = curRt / c; nrates[i] = newRt; } storedC = c; double pr = (((double)nn) - (double)nr) * log(c); return pr; }