|
|
|||
File indexing completed on 2026-08-06 09:38:32
0001 // -*- C++ -*- 0002 // 0003 // Selector.h is a part of ThePEG - Toolkit for HEP Event Generation 0004 // Copyright (C) 1999-2019 Leif Lonnblad 0005 // 0006 // ThePEG is licenced under version 3 of the GPL, see COPYING for details. 0007 // Please respect the MCnet academic guidelines, see GUIDELINES for details. 0008 // 0009 #ifndef ThePEG_Selector_H 0010 #define ThePEG_Selector_H 0011 // This is the declaration of the Selector class. 0012 0013 #include "ThePEG/Config/ThePEG.h" 0014 #include <stdexcept> 0015 #include <algorithm> 0016 #include <stdexcept> 0017 0018 namespace ThePEG { 0019 0020 /** 0021 * Selector is a templated class for storing objects associated with 0022 * probabilities in a way such that, given a flat random number 0023 * between 0 and 1, an object can be selected according to its 0024 * relative probability. Internally, the objects of class 0025 * <code>T</code> are stored in a map where the key is the 0026 * probability of the corresponding object plus the accumulated sum of 0027 * probabilities of all objects before the current one in the 0028 * map. This allows for fast retreival of an object according to its 0029 * probability. Where fast means that the time increases as a 0030 * logarithm of the number of objects in the selector. 0031 * 0032 * Here is an example on how to use the class:<br> 0033 * <code>double random();</code> // A random generator returning a 0034 * number between 0 and 1.<br> 0035 * <code>class foo;</code> // Any class.<BR> 0036 * <code>Selector<foo*> bar;</code> // A selector.<BR> 0037 * <code>foo f1, f2;</code> <BR> 0038 * <code>bar.insert(0.5,&f1)</code> // assign probability 0.5<BR> 0039 * <code>bar.insert(0.5,&f2)</code> // to each of f1 and f2<BR> 0040 * <code>foo * f = bar.select(random())</code> // randomly returns 0041 * a pointer to f1 or f2<BR> 0042 * 0043 * @see VSelector 0044 */ 0045 template <typename T, typename WeightType = double> 0046 class Selector { 0047 0048 public: 0049 0050 /** Map doubles to objects. */ 0051 typedef map<WeightType, T, less<WeightType> > MapType; 0052 0053 /** Iterator corresponding to the underlying map. */ 0054 typedef typename MapType::const_iterator const_iterator; 0055 0056 /** Iterator corresponding to the underlying map. */ 0057 typedef typename MapType::iterator iterator; 0058 0059 /** Size type of the underlying map. */ 0060 typedef typename MapType::size_type size_type; 0061 0062 public: 0063 0064 /** 0065 * Default constructor. 0066 */ 0067 Selector() : theSum(WeightType()) {} 0068 0069 /** 0070 * Swap the underlying representation with the argument. 0071 */ 0072 void swap(Selector & s) 0073 { 0074 theMap.swap(s.theMap); 0075 std::swap(theSum, s.theSum); 0076 } 0077 0078 /** 0079 * Insert an object given a probability for this object. If the 0080 * probability is zero or negative, the object will not be inserted 0081 * and the probability itself is returned. Otherwise the sum of 0082 * probabilities so far is returned. 0083 */ 0084 WeightType insert(WeightType d, const T & t) { 0085 typedef typename MapType::value_type value_type; 0086 WeightType newSum = theSum + d; 0087 if ( newSum <= theSum ) return d; 0088 theMap.insert(theMap.end(), value_type((theSum = newSum), t)); 0089 return theSum; 0090 } 0091 0092 /** 0093 * Reweight an object previously inserted giving it a new 0094 * weight. Semantically <code>reweight(w,o);</code> is equivalent to 0095 * <code>erase(o); insert(w,o);</code> 0096 */ 0097 WeightType reweight(WeightType d, const T & t) 0098 { 0099 erase(t); 0100 return insert(d, t); 0101 } 0102 0103 /** 0104 * Erase an object, previously inserted. If the object had not been 0105 * inserted, nothing will happen. If several copies of the object 0106 * has been inserted, all will be removed removed. In all cases the 0107 * sum of the remaining probabilities is returned. 0108 */ 0109 WeightType erase(const T &); 0110 0111 /** 0112 * Replace all occurencies of oldObject with newObject without 0113 * changing the probability for the entry. 0114 */ 0115 void replace(const T & oldObject, const T & newObject) { 0116 for ( iterator it = theMap.begin(); it != theMap.end(); ++it ) 0117 if ( it->second == oldObject ) it->second = newObject; 0118 } 0119 0120 /** 0121 * Select an object randomly. Given a random number flatly 0122 * distributed in the interval ]0,1[ Select an object according to 0123 * the individual probabilities specified when they were 0124 * inserted. If rnd <= 0 or if rnd >= 1 or the Selector is empty, a 0125 * range_error will be thrown. 0126 * @param rnd a flat random number in the interval ]0,1[ 0127 * @param remainder if non-zero the double pointed to will be set to 0128 * a uniform random number in the interval ]0,1[ calculated from the 0129 * fraction of rnd which was in the range of the selected object. 0130 */ 0131 T & select(double rnd, double * remainder = 0); 0132 0133 /** 0134 * Selct an object randomly. Given a random number flatly 0135 * distributed in the interval ]0,1[ Select an object according to 0136 * the individual probabilities specified when they were 0137 * inserted. If rnd <= 0 or if rnd >= 1 or the Selector is empty, a 0138 * range_error will be thrown. 0139 */ 0140 T & operator[](double rnd) { return select(rnd); } 0141 0142 /** 0143 * Selct an object randomly. Given a random number flatly 0144 * distributed in the interval ]0,1[ Select an object according to 0145 * the individual probabilities specified when they were 0146 * inserted. If rnd <= 0 or if rnd >= 1 or the Selector is empty, a 0147 * range_error will be thrown. 0148 * @param rnd a flat random number in the interval ]0,1[ 0149 * @param remainder if non-zero the double pointed to will be set to 0150 * a uniform random number in the interval ]0,1[ calculated from the 0151 * fraction of rnd which was in the range of the selected object. 0152 */ 0153 const T & select(double rnd, double * remainder = 0) const; 0154 0155 /** 0156 * Selct an object randomly. Given a random number flatly 0157 * distributed in the interval ]0,1[ select an object according to 0158 * the individual probabilities specified when they were 0159 * inserted. If rnd <= 0 or if rnd >= 1 or the Selector is empty, a 0160 * range_error will be thrown. 0161 */ 0162 const T & operator[](double rnd) const { return select(rnd); } 0163 0164 /** 0165 * Selct an object randomly. Given a random number generator which 0166 * generates flat random numbers in the interval ]0,1[ with the 0167 * <code>operator()()</code> function, select an object according to 0168 * the individual probabilities specified when they were 0169 * inserted. If the generated number is outside the allowed range or 0170 * the Selector is empty, a range_error will be thrown. The 0171 * generator should have a push_back function which will be used 0172 * push back a uniform random number in the interval ]0,1[ 0173 * calculated from the fraction of rnd which was in the range of the 0174 * selected object. 0175 */ 0176 template <typename RNDGEN> 0177 T & select(RNDGEN & rnd) { 0178 double rem = 0.0; 0179 T & t = select(rnd(), &rem); 0180 rnd.push_back(rem); 0181 return t; 0182 } 0183 0184 /** 0185 * Selct an object randomly. Given a random number generator which 0186 * generates flat random numbers in the interval ]0,1[ with the 0187 * <code>operator()()</code> function, select an object according to 0188 * the individual probabilities specified when they were 0189 * inserted. If the generated number is outside the allowed range or 0190 * the Selector is empty, a range_error will be thrown. The 0191 * generator should have a push_back function which will be used 0192 * push back a uniform random number in the interval ]0,1[ 0193 * calculated from the fraction of rnd which was in the range of the 0194 * selected object. 0195 */ 0196 template <typename RNDGEN> 0197 const T & select(RNDGEN & rnd) const { 0198 double rem = 0.0; 0199 const T & t = select(rnd(), &rem); 0200 rnd.push_back(rem); 0201 return t; 0202 } 0203 0204 /** 0205 * Return the sum of probabilities of the objects inserted. Note 0206 * that probabilities specified when objects are inserted are 0207 * rescaled with this number to give unit probability for 0208 * 'select()'. 0209 */ 0210 WeightType sum() const { return theSum; } 0211 0212 /** 0213 * Access to the <code>begin()</code> iterator of the underlying 0214 * map. Dereferenced, it will give a std::pair<WeightType, T>, where 0215 * 'first' is the sum of all probabilities up to this one, and 0216 * 'second' is the object inserted. 0217 */ 0218 const_iterator begin() const { return theMap.begin(); } 0219 0220 /** 0221 * Access to the <code>end()</code> iterator in the underlying 0222 * map. 0223 */ 0224 const_iterator end() const { return theMap.end(); } 0225 0226 /** 0227 * Returns true if the Selector is empty. 0228 */ 0229 bool empty() const { return theMap.empty(); } 0230 0231 /** 0232 * Returns the number of objects in the selector. 0233 */ 0234 size_type size() const { return theMap.size(); } 0235 0236 /** 0237 * Erases all objects. 0238 */ 0239 void clear() { theMap.clear(); theSum = WeightType(); } 0240 0241 /** 0242 * Output to a stream for dimensionful units. 0243 */ 0244 template <typename OStream> 0245 void output(OStream &, DimensionT) const; 0246 0247 /** 0248 * Input from a stream for dimensionful units. 0249 */ 0250 template <typename IStream> 0251 void input(IStream &, DimensionT); 0252 0253 /** 0254 * Output to a stream. 0255 */ 0256 template <typename OStream> 0257 void output(OStream &, StandardT) const; 0258 0259 /** 0260 * Input from a stream. 0261 */ 0262 template <typename IStream> 0263 void input(IStream &, StandardT); 0264 0265 private: 0266 0267 /** 0268 * The underlying map relating sums of probabilities to inserted objects. 0269 */ 0270 MapType theMap; 0271 0272 /** 0273 * The sum of all probabilities assicialted with inserted objects. 0274 */ 0275 WeightType theSum; 0276 0277 }; 0278 0279 /** 0280 * Output a Selector to a stream. 0281 */ 0282 template <typename OStream, typename T, typename WeightType> 0283 OStream & operator<<(OStream & os, const Selector<T,WeightType> & s) 0284 { 0285 s.output(os, typename TypeTraits<WeightType>::DimType()); 0286 return os; 0287 } 0288 0289 /** 0290 * Input a Selector from a stream. 0291 */ 0292 template <typename IStream, typename T, typename WeightType> 0293 IStream & operator>>(IStream & is, Selector<T,WeightType> & s) 0294 { 0295 s.input(is, typename TypeTraits<WeightType>::DimType()); 0296 return is; 0297 } 0298 0299 0300 } 0301 0302 #ifndef ThePEG_TEMPLATES_IN_CC_FILE 0303 #include "Selector.tcc" 0304 #endif 0305 0306 #endif /* ThePEG_Selector_H */
| [ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
|
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |
|