/*******************************************************************************
*
* TRIQS: a Toolbox for Research in Interacting Quantum Systems
*
* Copyright (C) 2011 by M. Ferrero, 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 .
*
******************************************************************************/
#ifndef TRIQS_TOOLS_MC_MOVE_SET1_H
#define TRIQS_TOOLS_MC_MOVE_SET1_H
#include
#include
#include "random_generator.hpp"
#include
#include
namespace triqs { namespace mc_tools {
namespace mpi=boost::mpi;
template class move_set;
namespace details {
template
struct move_base {
virtual ~move_base(){}
virtual MCSignType Try()=0;
virtual MCSignType Accept()=0;
virtual void Reject()=0;
virtual double acceptance_probability(mpi::communicator const & c) const=0;// on master,0 on nodes
virtual void print (triqs::utility::report_stream &, mpi::communicator const &, std::string name, std::string decal) const =0;
};
//--------------------------------------------------------------------
template struct IsMove {
BOOST_CONCEPT_USAGE(IsMove)
{
Y r = i.Try();
r = i.Accept();
i.Reject();
}
private:
X i;
};
//--------------------------------------------------------------------
template
void print_move (MoveType const &,triqs::utility::report_stream &,mpi::communicator const &,std::string name,std::string decal){}
template
void print_move (move_set const & M, triqs::utility::report_stream & report, mpi::communicator const & c, std::string name, std::string decal);
//--------------------------------------------------------------------
template
class move_impl : boost::noncopyable, public move_base {
BOOST_CONCEPT_ASSERT((IsMove));
private:
boost::shared_ptr ptr; // ptr to the move
uint64_t NProposed,NAccepted; // Statistics
void operator=(move_impl const &); // forbidden
public:
move_impl(MoveType * move_ptr):move_base(),ptr(move_ptr),NProposed(0),NAccepted(0) {}
move_impl(boost::shared_ptr sptr):move_base(),ptr(sptr),NProposed(0),NAccepted(0) {}
move_impl(move_impl const & M):
move_base(),ptr(new MoveType (*M.ptr.get())),
NProposed(M.NProposed),NAccepted(M.NAccepted){}
virtual ~move_impl(){}
virtual MCSignType Try(){ NProposed++; return ptr->Try();}
virtual MCSignType Accept() { NAccepted++; return ptr->Accept(); }
virtual void Reject() { ptr->Reject();}
const MoveType * get() const { return ptr.get();}
/// Acceptance Probability on the master and 0 on the nodes
virtual double acceptance_probability(mpi::communicator const & c) const {
uint64_t nacc_tot=0, nprop_tot=1;
mpi::reduce(c, NAccepted, nacc_tot, std::plus(), 0);
mpi::reduce(c, NProposed, nprop_tot, std::plus(), 0);
return nacc_tot/static_cast(nprop_tot);
}
virtual void print (triqs::utility::report_stream & report, mpi::communicator const & c, std::string name, std::string decal) const {
report<< decal <<"Acceptance probability of move : "<
class move_set {
boost::ptr_vector > moves_;
std::vector names_;
details::move_base * current;
size_t current_move_number;
random_generator & RNG;
std::vector Proba_Moves, Proba_Moves_Acc_Sum;
public:
///
move_set(random_generator & R): RNG(R) { Proba_Moves.push_back(0); }
/**
* Add move M with its probability of being proposed.
* NB : the PropositionProbability needs to be >0 but does not need to be
* normalized. Normalization is automatically done with all the added moves
* before starting the run
*
* WARNING : the pointer is deleted automatically by the MC class at destruction.
*/
template
void add (MoveType * && M, std::string name, double PropositionProbability) {
moves_.push_back(new details::move_impl(M));
assert(PropositionProbability >=0);
Proba_Moves.push_back(PropositionProbability);
names_.push_back(name);
normaliseProba();// ready to run after each add !
}
template
void add (boost::shared_ptr sptr, std::string name, double PropositionProbability) {
moves_.push_back(new details::move_impl(sptr));
assert(PropositionProbability >=0);
Proba_Moves.push_back(PropositionProbability);
names_.push_back(name);
normaliseProba();// ready to run after each add !
}
//-----------------
/**
* - Picks up one of the move at random (weighted by their proposition probability),
* - Call Try method of that move
* - Returns the metropolis ratio R (see move concept).
* The sign ratio returned by the try method of the move is kept.
*/
double Try() {
assert( Proba_Moves_Acc_Sum.size()>0);
// Choice of move with its probability
double proba = RNG();assert(proba>=0);
//std::cerr<<" Size of proba_moves_acc"<< Proba_Moves_Acc_Sum.size()<= Proba_Moves_Acc_Sum[current_move_number] ) { current_move_number++;}
//std::cerr << "curren move #"<0); assert(current_move_number<=this->size());
current_move_number--;
current = &moves_[current_move_number];
#ifdef DEBUG
std::cerr << "*******************************************************"<< std::endl;
std::cerr << "Name of the proposed move: " << name_of_currently_selected() << std::endl;
std::cerr <<" Proposition probability = "<Try();
if (!std::isfinite(std::abs(rate_ratio)))
TRIQS_RUNTIME_ERROR<<"Monte Carlo Error : the rate is not finite in move "<=0));
try_sign_ratio = ( abs_rate_ratio> 1.e-14 ? rate_ratio/abs_rate_ratio : 1); // keep the sign
return abs_rate_ratio;
}
//-----------------
/**
* Accept the move previously selected and tried.
* Returns the Sign computed as, if M is the move :
* Sign = sign (M.Try()) * M.Accept()
*/
MCSignType Accept() {
MCSignType accept_sign_ratio = current->Accept();
// just make sure that accept_sign_ratio is a sign!
assert(std::abs(std::abs(accept_sign_ratio)-1.0) < 1.e-10);
#ifdef DEBUG
std::cerr.setf(std::ios::scientific, std::ios::floatfield);
std::cerr<<" ... Move accepted"<Reject();
}
//-----------------
/// Number of moves registered in the move_set
size_t size() const { return moves_.size();}
//-----------------
/// Pretty printing of the acceptance probability of the moves.
void print (triqs::utility::report_stream & report, mpi::communicator const & c, std::string name="", std::string decal="") const {
report <0);
for (unsigned int u = 0; usize()+1);
}
/// for debug only
std::string name_of_currently_selected() const { return names_[current_move_number];}
};// class move_set
namespace details { // specialization for pretty print of move_set.
template
inline void print_move (move_set const & M, triqs::utility::report_stream & report, mpi::communicator const & c, std::string name, std::string decal) {
M.print(report,c,name,decal);
}
}
}
}// end namespace
#endif