@q $Id: quasi_mcarlo.cweb 431 2005-08-16 15:41:01Z kamenik $ @> @q Copyright 2005, Ondra Kamenik @> @ This is {\tt quasi\_mcarlo.cpp} file. @c #include "quasi_mcarlo.h" #include @<|RadicalInverse| constructor code@>; @<|RadicalInverse::eval| code@>; @<|RadicalInverse::increase| code@>; @<|RadicalInverse::print| code@>; @<|HaltonSequence| static data@>; @<|HaltonSequence| constructor code@>; @<|HaltonSequence::operator=| code@>; @<|HaltonSequence::increase| code@>; @<|HaltonSequence::eval| code@>; @<|HaltonSequence::print| code@>; @<|qmcpit| empty constructor code@>; @<|qmcpit| regular constructor code@>; @<|qmcpit| copy constructor code@>; @<|qmcpit| destructor@>; @<|qmcpit::operator==| code@>; @<|qmcpit::operator=| code@>; @<|qmcpit::operator++| code@>; @<|qmcpit::weight| code@>; @<|qmcnpit| empty constructor code@>; @<|qmcnpit| regular constructor code@>; @<|qmcnpit| copy constructor code@>; @<|qmcnpit| destructor@>; @<|qmcnpit::operator=| code@>; @<|qmcnpit::operator++| code@>; @<|WarnockPerScheme::permute| code@>; @<|ReversePerScheme::permute| code@>; @ Here in the constructor, we have to calculate a maximum length of |coeff| array for a given |base| and given maximum |maxn|. After allocation, we calculate the coefficients. @<|RadicalInverse| constructor code@>= RadicalInverse::RadicalInverse(int n, int b, int mxn) : num(n), base(b), maxn(mxn), coeff((int)(floor(log((double)maxn)/log((double)b))+2), 0) { int nr = num; j = -1; do { j++; coeff[j] = nr % base; nr = nr / base; } while (nr > 0); } @ This evaluates the radical inverse. If there was no permutation, we have to calculate $$ {c_0\over b}+{c_1\over b^2}+\ldots+{c_j\over b^{j+1}} $$ which is evaluated as $$ \left(\ldots\left(\left({c_j\over b}\cdot{1\over b}+{c_{j-1}\over b}\right) \cdot{1\over b}+{c_{j-2}\over b}\right) \ldots\right)\cdot{1\over b}+{c_0\over b} $$ Now with permutation $\pi$, we have $$ \left(\ldots\left(\left({\pi(c_j)\over b}\cdot{1\over b}+ {\pi(c_{j-1})\over b}\right)\cdot{1\over b}+ {\pi(c_{j-2})\over b}\right) \ldots\right)\cdot{1\over b}+{\pi(c_0)\over b} $$ @<|RadicalInverse::eval| code@>= double RadicalInverse::eval(const PermutationScheme& p) const { double res = 0; for (int i = j; i >= 0; i--) { int cper = p.permute(i, base, coeff[i]); res = (cper + res)/base; } return res; } @ We just add 1 to the lowest coefficient and check for overflow with respect to the base. @<|RadicalInverse::increase| code@>= void RadicalInverse::increase() { // todo: raise if |num+1 > maxn| num++; int i = 0; coeff[i]++; while (coeff[i] == base) { coeff[i] = 0; coeff[++i]++; } if (i > j) j = i; } @ Debug print. @<|RadicalInverse::print| code@>= void RadicalInverse::print() const { printf("n=%d b=%d c=", num, base); coeff.print(); } @ Here we have the first 170 primes. This means that we are not able to integrate dimensions greater than 170. @<|HaltonSequence| static data@>= int HaltonSequence::num_primes = 170; int HaltonSequence::primes[] = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997, 1009, 1013 }; @ This takes first |dim| primes and constructs |dim| radical inverses and calls |eval|. @<|HaltonSequence| constructor code@>= HaltonSequence::HaltonSequence(int n, int mxn, int dim, const PermutationScheme& p) : num(n), maxn(mxn), per(p), pt(dim) { // todo: raise if |dim > num_primes| // todo: raise if |n > mxn| for (int i = 0; i < dim; i++) ri.push_back(RadicalInverse(num, primes[i], maxn)); eval(); } @ @<|HaltonSequence::operator=| code@>= const HaltonSequence& HaltonSequence::operator=(const HaltonSequence& hs) { num = hs.num; maxn = hs.maxn; ri.clear(); for (unsigned int i = 0; i < hs.ri.size(); i++) ri.push_back(RadicalInverse(hs.ri[i])); pt = hs.pt; return *this; } @ This calls |RadicalInverse::increase| for all radical inverses and calls |eval|. @<|HaltonSequence::increase| code@>= void HaltonSequence::increase() { for (unsigned int i = 0; i < ri.size(); i++) ri[i].increase(); num++; if (num <= maxn) eval(); } @ This sets point |pt| to radical inverse evaluations in each dimension. @<|HaltonSequence::eval| code@>= void HaltonSequence::eval() { for (unsigned int i = 0; i < ri.size(); i++) pt[i] = ri[i].eval(per); } @ Debug print. @<|HaltonSequence::print| code@>= void HaltonSequence::print() const { for (unsigned int i = 0; i < ri.size(); i++) ri[i].print(); printf("point=[ "); for (unsigned int i = 0; i < ri.size(); i++) printf("%7.6f ", pt[i]); printf("]\n"); } @ @<|qmcpit| empty constructor code@>= qmcpit::qmcpit() : spec(NULL), halton(NULL), sig(NULL)@+ {} @ @<|qmcpit| regular constructor code@>= qmcpit::qmcpit(const QMCSpecification& s, int n) : spec(&s), halton(new HaltonSequence(n, s.level(), s.dimen(), s.getPerScheme())), sig(new ParameterSignal(s.dimen())) { } @ @<|qmcpit| copy constructor code@>= qmcpit::qmcpit(const qmcpit& qpit) : spec(qpit.spec), halton(NULL), sig(NULL) { if (qpit.halton) halton = new HaltonSequence(*(qpit.halton)); if (qpit.sig) sig = new ParameterSignal(qpit.spec->dimen()); } @ @<|qmcpit| destructor@>= qmcpit::~qmcpit() { if (halton) delete halton; if (sig) delete sig; } @ @<|qmcpit::operator==| code@>= bool qmcpit::operator==(const qmcpit& qpit) const { return (spec == qpit.spec) && ((halton == NULL && qpit.halton == NULL) || (halton != NULL && qpit.halton != NULL && halton->getNum() == qpit.halton->getNum())); } @ @<|qmcpit::operator=| code@>= const qmcpit& qmcpit::operator=(const qmcpit& qpit) { spec = qpit.spec; if (halton) delete halton; if (qpit.halton) halton = new HaltonSequence(*(qpit.halton)); else halton = NULL; return *this; } @ @<|qmcpit::operator++| code@>= qmcpit& qmcpit::operator++() { // todo: raise if |halton == null || qmcq == NULL| halton->increase(); return *this; } @ @<|qmcpit::weight| code@>= double qmcpit::weight() const { return 1.0/spec->level(); } @ @<|qmcnpit| empty constructor code@>= qmcnpit::qmcnpit() : qmcpit(), pnt(NULL)@+ {} @ @<|qmcnpit| regular constructor code@>= qmcnpit::qmcnpit(const QMCSpecification& s, int n) : qmcpit(s, n), pnt(new Vector(s.dimen())) { } @ @<|qmcnpit| copy constructor code@>= qmcnpit::qmcnpit(const qmcnpit& qpit) : qmcpit(qpit), pnt(NULL) { if (qpit.pnt) pnt = new Vector(*(qpit.pnt)); } @ @<|qmcnpit| destructor@>= qmcnpit::~qmcnpit() { if (pnt) delete pnt; } @ @<|qmcnpit::operator=| code@>= const qmcnpit& qmcnpit::operator=(const qmcnpit& qpit) { qmcpit::operator=(qpit); if (pnt) delete pnt; if (qpit.pnt) pnt = new Vector(*(qpit.pnt)); else pnt = NULL; return *this; } @ Here we inccrease a point in Halton sequence ant then store images of the points in |NormalICDF| function. @<|qmcnpit::operator++| code@>= qmcnpit& qmcnpit::operator++() { qmcpit::operator++(); for (int i = 0; i < halton->point().length(); i++) (*pnt)[i] = NormalICDF::get(halton->point()[i]); return *this; } @ Clear from code. @<|WarnockPerScheme::permute| code@>= int WarnockPerScheme::permute(int i, int base, int c) const { return (c+i) % base; } @ Clear from code. @<|ReversePerScheme::permute| code@>= int ReversePerScheme::permute(int i, int base, int c) const { return (base-c) % base; } @ End of {\tt quasi\_mcarlo.cpp} file.