/usr/include/ThePEG/Utilities/Selector.h is in libthepeg-dev 1.8.0-1.1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 | // -*- C++ -*-
//
// Selector.h is a part of ThePEG - Toolkit for HEP Event Generation
// Copyright (C) 1999-2011 Leif Lonnblad
//
// ThePEG is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
#ifndef ThePEG_Selector_H
#define ThePEG_Selector_H
// This is the declaration of the Selector class.
#include "ThePEG/Config/ThePEG.h"
#include <stdexcept>
#include <algorithm>
#include <stdexcept>
namespace ThePEG {
/**
* Selector is a templated class for storing objects associated with
* probabilities in a way such that, given a flat random number
* between 0 and 1, an object can be selected according to its
* relative probability. Internally, the objects of class
* <code>T</code> are stored in a map where the key is the
* probability of the corresponding object plus the accumulated sum of
* probabilities of all objects before the current one in the
* map. This allows for fast retreival of an object according to its
* probability. Where fast means that the time increases as a
* logarithm of the number of objects in the selector.
*
* Here is an example on how to use the class:<br>
* <code>double random();</code> // A random generator returning a
* number between 0 and 1.<br>
* <code>class foo;</code> // Any class.<BR>
* <code>Selector<foo*> bar;</code> // A selector.<BR>
* <code>foo f1, f2;</code> <BR>
* <code>bar.insert(0.5,&f1)</code> // assign probability 0.5<BR>
* <code>bar.insert(0.5,&f2)</code> // to each of f1 and f2<BR>
* <code>foo * f = bar.select(random())</code> // randomly returns
* a pointer to f1 or f2<BR>
*
* @see VSelector
*/
template <typename T, typename WeightType = double>
class Selector {
public:
/** Map doubles to objects. */
typedef map<WeightType, T, less<WeightType> > MapType;
/** Iterator corresponding to the underlying map. */
typedef typename MapType::const_iterator const_iterator;
/** Iterator corresponding to the underlying map. */
typedef typename MapType::iterator iterator;
/** Size type of the underlying map. */
typedef typename MapType::size_type size_type;
public:
/**
* Default constructor.
*/
Selector() : theSum(WeightType()) {}
/**
* Swap the underlying representation with the argument.
*/
void swap(Selector & s)
{
theMap.swap(s.theMap);
std::swap(theSum, s.theSum);
}
/**
* Insert an object given a probability for this object. If the
* probability is zero or negative, the object will not be inserted
* and the probability itself is returned. Otherwise the sum of
* probabilities so far is returned.
*/
WeightType insert(WeightType d, const T & t) {
typedef typename MapType::value_type value_type;
WeightType newSum = theSum + d;
if ( newSum <= theSum ) return d;
theMap.insert(theMap.end(), value_type((theSum = newSum), t));
return theSum;
}
/**
* Reweight an object previously inserted giving it a new
* weight. Semantically <code>reweight(w,o);</code> is equivalent to
* <code>erase(o); insert(w,o);</code>
*/
WeightType reweight(WeightType d, const T & t)
{
erase(t);
return insert(d, t);
}
/**
* Erase an object, previously inserted. If the object had not been
* inserted, nothing will happen. If several copies of the object
* has been inserted, all will be removed removed. In all cases the
* sum of the remaining probabilities is returned.
*/
WeightType erase(const T &);
/**
* Replace all occurencies of oldObject with newObject without
* changing the probability for the entry.
*/
void replace(const T & oldObject, const T & newObject) {
for ( iterator it = theMap.begin(); it != theMap.end(); ++it )
if ( it->second == oldObject ) it->second = newObject;
}
/**
* Select an object randomly. Given a random number flatly
* distributed in the interval ]0,1[ Select an object according to
* the individual probabilities specified when they were
* inserted. If rnd <= 0 or if rnd >= 1 or the Selector is empty, a
* range_error will be thrown.
* @param rnd a flat random number in the interval ]0,1[
* @param remainder if non-zero the double pointed to will be set to
* a uniform random number in the interval ]0,1[ calculated from the
* fraction of rnd which was in the range of the selected object.
*/
T & select(double rnd, double * remainder = 0) throw(range_error);
/**
* Selct an object randomly. Given a random number flatly
* distributed in the interval ]0,1[ Select an object according to
* the individual probabilities specified when they were
* inserted. If rnd <= 0 or if rnd >= 1 or the Selector is empty, a
* range_error will be thrown.
*/
T & operator[](double rnd) throw(range_error) { return select(rnd); }
/**
* Selct an object randomly. Given a random number flatly
* distributed in the interval ]0,1[ Select an object according to
* the individual probabilities specified when they were
* inserted. If rnd <= 0 or if rnd >= 1 or the Selector is empty, a
* range_error will be thrown.
* @param rnd a flat random number in the interval ]0,1[
* @param remainder if non-zero the double pointed to will be set to
* a uniform random number in the interval ]0,1[ calculated from the
* fraction of rnd which was in the range of the selected object.
*/
const T & select(double rnd, double * remainder = 0) const throw(range_error);
/**
* Selct an object randomly. Given a random number flatly
* distributed in the interval ]0,1[ select an object according to
* the individual probabilities specified when they were
* inserted. If rnd <= 0 or if rnd >= 1 or the Selector is empty, a
* range_error will be thrown.
*/
const T & operator[](double rnd) const throw(range_error) { return select(rnd); }
/**
* Selct an object randomly. Given a random number generator which
* generates flat random numbers in the interval ]0,1[ with the
* <code>operator()()</code> function, select an object according to
* the individual probabilities specified when they were
* inserted. If the generated number is outside the allowed range or
* the Selector is empty, a range_error will be thrown. The
* generator should have a push_back function which will be used
* push back a uniform random number in the interval ]0,1[
* calculated from the fraction of rnd which was in the range of the
* selected object.
*/
template <typename RNDGEN>
T & select(RNDGEN & rnd) throw(range_error) {
double rem = 0.0;
T & t = select(rnd(), &rem);
rnd.push_back(rem);
return t;
}
/**
* Selct an object randomly. Given a random number generator which
* generates flat random numbers in the interval ]0,1[ with the
* <code>operator()()</code> function, select an object according to
* the individual probabilities specified when they were
* inserted. If the generated number is outside the allowed range or
* the Selector is empty, a range_error will be thrown. The
* generator should have a push_back function which will be used
* push back a uniform random number in the interval ]0,1[
* calculated from the fraction of rnd which was in the range of the
* selected object.
*/
template <typename RNDGEN>
const T & select(RNDGEN & rnd) const throw(range_error) {
double rem = 0.0;
const T & t = select(rnd(), &rem);
rnd.push_back(rem);
return t;
}
/**
* Return the sum of probabilities of the objects inserted. Note
* that probabilities specified when objects are inserted are
* rescaled with this number to give unit probability for
* 'select()'.
*/
WeightType sum() const { return theSum; }
/**
* Access to the <code>begin()</code> iterator of the underlying
* map. Dereferenced, it will give a std::pair<WeightType, T>, where
* 'first' is the sum of all probabilities up to this one, and
* 'second' is the object inserted.
*/
const_iterator begin() const { return theMap.begin(); }
/**
* Access to the <code>end()</code> iterator in the underlying
* map.
*/
const_iterator end() const { return theMap.end(); }
/**
* Returns true if the Selector is empty.
*/
bool empty() const { return theMap.empty(); }
/**
* Returns the number of objects in the selector.
*/
size_type size() const { return theMap.size(); }
/**
* Erases all objects.
*/
void clear() { theMap.clear(); theSum = WeightType(); }
/**
* Output to a stream.
*/
template <typename OStream>
void output(OStream &) const;
/**
* Input from a stream.
*/
template <typename IStream>
void input(IStream &);
private:
/**
* The underlying map relating sums of probabilities to inserted objects.
*/
MapType theMap;
/**
* The sum of all probabilities assicialted with inserted objects.
*/
WeightType theSum;
};
/**
* Output a Selector to a stream.
*/
template <typename OStream, typename T, typename WeightType>
OStream & operator<<(OStream & os, const Selector<T,WeightType> & s)
{
s.output(os);
return os;
}
/**
* Input a Selector from a stream.
*/
template <typename IStream, typename T, typename WeightType>
IStream & operator>>(IStream & is, Selector<T,WeightType> & s)
{
s.input(is);
return is;
}
}
#ifndef ThePEG_TEMPLATES_IN_CC_FILE
#include "Selector.tcc"
#endif
#endif /* ThePEG_Selector_H */
|