/******************************************************************************* * * 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