mirror of
https://github.com/triqs/dft_tools
synced 2024-12-25 13:53:40 +01:00
Change implementation of random_generator & python wrapper.
- Use a new buffered_function to replace the complicated generator code from ALPS. - Clean the implementation of the random_generator - update the documentation - update to the new python wrapper (could not be done with the previous version, because of lack of move constructor).
This commit is contained in:
parent
2b5dd322ce
commit
e6529b608e
@ -1,7 +1,7 @@
|
|||||||
from pytriqs.random import *
|
from pytriqs.random_generator import *
|
||||||
from pytriqs.plot.mpl_interface import *
|
from pytriqs.plot.mpl_interface import *
|
||||||
|
|
||||||
r = RandomGenerator("lagged_fibonacci607", 237489)
|
r = RandomGenerator("lagged_fibonacci607", 237489)
|
||||||
l = []
|
l = []
|
||||||
for i in range(10000): l += [r.rand(),]
|
for i in range(10000): l += [r(),]
|
||||||
plt.hist(l, 30, normed=True);
|
plt.hist(l, 30, normed=True)
|
||||||
|
@ -1,33 +1,34 @@
|
|||||||
.. index:: Random number generator
|
.. index:: Random number generator
|
||||||
|
|
||||||
.. module:: pytriqs.random
|
.. module:: pytriqs.random_generator
|
||||||
|
|
||||||
.. _random_generator:
|
.. _random_generator:
|
||||||
|
|
||||||
Random generator class
|
Random generator class
|
||||||
======================
|
======================
|
||||||
|
|
||||||
TRIQS has a simple random number generator class called ``RandomGenerator``. It is based on boost
|
TRIQS exposes to python the random number generators used in C++,
|
||||||
just like the C++ random generator provided by TRIQS.
|
in the module ``RandomGenerator``.
|
||||||
|
The generators are the boost random generators.
|
||||||
|
|
||||||
Usage
|
Usage
|
||||||
-----
|
-----
|
||||||
|
|
||||||
The generator is constructed from a name and a seed::
|
The generator is constructed from a name (the name of the boost generator) and a seed::
|
||||||
|
|
||||||
from pytriqs.random import *
|
from pytriqs.random_generator import *
|
||||||
r = RandomGenerator("mt19937", 237849)
|
r = RandomGenerator("mt19937", 237849)
|
||||||
|
|
||||||
A list of possible random generator names is obtained with::
|
A list of available random generators is obtained with::
|
||||||
|
|
||||||
print available_generator_names()
|
print random_generator_names_list()
|
||||||
|
|
||||||
Then you can either generate float number on the interval :math:`[0,1[` using
|
Then you can either generate float number on the interval :math:`[0,1[`
|
||||||
the ``rand()`` method or integer numbers in the inverval :math:`[0,N-1]` using
|
simply by calling the generator, or integer numbers in the inverval :math:`[0,N-1]` by calling
|
||||||
``int_rand(N)``::
|
it with `N` ::
|
||||||
|
|
||||||
print r.rand()
|
print r()
|
||||||
print r.int_rand(10)
|
print r(10)
|
||||||
|
|
||||||
Example
|
Example
|
||||||
-------
|
-------
|
||||||
@ -42,7 +43,7 @@ Here's a simple example showing how to use the generator.
|
|||||||
Complete reference
|
Complete reference
|
||||||
------------------
|
------------------
|
||||||
|
|
||||||
.. autoclass:: pytriqs.random.RandomGenerator
|
.. autoclass:: pytriqs.random_generator.RandomGenerator
|
||||||
:members:
|
:members:
|
||||||
|
|
||||||
.. autofunction:: pytriqs.random.available_generator_names
|
.. autofunction:: pytriqs.random_generator.random_generator_names_list
|
||||||
|
@ -1,5 +0,0 @@
|
|||||||
|
|
||||||
from random_generator import RandomGenerator, available_generator_names
|
|
||||||
|
|
||||||
__all__ = ['RandomGenerator','available_generator_names']
|
|
||||||
|
|
@ -1,49 +0,0 @@
|
|||||||
from dcomplex cimport *
|
|
||||||
from libcpp.string cimport string
|
|
||||||
|
|
||||||
# The c++ random generator class
|
|
||||||
# We wrap two members only
|
|
||||||
cdef extern from "triqs/mc_tools/random_generator.hpp":
|
|
||||||
|
|
||||||
cdef cppclass random_generator "triqs::mc_tools::random_generator":
|
|
||||||
|
|
||||||
random_generator(string, long) except +
|
|
||||||
double operator() () except +
|
|
||||||
int operator() (int) except +
|
|
||||||
|
|
||||||
# This is the wrapping of the static member random_generator_names
|
|
||||||
# It is a bit of a hack but there is no notion of ststic members in cython
|
|
||||||
cdef extern from "triqs/mc_tools/random_generator.hpp" namespace "triqs::mc_tools::random_generator":
|
|
||||||
|
|
||||||
string random_generator_names(string) except +
|
|
||||||
|
|
||||||
|
|
||||||
# The python RandomGenerator class
|
|
||||||
cdef class RandomGenerator:
|
|
||||||
|
|
||||||
cdef random_generator * _c
|
|
||||||
|
|
||||||
def __init__(self, name, seed):
|
|
||||||
"""This is a random number generator class based on boost.
|
|
||||||
|
|
||||||
:param name: (string) Name of the random number generator
|
|
||||||
:param seed: (int) Random number seed
|
|
||||||
"""
|
|
||||||
self._c = new random_generator(name, seed)
|
|
||||||
|
|
||||||
def __dealloc__(self):
|
|
||||||
del self._c
|
|
||||||
|
|
||||||
def rand(self):
|
|
||||||
"""Generate a float random number in [0,1["""
|
|
||||||
return self._c[0]()
|
|
||||||
|
|
||||||
def int_rand(self, N):
|
|
||||||
"""Generate an integer random number in [0,N-1]"""
|
|
||||||
return self._c[0](N)
|
|
||||||
|
|
||||||
# The list of generator names accessed through the static member
|
|
||||||
def available_generator_names():
|
|
||||||
"""Get a list of available random generator names"""
|
|
||||||
return random_generator_names(",").split(',')
|
|
||||||
|
|
@ -2,7 +2,8 @@ SET(PYTHON_SOURCES
|
|||||||
${CMAKE_CURRENT_SOURCE_DIR}/__init__.py
|
${CMAKE_CURRENT_SOURCE_DIR}/__init__.py
|
||||||
)
|
)
|
||||||
|
|
||||||
install (FILES ${PYTHON_SOURCES} DESTINATION ${TRIQS_PYTHON_LIB_DEST}/random)
|
install (FILES ${PYTHON_SOURCES} DESTINATION ${TRIQS_PYTHON_LIB_DEST}/random_generator)
|
||||||
|
|
||||||
|
# Build C extension module
|
||||||
|
triqs_python_extension(random_generator random_generator)
|
||||||
|
|
||||||
# the c++ code
|
|
||||||
cython_module(random random_generator random)
|
|
5
pytriqs/random_generator/__init__.py
Normal file
5
pytriqs/random_generator/__init__.py
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
|
||||||
|
from random_generator import RandomGenerator, random_generator_names_list
|
||||||
|
|
||||||
|
__all__ = ['RandomGenerator','random_generator_names_list']
|
||||||
|
|
46
pytriqs/random_generator/random_generator_desc.py
Normal file
46
pytriqs/random_generator/random_generator_desc.py
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
from wrap_generator import *
|
||||||
|
|
||||||
|
module = module_(full_name = "pytriqs.random_generator", doc = "")
|
||||||
|
module.add_include("<triqs/mc_tools/random_generator.hpp>")
|
||||||
|
module.add_using("namespace triqs::mc_tools")
|
||||||
|
# Not needed. Reorganize the hpp wrapper tool
|
||||||
|
module.add_include("<triqs/h5.hpp>")
|
||||||
|
module.add_include("<triqs/arrays.hpp>")
|
||||||
|
|
||||||
|
# --------- RandomGenerator ----------------------------------
|
||||||
|
|
||||||
|
r = class_(py_type = "RandomGenerator",
|
||||||
|
c_type = "random_generator",
|
||||||
|
c_type_absolute = "triqs::mc_tools::random_generator",
|
||||||
|
)
|
||||||
|
|
||||||
|
r.add_constructor(signature = "(std::string name, int seed)",
|
||||||
|
doc =
|
||||||
|
"""
|
||||||
|
This is a random number generator class based on boost.
|
||||||
|
|
||||||
|
name Name of the random number generator
|
||||||
|
seed Random number seed
|
||||||
|
""")
|
||||||
|
|
||||||
|
r.add_call(signature = "int(int N)", doc = """Generate an integer random number in [0,N-1]""")
|
||||||
|
r.add_call(signature = "double()", doc = """Generate a float random number in [0,1[""")
|
||||||
|
|
||||||
|
module.add_class(r)
|
||||||
|
|
||||||
|
# --------- Module functions ----------------------------------
|
||||||
|
|
||||||
|
module.add_function(name = "random_generator_names_list",
|
||||||
|
signature = "std::vector<std::string>()",
|
||||||
|
doc = """Get a list of available random generator names"""
|
||||||
|
)
|
||||||
|
|
||||||
|
########################
|
||||||
|
## Code generation
|
||||||
|
########################
|
||||||
|
|
||||||
|
if __name__ == '__main__' :
|
||||||
|
module.generate_code(mako_template = sys.argv[1], wrap_file = sys.argv[2])
|
||||||
|
module.generate_py_converter_header(mako_template = sys.argv[3], wrap_file = sys.argv[4])
|
||||||
|
|
||||||
|
|
37
test/triqs/utility/buffered_function.cpp
Normal file
37
test/triqs/utility/buffered_function.cpp
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
*
|
||||||
|
* TRIQS: a Toolbox for Research in Interacting Quantum Systems
|
||||||
|
*
|
||||||
|
* Copyright (C) 2014 by O. Parcollet
|
||||||
|
*
|
||||||
|
* TRIQS is free software: you can redistribute it and/or modify it under the
|
||||||
|
* terms of the GNU General Public License as published by the Free Software
|
||||||
|
* Foundation, either version 3 of the License, or (at your option) any later
|
||||||
|
* version.
|
||||||
|
*
|
||||||
|
* TRIQS 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.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along with
|
||||||
|
* TRIQS. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
******************************************************************************/
|
||||||
|
#include <triqs/utility/buffered_function.hpp>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
int main(int argc, char **argv) {
|
||||||
|
|
||||||
|
// a function that generates all the square ....
|
||||||
|
int x = 0;
|
||||||
|
auto f = [x]() mutable { return x * (x++); };
|
||||||
|
|
||||||
|
// C++14 : init-capture
|
||||||
|
// auto f = [x=0]() mutable { return x*(x++);};
|
||||||
|
|
||||||
|
auto gen = triqs::utility::buffered_function<double>(f, 5);
|
||||||
|
|
||||||
|
for (int u = 0; u < 22; ++u)
|
||||||
|
if (gen() != u * u) throw "Error";
|
||||||
|
}
|
@ -1,96 +0,0 @@
|
|||||||
// (C) Copyright 2008-10 Lukas Gamper <gamperl -at- gmail.com>
|
|
||||||
// Brigitte Surer <surerb -at- phys.ethz.ch>
|
|
||||||
// Bela Bauer <bauerb -at- phys.ethz.ch>
|
|
||||||
//
|
|
||||||
// downgraded by O. Parcollet for compilation with icc11 & boost 1.45
|
|
||||||
//
|
|
||||||
// Use, modification, and distribution are subject to the Boost Software
|
|
||||||
// License, Version 1.0. (See at <http://www.boost.org/LICENSE_1_0.txt>.)
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include <algorithm>
|
|
||||||
#include <boost/function.hpp>
|
|
||||||
#include <boost/ref.hpp>
|
|
||||||
#include <boost/shared_ptr.hpp>
|
|
||||||
#include <boost/make_shared.hpp>
|
|
||||||
#include <boost/lambda/lambda.hpp>
|
|
||||||
#include <boost/lambda/bind.hpp>
|
|
||||||
#include <boost/lambda/construct.hpp>
|
|
||||||
#include <boost/lambda/exceptions.hpp>
|
|
||||||
|
|
||||||
namespace boost{
|
|
||||||
template<typename R> class generator {
|
|
||||||
public:
|
|
||||||
static std::size_t const buffer_size = 1000;
|
|
||||||
template<typename Generator> generator(Generator const & gen, std::size_t size = buffer_size)
|
|
||||||
:
|
|
||||||
buf(make_shared<buffer>(gen, size))
|
|
||||||
, cur(buf->cur)
|
|
||||||
, end(buf->end())
|
|
||||||
{}
|
|
||||||
inline R const operator()() {
|
|
||||||
if (cur == end)
|
|
||||||
buf->fill();
|
|
||||||
return *cur++;
|
|
||||||
}
|
|
||||||
inline R const preview() {
|
|
||||||
if (cur == end)
|
|
||||||
buf->fill();
|
|
||||||
return *cur;
|
|
||||||
}
|
|
||||||
|
|
||||||
generator(generator<R> const & rhs)
|
|
||||||
:
|
|
||||||
buf(new buffer (*rhs.buf))
|
|
||||||
, cur(buf->cur)
|
|
||||||
, end(buf->end())
|
|
||||||
{}
|
|
||||||
generator<R> & operator=(generator<R> rhs) {
|
|
||||||
swap(*this, rhs);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
class buffer: public std::vector<R> {
|
|
||||||
public:
|
|
||||||
friend class generator<R>;
|
|
||||||
template<typename Generator> buffer(Generator const & gen, std::size_t size)
|
|
||||||
: std::vector<R>(size)
|
|
||||||
, engine(make_shared<Generator>(gen))
|
|
||||||
, cur(this->end())
|
|
||||||
, fill_helper(lambda::bind(std::generate<typename buffer::iterator, Generator &>, lambda::_1, lambda::_2, ref(*reinterpret_cast<Generator *>(engine.get()))))
|
|
||||||
, clone(lambda::bind(buffer::template type_keeper<Generator>, lambda::_1, lambda::_2))
|
|
||||||
{}
|
|
||||||
template<typename Generator> buffer(reference_wrapper<Generator> gen, std::size_t size)
|
|
||||||
: std::vector<R>(size)
|
|
||||||
, cur(this->end())
|
|
||||||
, fill_helper(lambda::bind(std::generate<typename buffer::iterator, Generator &>, lambda::_1, lambda::_2, gen))
|
|
||||||
{}
|
|
||||||
buffer(buffer const & rhs)
|
|
||||||
: std::vector<R>(rhs)
|
|
||||||
, cur(this->begin() + (rhs.cur - rhs.begin()))
|
|
||||||
, fill_helper(rhs.fill_helper)
|
|
||||||
, clone(rhs.clone)
|
|
||||||
{
|
|
||||||
if (rhs.engine)
|
|
||||||
clone(*this, rhs);
|
|
||||||
}
|
|
||||||
inline void fill() {
|
|
||||||
fill_helper(this->begin(), this->end());
|
|
||||||
cur = this->begin();
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
template<typename Generator> static void type_keeper(buffer & lhs, buffer const & rhs) {
|
|
||||||
lhs.engine = make_shared<Generator>(*reinterpret_cast<Generator *>(rhs.engine.get()));
|
|
||||||
lhs.fill_helper = lambda::bind(std::generate<typename buffer::iterator, Generator &>, lambda::_1, lambda::_2, ref(*reinterpret_cast<Generator *>(lhs.engine.get())));
|
|
||||||
}
|
|
||||||
shared_ptr<void> engine;
|
|
||||||
typename std::vector<R>::const_iterator cur;
|
|
||||||
function<void(typename std::vector<R>::iterator, typename std::vector<R>::iterator)> fill_helper;
|
|
||||||
function<void(buffer &, buffer const &)> clone;
|
|
||||||
};
|
|
||||||
|
|
||||||
shared_ptr<buffer> buf;
|
|
||||||
typename buffer::const_iterator & cur;
|
|
||||||
typename buffer::const_iterator end;
|
|
||||||
};
|
|
||||||
}
|
|
@ -1,9 +1,8 @@
|
|||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
*
|
*
|
||||||
* TRIQS: a Toolbox for Research in Interacting Quantum Systems
|
* TRIQS: a Toolbox for Research in Interacting Quantum Systems
|
||||||
*
|
*
|
||||||
* Copyright (C) 2011 by M. Ferrero, O. Parcollet
|
* Copyright (C) 2011-2014 by M. Ferrero, O. Parcollet
|
||||||
*
|
*
|
||||||
* TRIQS is free software: you can redistribute it and/or modify it under the
|
* TRIQS is free software: you can redistribute it and/or modify it under the
|
||||||
* terms of the GNU General Public License as published by the Free Software
|
* terms of the GNU General Public License as published by the Free Software
|
||||||
@ -19,7 +18,6 @@
|
|||||||
* TRIQS. If not, see <http://www.gnu.org/licenses/>.
|
* TRIQS. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*
|
*
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
#include "random_generator.hpp"
|
#include "random_generator.hpp"
|
||||||
#include "./MersenneRNG.hpp"
|
#include "./MersenneRNG.hpp"
|
||||||
#include <boost/random.hpp>
|
#include <boost/random.hpp>
|
||||||
@ -32,29 +30,34 @@
|
|||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <boost/preprocessor/seq.hpp>
|
#include <boost/preprocessor/seq.hpp>
|
||||||
#include <boost/preprocessor/control/if.hpp>
|
#include <boost/preprocessor/control/if.hpp>
|
||||||
#define AS_STRING(X) AS_STRING2(X)
|
|
||||||
#define AS_STRING2(X) #X
|
|
||||||
|
|
||||||
// List of All available Boost random number generator
|
// List of All available Boost random number generator
|
||||||
#define RNG_LIST (mt19937)(mt11213b)\
|
#define RNG_LIST \
|
||||||
(lagged_fibonacci607) (lagged_fibonacci1279) (lagged_fibonacci2281) (lagged_fibonacci3217) (lagged_fibonacci4423)\
|
(mt19937)(mt11213b)(lagged_fibonacci607)(lagged_fibonacci1279)(lagged_fibonacci2281)(lagged_fibonacci3217)( \
|
||||||
(lagged_fibonacci9689) (lagged_fibonacci19937) (lagged_fibonacci23209) (lagged_fibonacci44497) (ranlux3)
|
lagged_fibonacci4423)(lagged_fibonacci9689)(lagged_fibonacci19937)(lagged_fibonacci23209)(lagged_fibonacci44497)(ranlux3)
|
||||||
|
|
||||||
|
|
||||||
namespace triqs {
|
namespace triqs {
|
||||||
namespace mc_tools {
|
namespace mc_tools {
|
||||||
|
|
||||||
typedef boost::generator <double> gen_type;
|
random_generator::random_generator(std::string const& RandomGeneratorName, uint32_t seed_) {
|
||||||
|
_name = RandomGeneratorName;
|
||||||
|
|
||||||
inline gen_type * choose_gen(std::string const & RandomGeneratorName, std::size_t seed_, boost::shared_ptr<void> &ptr) {
|
if (RandomGeneratorName == "") {
|
||||||
|
gen = utility::buffered_function<double>(mc_tools::RandomGenerators::RandMT(seed_));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (RandomGeneratorName=="") return new gen_type( mc_tools::RandomGenerators::RandMT (seed_));
|
boost::uniform_real<> dis;
|
||||||
|
|
||||||
|
#define AS_STRING(X) AS_STRING2(X)
|
||||||
|
#define AS_STRING2(X) #X
|
||||||
|
|
||||||
// now boost random number generators
|
// now boost random number generators
|
||||||
#define DRNG(r,data,XX) if (RandomGeneratorName==AS_STRING(XX)) { \
|
#define DRNG(r, data, XX) \
|
||||||
boost::shared_ptr<boost::XX> localptr = boost::make_shared<boost::XX>(seed_);\
|
if (RandomGeneratorName == AS_STRING(XX)) { \
|
||||||
ptr = localptr; boost::uniform_real<> dis;\
|
gen = utility::buffered_function<double>(boost::variate_generator<boost::XX, boost::uniform_real<>>(boost::XX(seed_), dis)); \
|
||||||
return new gen_type( boost::variate_generator<boost::XX&, boost::uniform_real<> >(*localptr,dis));}
|
return; \
|
||||||
|
}
|
||||||
|
|
||||||
BOOST_PP_SEQ_FOR_EACH(DRNG, ~, RNG_LIST)
|
BOOST_PP_SEQ_FOR_EACH(DRNG, ~, RNG_LIST)
|
||||||
|
|
||||||
@ -63,19 +66,16 @@ namespace triqs {
|
|||||||
|
|
||||||
//---------------------------------------------
|
//---------------------------------------------
|
||||||
|
|
||||||
random_generator::random_generator(std::string const & RandomGeneratorName, std::size_t seed_ ) :
|
std::string random_generator_names(std::string const &sep) {
|
||||||
rng_ptr(), gen (choose_gen(RandomGeneratorName,seed_,rng_ptr)), name(RandomGeneratorName),seed(seed_) {}
|
|
||||||
|
|
||||||
//---------------------------------------------
|
|
||||||
|
|
||||||
random_generator::random_generator( random_generator const & p) :
|
|
||||||
rng_ptr(), gen (choose_gen(p.name,p.seed,rng_ptr)), name (p.name),seed(p.seed) {}
|
|
||||||
|
|
||||||
//---------------------------------------------
|
|
||||||
|
|
||||||
std::string random_generator::random_generator_names(std::string const & sep) {
|
|
||||||
#define PR(r, sep, p, XX) BOOST_PP_IF(p, +sep +, ) std::string(AS_STRING(XX))
|
#define PR(r, sep, p, XX) BOOST_PP_IF(p, +sep +, ) std::string(AS_STRING(XX))
|
||||||
return BOOST_PP_SEQ_FOR_EACH_I(PR, sep, RNG_LIST);
|
return BOOST_PP_SEQ_FOR_EACH_I(PR, sep, RNG_LIST);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> random_generator_names_list() {
|
||||||
|
std::vector<std::string> res;
|
||||||
|
#define PR2(r, sep, p, XX) res.push_back(AS_STRING(XX));
|
||||||
|
BOOST_PP_SEQ_FOR_EACH_I(PR2, sep, RNG_LIST);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
*
|
*
|
||||||
* TRIQS: a Toolbox for Research in Interacting Quantum Systems
|
* TRIQS: a Toolbox for Research in Interacting Quantum Systems
|
||||||
*
|
*
|
||||||
* Copyright (C) 2011 by M. Ferrero, O. Parcollet
|
* Copyright (C) 2011-2014 by M. Ferrero, O. Parcollet
|
||||||
*
|
*
|
||||||
* TRIQS is free software: you can redistribute it and/or modify it under the
|
* TRIQS is free software: you can redistribute it and/or modify it under the
|
||||||
* terms of the GNU General Public License as published by the Free Software
|
* terms of the GNU General Public License as published by the Free Software
|
||||||
@ -18,62 +18,70 @@
|
|||||||
* TRIQS. If not, see <http://www.gnu.org/licenses/>.
|
* TRIQS. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*
|
*
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
#pragma once
|
||||||
#ifndef POLYMORPH_RANDOM_GENERATOR_H
|
|
||||||
#define POLYMORPH_RANDOM_GENERATOR_H
|
|
||||||
#include <triqs/utility/first_include.hpp>
|
#include <triqs/utility/first_include.hpp>
|
||||||
#include <boost/scoped_ptr.hpp>
|
|
||||||
#include "../utility/exceptions.hpp"
|
#include "../utility/exceptions.hpp"
|
||||||
#include "./generator.hpp"
|
#include "../utility/buffered_function.hpp"
|
||||||
#include "math.h"
|
#include "math.h"
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
namespace triqs {
|
namespace triqs {
|
||||||
namespace mc_tools {
|
namespace mc_tools {
|
||||||
|
|
||||||
|
/// Return a list of the names of available generators, with separator sep
|
||||||
|
std::string random_generator_names(std::string const & sep=" ");
|
||||||
|
std::vector<std::string> random_generator_names_list();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is a random generator that take the name of the random generator at construct
|
* Random generator, adapting the boost random generator.
|
||||||
* and serve random numbers, buffered with a version boost::generator ,
|
*
|
||||||
* to hide the cost of dynamical polymorphism.
|
* The name of the generator is given at construction, and its type is erased in this class.
|
||||||
|
* For performance, the call to the generator is bufferized, with chunks of 1000 numbers.
|
||||||
*/
|
*/
|
||||||
class random_generator {
|
class random_generator {
|
||||||
boost::shared_ptr<void> rng_ptr;
|
utility::buffered_function<double> gen;
|
||||||
boost::scoped_ptr< boost::generator <double> > gen;
|
std::string _name;
|
||||||
std::string name;
|
|
||||||
void operator = ( random_generator const & p); //forbid
|
|
||||||
std::size_t seed;
|
|
||||||
public:
|
|
||||||
|
|
||||||
/// Takes the boost name of the generator e.g. mt19937,...
|
public:
|
||||||
random_generator(std::string const & RandomGeneratorName, std::size_t seed_ );
|
/** Constructor
|
||||||
|
* @param RandomGeneratorName : Name of a boost generator e.g. mt19937, or "" (another Mersenne Twister).
|
||||||
|
* @param seed : The seed of the random generator
|
||||||
|
*/
|
||||||
|
random_generator(std::string const& RandomGeneratorName, uint32_t seed_);
|
||||||
|
|
||||||
|
random_generator() : random_generator("mt19937", 198) {}
|
||||||
|
|
||||||
///
|
///
|
||||||
random_generator(random_generator const& p);
|
random_generator(random_generator const& p);
|
||||||
|
|
||||||
/// Return a list of the names of available generators, with separator sep
|
random_generator(random_generator&&) = default;
|
||||||
static std::string random_generator_names(std::string const & sep=" ");
|
|
||||||
|
//
|
||||||
|
random_generator & operator=(random_generator&&) = default;
|
||||||
|
|
||||||
|
/// Name of the random generator
|
||||||
|
std::string name() const { return _name; }
|
||||||
|
|
||||||
/// Returns a integer in [0,i-1] with flat distribution
|
/// Returns a integer in [0,i-1] with flat distribution
|
||||||
#define INTEGER_OVERLOAD(T) T operator()(T i) { return (i==1 ? 0 : T(floor(i*((*gen)()))));}
|
template <typename T> typename std::enable_if<std::is_integral<T>::value, T>::type operator()(T i) {
|
||||||
INTEGER_OVERLOAD(int)
|
return (i == 1 ? 0 : T(floor(i * (gen()))));
|
||||||
INTEGER_OVERLOAD(size_t)
|
}
|
||||||
#undef INTEGER_OVERLOAD
|
|
||||||
|
|
||||||
/// Returns a double in [0,1[ with flat distribution
|
/// Returns a double in [0,1[ with flat distribution
|
||||||
double preview() { return gen->preview();}
|
double preview() { return gen.preview();}
|
||||||
|
|
||||||
/// Returns a double in [0,1[ with flat distribution
|
double operator()() { return gen(); }
|
||||||
double operator()() { return ((*gen)());}
|
|
||||||
|
|
||||||
/// Returns a double in [0,x[ with flat distribution
|
/// Returns a double in [0,x[ with flat distribution
|
||||||
double operator()(double x) { return x*((*gen)());}
|
double operator()(double x) { return x * (gen()); }
|
||||||
|
|
||||||
/// Returns a double in [a,b[ with flat distribution
|
/// Returns a double in [a,b[ with flat distribution
|
||||||
double operator()(double a, double b) { assert (b>a); return a + (b-a)*((*gen)());}
|
double operator()(double a, double b) {
|
||||||
|
assert(b > a);
|
||||||
|
return a + (b - a) * (gen());
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
74
triqs/utility/buffered_function.hpp
Normal file
74
triqs/utility/buffered_function.hpp
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
*
|
||||||
|
* TRIQS: a Toolbox for Research in Interacting Quantum Systems
|
||||||
|
*
|
||||||
|
* Copyright (C) 2014 by O. Parcollet
|
||||||
|
*
|
||||||
|
* TRIQS is free software: you can redistribute it and/or modify it under the
|
||||||
|
* terms of the GNU General Public License as published by the Free Software
|
||||||
|
* Foundation, either version 3 of the License, or (at your option) any later
|
||||||
|
* version.
|
||||||
|
*
|
||||||
|
* TRIQS 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.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along with
|
||||||
|
* TRIQS. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
******************************************************************************/
|
||||||
|
#pragma once
|
||||||
|
#include <vector>
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
|
namespace triqs {
|
||||||
|
namespace utility {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A simple buffer for a generator.
|
||||||
|
* Given a function, it provides a buffer of this function
|
||||||
|
* Advantage :
|
||||||
|
* - do not pay the indirection cost at each call, but once every size call.
|
||||||
|
* - erase the function type
|
||||||
|
* It is a semi-regular type.
|
||||||
|
*/
|
||||||
|
template <typename R> struct buffered_function {
|
||||||
|
|
||||||
|
/// Default constructor : no function bufferized. () will throw in this state
|
||||||
|
buffered_function() = default;
|
||||||
|
|
||||||
|
/** Constructor
|
||||||
|
*
|
||||||
|
* @tparam Function : type of the function to bufferize
|
||||||
|
* @param f : function to bufferize
|
||||||
|
* @param size : size of the buffer [optional]
|
||||||
|
*/
|
||||||
|
template <typename Function> buffered_function(Function f, size_t size = 1000) : buffer(size) {
|
||||||
|
refill = [f](buffered_function *bf) mutable { // without the mutable, the () of the lambda object is const, hence f
|
||||||
|
for (auto &x : bf->buffer) x = f();
|
||||||
|
bf->index = 0;
|
||||||
|
};
|
||||||
|
refill(this); // first filling of the buffer
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the next element. Refills the buffer if necessary.
|
||||||
|
R operator()() {
|
||||||
|
if (index > buffer.size() - 1) refill(this);
|
||||||
|
return buffer[index++];
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the future next element, without increasing the index. Refills the buffer if necessary.
|
||||||
|
R preview() {
|
||||||
|
if (index > buffer.size() - 1) refill(this);
|
||||||
|
return buffer[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
size_t index;
|
||||||
|
std::vector<R> buffer;
|
||||||
|
std::function<void(buffered_function *)> refill; // this refills the buffer and reset index of a buffered_function.
|
||||||
|
// NB : can not capture this in refill because we want the object to be copyable and movable
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user