Skip to content

Commit

Permalink
Merge pull request #162 from mcveanlab/randomNumberGenerator
Browse files Browse the repository at this point in the history
Random number generator
  • Loading branch information
shajoezhu authored Nov 24, 2016
2 parents 90eb36e + 19cb235 commit bf45d1e
Show file tree
Hide file tree
Showing 8 changed files with 269 additions and 52 deletions.
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ script:
- if [ $TRAVIS_OS_NAME == linux ]; then ./tests/test_binary.sh; fi
- ./tests/testPOS.sh
- ./tests/test_binaryVcfVsTxt.sh
- ./tests/test-against-previous-version.sh
#- ./tests/test-against-previous-version.sh
- ./tests/test_binaryReproducible.sh
- if [ $TRAVIS_OS_NAME == linux ]; then cd docs/doxygen; doxygen Doxyfile; cd ../..; fi

Expand Down
2 changes: 1 addition & 1 deletion circle.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,6 @@ test:
- ./tests/test_binary.sh
- ./tests/testPOS.sh
- ./tests/test_binaryVcfVsTxt.sh
- ./tests/test-against-previous-version.sh
#- ./tests/test-against-previous-version.sh
- ./tests/test_binaryReproducible.sh
#- coveralls --exclude lib --exclude tests --exclude src/random --exclude src/codeCogs/ --exclude src/export/ --gcov-options '\-lp'
124 changes: 124 additions & 0 deletions src/codeCogs/mersenne.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
// GNU General Public License Agreement
// Copyright (C) 2004-2010 CodeCogs, Zyba Ltd, Broadwood, Holford, TA5 1DU, England.
//
// This program is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by CodeCogs.
// You must retain a copy of this licence in all copies.
//
// This program is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE. See the GNU General Public License for more details.
// ---------------------------------------------------------------------------------
//! Random number generator class using the Mersenne Twister algorithm

#ifndef STATS_RANDOM_MERSENNE_H
#define STATS_RANDOM_MERSENNE_H

#include <assert.h>

#define N 624
#define M 397
#define MATRIX_A 0x9908b0dfUL
#define UPPER_MASK 0x80000000UL
#define LOWER_MASK 0x7fffffffUL
#define MERSENNEDIV 4294967296.0


//! Random number generator class using the Mersenne Twister algorithm

class Mersenne {
public:

//! Constructor that initializes the generator with the given seed.

Mersenne(size_t s = 46875) {
this->setSeed(s);
Init((unsigned long)(s));
}

//! Copy constructor

Mersenne(const Mersenne &C) {
size_t s = C.getSeed();
this->setSeed (s);
Init((unsigned long)(s));
}

//! Generates an uniform floating point number in the (0, 1) interval (endpoints are excluded).

double genReal() {
return ((double)Next() + 0.5) / MERSENNEDIV;
}

//! Generates an uniform large integer in the (0, 2^32 - 1) interval.

unsigned int genInt() {
return Next();
}

//! Resets the seed of the generator to the given parameter.

void setSeed(size_t s) {
this->seed_ = s;
Init((unsigned long)(s));
}

//! Returns the seed of the generator.

size_t getSeed() const {
return seed_;
}

private:
void Init(unsigned long s){
mt[0]= s & 0xffffffffUL;
for (mti = 1; mti < N; ++mti) {
mt[mti] = (1812433253UL * (mt[mti-1] ^ (mt[mti-1] >> 30)) + mti);
mt[mti] &= 0xffffffffUL;
}
}

unsigned long Next(){
unsigned long y;
if (mti >= N) {
int k;
unsigned long tmp[2] = {0x0UL, MATRIX_A};
for (k = 0; k < N - M; ++k) {
y = (mt[k] & UPPER_MASK) | (mt[k + 1] & LOWER_MASK);
mt[k] = mt[k + M] ^ (y >> 1) ^ tmp[y & 0x1UL];
}

for (; k < N - 1; ++k) {
y = (mt[k] & UPPER_MASK) | (mt[k+1] & LOWER_MASK);
mt[k] = mt[k + (M - N)] ^ (y >> 1) ^ tmp[y & 0x1UL];
}

y = (mt[N - 1] & UPPER_MASK) | (mt[0] & LOWER_MASK);
mt[N - 1] = mt[M - 1] ^ (y >> 1) ^ tmp[y & 0x1UL];
mti = 0;
}

y = mt[mti++];

y ^= (y >> 11);
y ^= (y << 7) & 0x9d2c5680UL;
y ^= (y << 15) & 0xefc60000UL;
y ^= (y >> 18);

return y;

}
size_t seed_;
unsigned long mt[N];
int mti;
};


#undef N
#undef M
#undef MATRIX_A
#undef UPPER_MASK
#undef LOWER_MASK

#endif

81 changes: 81 additions & 0 deletions src/codeCogs/randomSample.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
// GNU General Public License Agreement
// Copyright (C) 2004-2010 CodeCogs, Zyba Ltd, Broadwood, Holford, TA5 1DU, England.
//
// This program is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by CodeCogs.
// You must retain a copy of this licence in all copies.
//
// This program is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE. See the GNU General Public License for more details.
// ---------------------------------------------------------------------------------
//! Generates random numbers following a standard normal distribution.

#ifndef STATS_DISTS_CONTINUOUS_NORMAL_RANDOMSAMPLE_H
#define STATS_DISTS_CONTINUOUS_NORMAL_RANDOMSAMPLE_H

#include <mersenne.hpp>
#include <math.h>

#define NORMALDENS(x) ((fabs(x) > 8.0) ? 0 : 0.398942280 * exp(- x * x / 2))


//! Generates random numbers following a standard normal distribution.

class StandNormalRandomSample : public Mersenne {
public:

//! Class constructor.
StandNormalRandomSample(double s = 0.65234) : Mersenne(s) {
sx = new double[60];
sfx = new double[60];
double sxi = 0.0;
double inc = 0.01;
for (int i = 0; i < 60; ++i) {

sx[i] = sxi;
double f1 = NORMALDENS(sxi);
sfx[i] = f1;
if (f1 <= 0.0) {
xi = 2 * i;
return;
}
sxi += inc / f1;
}
}

//! Class destructor.
~StandNormalRandomSample() {
delete [] sx;
delete [] sfx;
}

//! Generates a random deviate from the standard normal distribution.
double genReal() {
int ir;
double s, ak, y;
do {

s = 1.0;
double r1 = Mersenne::genReal();
if (r1 > 0.5) {
s = -1.0;
r1 = 1.0 - r1;
}
ir = (int)(r1 * xi);
double sxi = sx[ir];
ak = sxi + (sx[ir + 1] - sxi) * Mersenne::genReal();
y = sfx[ir] * Mersenne::genReal();

} while (y >= sfx[ir + 1] && y >= NORMALDENS(ak));

return s * ak;
}

private:
double xi, *sx, *sfx;
};


#endif

42 changes: 5 additions & 37 deletions src/mcmc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,7 @@ McmcMachinery::McmcMachinery(DEploidIO* dEploidIO, Panel *panel, McmcSample *mcm
this->SD_LOG_TITRE = 3.0;
this->PROP_SCALE = 40.0;

std_generator_ = new std::default_random_engine(this->seed_);
initialTitre_normal_distribution_ = new std::normal_distribution<double>(MN_LOG_TITRE, SD_LOG_TITRE);
deltaX_normal_distribution_ = new std::normal_distribution<double>(MN_LOG_TITRE, 1.0/PROP_SCALE);
stdNorm_ = new StandNormalRandomSample((double)this->seed_);

this->kStrain_ = this->dEploidIO_->kStrain_;
this->nLoci_ = this->dEploidIO_->plaf_.size();
Expand All @@ -65,38 +63,9 @@ McmcMachinery::McmcMachinery(DEploidIO* dEploidIO, Panel *panel, McmcSample *mcm


McmcMachinery::~McmcMachinery(){
//if ( this->hapRg_ ){
//this->hapRg_->clearFastFunc();
//delete hapRg_;
//}

//if ( this->mcmcEventRg_ ){
//this->mcmcEventRg_->clearFastFunc();
//delete mcmcEventRg_;
//}

//if ( this->propRg_ ){
//this->propRg_->clearFastFunc();
//delete propRg_;
//}

//if ( this->initialHapRg_ ){
//this->initialHapRg_->clearFastFunc();
//delete initialHapRg_;
//}

if ( this->std_generator_ ){
delete std_generator_;
if ( this->stdNorm_ ){
delete stdNorm_;
}

if ( this->initialTitre_normal_distribution_ ){
delete initialTitre_normal_distribution_;
}

if ( this->deltaX_normal_distribution_ ){
delete deltaX_normal_distribution_;
}

}


Expand Down Expand Up @@ -187,8 +156,7 @@ void McmcMachinery::initializeTitre(){

if ( this->dEploidIO_->doUpdateProp() ){
for ( size_t k = 0; k < this->kStrain_; k++){
double tmp = (*this->initialTitre_normal_distribution_)((*std_generator_));
this->currentTitre_[k] = tmp;
this->currentTitre_[k] = this->initialTitreNormalVariable();
}
}
assert( currentTitre_.size() == this->kStrain_);
Expand Down Expand Up @@ -322,7 +290,7 @@ double McmcMachinery::deltaLLKs ( vector <double> &newLLKs ){
vector <double> McmcMachinery::calcTmpTitre(){
vector <double> tmpTitre;
for ( size_t k = 0; k < this->kStrain_; k++){
double dt = (*this->deltaX_normal_distribution_)((*std_generator_));
double dt = this->deltaXnormalVariable();
tmpTitre.push_back( currentTitre_[k] + dt );
}
return tmpTitre;
Expand Down
22 changes: 11 additions & 11 deletions src/mcmc.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include "panel.hpp"
#include "utility.hpp"
#include "global.h"
#include "randomSample.hpp"

#ifndef MCMC
#define MCMC
Expand All @@ -52,7 +53,6 @@ class McmcSample {
moves.clear();
}


vector < vector <double> > proportion;
vector < vector <double> > hap;
vector < double > sumLLKs;
Expand Down Expand Up @@ -95,9 +95,11 @@ class McmcMachinery {
RandomGenerator* propRg_;
RandomGenerator* initialHapRg_;

std::default_random_engine* std_generator_;// (this->seed_);
std::normal_distribution<double>* initialTitre_normal_distribution_;// (MN_LOG_TITRE, SD_LOG_TITRE);
std::normal_distribution<double>* deltaX_normal_distribution_;// (0, 1/PROP_SCALE);
//std::normal_distribution<double>* initialTitre_normal_distribution_;// (MN_LOG_TITRE, SD_LOG_TITRE);
//std::normal_distribution<double>* deltaX_normal_distribution_;// (0, 1/PROP_SCALE);
StandNormalRandomSample* stdNorm_;
double initialTitreNormalVariable(){ return this->stdNorm_->genReal() * SD_LOG_TITRE + MN_LOG_TITRE; }
double deltaXnormalVariable(){ return this->stdNorm_->genReal() * 1.0/PROP_SCALE + MN_LOG_TITRE; }
double MN_LOG_TITRE;
double SD_LOG_TITRE;
double PROP_SCALE;
Expand All @@ -114,20 +116,18 @@ class McmcMachinery {
void calcMaxIteration( size_t nSample, size_t McmcMachineryRate, double burnIn );
/* Initialize */
void initializeMcmcChain();
void initializeProp();
void initializeTitre();
void initializeHap();
void initializellk();
void initializeExpectedWsaf();
void initializeProp();
void initializeTitre();
void initializeHap();
void initializellk();
void initializeExpectedWsaf();

vector <double> calcExpectedWsaf(vector <double> &proportion );
vector <double> titre2prop(vector <double> & tmpTitre);


double calcLogPriorTitre( vector <double> &tmpTitre);
double rBernoulli(double p);


void printArray ( vector <double> array ){
for (auto const& value: array){
cout << value << " ";
Expand Down
Loading

0 comments on commit bf45d1e

Please sign in to comment.