Page MenuHomeHEPForge

No OneTemporary

diff --git a/Exsample2/Makefile.am b/Exsample2/Makefile.am
new file mode 100644
--- /dev/null
+++ b/Exsample2/Makefile.am
@@ -0,0 +1,9 @@
+# SUBDIRS = exsample
+
+pkglib_LTLIBRARIES = HwExsample2.la
+HwExsample2_la_LDFLAGS = -module -version-info 11:1:0
+HwExsample2_la_SOURCES = \
+exsampler.h exsampler.cc
+
+# HwExsample2_la_LIBADD = \
+# exsample/libexsample.la
diff --git a/Exsample2/exsample/Makefile.am b/Exsample2/exsample/Makefile.am
new file mode 100644
--- /dev/null
+++ b/Exsample2/exsample/Makefile.am
@@ -0,0 +1,19 @@
+noinst_LTLIBRARIES = libexsample.la
+libexsample_la_SOURCES = \
+adaption_info.h \
+adaption_info.icc \
+binary_tree.h \
+cell.h \
+cell.icc \
+config.h \
+exponential_generator.h \
+exponential_generator.icc \
+generator.h \
+generator.icc \
+linear_interpolator.h \
+linear_interpolator.icc \
+selectors.h \
+selectors.icc \
+statistics.h \
+statistics.icc \
+utility.h
diff --git a/Exsample2/exsample/adaption_info.h b/Exsample2/exsample/adaption_info.h
new file mode 100644
--- /dev/null
+++ b/Exsample2/exsample/adaption_info.h
@@ -0,0 +1,72 @@
+// -*- C++ -*-
+//
+// adaption_info.h is part of ExSample -- A Library for Sampling Sudakov-Type Distributions
+//
+// Copyright (C) 2008-2011 Simon Platzer -- simon.plaetzer@desy.de
+//
+// ExSample is licenced under version 2 of the GPL, see COPYING for details.
+// Please respect the MCnet academic guidelines, see GUIDELINES for details.
+//
+//
+#ifndef EXSAMPLE_adaption_info_h_included
+#define EXSAMPLE_adaption_info_h_included
+
+namespace exsample {
+
+ /// \brief adaption_info is a container for parameters relevant to
+ /// sampling and adaption.
+ struct adaption_info {
+
+ /// the default constructor
+ adaption_info()
+ : dimension(0), lower_left(), upper_right(),
+ presampling_points(100000),
+ histo_depth(2), adapt(), freeze_grid(0),
+ maxtry(200000), efficiency_threshold(.9),
+ gain_threshold(.1) {}
+
+ /// the phasespace dimension
+ std::size_t dimension;
+
+ /// the lower left corner of the function's support
+ std::vector<double> lower_left;
+
+ /// the upper right corner of the function's support
+ std::vector<double> upper_right;
+
+ /// the number of presampling points
+ unsigned long presampling_points;
+
+ /// use 2^histo_depth bins in efficiency histograms
+ std::size_t histo_depth;
+
+ /// indicate which dimensions should be adapted
+ std::vector<bool> adapt;
+
+ /// the number of accepted events after the grid is frozen
+ unsigned long freeze_grid;
+
+ /// the maximum number of misses allowed
+ unsigned long maxtry;
+
+ /// the efficiency threshold below which splits are considered
+ double efficiency_threshold;
+
+ /// a minimum gain for splits to be performed
+ double gain_threshold;
+
+ /// put to ostream
+ template<class OStream>
+ void put(OStream& os) const;
+
+ /// get from istream
+ template<class IStream>
+ void get(IStream& is);
+
+ };
+
+}
+
+#include "adaption_info.icc"
+
+#endif // EXSAMPLE_adaption_info_h_included
diff --git a/Exsample2/exsample/adaption_info.icc b/Exsample2/exsample/adaption_info.icc
new file mode 100644
--- /dev/null
+++ b/Exsample2/exsample/adaption_info.icc
@@ -0,0 +1,67 @@
+// -*- C++ -*-
+//
+// adaption_info.icc is part of ExSample -- A Library for Sampling Sudakov-Type Distributions
+//
+// Copyright (C) 2008-2011 Simon Platzer -- simon.plaetzer@desy.de
+//
+// ExSample is licenced under version 2 of the GPL, see COPYING for details.
+// Please respect the MCnet academic guidelines, see GUIDELINES for details.
+//
+//
+namespace exsample {
+
+ template<class OStream>
+ void adaption_info::put(OStream& os) const {
+ os << dimension;
+ ostream_traits<OStream>::separator(os);
+ for (std::size_t k = 0; k < dimension; ++k) {
+ os << lower_left[k];
+ ostream_traits<OStream>::separator(os);
+ }
+ for (std::size_t k = 0; k < dimension; ++k) {
+ os << upper_right[k];
+ ostream_traits<OStream>::separator(os);
+ }
+ os << presampling_points;
+ ostream_traits<OStream>::separator(os);
+ os << histo_depth;
+ ostream_traits<OStream>::separator(os);
+ for (std::size_t k = 0; k < dimension; ++k) {
+ os << adapt[k];
+ ostream_traits<OStream>::separator(os);
+ }
+ os << freeze_grid;
+ ostream_traits<OStream>::separator(os);
+ os << maxtry;
+ ostream_traits<OStream>::separator(os);
+ os << efficiency_threshold;
+ ostream_traits<OStream>::separator(os);
+ os << gain_threshold;
+ ostream_traits<OStream>::separator(os);
+ }
+
+ template<class IStream>
+ void adaption_info::get(IStream& is) {
+ is >> dimension;
+ lower_left.resize(dimension);
+ upper_right.resize(dimension);
+ adapt.resize(dimension);
+ for (std::size_t k = 0; k < dimension; ++k) {
+ is >> lower_left[k];
+ }
+ for (std::size_t k = 0; k < dimension; ++k) {
+ is >> upper_right[k];
+ }
+ is >> presampling_points >> histo_depth;
+ for (std::size_t k = 0; k < dimension; ++k) {
+ // strange. is >> adapt[k]
+ // gives: warning: value computet is not used
+ // with gcc 4.2.1
+ bool v; is >> v;
+ adapt[k] = v;
+ }
+ is >> freeze_grid >> maxtry
+ >> efficiency_threshold >> gain_threshold;
+ }
+
+}
diff --git a/Exsample2/exsample/binary_tree.h b/Exsample2/exsample/binary_tree.h
new file mode 100644
--- /dev/null
+++ b/Exsample2/exsample/binary_tree.h
@@ -0,0 +1,887 @@
+// -*- C++ -*-
+//
+// binary_tree.h is part of ExSample -- A Library for Sampling Sudakov-Type Distributions
+//
+// Copyright (C) 2008-2011 Simon Platzer -- simon.plaetzer@desy.de
+//
+// ExSample is licenced under version 2 of the GPL, see COPYING for details.
+// Please respect the MCnet academic guidelines, see GUIDELINES for details.
+//
+//
+#ifndef EXSAMPLE_binary_tree_h_included
+#define EXSAMPLE_binary_tree_h_included
+
+#include "utility.h"
+
+namespace exsample {
+
+ /// \brief binary_tree represents a binary tree with the ability to
+ /// `cascade' visitor objects down the tree
+ template<class Value>
+ class binary_tree {
+
+ public:
+
+ ///@name type definitions
+ //@{
+
+ /// define the object type
+ typedef Value value_type;
+
+ //@}
+
+ public:
+
+ ///@name constructors
+ //@{
+
+ /// default constructor
+ binary_tree()
+ : neighbours_(0,0),
+ parent_(0), value_(),
+ children_()
+ { }
+
+ /// construct giving key/cell and parent
+ binary_tree(const value_type& thevalue,
+ binary_tree * theparent = 0)
+ : neighbours_(0,0), parent_(theparent),
+ value_(new value_type(thevalue)),
+ children_()
+ { }
+
+ /// binary_tree has a strict ownership; on copying
+ /// binary trees ownership is transferred
+ binary_tree(const binary_tree& x)
+ : neighbours_(x.neighbours_),
+ parent_(x.parent_), value_(),
+ children_() {
+ assert(x.root());
+ binary_tree& nc_x = const_cast<binary_tree&>(x);
+ value_.swap(nc_x.value_);
+ children_.first.swap(nc_x.children_.first);
+ children_.second.swap(nc_x.children_.second);
+ nc_x.parent_ = 0;
+ nc_x.neighbours_.first = 0;
+ nc_x.neighbours_.second = 0;
+ }
+
+ /// binary_tree has a strict ownership; on copying
+ /// binary trees ownership is transferred
+ binary_tree& operator=(const binary_tree& x) {
+ if (this == &x)
+ return *this;
+ assert(x.root());
+ binary_tree& nc_x = const_cast<binary_tree&>(x);
+ value_.swap(nc_x.value_);
+ children_.first.swap(nc_x.children_.first);
+ children_.second.swap(nc_x.children_.second);
+ neighbours_ = x.neighbours_;
+ parent_ = x.parent_;
+ nc_x.parent_ = 0;
+ nc_x.neighbours_.first = 0;
+ nc_x.neighbours_.second = 0;
+ return *this;
+ }
+
+ //@}
+
+ ///@name standard-conforming leaf iterators
+ //@{
+
+ public:
+
+ class const_iterator;
+
+ /// iterator
+ class iterator {
+
+ public:
+
+ ///@name type definitions for iterator traits
+ //@{
+
+ /// define the iterator category
+ typedef std::bidirectional_iterator_tag iterator_category;
+
+ /// define the difference_type
+ typedef int difference_type;
+
+ /// define the value type
+ typedef Value value_type;
+
+ /// define the reference type
+ typedef value_type& reference;
+
+ /// define the pointer type
+ typedef value_type * pointer;
+
+ //@}
+
+ public:
+
+ ///@name constructors
+ //@{
+
+ /// default constructor
+ iterator() : pointee(0), post_end(0), pre_begin(0) { }
+
+ /// constructor taking pointee
+ iterator(binary_tree * p, std::size_t end = 0)
+ : pointee(p), post_end(end), pre_begin(0) { }
+
+ //@
+
+ public:
+
+ ///@name comparisons
+ //@{
+
+ /// comparison
+ bool operator==(const iterator& x) const {
+ return ((pointee == x.pointee) &&
+ (post_end == x.post_end) &&
+ (pre_begin == x.pre_begin));
+ }
+
+ /// comparison
+ bool operator!=(const iterator& x) const { return !(*this == x); }
+
+ //@}
+
+ public:
+
+ ///@name derefrence and indirection
+ //@{
+
+ /// dereference
+ reference operator*() { return pointee->value(); }
+
+ /// indirection
+ pointer operator->() { return &**this; }
+
+ /// return reference to the node
+ binary_tree& node() { return *pointee; }
+
+ //@}
+
+ /// return raw pointer to the element pointed to
+ binary_tree * get() const { return pointee; }
+
+ ///@name biderectional iterator increment/decrements
+ //@{
+
+ /// pre-increment
+ iterator& operator++() {
+ if (post_end) { ++post_end; return *this; }
+ if (pre_begin) { --pre_begin; return *this; }
+ if(!(pointee->right_neighbour())) { post_end = 1; return *this; }
+ pointee = pointee->right_neighbour();
+ return *this;
+ }
+
+ /// pre-decrement
+ iterator& operator--() {
+ if (post_end) { --post_end; return *this; }
+ if (pre_begin) { ++pre_begin; return *this; }
+ if(!(pointee->left_neighbour())) { pre_begin = 1; return *this; }
+ pointee = pointee->left_neighbour();
+ return *this;
+ }
+
+ /// post-increment
+ template<typename Dummy>
+ iterator operator++(Dummy) {
+ iterator tmp = *this;
+ ++(*this);
+ return tmp;
+ }
+
+ /// post-decrement
+ template<typename Dummy>
+ iterator operator--(Dummy) {
+ iterator tmp = *this;
+ --(*this);
+ return tmp;
+ }
+
+ //@}
+
+ private:
+
+ /// friend for conversion
+ friend class const_iterator;
+
+ /// the node pointed to
+ binary_tree * pointee;
+
+ /// the distance from --end() (if above --end())
+ std::size_t post_end;
+
+ /// the distance from begin() (if below begin())
+ std::size_t pre_begin;
+
+ };
+
+ /// return begin iterator
+ iterator begin() { return iterator(left_most()); }
+
+ /// return end iterator
+ iterator end() { return iterator(right_most(),1); }
+
+ /// return global begin iterator
+ iterator global_begin() {
+ if (!root())
+ return parent().global_begin();
+ return iterator(left_most());
+ }
+
+ /// return global end iterator
+ iterator global_end() {
+ if (!root())
+ return parent().global_end();
+ return iterator(right_most(),1);
+ }
+
+ /// const_iterator
+ class const_iterator {
+
+ public:
+
+ ///@name type definitions for iterator traits
+ //@{
+
+ /// define the iterator category
+ typedef std::bidirectional_iterator_tag iterator_category;
+
+ /// define the difference type
+ typedef int difference_type;
+
+ /// define the value type
+ typedef const Value value_type;
+
+ /// define the reference type
+ typedef const value_type& reference;
+
+ /// define the pointer type
+ typedef const value_type * pointer;
+
+ //@}
+
+ public:
+
+ ///@name constructors
+ //@{
+
+ /// default constructor
+ const_iterator() : pointee(0), post_end(0), pre_begin(0) { }
+
+ /// constructor taking pointee
+ const_iterator(binary_tree * p, std::size_t end = 0)
+ : pointee(p), post_end(end), pre_begin(0) { }
+
+ /// conversion from iterator
+ const_iterator(const iterator& x)
+ : pointee(x.pointee), post_end(x.post_end), pre_begin(x.pre_begin) { }
+
+ //@}
+
+ public:
+
+ ///@name comparisons
+ //@{
+
+ /// comparison
+ bool operator==(const const_iterator& x) const {
+ return ((pointee == x.pointee) &&
+ (post_end == x.post_end) &&
+ (pre_begin == x.pre_begin));
+ }
+
+ /// comparison
+ bool operator!=(const const_iterator& x) const { return !(*this == x); }
+
+ //@}
+
+ public:
+
+ ///@name dereference and indirection
+ //@{
+
+ /// dereference
+ reference operator*() const { return pointee->value(); }
+
+ /// indirection
+ pointer operator->() const { return &**this; }
+
+ /// return reference to the node
+ const binary_tree& node() const { return *pointee; }
+
+ //@}
+
+ ///@name biderectional iterator increment/decrements
+ //@{
+
+ /// pre-increment
+ const_iterator& operator++() {
+ if (post_end) { ++post_end; return *this; }
+ if (pre_begin) { --pre_begin; return *this; }
+ if(!(pointee->right_neighbour())) { post_end = 1; return *this; }
+ pointee = pointee->right_neighbour();
+ return *this;
+ }
+
+ /// pre-decrement
+ const_iterator& operator--() {
+ if (post_end) { --post_end; return *this; }
+ if (pre_begin) { ++pre_begin; return *this; }
+ if(!(pointee->left_neighbour())) { pre_begin = 1; return *this; }
+ pointee = pointee->left_neighbour();
+ return *this;
+ }
+
+ /// post-increment
+ template<typename Dummy>
+ const_iterator operator++(Dummy) {
+ const_iterator tmp = *this;
+ ++(*this);
+ return tmp;
+ }
+
+ /// post-decrement
+ template<typename Dummy>
+ const_iterator operator--(Dummy) {
+ const_iterator tmp = *this;
+ --(*this);
+ return tmp;
+ }
+
+ //@}
+
+ private:
+
+ /// the node pointed to
+ binary_tree * pointee;
+
+ /// the distance from --end() (if above --end())
+ std::size_t post_end;
+
+ /// the distance from begin() (if below begin())
+ std::size_t pre_begin;
+
+ };
+
+ /// return begin const_iterator
+ const_iterator begin() const { return const_iterator(left_most()); }
+
+ /// return end const_iterator
+ const_iterator end() const { return const_iterator(right_most(),1); }
+
+ /// return global begin iterator
+ const_iterator global_begin() const {
+ if (!root())
+ return parent().global_begin();
+ return iterator(left_most());
+ }
+
+ /// return global end iterator
+ const_iterator global_end() const {
+ if (!root())
+ return parent().global_end();
+ return iterator(right_most(),1);
+ }
+
+ private:
+
+ /// set the left neighbour
+ void left_neighbour(binary_tree * n) { neighbours_.first = n; }
+
+ /// set the right neighbour
+ void right_neighbour(binary_tree * n) { neighbours_.second = n; }
+
+ /// get the left neighbour
+ binary_tree * left_neighbour() const { return neighbours_.first; }
+
+ /// get the right neighbour
+ binary_tree * right_neighbour() const { return neighbours_.second; }
+
+ /// return the left-most leaf
+ binary_tree * left_most() {
+ if(leaf()) return this;
+ return left_child().left_most();
+ }
+
+ /// return the right-most leaf
+ binary_tree * right_most() {
+ if(leaf()) return this;
+ return right_child().right_most();
+ }
+
+ /// return the left-most leaf
+ const binary_tree * left_most() const {
+ if(leaf()) return this;
+ return left_child().left_most();
+ }
+
+ /// return the right-most leaf
+ const binary_tree * right_most() const {
+ if(leaf()) return this;
+ return right_child().right_most();
+ }
+
+ /// the iterator is a good friend
+ friend class binary_tree<value_type>::iterator;
+
+ /// the iterator is a good friend
+ friend class binary_tree<value_type>::const_iterator;
+
+ /// the left and right neighbours of this node
+ std::pair<binary_tree*,binary_tree*> neighbours_;
+
+ //@}
+
+ public:
+
+ /// return true, if this node is empty
+ bool empty() const { return root() && leaf() && !value_; }
+
+ /// clear this node
+ void clear() {
+ neighbours_ = std::make_pair<binary_tree*,binary_tree*>(0,0);
+ parent_ = 0;
+ value_.reset(0);
+ if (!leaf()) {
+ left_child().clear();
+ right_child().clear();
+ }
+ children_.first.reset(0);
+ children_.second.reset(0);
+ }
+
+ public:
+
+ /// split this node
+ std::pair<iterator,iterator> split(std::pair<value_type,value_type> children) {
+
+ assert(leaf());
+
+ children_.first.reset(new binary_tree(children.first,this));
+ children_.second.reset(new binary_tree(children.second,this));
+
+ children_.first->left_neighbour(neighbours_.first);
+ children_.first->right_neighbour(children_.second.get());
+ children_.second->left_neighbour(children_.first.get());
+ children_.second->right_neighbour(neighbours_.second);
+
+ // adjust original neighbours
+
+ if(neighbours_.first) {
+ neighbours_.first->right_neighbour(children_.first.get());
+ }
+
+ if (neighbours_.second) {
+ neighbours_.second->left_neighbour(children_.second.get());
+ }
+
+ neighbours_.first = 0; neighbours_.second = 0;
+
+ return std::make_pair(iterator(children_.first.get()),iterator(children_.second.get()));
+
+ }
+
+ public:
+
+ /// select using a selector
+ template<class Selector>
+ iterator select(const Selector& selector) {
+
+ if(leaf()) {
+ bool use = selector.use(value());
+ if (use) return iterator(this);
+ return global_end();
+ }
+
+ std::pair<bool,bool> which(selector.use(value(),left_child().value(),right_child().value()));
+
+ assert(!which.first || !which.second);
+
+ if (!which.first && !which.second) {
+ return global_end();
+ }
+
+ if (which.first) {
+ return left_child().select(selector);
+ }
+ else {
+ return right_child().select(selector);
+ }
+
+ return global_end();
+
+ }
+
+ /// generate a hash value for the sub-tree
+ /// selected by the given selector object
+ template<class Selector, unsigned long bits>
+ void subtree_hash(const Selector& selector, bit_container<bits>& bhash) {
+ bhash = bit_container<bits>();
+ unsigned long pos = 0;
+ do_subtree_hash<Selector,bits>(selector,bhash,pos);
+ }
+
+ /// accumulate values using a binary function
+ /// and accessor object
+ template<class Accessor, class BinaryOp>
+ typename BinaryOp::result_type accumulate(const Accessor& acc,
+ BinaryOp binary_op) const {
+
+ if (!leaf()) {
+ return
+ binary_op(left_child().accumulate(acc,binary_op),
+ right_child().accumulate(acc,binary_op));
+ }
+
+ return acc.get(value(),true);
+
+ }
+
+ /// accumulate values only from branches
+ /// matching a Selector
+ template<class Selector, class Accessor, class BinaryOp>
+ typename BinaryOp::result_type accumulate(const Selector& selector,
+ const Accessor& acc,
+ BinaryOp binary_op) const {
+
+ if (!leaf()) {
+ std::pair<bool,bool> which(selector.use(value(),left_child().value(),right_child().value()));
+ assert(which.first || which.second);
+ if (which.first && which.second) {
+ return
+ binary_op(left_child().accumulate(selector,acc,binary_op),
+ right_child().accumulate(selector,acc,binary_op));
+ } else if (which.first) {
+ return left_child().accumulate(selector,acc,binary_op);
+ } else if (which.second) {
+ return right_child().accumulate(selector,acc,binary_op);
+ }
+ }
+
+ return acc.get(value(),true);
+
+ }
+
+ /// accumulate values using a binary function
+ /// and accessor object, storing intermediate
+ /// values in nodes
+ template<class Accessor, class BinaryOp>
+ typename BinaryOp::result_type tree_accumulate(const Accessor& acc,
+ BinaryOp binary_op) {
+
+ if (!leaf()) {
+ acc.set(value()) =
+ binary_op(left_child().tree_accumulate(acc,binary_op),
+ right_child().tree_accumulate(acc,binary_op));
+ return acc.get(value(),false);
+ }
+
+ acc.set(value()) = acc.get(value(),true);
+ return acc.get(value(),true);
+
+ }
+
+ /// accumulate values only from branches
+ /// matching a Selector
+ template<class Selector, class Accessor, class BinaryOp>
+ typename BinaryOp::result_type tree_accumulate(const Selector& selector,
+ const Accessor& acc,
+ BinaryOp binary_op) {
+
+ if (!leaf()) {
+ std::pair<bool,bool> which(selector.use(value(),left_child().value(),right_child().value()));
+ assert(which.first || which.second);
+ if (which.first && which.second) {
+ acc.set(value()) =
+ binary_op(left_child().tree_accumulate(selector,acc,binary_op),
+ right_child().tree_accumulate(selector,acc,binary_op));
+ } else if (which.first) {
+ acc.set(value()) = left_child().tree_accumulate(selector,acc,binary_op);
+ } else if (which.second) {
+ acc.set(value()) = right_child().tree_accumulate(selector,acc,binary_op);
+ }
+ return acc.get(value(),false);
+ }
+
+ acc.set(value()) = acc.get(value(),true);
+ return acc.get(value(),true);
+
+ }
+
+ /// forward propagate a visitor to all children nodes
+ template<class Visitor>
+ void cascade(Visitor visitor) const {
+ if (leaf()) {
+ visitor.visit(value());
+ return;
+ } else visitor.visit(value(),left_child().value(),right_child().value());
+ left_child().cascade(visitor);
+ right_child().cascade(visitor);
+ }
+
+ /// succesively split using a generator
+ template<class Generator>
+ void generate(Generator generator) {
+ if (root())
+ value_.reset(new value_type(generator.root()));
+ if (generator.split()) {
+ std::pair<iterator,iterator> ch = split(generator.generate(value()));
+ ch.first.node().generate(generator);
+ ch.second.node().generate(generator);
+ }
+ }
+
+ public:
+
+ ///@name Public member access
+ //@{
+
+ /// return the value held by this node
+ value_type& value() { return *value_; }
+
+ /// return the value held by this node
+ const value_type& value() const { return *value_; }
+
+ /// return true, if this is the root node
+ bool root() const { return !parent_; }
+
+ /// return true, if this node has got children
+ bool leaf() const { return !(children_.first.get() && children_.second.get()); }
+
+ //@}
+
+ public:
+
+ ///@name put and get from streams
+ //@{
+
+ /// forward visitor writing out the tree to given ostream
+ template<class OStream>
+ struct ostream_visitor {
+
+ /// construct from ostream reference
+ explicit ostream_visitor(OStream& os) : os_(&os), first_time_(true) {}
+
+ /// visit a leaf node
+ void visit(const value_type&) {
+ (*os_) << "end_branch";
+ ostream_traits<OStream>::separator(*os_);
+ }
+
+ /// visit a branching
+ void visit(const value_type& parent,
+ const value_type& left, const value_type& right) {
+ if (first_time_) {
+ (*os_) << "root_node";
+ ostream_traits<OStream>::separator(*os_);
+ parent.put(*os_);
+ first_time_ = false;
+ }
+
+ (*os_) << "left_child";
+ ostream_traits<OStream>::separator(*os_);
+ left.put(*os_);
+
+ (*os_) << "right_child";
+ ostream_traits<OStream>::separator(*os_);
+ right.put(*os_);
+
+ }
+
+ private:
+
+ /// pointer to the ostream to write to
+ OStream* os_;
+
+ /// whether we are at the or not
+ bool first_time_;
+
+ };
+
+ /// generator reading binary tree from istream
+ template<class IStream>
+ struct istream_generator {
+
+ /// construct from istream reference
+ explicit istream_generator(IStream& is)
+ : is_(&is), children_(), tag_("") {}
+
+ /// copy constructor
+ istream_generator(const istream_generator& x)
+ : is_(x.is_), children_(), tag_("") {}
+
+ /// read the root node
+ value_type root() {
+
+ *is_ >> tag_;
+ assert(tag_ == "root_node");
+ value_type rnode;
+ rnode.get(*is_);
+
+ return rnode;
+ }
+
+ /// read children nodes
+ bool split() {
+
+ *is_ >> tag_;
+
+ if (tag_ == "end_branch") {
+ return false;
+ }
+
+ assert (tag_ == "left_child");
+ children_.first.get(*is_);
+
+ *is_ >> tag_;
+ assert(tag_ == "right_child");
+ children_.second.get(*is_);
+
+ return true;
+
+ }
+
+ /// return the children generated
+ std::pair<value_type,value_type> generate(const value_type&) {
+ return children_;
+ }
+
+ /// initialize a leaf
+ void initialize_leaf(const value_type&) {}
+
+ private:
+
+ /// pointer to the istream used
+ IStream* is_;
+
+ /// the children currently handled
+ std::pair<value_type,value_type> children_;
+
+ /// temporary storage for tags
+ std::string tag_;
+
+ };
+
+ /// put to ostream
+ template<class OStream>
+ void put(OStream& os) const {
+
+ if (empty()) {
+ os << "empty";
+ ostream_traits<OStream>::separator(os);
+ return;
+ } else if (root() && leaf()) {
+ os << "root_only";
+ ostream_traits<OStream>::separator(os);
+ value().put(os);
+ return;
+ } else {
+ os << "non_empty";
+ ostream_traits<OStream>::separator(os);
+ }
+
+ assert(root());
+ cascade(ostream_visitor<OStream>(os));
+
+ }
+
+ /// get from istream
+ template<class IStream>
+ void get(IStream& is) {
+
+ std::string state;
+ is >> state;
+
+ if (state == "empty") {
+ return;
+ }
+ if (state == "root_only") {
+ value_.reset(new value_type());
+ value().get(is);
+ return;
+ }
+
+ assert(empty());
+ generate(istream_generator<IStream>(is));
+
+ }
+
+ //@}
+
+
+ private:
+
+ /// calculate hash value
+ template<class Selector, unsigned long bits>
+ void do_subtree_hash(const Selector& selector,
+ bit_container<bits>& current,
+ unsigned long& position,
+ bool selected = true) const {
+
+ if (!leaf()) {
+
+ std::pair<bool,bool> which(false,false);
+ if (selected)
+ which = selector.use(value(),left_child().value(),right_child().value());
+
+ current.bit(position,which.first);
+ current.bit(position+1,which.second);
+
+ position += 2;
+
+ left_child().do_subtree_hash(selector,current,position,which.first && selected);
+ right_child().do_subtree_hash(selector,current,position,which.second && selected);
+ }
+
+ }
+
+ private:
+
+ ///@name private member access
+ //@{
+
+ /// return the parent of this node
+ binary_tree& parent() { assert(parent_); return *parent_; }
+
+ /// return the parent of this node
+ const binary_tree& parent() const { assert(parent_); return *parent_; }
+
+ /// return the left child of this node
+ binary_tree& left_child() { assert(children_.first.get()); return *children_.first; }
+
+ /// return the left child of this node
+ const binary_tree& left_child() const { assert(children_.first.get()); return *children_.first; }
+
+ /// return the right child of this node
+ binary_tree& right_child() { assert(children_.second.get()); return *children_.second; }
+
+ /// return the right child of this node
+ const binary_tree& right_child() const { assert(children_.second.get()); return *children_.second; }
+
+ //@}
+
+ private:
+
+ /// the parent of this node
+ binary_tree * parent_;
+
+ /// the cell held by this node
+ boost::scoped_ptr<value_type> value_;
+
+ /// the children of this node
+ std::pair<boost::scoped_ptr<binary_tree>,
+ boost::scoped_ptr<binary_tree> > children_;
+
+ };
+
+}
+
+#endif // EXSAMPLE_binary_tree_h_included
diff --git a/Exsample2/exsample/cell.h b/Exsample2/exsample/cell.h
new file mode 100644
--- /dev/null
+++ b/Exsample2/exsample/cell.h
@@ -0,0 +1,304 @@
+// -*- C++ -*-
+//
+// cell.h is part of ExSample -- A Library for Sampling Sudakov-Type Distributions
+//
+// Copyright (C) 2008-2011 Simon Platzer -- simon.plaetzer@desy.de
+//
+// ExSample is licenced under version 2 of the GPL, see COPYING for details.
+// Please respect the MCnet academic guidelines, see GUIDELINES for details.
+//
+//
+#ifndef EXSAMPLE_cell_h_included
+#define EXSAMPLE_cell_h_included
+
+#include "utility.h"
+#include "adaption_info.h"
+#include "statistics.h"
+
+namespace exsample {
+
+ /// \brief Information contained in a leaf cell
+ class cell_info {
+
+ public:
+
+ /// the default constructor
+ cell_info();
+
+ /// construct from boundaries and adaption info
+ cell_info(const std::vector<double>& ll,
+ const std::vector<double>& ur,
+ const adaption_info& ainfo);
+
+ /// construct from boundaries, flags for variables to be sampled,
+ /// and adaption info
+ cell_info(const std::vector<double>& ll,
+ const std::vector<double>& ur,
+ const std::vector<bool>& sampled_variables,
+ const adaption_info& ainfo);
+
+ public:
+
+ /// generate a flat trial point in this cell
+ template<class Random>
+ void select(Random&,
+ std::vector<double>&);
+
+ /// generate a flat trial point in this cell
+ /// only for the variables falgged as true
+ template<class Random>
+ void select(Random&,
+ std::vector<double>&,
+ const std::vector<bool>&);
+
+ /// indicate a function value for the given point
+ void selected(const std::vector<double>&,
+ double,
+ const adaption_info&);
+
+ /// indicate that a point has been
+ /// accepted in this cell
+ void accept() { ++accepted_; }
+
+ /// reject a previously accepted event
+ void reject() { --accepted_; }
+
+ public:
+
+ /// return true, if below efficiency threshold
+ bool bad(const adaption_info& ainfo) const {
+ return ((static_cast<double>(accepted_)/static_cast<double>(attempted_)) <
+ ainfo.efficiency_threshold);
+ }
+
+ /// suggest a split and indicate wether it is worth
+ /// to be performed
+ std::pair<std::size_t,double> get_split(const adaption_info&,
+ bool&) const;
+
+ /// explore this cell performing a flat sampling,
+ /// updating the given statistics object and pre-filling
+ /// the efficiency histogram by a trial unweighting
+ template<class Random, class Function, class SlaveStatistics>
+ void explore(Random&, const adaption_info&, Function*, statistics*,
+ SlaveStatistics& opt);
+
+ /// explore this cell in a more refined way, which
+ /// is however not suited for already calculating integrals
+ /// and stuff
+ template<class Random, class Function>
+ void explore(Random&, const adaption_info&, Function*);
+
+ public:
+
+ /// get the current overestimate
+ double overestimate() const { return overestimate_; }
+
+ /// return the position of the last maximum
+ const std::vector<double>& last_max_position() const { return last_max_position_; }
+
+ /// set the current overestimate and maximum position
+ void overestimate(double v, const std::vector<double>& pos) {
+ overestimate_ = v;
+ last_max_position_ = pos;
+ }
+
+ /// get the volume
+ double volume() const { return volume_; }
+
+ /// get the lower left corner
+ const std::vector<double>& lower_left() const { return lower_left_; }
+
+ /// get the upper right corner
+ const std::vector<double>& upper_right() const { return upper_right_; }
+
+ /// get the number of attempted events
+ unsigned long attempted() const { return attempted_; }
+
+ /// get the number of accepted events
+ unsigned long accepted() const { return accepted_; }
+
+ public:
+
+ /// return the number of missing events
+ /// for the given parameter bin id
+ int parametric_missing(const bit_container<parameter_hash_bits>& id) const;
+
+ /// set the number of missing events
+ /// for the given parameter bin id
+ void parametric_missing(const bit_container<parameter_hash_bits>& id, int n);
+
+ /// increase to the number of missing events
+ /// for the given parameter bin id
+ void increase_parametric_missing(const bit_container<parameter_hash_bits>& id);
+
+ /// decrease to the number of missing events
+ /// for the given parameter bin id
+ void decrease_parametric_missing(const bit_container<parameter_hash_bits>& id);
+
+ /// return true, if the cell is compensating in
+ /// at least one parameter bin
+ bool parametric_compensating() const {
+ return !parametric_missing_map_.empty();
+ }
+
+ /// return true, if the cell contains the
+ /// indicated parameter point
+ bool contains_parameter(const std::vector<double>& point,
+ const std::vector<bool>& sampled) const;
+
+ public:
+
+ /// put to ostream
+ template<class OStream>
+ void put(OStream& os) const;
+
+ /// get from istream
+ template<class IStream>
+ void get(IStream& is);
+
+ private:
+
+ /// the value of the overestimate in this cell
+ double overestimate_;
+
+ /// the volume of this cell
+ double volume_;
+
+ /// the lower left corner of this cell
+ std::vector<double> lower_left_;
+
+ /// the upper right corner of this cell
+ std::vector<double> upper_right_;
+
+ /// midpoint of this cell
+ std::vector<double> mid_point_;
+
+ /// the position of the last encountered
+ /// maximum in this cell
+ std::vector<double> last_max_position_;
+
+ /// left-right statistics of average weight
+ std::vector<std::pair<double,double> > avg_weight_;
+
+ /// the number of attempts in this cell
+ unsigned long attempted_;
+
+ /// the number of accepted events in this cell
+ unsigned long accepted_;
+
+ /// an optional map of parameter bin ids
+ /// to the number of missing events
+ std::map<bit_container<parameter_hash_bits>,int> parametric_missing_map_;
+
+ };
+
+ /// \brief the general cell class
+ class cell {
+
+ public:
+
+ /// default constructor
+ cell();
+
+ /// construct from boundaries and adaption info
+ cell(const std::vector<double>& ll,
+ const std::vector<double>& ur,
+ const adaption_info& ainfo);
+
+ /// construct from boundaries, flags for variables to be sampled,
+ /// and adaption info
+ cell(const std::vector<double>& ll,
+ const std::vector<double>& ur,
+ const std::vector<bool>& sampled_variables,
+ const adaption_info& ainfo);
+
+ /// copy constructor
+ cell(const cell& x);
+
+ /// assignment
+ cell& operator=(const cell& x);
+
+ public:
+
+ /// split this cell, exploring the
+ /// child not containing the current overestimate
+ template<class Random, class Function>
+ std::pair<cell,cell> split(std::pair<std::size_t,double> split_d,
+ Random& rnd_gen,
+ Function* f,
+ const adaption_info& ainfo,
+ const std::vector<bool>& sampled =
+ std::vector<bool>());
+
+ public:
+
+ /// return the split dimension
+ std::size_t split_dimension() const { return split_dimension_; }
+
+ /// return the split value
+ double split_point() const { return split_point_; }
+
+ /// return the integral
+ double integral() const { return integral_; }
+
+ /// access the integral
+ double& integral() { return integral_; }
+
+ /// set the integral
+ void integral(double v) { integral_ = v; }
+
+ /// access the number of missing events
+ int& missing_events() { return missing_events_; }
+
+ /// return the number of missing events
+ int missing_events() const { return missing_events_; }
+
+ /// set the number of missing events
+ void missing_events(int n) { missing_events_ = n; }
+
+ /// access the cell_info object
+ cell_info& info() { assert(cell_info_); return *cell_info_; }
+
+ /// return the cell_info object
+ const cell_info& info() const { assert(cell_info_); return *cell_info_; }
+
+ public:
+
+ /// put to ostream
+ template<class OStream>
+ void put(OStream& os) const;
+
+ /// get from istream
+ template<class IStream>
+ void get(IStream& is);
+
+ private:
+
+ /// the dimension along this cell
+ /// was split
+ std::size_t split_dimension_;
+
+ /// the value, where this cell was split
+ double split_point_;
+
+ /// the integral of the absolute value
+ /// of the overestimate over all the
+ /// children cells
+ double integral_;
+
+ /// the number of missing events in this cell
+ int missing_events_;
+
+ /// a pointer to the cell info object,
+ /// if this is a leaf cell
+ boost::scoped_ptr<cell_info> cell_info_;
+
+
+ };
+
+}
+
+#include "cell.icc"
+
+#endif // EXSAMPLE_cell_h_included
diff --git a/Exsample2/exsample/cell.icc b/Exsample2/exsample/cell.icc
new file mode 100644
--- /dev/null
+++ b/Exsample2/exsample/cell.icc
@@ -0,0 +1,409 @@
+// -*- C++ -*-
+//
+// cell.icc is part of ExSample -- A Library for Sampling Sudakov-Type Distributions
+//
+// Copyright (C) 2008-2011 Simon Platzer -- simon.plaetzer@desy.de
+//
+// ExSample is licenced under version 2 of the GPL, see COPYING for details.
+// Please respect the MCnet academic guidelines, see GUIDELINES for details.
+//
+//
+namespace exsample {
+
+
+ template<class Random>
+ void cell_info::select (Random& rnd_gen,
+ std::vector<double>& p) {
+ std::transform(lower_left_.begin(),lower_left_.end(),
+ upper_right_.begin(),p.begin(),
+ rnd_gen);
+ ++attempted_;
+ }
+
+
+ template<class Random>
+ void cell_info::select (Random& rnd_gen,
+ std::vector<double>& p,
+ const std::vector<bool>& sample) {
+ conditional_transform(lower_left_.begin(),lower_left_.end(),
+ upper_right_.begin(),sample.begin(),
+ p.begin(),rnd_gen);
+ ++attempted_;
+ }
+
+
+
+ template<class Random, class Function, class SlaveStatistics>
+ void cell_info::explore(Random& rnd_gen,
+ const adaption_info& ainfo,
+ Function* function, statistics* stats,
+ SlaveStatistics& opt) {
+ function->start_presampling();
+ unsigned long n_sampled = 0;
+ std::vector<double> ll = lower_left_;
+ std::vector<double> ur = upper_right_;
+ double val = 0.;
+ std::vector<double> pos (ll.size());
+ while (n_sampled < ainfo.presampling_points) {
+ std::transform(ll.begin(),ll.end(),
+ ur.begin(),pos.begin(),
+ rnd_gen);
+ val = function->evaluate(pos);
+ stats->presampled(val);
+ opt.select(val);
+ if (std::abs(val) > std::abs(overestimate_)) {
+ overestimate_ = std::abs(val);
+ last_max_position_ = pos;
+ }
+ selected(pos,std::abs(val),ainfo);
+ ++n_sampled;
+ }
+ function->stop_presampling();
+ }
+
+
+ template<class Random, class Function>
+ void cell_info::explore (Random& rnd_gen,
+ const adaption_info& ainfo, Function* function) {
+ function->start_presampling();
+ unsigned long n_sampled = 0;
+ std::vector<double> ll = lower_left_;
+ std::vector<double> ur = upper_right_;
+ double val = 0.;
+ std::vector<double> pos (ll.size());
+ std::vector<double> next_to_largest (ll.size());
+ while (n_sampled < ainfo.presampling_points) {
+ std::transform(ll.begin(),ll.end(),
+ ur.begin(),pos.begin(),
+ rnd_gen);
+ val = function->evaluate(pos);
+ if (std::abs(val) > std::abs(overestimate_)) {
+ next_to_largest = last_max_position_;
+ overestimate_ = std::abs(val);
+ last_max_position_ = pos;
+ }
+ ++n_sampled;
+ }
+ function->stop_presampling();
+ }
+
+
+ template<class OStream>
+ void cell_info::put (OStream& os) const {
+ os << overestimate_;
+ ostream_traits<OStream>::separator(os);
+ os << volume_;
+ ostream_traits<OStream>::separator(os);
+ os << lower_left_.size();
+ ostream_traits<OStream>::separator(os);
+ for (std::size_t k = 0; k < lower_left_.size(); ++k) {
+ os << lower_left_[k];
+ ostream_traits<OStream>::separator(os);
+ }
+ for (std::size_t k = 0; k < upper_right_.size(); ++k) {
+ os << upper_right_[k];
+ ostream_traits<OStream>::separator(os);
+ }
+ for (std::size_t k = 0; k < mid_point_.size(); ++k) {
+ os << mid_point_[k];
+ ostream_traits<OStream>::separator(os);
+ }
+ for (std::size_t k = 0; k < last_max_position_.size(); ++k) {
+ os << last_max_position_[k];
+ ostream_traits<OStream>::separator(os);
+ }
+ for (std::size_t k = 0; k < avg_weight_.size(); ++k) {
+ os << avg_weight_[k].first;
+ ostream_traits<OStream>::separator(os);
+ os << avg_weight_[k].second;
+ ostream_traits<OStream>::separator(os);
+ }
+ }
+
+
+ template<class IStream>
+ void cell_info::get (IStream& is) {
+ std::size_t dim;
+ is >> overestimate_ >> volume_ >> dim;
+ lower_left_.resize(dim);
+ for (std::size_t k = 0; k < lower_left_.size(); ++k) {
+ is >> lower_left_[k];
+ }
+ upper_right_.resize(dim);
+ for (std::size_t k = 0; k < upper_right_.size(); ++k) {
+ is >> upper_right_[k];
+ }
+ mid_point_.resize(dim);
+ for (std::size_t k = 0; k < mid_point_.size(); ++k) {
+ is >> mid_point_[k];
+ }
+ last_max_position_.resize(dim);
+ for (std::size_t k = 0; k < last_max_position_.size(); ++k) {
+ is >> last_max_position_[k];
+ }
+ avg_weight_.resize(dim);
+ for (std::size_t k = 0; k < avg_weight_.size(); ++k) {
+ is >> avg_weight_[k].first >> avg_weight_[k].second;
+ }
+ }
+
+ template<class Random, class Function>
+ std::pair<cell,cell >
+ cell::split (std::pair<std::size_t,double> split_d,
+ Random& rnd_gen,
+ Function* function,
+ const adaption_info& ainfo,
+ const std::vector<bool>& sampled) {
+ assert(!missing_events() && !info().parametric_compensating());
+ split_dimension_ = split_d.first;
+ split_point_ = split_d.second;
+ std::vector<double> lower_left1 = info().lower_left();
+ std::vector<double> upper_right1 = info().upper_right();
+ std::vector<double> lower_left2 = info().lower_left();
+ std::vector<double> upper_right2 = info().upper_right();
+ upper_right1[split_dimension_] = split_point_;
+ lower_left2[split_dimension_] = split_point_;
+ std::pair<cell,cell> children;
+ if (sampled.empty())
+ children = std::pair<cell,cell>(cell(lower_left1,upper_right1,ainfo),
+ cell(lower_left2,upper_right2,ainfo));
+ else
+ children = std::pair<cell,cell> (cell(lower_left1,upper_right1,sampled,ainfo),
+ cell(lower_left2,upper_right2,sampled,ainfo));
+ if (info().last_max_position()[split_dimension_] <= split_point_) {
+ children.first.info().overestimate(info().overestimate(),info().last_max_position());
+ children.second.info().explore(rnd_gen,ainfo,function);
+ } else {
+ children.second.info().overestimate(info().overestimate(),info().last_max_position());
+ children.first.info().explore(rnd_gen,ainfo,function);
+ }
+ cell_info_.reset(0);
+ children.first.integral(children.first.info().volume() * children.first.info().overestimate());
+ children.second.integral(children.second.info().volume() * children.second.info().overestimate());
+ return children;
+ }
+
+
+ template<class OStream>
+ void cell::put (OStream& os) const {
+ os << split_dimension_;
+ ostream_traits<OStream>::separator(os);
+ os << split_point_;
+ ostream_traits<OStream>::separator(os);
+ os << integral_;
+ ostream_traits<OStream>::separator(os);
+ if (cell_info_) {
+ os << "has_cell_info";
+ ostream_traits<OStream>::separator(os);
+ cell_info_->put(os);
+ } else {
+ os << "has_no_cell_info";
+ ostream_traits<OStream>::separator(os);
+ }
+ }
+
+
+ template<class IStream>
+ void cell::get (IStream& is) {
+ std::string info_tag;
+ is >> split_dimension_ >> split_point_
+ >> integral_ >> info_tag;
+ if (info_tag == "has_cell_info") {
+ cell_info_.reset(new cell_info());
+ cell_info_->get(is);
+ }
+ }
+
+ inline cell_info::cell_info()
+ : overestimate_(0.), volume_(0.),
+ lower_left_(), upper_right_(), mid_point_(),
+ last_max_position_(), avg_weight_(),
+ attempted_(0), accepted_(0) {}
+
+ inline cell_info::cell_info(const std::vector<double>& ll,
+ const std::vector<double>& ur,
+ const adaption_info& ainfo)
+ : overestimate_(0.), volume_(),
+ lower_left_(ll), upper_right_(ur), mid_point_(),
+ last_max_position_(),
+ avg_weight_(std::vector<std::pair<double,double> >
+ (ainfo.dimension,std::make_pair(0.,0.))),
+ attempted_(0), accepted_(0) {
+
+ std::vector<double> delta;
+ std::transform(ur.begin(),ur.end(),
+ ll.begin(),std::back_inserter(delta),
+ std::minus<double>());
+
+ volume_ =
+ std::accumulate(delta.begin(),delta.end(),1.,std::multiplies<double>());
+
+ std::transform(ur.begin(),ur.end(),
+ ll.begin(),std::back_inserter(mid_point_),
+ std::plus<double>());
+
+ for (std::size_t k = 0; k < ainfo.dimension; ++k)
+ mid_point_[k] /= 2.;
+
+ }
+
+ inline cell_info::cell_info(const std::vector<double>& ll,
+ const std::vector<double>& ur,
+ const std::vector<bool>& sampled_variables,
+ const adaption_info& ainfo)
+ : overestimate_(0.), volume_(),
+ lower_left_(ll), upper_right_(ur), mid_point_(),
+ last_max_position_(),
+ avg_weight_(std::vector<std::pair<double,double> >
+ (ainfo.dimension,std::make_pair(0.,0.))),
+ attempted_(0), accepted_(0) {
+
+ std::vector<double> delta;
+ conditional_transform(ur.begin(),ur.end(),
+ ll.begin(),sampled_variables.begin(),
+ std::back_inserter(delta),
+ std::minus<double>());
+
+ volume_ =
+ std::accumulate(delta.begin(),delta.end(),1.,std::multiplies<double>());
+
+ std::transform(ur.begin(),ur.end(),
+ ll.begin(),std::back_inserter(mid_point_),
+ std::plus<double>());
+
+ for (std::size_t k = 0; k < ainfo.dimension; ++k)
+ mid_point_[k] /= 2.;
+
+ }
+
+
+ inline int cell_info::parametric_missing(const bit_container<parameter_hash_bits>& id) const {
+ std::map<bit_container<parameter_hash_bits>,int>::const_iterator mit
+ = parametric_missing_map_.find(id);
+ if (mit == parametric_missing_map_.end())
+ return 0;
+ return mit->second;
+ }
+
+ inline void cell_info::parametric_missing(const bit_container<parameter_hash_bits>& id, int n) {
+ if (n == 0) {
+ std::map<bit_container<parameter_hash_bits>,int>::iterator mit
+ = parametric_missing_map_.find(id);
+ if (mit != parametric_missing_map_.end())
+ parametric_missing_map_.erase(mit);
+ return;
+ }
+ parametric_missing_map_[id] = n;
+ }
+
+ inline void cell_info::increase_parametric_missing(const bit_container<parameter_hash_bits>& id) {
+ std::map<bit_container<parameter_hash_bits>,int>::iterator mit
+ = parametric_missing_map_.find(id);
+ if (mit != parametric_missing_map_.end()) {
+ mit->second += 1;
+ if (mit->second == 0) parametric_missing_map_.erase(mit);
+ } else parametric_missing_map_[id] = 1;
+ }
+
+ inline void cell_info::decrease_parametric_missing(const bit_container<parameter_hash_bits>& id) {
+ std::map<bit_container<parameter_hash_bits>,int>::iterator mit
+ = parametric_missing_map_.find(id);
+ if (mit != parametric_missing_map_.end()) {
+ mit->second -= 1;
+ if (mit->second == 0) parametric_missing_map_.erase(mit);
+ } else assert(false);
+ }
+
+ inline void cell_info::selected(const std::vector<double>& p,
+ double weight,
+ const adaption_info& ainfo) {
+ for (std::size_t k = 0; k < p.size(); ++k) {
+ if (ainfo.adapt[k]) {
+ if (p[k] < mid_point_[k])
+ avg_weight_[k].first += weight;
+ else
+ avg_weight_[k].second += weight;
+ }
+ }
+ }
+
+ inline std::pair<std::size_t,double> cell_info::get_split (const adaption_info& ainfo,
+ bool& worth) const {
+ std::size_t split_d = 0;
+ double gain = 0.;
+ for (std::size_t k = 0; k < ainfo.dimension; ++k) {
+ double xgain = 0.;
+ double left = avg_weight_[k].first;
+ double right = avg_weight_[k].second;
+ if (left+right > 0.) {
+ xgain = std::abs(left-right)/(left+right);
+ }
+ if (xgain > gain) {
+ gain = xgain;
+ split_d = k;
+ }
+ }
+ worth = (gain >= ainfo.gain_threshold);
+ return std::make_pair(split_d,mid_point_[split_d]);
+ }
+
+ inline bool cell_info::contains_parameter (const std::vector<double>& point,
+ const std::vector<bool>& sampled) const {
+ std::vector<double>::const_iterator p = point.begin();
+ std::vector<double>::const_iterator l = lower_left_.begin();
+ std::vector<double>::const_iterator u = upper_right_.begin();
+ std::vector<bool>::const_iterator f = sampled.begin();
+ for (; p < point.end(); ++p, ++f, ++l, ++u)
+ if (!(*f)) {
+ if (((*l) > (*p)) ||
+ ((*u) < (*p)))
+ return false;
+ }
+ return true;
+ }
+
+
+ inline cell::cell()
+ : split_dimension_(0), split_point_(0.),
+ integral_(0.), missing_events_(0),
+ cell_info_(0) {}
+
+ inline cell::cell(const std::vector<double>& ll,
+ const std::vector<double>& ur,
+ const adaption_info& ainfo)
+ : split_dimension_(0), split_point_(0.),
+ integral_(0.), missing_events_(0),
+ cell_info_(new cell_info(ll,ur,ainfo)) {}
+
+ inline cell::cell(const std::vector<double>& ll,
+ const std::vector<double>& ur,
+ const std::vector<bool>& sampled_variables,
+ const adaption_info& ainfo)
+ : split_dimension_(0), split_point_(0.),
+ integral_(0.), missing_events_(0),
+ cell_info_(new cell_info(ll,ur,sampled_variables,ainfo)) {}
+
+ inline cell::cell(const cell& x)
+ : split_dimension_(x.split_dimension_),
+ split_point_(x.split_point_),
+ integral_(x.integral_),
+ missing_events_(x.missing_events_),
+ cell_info_(0) {
+ if (x.cell_info_)
+ cell_info_.reset(new cell_info(*x.cell_info_));
+ }
+
+ inline cell& cell::operator=(const cell& x) {
+ if (this == &x)
+ return *this;
+ split_dimension_ = x.split_dimension_;
+ split_point_ = x.split_point_;
+ integral_ = x.integral_;
+ missing_events_ = x.missing_events_;
+ if (x.cell_info_)
+ cell_info_.reset(new cell_info(*x.cell_info_));
+ return *this;
+ }
+
+
+}
diff --git a/Exsample2/exsample/config.h b/Exsample2/exsample/config.h
new file mode 100644
--- /dev/null
+++ b/Exsample2/exsample/config.h
@@ -0,0 +1,48 @@
+// -*- C++ -*-
+//
+// config.h is part of ExSample -- A Library for Sampling Sudakov-Type Distributions
+//
+// Copyright (C) 2008-2011 Simon Platzer -- simon.plaetzer@desy.de
+//
+// ExSample is licenced under version 2 of the GPL, see COPYING for details.
+// Please respect the MCnet academic guidelines, see GUIDELINES for details.
+//
+//
+#ifndef EXSAMPLE_config_h_included
+#define EXSAMPLE_config_h_included
+
+#include <vector>
+#include <map>
+#include <set>
+#include <string>
+
+#include <cmath>
+#include <cassert>
+#include <climits>
+
+#include <algorithm>
+#include <numeric>
+#include <limits>
+
+#include <boost/utility.hpp>
+#include <boost/scoped_array.hpp>
+#include <boost/scoped_ptr.hpp>
+
+#define EXSAMPLE_has_ThePEG
+
+#ifdef EXSAMPLE_has_ThePEG
+
+#include "ThePEG/Persistency/PersistentOStream.h"
+
+#endif // EXSAMPLE_has_ThePEG
+
+namespace exsample {
+
+ static const unsigned long parameter_hash_bits = 512;
+
+ using boost::next;
+ using boost::prior;
+
+}
+
+#endif // EXSAMPLE_config_h_included
diff --git a/Exsample2/exsample/exponential_generator.h b/Exsample2/exsample/exponential_generator.h
new file mode 100644
--- /dev/null
+++ b/Exsample2/exsample/exponential_generator.h
@@ -0,0 +1,210 @@
+// -*- C++ -*-
+//
+// exponential_generator.h is part of ExSample -- A Library for Sampling Sudakov-Type Distributions
+//
+// Copyright (C) 2008-2011 Simon Platzer -- simon.plaetzer@desy.de
+//
+// ExSample is licenced under version 2 of the GPL, see COPYING for details.
+// Please respect the MCnet academic guidelines, see GUIDELINES for details.
+//
+//
+#ifndef EXSAMPLE_exponential_generator_h_included
+#define EXSAMPLE_exponential_generator_h_included
+
+#include "cell.h"
+#include "selectors.h"
+#include "statistics.h"
+#include "linear_interpolator.h"
+#include "binary_tree.h"
+
+namespace exsample {
+
+ /// \brief Exception thrown, if the exponential_generator has just changed its
+ /// state. The attempt of generating an event should be repeated.
+ struct exponential_regenerate{};
+
+ /// \brief The generator for sudakov-type distributions.
+ template<class Function, class Random>
+ class exponential_generator {
+
+ public:
+
+ /// default constructor
+ exponential_generator()
+ : function_(0), check_events_(0), adaption_info_(), root_cell_(),
+ rnd_gen_(), did_split_(false), initialized_(false),
+ evolution_variable_(0), evolution_cutoff_(0.),
+ sample_variables_(), sample_other_variables_(),
+ parameter_splits_(),
+ last_cell_(), last_point_(), last_value_(0.),
+ last_parameter_bin_(), exponents_(),
+ last_exponent_integrand_(),
+ last_exponent_(), compensating_(false),
+ integral_accessor_(), missing_accessor_(),
+ parametric_selector_(), exponent_selector_(),
+ parametric_sampler_(), attempts_(0), accepts_(0),
+ splits_(0) {}
+
+ public:
+
+ /// initialize this generator
+ void initialize();
+
+ /// finalize this generator
+ void finalize() {}
+
+ /// generate an event, returning
+ /// the sign of the weight or zero
+ /// for an event below the evolution cutoff
+ double generate();
+
+ /// return the last sampled phase space point
+ const std::vector<double>& last_point() const { return last_point_; }
+
+ /// return the last evaluated function
+ double last_value() const { return last_value_; }
+
+ /// indicate that the last generated point has been rejected
+ void reject() {
+ last_cell_->info().reject();
+ }
+
+ public:
+
+ /// return true, if this generator has been initialized
+ bool initialized() const { return initialized_; }
+
+ /// return true, if at least one split has been performed
+ bool did_split() const { return did_split_; }
+
+ /// access the function
+ Function& function() { return *function_; }
+
+ /// set the function
+ void function(Function * f) { function_ = f; }
+
+ /// access the adaption_info object
+ adaption_info& sampling_parameters() { return adaption_info_; }
+
+ private:
+
+ /// check for and possibly split
+ /// the last selected cell
+ bool split();
+
+ /// get the projection of the density integrating over every
+ /// variable to be sampled, except the evolution variable for the
+ /// indicated parameter point. the k'th entry in
+ /// last_exponent_integrand_ is the value in the evolution
+ /// variable bin from evolution_splits_[k] to
+ /// evolution_splits_[k+1]
+ void get_exponent();
+
+ /// compensate
+ void compensate();
+
+ /// get all parameter points to build
+ /// all possible sub tree hashes
+ std::set<std::vector<double> > parameter_points();
+
+ /// get all parameter points to build
+ /// all possible sub tree hashes
+ void recursive_parameter_points(std::set<std::vector<double> >&,
+ std::vector<double>&,
+ size_t);
+
+ /// function to be sampled
+ Function * function_;
+
+ /// the number of events after which
+ /// a cell is checked for splits
+ unsigned long check_events_;
+
+ /// the adaption info object
+ adaption_info adaption_info_;
+
+ /// the root cell
+ binary_tree<cell> root_cell_;
+
+ /// the random number generator to be used
+ rnd_generator<Random> rnd_gen_;
+
+ /// wether a split has already been performed
+ bool did_split_;
+
+ /// wether this generator has been initialized
+ bool initialized_;
+
+ /// the position of the evolution variable
+ std::size_t evolution_variable_;
+
+ /// the cutoff on the evolution variable
+ double evolution_cutoff_;
+
+ /// flags of variables to be sampled
+ /// including the evolution variable
+ std::vector<bool> sample_variables_;
+
+ /// flags of variables to be sampled
+ /// excluding the evolution variable
+ std::vector<bool> sample_other_variables_;
+
+ /// the splits in any parameter done so far
+ /// (including the evolution variable)
+ std::map<std::size_t,std::vector<double> > parameter_splits_;
+
+ /// the last selected cell
+ binary_tree<cell>::iterator last_cell_;
+
+ /// the last sampled phasespace point
+ std::vector<double> last_point_;
+
+ /// the last function value
+ double last_value_;
+
+ /// the last parameter bin id
+ bit_container<parameter_hash_bits> last_parameter_bin_;
+
+ /// map parameter bin ids to exponent interpolations
+ std::map<bit_container<parameter_hash_bits>,linear_interpolator > exponents_;
+
+ /// the last exponent integrand
+ std::vector<double> last_exponent_integrand_;
+
+ /// the last exponent
+ std::map<bit_container<parameter_hash_bits>,linear_interpolator >::iterator last_exponent_;
+
+ /// wether or not we are compensating
+ bool compensating_;
+
+ /// the integral accessor to be used
+ integral_accessor integral_accessor_;
+
+ /// the missing events accessor to be used
+ parametric_missing_accessor missing_accessor_;
+
+ /// the parametric selector to be used
+ parametric_selector parametric_selector_;
+
+ /// the parametric selector to be used for parameter bins
+ parametric_selector exponent_selector_;
+
+ /// the parametric sampler to be used
+ parametric_sampling_selector<rnd_generator<Random> > parametric_sampler_;
+
+ /// the number of trials in the veto loo so far
+ unsigned long attempts_;
+
+ /// the number of accepted events so far
+ unsigned long accepts_;
+
+ /// number of splits done
+ unsigned long splits_;
+
+ };
+
+}
+
+#include "exponential_generator.icc"
+
+#endif // EXSAMPLE_exponential_generator_h_included
diff --git a/Exsample2/exsample/exponential_generator.icc b/Exsample2/exsample/exponential_generator.icc
new file mode 100644
--- /dev/null
+++ b/Exsample2/exsample/exponential_generator.icc
@@ -0,0 +1,323 @@
+// -*- C++ -*-
+//
+// exponential_generator.icc is part of ExSample -- A Library for Sampling Sudakov-Type Distributions
+//
+// Copyright (C) 2008-2011 Simon Platzer -- simon.plaetzer@desy.de
+//
+// ExSample is licenced under version 2 of the GPL, see COPYING for details.
+// Please respect the MCnet academic guidelines, see GUIDELINES for details.
+//
+//
+namespace exsample {
+
+ template<class Function, class Random>
+ void exponential_generator<Function,Random>::initialize() {
+ adaption_info_.dimension = function_->dimension();
+ adaption_info_.lower_left = function_->support().first;
+ adaption_info_.upper_right = function_->support().second;
+ if (adaption_info_.adapt.empty())
+ adaption_info_.adapt = std::vector<bool>(adaption_info_.dimension,true);
+ evolution_variable_ = function_->evolution_variable();
+ evolution_cutoff_ = function_->evolution_cutoff();
+ sample_variables_ = function_->variable_flags();
+ sample_other_variables_ = sample_variables_;
+ sample_other_variables_[evolution_variable_] = false;
+ last_point_.resize(adaption_info_.dimension);
+ parametric_selector_ = parametric_selector(&last_point_,sample_other_variables_);
+ exponent_selector_ = parametric_selector(&last_point_,sample_variables_);
+ missing_accessor_ = parametric_missing_accessor(&last_parameter_bin_);
+ parametric_sampler_ = parametric_sampling_selector<rnd_generator<Random> >
+ (&last_point_,&last_parameter_bin_,sample_other_variables_,rnd_gen_);
+ if (initialized_) return;
+ splits_ = 0;
+ for ( std::size_t k = 0; k < adaption_info_.dimension; ++k ) {
+ if ( sample_other_variables_[k] )
+ continue;
+ parameter_splits_[k].push_back(adaption_info_.lower_left[k]);
+ parameter_splits_[k].push_back(adaption_info_.upper_right[k]);
+ }
+ root_cell_ =
+ binary_tree<cell>(cell(adaption_info_.lower_left,
+ adaption_info_.upper_right,
+ sample_other_variables_,
+ adaption_info_));
+ root_cell_.value().info().explore(rnd_gen_,adaption_info_,function_);
+ root_cell_.value().integral(root_cell_.value().info().volume() * root_cell_.value().info().overestimate());
+ last_exponent_integrand_.resize(1);
+ check_events_ = adaption_info_.presampling_points;
+ initialized_ = true;
+ }
+
+ template<class Function, class Random>
+ bool exponential_generator<Function,Random>::split () {
+ if (++splits_ > parameter_hash_bits/2)
+ return false;
+ if (adaption_info_.freeze_grid == accepts_)
+ return false;
+ if (compensating_)
+ return false;
+ if (!(*last_cell_).info().bad(adaption_info_)) return false;
+ bool dosplit = false;
+ std::pair<std::size_t,double> sp =
+ (*last_cell_).info().get_split(adaption_info_,dosplit);
+ if (!dosplit) return false;
+ if (!adaption_info_.adapt[sp.first]) return false;
+ last_cell_.node().split((*last_cell_).split(sp,rnd_gen_,function_,adaption_info_,sample_other_variables_));
+ if ( !sample_other_variables_[sp.first] ) {
+ if ( std::find(parameter_splits_[sp.first].begin(),parameter_splits_[sp.first].end(),sp.second)
+ == parameter_splits_[sp.first].end() ) {
+ parameter_splits_[sp.first].push_back(sp.second);
+ std::sort(parameter_splits_[sp.first].begin(),parameter_splits_[sp.first].end());
+ if ( sp.first == evolution_variable_ ) {
+ last_exponent_integrand_.push_back(0.);
+ }
+ }
+ }
+ did_split_ = true;
+ last_point_ = function_->parameter_point();
+ root_cell_.tree_accumulate(parametric_selector_,integral_accessor_,std::plus<double>());
+ exponents_.clear();
+ get_exponent();
+ return true;
+ }
+
+ template<class Function, class Random>
+ void exponential_generator<Function,Random>::get_exponent () {
+ last_parameter_bin_.reset();
+ root_cell_.subtree_hash (exponent_selector_,last_parameter_bin_);
+ last_exponent_ = exponents_.find(last_parameter_bin_);
+ if (last_exponent_ != exponents_.end())
+ return;
+ exponents_[last_parameter_bin_] = linear_interpolator();
+ last_exponent_ = exponents_.find(last_parameter_bin_);
+ double old_evo = last_point_[evolution_variable_];
+ std::vector<double>::iterator exp_it = last_exponent_integrand_.begin();
+ for (std::vector<double>::iterator esp = parameter_splits_[evolution_variable_].begin();
+ esp < prior(parameter_splits_[evolution_variable_].end()); ++esp, ++exp_it) {
+ last_point_[evolution_variable_] = (*esp + *next(esp))/2.;
+ *exp_it = root_cell_.accumulate(parametric_selector_,integral_accessor_,std::plus<double>());
+ }
+ exp_it = prior(last_exponent_integrand_.end());
+ double total = 0.;
+ for (std::vector<double>::iterator esp = prior(parameter_splits_[evolution_variable_].end());
+ esp > parameter_splits_[evolution_variable_].begin(); --esp, --exp_it) {
+ last_exponent_->second.set_interpolation(*esp,total);
+ total += (*exp_it) * ((*esp) - (*prior(esp)));
+ }
+ last_exponent_->second.set_interpolation(parameter_splits_[evolution_variable_].front(),total);
+ last_point_[evolution_variable_] = old_evo;
+ }
+
+ template<class Function, class Random>
+ std::set<std::vector<double> >
+ exponential_generator<Function,Random>::parameter_points() {
+ std::set<std::vector<double> > res;
+ std::vector<double> pt(adaption_info_.dimension,0.);
+ recursive_parameter_points(res,pt,0);
+ return res;
+ }
+
+ template<class Function, class Random>
+ void exponential_generator<Function,Random>::
+ recursive_parameter_points(std::set<std::vector<double> >& res,
+ std::vector<double>& pt,
+ size_t current) {
+ if ( current == adaption_info_.dimension ) {
+ res.insert(pt);
+ return;
+ }
+ if ( sample_variables_[current] ) {
+ recursive_parameter_points(res,pt,current+1);
+ return;
+ }
+ for ( std::vector<double>::const_iterator sp =
+ parameter_splits_[current].begin();
+ sp != prior(parameter_splits_[current].end()); ++sp ) {
+ pt[current] = (*sp + *next(sp))/2.;
+ recursive_parameter_points(res,pt,current+1);
+ }
+ }
+
+ template<class Function, class Random>
+ void exponential_generator<Function,Random>::compensate() {
+ if (!did_split_) {
+ exponents_.clear();
+ root_cell_.value().info().overestimate(last_value_,last_point_);
+ root_cell_.value().integral(root_cell_.value().info().volume() * root_cell_.value().info().overestimate());
+ last_point_ = function_->parameter_point();
+ get_exponent();
+ return;
+ }
+ std::vector<double> themaxpoint = last_point_;
+ std::set<std::vector<double> > id_points
+ = parameter_points();
+ for ( std::set<std::vector<double> >::const_iterator id =
+ id_points.begin(); id != id_points.end(); ++id ) {
+ last_point_ = *id;
+ get_exponent();
+ }
+ std::map<bit_container<parameter_hash_bits>,linear_interpolator >
+ old_exponents = exponents_;
+ double old_oe = last_cell_->info().overestimate();
+ last_cell_->info().overestimate(last_value_,themaxpoint);
+ last_cell_->integral(last_cell_->info().volume() * last_cell_->info().overestimate());
+ exponents_.clear();
+ for ( std::set<std::vector<double> >::const_iterator id =
+ id_points.begin(); id != id_points.end(); ++id ) {
+ last_point_ = *id;
+ get_exponent();
+ std::map<bit_container<parameter_hash_bits>,linear_interpolator >::iterator
+ old_exp = old_exponents.find(last_parameter_bin_);
+ std::map<bit_container<parameter_hash_bits>,linear_interpolator >::iterator
+ new_exp = exponents_.find(last_parameter_bin_);
+ assert(old_exp != old_exponents.end() && new_exp != exponents_.end());
+ double old_norm = 1. - std::exp(-(old_exp->second)(adaption_info_.lower_left[evolution_variable_]));
+ double new_norm = 1. - std::exp(-(new_exp->second)(adaption_info_.lower_left[evolution_variable_]));
+ for (binary_tree<cell>::iterator it = root_cell_.begin();
+ it != root_cell_.end(); ++it) {
+ if ( !it->info().contains_parameter(last_point_,sample_other_variables_) )
+ continue;
+ double old_int = 0.;
+ double new_int = 0.;
+ for ( std::vector<double>::const_iterator sp = parameter_splits_[evolution_variable_].begin();
+ sp != prior(parameter_splits_[evolution_variable_].end()); ++sp ) {
+ if ( *sp >= it->info().lower_left()[evolution_variable_] &&
+ *sp < it->info().upper_right()[evolution_variable_] ) {
+ double xl = *sp;
+ double xxl = *next(sp);
+ double old_al =
+ (old_exp->second.interpolation()[xxl] - old_exp->second.interpolation()[xl]) /
+ (xxl-xl);
+ double old_bl =
+ (xxl * old_exp->second.interpolation()[xl] -
+ xl * old_exp->second.interpolation()[xxl]) /
+ (xxl-xl);
+ double new_al =
+ (new_exp->second.interpolation()[xxl] - new_exp->second.interpolation()[xl]) /
+ (xxl-xl);
+ double new_bl =
+ (xxl * new_exp->second.interpolation()[xl] -
+ xl * new_exp->second.interpolation()[xxl]) /
+ (xxl-xl);
+ if ( std::abs(old_al) > std::numeric_limits<double>::epsilon() ) {
+ old_int += (exp(-(old_al*xl+old_bl)) - exp(-(old_al*xxl+old_bl)))/old_al;
+ } else {
+ old_int += (xxl-xl)*exp(-old_bl);
+ }
+ if ( std::abs(new_al) > std::numeric_limits<double>::epsilon() ) {
+ new_int += (exp(-(new_al*xl+new_bl)) - exp(-(new_al*xxl+new_bl)))/new_al;
+ } else {
+ new_int += (xxl-xl)*exp(-new_bl);
+ }
+ }
+ }
+ double scaling;
+ if (it != last_cell_) {
+ if (old_int > std::numeric_limits<double>::epsilon() &&
+ new_int > std::numeric_limits<double>::epsilon())
+ scaling = ((old_norm * new_int) /
+ (new_norm * old_int)) - 1.;
+ else
+ scaling = 0.;
+ } else {
+ if (old_int > std::numeric_limits<double>::epsilon() &&
+ new_int > std::numeric_limits<double>::epsilon())
+ scaling = ((last_value_ * old_norm * new_int) /
+ (old_oe * new_norm * old_int)) - 1.;
+ else
+ scaling = 0.;
+ }
+ it->info().parametric_missing(last_parameter_bin_,
+ it->info().parametric_missing(last_parameter_bin_) +
+ static_cast<int>(round(scaling * it->info().attempted())));
+ if (it->info().parametric_missing(last_parameter_bin_) != 0) {
+ compensating_ = true;
+ }
+ }
+ }
+ last_point_ = function_->parameter_point();
+ }
+
+ template<class Function, class Random>
+ double exponential_generator<Function,Random>::generate () {
+ if (compensating_) {
+ compensating_ = false;
+ for (binary_tree<cell>::iterator it = root_cell_.begin();
+ it != root_cell_.end(); ++it)
+ if (it->info().parametric_compensating()) {
+ compensating_ = true;
+ break;
+ }
+ parametric_sampler_.compensate(compensating_);
+ }
+ last_point_ = function_->parameter_point();
+ if (last_point_[evolution_variable_] < evolution_cutoff_) {
+ return 0.;
+ }
+ unsigned long n_hit_miss = 0;
+ unsigned long n_select = 0;
+ double minus_log_r;
+ root_cell_.tree_accumulate(parametric_selector_,integral_accessor_,std::plus<double>());
+ get_exponent();
+ while (true) {
+ n_select = 0;
+ minus_log_r = -std::log(rnd_gen_()) + last_exponent_->second(last_point_[evolution_variable_]);
+ if (!last_exponent_->second.invertible(minus_log_r)) {
+ return 0.;
+ }
+ try {
+ last_point_[evolution_variable_] = last_exponent_->second.unique_inverse(minus_log_r);
+ } catch (constant_interpolation& c) {
+ last_point_[evolution_variable_] = rnd_gen_(c.range.first,c.range.second);
+ }
+ assert(!std::isnan(last_point_[evolution_variable_]) &&
+ !std::isinf(last_point_[evolution_variable_]));
+ if (last_point_[evolution_variable_] < evolution_cutoff_) {
+ return 0.;
+ }
+ ++attempts_;
+ if (compensating_) {
+ root_cell_.tree_accumulate(missing_accessor_,std::plus<int>());
+ }
+ if (parameter_splits_[evolution_variable_].size() > 2)
+ root_cell_.tree_accumulate(parametric_selector_,integral_accessor_,std::plus<double>());
+ if (did_split_)
+ while ((last_cell_ = root_cell_.select(parametric_sampler_)) == root_cell_.end()) {
+ root_cell_.tree_accumulate(missing_accessor_,std::plus<int>());
+ if(++n_select > adaption_info_.maxtry)
+ throw selection_maxtry();
+ }
+ else
+ last_cell_ = root_cell_.begin();
+ last_cell_->info().select(rnd_gen_,last_point_,sample_other_variables_);
+ last_value_ = function_->evaluate(last_point_);
+ assert(last_value_ >= 0.);
+ last_cell_->info().selected(last_point_,last_value_,adaption_info_);
+ if (last_value_ > last_cell_->info().overestimate()) {
+ if ( std::abs(last_value_)/last_cell_->info().overestimate() > 2. ) {
+ last_value_ =
+ last_value_*(1.+exp(2.*(2.-std::abs(last_value_)/last_cell_->info().overestimate())));
+ }
+ compensate();
+ throw exponential_regenerate();
+ }
+ if (last_cell_->info().attempted() % check_events_ == 0) {
+ if (split()) {
+ throw exponential_regenerate();
+ }
+ }
+ if (last_value_/last_cell_->info().overestimate() > rnd_gen_())
+ break;
+ if(++n_hit_miss > adaption_info_.maxtry)
+ throw hit_and_miss_maxtry();
+ }
+ if (last_value_ == 0.)
+ return 0.;
+ ++accepts_;
+ ++check_events_;
+ last_cell_->info().accept();
+ return 1.;
+ }
+
+
+}
diff --git a/Exsample2/exsample/generator.h b/Exsample2/exsample/generator.h
new file mode 100644
--- /dev/null
+++ b/Exsample2/exsample/generator.h
@@ -0,0 +1,181 @@
+// -*- C++ -*-
+//
+// generator.h is part of ExSample -- A Library for Sampling Sudakov-Type Distributions
+//
+// Copyright (C) 2008-2011 Simon Platzer -- simon.plaetzer@desy.de
+//
+// ExSample is licenced under version 2 of the GPL, see COPYING for details.
+// Please respect the MCnet academic guidelines, see GUIDELINES for details.
+//
+//
+#ifndef EXSAMPLE_generator_h_included
+#define EXSAMPLE_generator_h_included
+
+#include "cell.h"
+#include "selectors.h"
+#include "statistics.h"
+#include "binary_tree.h"
+
+namespace exsample {
+
+ /// \brief Exception thrown, if the generator has just changed its
+ /// state. The attempt of generating an event should be repeated.
+ struct generator_update{};
+
+ /// \brief A generator for plain sampling and integrating
+ template<class Function, class Random>
+ class generator {
+
+ public:
+
+ /// default constructor
+ generator()
+ : function_(0), statistics_(), check_events_(0),
+ adaption_info_(), root_cell_(),
+ rnd_gen_(), did_split_(false), initialized_(false),
+ last_cell_(), last_point_(), last_value_(0.),
+ compensating_(false) {}
+
+ public:
+
+ /// initialize this generator
+ template<class SlaveStatistics>
+ void initialize(SlaveStatistics&);
+
+ /// generate an event, returning
+ /// the sign of the weight
+ template<class SlaveStatistics>
+ double generate(SlaveStatistics&);
+
+ /// return the last sampled phase space point
+ const std::vector<double>& last_point() const { return last_point_; }
+
+ /// indicate that the last generated point has been rejected
+ void reject() {
+ statistics_.reject(last_value_);
+ last_cell_->info().reject();
+ }
+
+ /// finalize this generator
+ void finalize() {
+ statistics_.reset();
+ }
+
+ public:
+
+ /// return true, if this generator has been initialized
+ bool initialized() const { return initialized_; }
+
+ /// return true, if at least one split has been performed
+ bool did_split() const { return did_split_; }
+
+ /// access the function
+ Function& function() { return *function_; }
+
+ /// set the function
+ void function(Function * f) { function_ = f; }
+
+ /// return the statistics object
+ const statistics& stats() const { return statistics_; }
+
+ /// return the sampled volume
+ double volume() const {
+ return exsample::volume(adaption_info_.lower_left, adaption_info_.upper_right);
+ }
+
+ /// return the integral
+ double integral() const {
+ return volume() * statistics_.average_weight();
+ }
+
+ /// return the error on the integral
+ double integral_uncertainty() const {
+ return volume() * std::sqrt(statistics_.average_weight_variance());
+ }
+
+ /// return the integral
+ double current_integral() const {
+ return volume() * statistics_.current().first;
+ }
+
+ /// return the error on the integral
+ double current_integral_uncertainty() const {
+ return volume() * std::sqrt(statistics_.current().second);
+ }
+
+ /// return the variance of the integral estimate
+ double integral_variance() const {
+ return sqr(volume()) * statistics_.average_weight_variance();
+ }
+
+ /// access the adaption_info object
+ adaption_info& sampling_parameters() { return adaption_info_; }
+
+ /// return true, if still compensating
+ bool compensating() const { return compensating_; }
+
+ public:
+
+ /// put to ostream
+ template<class OStream>
+ void put(OStream& os) const;
+
+ /// get from istream
+ template<class IStream>
+ void get(IStream& is);
+
+ private:
+
+ /// check for and possibly split
+ /// the last selected cell
+ bool split();
+
+ /// compensate the last selected cell indicating the
+ /// value and position of the new overestimate
+ void compensate();
+
+ /// function to be sampled
+ Function * function_;
+
+ /// the global statistics object
+ statistics statistics_;
+
+ /// the number of events after which
+ /// a cell is checked for splits
+ unsigned long check_events_;
+
+ /// the adaption info object
+ adaption_info adaption_info_;
+
+ /// the root cell
+ binary_tree<cell> root_cell_;
+
+ /// the random number generator to be used
+ rnd_generator<Random> rnd_gen_;
+
+ /// wether a split has already been performed
+ bool did_split_;
+
+ /// wether this generator has been initialized
+ bool initialized_;
+
+ /// the last selected cell
+ binary_tree<cell>::iterator last_cell_;
+
+ /// the last sampled phasespace point
+ std::vector<double> last_point_;
+
+ /// the last function value
+ double last_value_;
+
+ /// wether or not we are compensating
+ bool compensating_;
+
+ };
+
+}
+
+#include "generator.icc"
+
+#endif // EXSAMPLE_generator_h_included
+
diff --git a/Exsample2/exsample/generator.icc b/Exsample2/exsample/generator.icc
new file mode 100644
--- /dev/null
+++ b/Exsample2/exsample/generator.icc
@@ -0,0 +1,178 @@
+// -*- C++ -*-
+//
+// generator.icc is part of ExSample -- A Library for Sampling Sudakov-Type Distributions
+//
+// Copyright (C) 2008-2011 Simon Platzer -- simon.plaetzer@desy.de
+//
+// ExSample is licenced under version 2 of the GPL, see COPYING for details.
+// Please respect the MCnet academic guidelines, see GUIDELINES for details.
+//
+//
+namespace exsample {
+
+ template<class Function, class Random>
+ template<class SlaveStatistics>
+ void generator<Function,Random>::initialize(SlaveStatistics& opt) {
+ adaption_info_.dimension = function_->dimension();
+ adaption_info_.lower_left = function_->support().first;
+ adaption_info_.upper_right = function_->support().second;
+ if (adaption_info_.adapt.empty())
+ adaption_info_.adapt = std::vector<bool>(adaption_info_.dimension,true);
+ last_point_.resize(adaption_info_.dimension);
+ if (initialized_) return;
+ root_cell_ =
+ binary_tree<cell>(cell(adaption_info_.lower_left,
+ adaption_info_.upper_right,
+ adaption_info_));
+ root_cell_.value().info().explore(rnd_gen_,adaption_info_,function_,&statistics_,opt);
+ root_cell_.value().integral(root_cell_.value().info().volume() * root_cell_.value().info().overestimate());
+ statistics_.reset();
+ check_events_ = adaption_info_.presampling_points;
+ initialized_ = true;
+ }
+
+ template<class Function, class Random>
+ bool generator<Function,Random>::split() {
+ if (adaption_info_.freeze_grid < statistics_.accepted() &&
+ adaption_info_.freeze_grid != 0)
+ return false;
+ if (compensating_) return false;
+ if (!(*last_cell_).info().bad(adaption_info_)) return false;
+ bool dosplit = false;
+ std::pair<std::size_t,double> sp =
+ (*last_cell_).info().get_split(adaption_info_,dosplit);
+ if (!dosplit || !adaption_info_.adapt[sp.first]) {
+ return false;
+ }
+ std::pair<binary_tree<cell>::iterator,binary_tree<cell>::iterator> spit =
+ last_cell_.node().split((*last_cell_).split(sp,rnd_gen_,function_,adaption_info_));
+ integral_accessor iacc;
+ root_cell_.tree_accumulate(iacc,std::plus<double>());
+ did_split_ = true;
+ statistics_.reset();
+ return true;
+ }
+
+ template<class Function, class Random>
+ void generator<Function,Random>::compensate() {
+ if (!did_split_) {
+ root_cell_.value().info().overestimate(std::abs(last_value_),last_point_);
+ root_cell_.value().integral(root_cell_.value().info().volume() * root_cell_.value().info().overestimate());
+ return;
+ }
+ double old_norm = root_cell_.value().integral();
+ double new_norm = old_norm - (*last_cell_).integral() + std::abs(last_value_) * (*last_cell_).info().volume();
+ compensating_ = false;
+ last_cell_->missing_events() +=
+ static_cast<int>(round(((std::abs(last_value_) * old_norm)/(last_cell_->info().overestimate() * new_norm) - 1.) *
+ (last_cell_->info().attempted())));
+ if (last_cell_->missing_events() != 0)
+ compensating_ = true;
+ last_cell_->info().overestimate(std::abs(last_value_),last_point_);
+ last_cell_->integral(last_cell_->info().volume() * last_cell_->info().overestimate());
+ for (binary_tree<cell>::iterator it = root_cell_.begin();
+ it != root_cell_.end(); ++it)
+ if (it != last_cell_) {
+ it->missing_events() += static_cast<int>(round((old_norm/new_norm - 1.) * (it->info().attempted())));
+ if (it->missing_events() != 0) {
+ compensating_ = true;
+ }
+ }
+ integral_accessor iacc;
+ root_cell_.tree_accumulate(iacc,std::plus<double>());
+ statistics_.reset();
+ root_cell_.tree_accumulate(missing_accessor(),std::plus<int>());
+ }
+
+ template<class Function, class Random>
+ template<class SlaveStatistics>
+ double generator<Function,Random>::generate(SlaveStatistics& opt) {
+ unsigned long n_hit_miss = 0;
+ unsigned long n_select = 0;
+ sampling_selector<rnd_generator<Random> > sampler (rnd_gen_,compensating_);
+ missing_accessor macc;
+ if (compensating_) {
+ compensating_ = false;
+ for (binary_tree<cell>::iterator it = root_cell_.begin();
+ it != root_cell_.end(); ++it)
+ if (it->missing_events() != 0) {
+ compensating_ = true;
+ break;
+ }
+ }
+ while (true) {
+ sampler.compensate = compensating_;
+ n_select = 0;
+ if (did_split_)
+ while ((last_cell_ = root_cell_.select(sampler)) == root_cell_.end()) {
+ root_cell_.tree_accumulate(macc,std::plus<int>());
+ if(++n_select > adaption_info_.maxtry)
+ throw selection_maxtry();
+ }
+ else
+ last_cell_ = root_cell_.begin();
+ last_cell_->info().select(rnd_gen_,last_point_);
+ last_value_ = function_->evaluate(last_point_);
+ last_cell_->info().selected(last_point_,std::abs(last_value_),adaption_info_);
+ if (std::abs(last_value_) > last_cell_->info().overestimate()) {
+ if ( std::abs(last_value_)/last_cell_->info().overestimate() > 2. ) {
+ last_value_ =
+ last_value_*(1.+exp(2.*(2.-std::abs(last_value_)/last_cell_->info().overestimate())));
+ }
+ compensate();
+ n_hit_miss = 0;
+ continue;
+ }
+ if (last_cell_->info().attempted() % check_events_ == 0) {
+ if (split()) {
+ throw generator_update();
+ }
+ }
+ if (did_split_) {
+ statistics_.select(last_value_ * root_cell_.value().integral() /
+ last_cell_->info().overestimate(), !compensating_);
+ opt.select(last_value_ * root_cell_.value().integral() /
+ last_cell_->info().overestimate(), !compensating_);
+ } else {
+ statistics_.select(last_value_, !compensating_);
+ opt.select(last_value_, !compensating_);
+ }
+ if (std::abs(last_value_)/last_cell_->info().overestimate() > rnd_gen_())
+ break;
+ if(++n_hit_miss > adaption_info_.maxtry)
+ throw hit_and_miss_maxtry();
+ }
+ last_cell_->info().accept();
+ if (did_split_)
+ last_value_ *= root_cell_.value().integral() / last_cell_->info().overestimate();
+ statistics_.accept(last_value_);
+ ++check_events_;
+ if (last_value_ < 0.)
+ return -1.;
+ return 1.;
+ }
+
+ template<class Function, class Random>
+ template<class OStream>
+ void generator<Function,Random>::put (OStream& os) const {
+ adaption_info_.put(os);
+ root_cell_.put(os);
+ statistics_.put(os);
+ os << check_events_;
+ ostream_traits<OStream>::separator(os);
+ os << did_split_;
+ ostream_traits<OStream>::separator(os);
+ os << initialized_;
+ ostream_traits<OStream>::separator(os);
+ }
+
+ template<class Function, class Random>
+ template<class IStream>
+ void generator<Function,Random>::get (IStream& is) {
+ adaption_info_.get(is);
+ root_cell_.get(is);
+ statistics_.get(is);
+ is >> check_events_ >> did_split_ >> initialized_;
+ }
+
+}
diff --git a/Exsample2/exsample/linear_interpolator.h b/Exsample2/exsample/linear_interpolator.h
new file mode 100644
--- /dev/null
+++ b/Exsample2/exsample/linear_interpolator.h
@@ -0,0 +1,123 @@
+// -*- C++ -*-
+//
+// linear_interpolator.h is part of ExSample -- A Library for Sampling Sudakov-Type Distributions
+//
+// Copyright (C) 2008-2011 Simon Platzer -- simon.plaetzer@desy.de
+//
+// ExSample is licenced under version 2 of the GPL, see COPYING for details.
+// Please respect the MCnet academic guidelines, see GUIDELINES for details.
+//
+//
+#ifndef EXSAMPLE_linear_interpolator_h_included
+#define EXSAMPLE_linear_interpolator_h_included
+
+#include "utility.h"
+
+namespace exsample {
+
+ /// \brief Exception thrown, if inversion of the interpolation has
+ /// no solution
+ struct inversion_has_no_solution { };
+
+ /// \brief Exception thrown, if a constant piece of the
+ /// interpolation has been hit
+ struct constant_interpolation {
+
+ /// standard constructor
+ constant_interpolation(double xlow,
+ double xhigh,
+ double h)
+ : range(xlow,xhigh), value(h) {}
+
+ /// The range in which the interpolation is constant
+ std::pair<double,double> range;
+
+ /// The value of the interpolation in the range
+ double value;
+
+ };
+
+ /// \brief A linear interpolation allowing for inversion of the
+ /// linear interpolation
+ class linear_interpolator {
+
+ public:
+
+ /// default constructor
+ linear_interpolator();
+
+ /// construct a linear interpolator given the
+ /// map of interpolation points and values
+ explicit linear_interpolator(const std::map<double,double>& points);
+
+ public:
+
+ /// return the interpolations value at the given point
+ double operator()(double x) const;
+
+ /// return the range of the interpolation
+ std::pair<double,double> range() const { return range_; }
+
+ public:
+
+ /// return true, if an inverse exists for
+ /// the given value
+ bool invertible(double f) const {
+ return (range_.first <= f &&
+ range_.second >= f);
+ }
+
+ /// return the inverse, assuming the inverse
+ /// is unique
+ double unique_inverse(double f) const;
+
+ /// access the interpolation map
+ std::map<double,double>& interpolation() {
+ return interpolation_;
+ }
+
+ /// set the value at the given point
+ void set_interpolation(double point, double value);
+
+ /// reset after interpolation points have been changed
+ void reset();
+
+ public:
+
+ /// put to ostream
+ template<class OStream>
+ void put(OStream& os) const;
+
+ /// get from istream
+ template<class IStream>
+ void get(IStream& is);
+
+ private:
+
+ /// map points to values
+ std::map<double, double> interpolation_;
+
+ /// the range of the interpolation
+ std::pair<double,double> range_;
+
+ };
+
+ /// ostream operator for linear_interpolator objects
+ template<class OStream>
+ inline OStream& operator<<(OStream& os, const linear_interpolator& ip) {
+ ip.put(os);
+ return os;
+ }
+
+ /// istream operator for linear_interpolator objects
+ template<class IStream>
+ inline IStream& operator>>(IStream& is, linear_interpolator& ip) {
+ ip.get(is);
+ return is;
+ }
+
+}
+
+#include "linear_interpolator.icc"
+
+#endif // EXSAMPLE_linear_interpolator_h_included
diff --git a/Exsample2/exsample/linear_interpolator.icc b/Exsample2/exsample/linear_interpolator.icc
new file mode 100644
--- /dev/null
+++ b/Exsample2/exsample/linear_interpolator.icc
@@ -0,0 +1,111 @@
+// -*- C++ -*-
+//
+// linear_interpolator.icc is part of ExSample -- A Library for Sampling Sudakov-Type Distributions
+//
+// Copyright (C) 2008-2011 Simon Platzer -- simon.plaetzer@desy.de
+//
+// ExSample is licenced under version 2 of the GPL, see COPYING for details.
+// Please respect the MCnet academic guidelines, see GUIDELINES for details.
+//
+//
+namespace exsample {
+
+ inline linear_interpolator::linear_interpolator()
+ : interpolation_(), range_() {}
+
+ inline linear_interpolator::linear_interpolator(const std::map<double,double>& points)
+ : interpolation_(points) {
+ reset();
+ }
+
+
+ inline void linear_interpolator::set_interpolation(double point, double value) {
+ interpolation_[point] = value;
+ if (value > range_.second)
+ range_.second = value;
+ if(value < range_.first)
+ range_.first = value;
+ }
+
+
+ inline void linear_interpolator::reset() {
+ range_.first = interpolation_.begin()->second;
+ range_.second = interpolation_.begin()->second;
+ for (std::map<double,double>::const_iterator c = interpolation_.begin();
+ c != interpolation_.end(); ++c) {
+ if (c->second < range_.first)
+ range_.first = c->second;
+ if (c->second > range_.second)
+ range_.second = c->second;
+ }
+ }
+
+
+ inline double linear_interpolator::operator()(double x) const {
+ std::map<double, double>::const_iterator upper =
+ interpolation_.upper_bound(x);
+ if (upper == interpolation_.end()) {
+ upper = interpolation_.upper_bound(x-1e-10);
+ }
+ if (upper == interpolation_.end()) {
+ upper = interpolation_.upper_bound(x+1e-10);
+ }
+ assert(upper != interpolation_.begin() &&
+ upper != interpolation_.end());
+ return ((upper->second-prior(upper)->second)*x +
+ prior(upper)->second*upper->first - upper->second*prior(upper)->first)/
+ (upper->first - prior(upper)->first);
+ }
+
+
+ inline double linear_interpolator::unique_inverse(double f) const {
+ if(!invertible(f)) throw inversion_has_no_solution();
+ std::map<double, double>::const_iterator lower = interpolation_.begin();
+ bool gotone = false;
+ for (; lower != --interpolation_.end(); ++lower)
+ if ((lower->second >= f && next(lower)->second <= f) ||
+ (lower->second <= f && next(lower)->second >= f)) {
+ gotone = true;
+ break;
+ }
+ if(!gotone) throw inversion_has_no_solution();
+ if (lower->second == next(lower)->second) {
+ throw constant_interpolation(lower->first,next(lower)->first,lower->second);
+ }
+ double xdiff = next(lower)->first - lower->first;
+ double wdiff = next(lower)->second - lower->second;
+ double woffset = lower->second * next(lower)->first - next(lower)->second * lower->first;
+ return (xdiff/wdiff)*(f - woffset/xdiff);
+ }
+
+
+ template<class OStream>
+ void linear_interpolator::put(OStream& os) const {
+ os << interpolation_.size();
+ ostream_traits<OStream>::separator(os);
+ for (std::map<double, double>::const_iterator p
+ = interpolation_.begin(); p != interpolation_.end(); ++p) {
+ os << p->first;
+ ostream_traits<OStream>::separator(os);
+ os << p->second;
+ ostream_traits<OStream>::separator(os);
+ }
+ os << range_.first;
+ ostream_traits<OStream>::separator(os);
+ os << range_.second;
+ ostream_traits<OStream>::separator(os);
+ }
+
+ template<class IStream>
+ void linear_interpolator::get(IStream& is) {
+ std::size_t size;
+ is >> size;
+ std::pair<double,double> point;
+ for (std::size_t k = 0; k < size; ++k) {
+ is >> point.first >> point.second;
+ interpolation_.insert(point);
+ }
+ is >> range_.first >> range_.second;
+ }
+
+}
diff --git a/Exsample2/exsample/selectors.h b/Exsample2/exsample/selectors.h
new file mode 100644
--- /dev/null
+++ b/Exsample2/exsample/selectors.h
@@ -0,0 +1,201 @@
+// -*- C++ -*-
+//
+// selectors.h is part of ExSample -- A Library for Sampling Sudakov-Type Distributions
+//
+// Copyright (C) 2008-2011 Simon Platzer -- simon.plaetzer@desy.de
+//
+// ExSample is licenced under version 2 of the GPL, see COPYING for details.
+// Please respect the MCnet academic guidelines, see GUIDELINES for details.
+//
+//
+#ifndef EXSAMPLE_selectors_h_included
+#define EXSAMPLE_selectors_h_included
+
+#include "cell.h"
+
+namespace exsample {
+
+ /// \brief flat sampling selector
+ template<class Random>
+ struct sampling_selector {
+
+ /// the default constructor
+ sampling_selector()
+ : rnd_gen(), compensate(false) {}
+
+ /// the standard constructor
+ explicit sampling_selector(const Random& r, bool comp = true)
+ : rnd_gen(r), compensate(comp) {}
+
+ /// return which of the children cells should be considered
+ std::pair<bool,bool> use(cell& parent,
+ const cell& first_child,
+ const cell& second_child) const;
+
+ /// return true, if the leaf cell should be considered
+ bool use(cell& leaf) const;
+
+ /// The random number generator to be used
+ Random rnd_gen;
+
+ /// Whether or not compensation is needed
+ bool compensate;
+
+ };
+
+ /// \brief selector selecting only bins
+ /// which contain the given parameter point
+ class parametric_selector {
+
+ public:
+
+ /// the default constructor
+ parametric_selector ()
+ : point_(), sampled_variables_() {}
+
+ /// construct from reference to point and flags to sample variables
+ parametric_selector(std::vector<double> * point,
+ const std::vector<bool>& sample)
+ : point_(point), sampled_variables_(sample) {}
+
+ public:
+
+ /// return which of the children cells should be considered
+ std::pair<bool,bool> use(const cell& parent,
+ const cell&,
+ const cell&) const;
+
+ /// return true, if the leaf cell should be considered
+ bool use(const cell&) const { return true; }
+
+ private:
+
+ /// the point chosen
+ std::vector<double> * point_;
+
+ /// flags for variables to be sampled
+ std::vector<bool> sampled_variables_;
+
+ };
+
+ /// \brief sampling selector selecting only bins
+ /// which contain the given parameter point
+ template<class Random>
+ class parametric_sampling_selector {
+
+ public:
+
+ /// the default constructor
+ parametric_sampling_selector()
+ : point_(), bin_id_(),
+ sampled_variables_(), rnd_gen_(),
+ compensate_(false) {}
+
+ /// construct from reference to point, subtree hash, flags of
+ /// variables to be sampled, and random number generator
+ parametric_sampling_selector(std::vector<double> * p,
+ bit_container<parameter_hash_bits> * bin_id,
+ const std::vector<bool>& sample,
+ const Random& rnd_gen)
+ : point_(p), bin_id_(bin_id),
+ sampled_variables_(sample), rnd_gen_(rnd_gen),
+ compensate_(false) {}
+
+ public:
+
+ /// return which of the children cells should be considered
+ std::pair<bool,bool> use(cell& parent,
+ const cell& first_child,
+ const cell& second_child) const;
+
+ /// return true, if the leaf cell should be considered
+ bool use(cell& leaf) const;
+
+ /// indicate that compensation is to take place
+ void compensate (bool doit = true) { compensate_ = doit; }
+
+ private:
+
+ /// the point chosen
+ std::vector<double> * point_;
+
+ /// the corresponding bin id
+ bit_container<parameter_hash_bits> * bin_id_;
+
+ /// flags for variables to be sampled
+ std::vector<bool> sampled_variables_;
+
+ /// the random number generator
+ Random rnd_gen_;
+
+ /// wether or not compensation is needed
+ bool compensate_;
+
+ };
+
+ /// \brief accessor returning the integral of a cell
+ struct integral_accessor {
+
+ /// update and return the value
+ double& set(cell& node) const {
+ return node.integral();
+ }
+
+ /// get the value
+ double get(const cell& node, bool) const {
+ return node.integral();
+ }
+
+ };
+
+ /// \brief accessor returning the number of missing events
+ struct missing_accessor {
+
+ /// update and return the value
+ int& set(cell& node) const {
+ return node.missing_events();
+ }
+
+ /// get the value
+ int get(const cell& node, bool) const {
+ return node.missing_events();
+ }
+
+ };
+
+ /// \brief accessor returning the number of missing events
+ /// for given parameter bin id
+ struct parametric_missing_accessor {
+
+ /// the default constructor
+ parametric_missing_accessor ()
+ : id_() {}
+
+ /// construct from subtree hash to consider
+ explicit parametric_missing_accessor (bit_container<parameter_hash_bits>* id)
+ : id_ (id) {}
+
+ /// update and return the value
+ int& set(cell& node) const {
+ return node.missing_events();
+ }
+
+ /// get the value
+ int get(const cell& node, bool isleaf) const {
+ if (isleaf)
+ return node.info().parametric_missing(*id_);
+ return node.missing_events();
+ }
+
+ private:
+
+ /// the subtree hash to consider
+ bit_container<parameter_hash_bits>* id_;
+
+ };
+
+}
+
+#include "selectors.icc"
+
+#endif // EXSAMPLE_selectors_h_included
diff --git a/Exsample2/exsample/selectors.icc b/Exsample2/exsample/selectors.icc
new file mode 100644
--- /dev/null
+++ b/Exsample2/exsample/selectors.icc
@@ -0,0 +1,133 @@
+// -*- C++ -*-
+//
+// selectors.icc is part of ExSample -- A Library for Sampling Sudakov-Type Distributions
+//
+// Copyright (C) 2008-2011 Simon Platzer -- simon.plaetzer@desy.de
+//
+// ExSample is licenced under version 2 of the GPL, see COPYING for details.
+// Please respect the MCnet academic guidelines, see GUIDELINES for details.
+//
+//
+namespace exsample {
+
+ template<class Random>
+ std::pair<bool,bool> sampling_selector<Random>::use(cell& parent,
+ const cell& first_child,
+ const cell& second_child) const {
+ std::pair<bool,bool> selected (false,false);
+ if (compensate) {
+ if (first_child.missing_events() > 0 && second_child.missing_events() <= 0) {
+ selected.first = true;
+ --parent.missing_events();
+ return selected;
+ }
+ if (first_child.missing_events() <= 0 && second_child.missing_events() > 0) {
+ selected.second = true;
+ --parent.missing_events();
+ return selected;
+ }
+ if (first_child.missing_events() > 0 && second_child.missing_events() > 0) {
+ if (first_child.integral()/parent.integral() > rnd_gen())
+ selected.first = true;
+ else
+ selected.second = true;
+ --parent.missing_events();
+ return selected;
+ }
+ }
+ if (first_child.integral()/parent.integral() > rnd_gen())
+ selected.first = true;
+ else
+ selected.second = true;
+ return selected;
+ }
+
+ template<class Random>
+ bool sampling_selector<Random>::use(cell& leaf) const {
+ if (compensate) {
+ if (leaf.missing_events() < 0) {
+ ++leaf.missing_events();
+ return false;
+ }
+ if (leaf.missing_events() > 0)
+ --leaf.missing_events();
+ }
+ return true;
+ }
+
+ inline std::pair<bool,bool> parametric_selector::use(const cell& parent,
+ const cell&,
+ const cell&) const {
+ std::pair<bool,bool> match_para (true,true);
+ if (!sampled_variables_[parent.split_dimension()]) {
+ match_para.first = (parent.split_point() > (*point_)[parent.split_dimension()]);
+ match_para.second = (parent.split_point() <= (*point_)[parent.split_dimension()]);
+ }
+ return match_para;
+ }
+
+ template<class Random>
+ std::pair<bool,bool> parametric_sampling_selector<Random>::use(cell& parent,
+ const cell& first_child,
+ const cell& second_child) const {
+ std::pair<bool,bool> match_para (true,true);
+ std::pair<bool,bool> selected (false,false);
+ if (!sampled_variables_[parent.split_dimension()]) {
+ match_para.first = (parent.split_point() > (*point_)[parent.split_dimension()]);
+ match_para.second = (parent.split_point() <= (*point_)[parent.split_dimension()]);
+ }
+ if (match_para.first && match_para.second) {
+ if (compensate_) {
+ if (first_child.missing_events() > 0 && second_child.missing_events() <= 0) {
+ selected.first = true;
+ --parent.missing_events();
+ return selected;
+ }
+ if (first_child.missing_events() <= 0 && second_child.missing_events() > 0) {
+ selected.second = true;
+ --parent.missing_events();
+ return selected;
+ }
+
+ if (first_child.missing_events() > 0 && second_child.missing_events() > 0) {
+ if (first_child.integral()/parent.integral() > rnd_gen_())
+ selected.first = true;
+ else
+ selected.second = true;
+ --parent.missing_events();
+ return selected;
+ }
+ }
+ if (first_child.integral()/parent.integral() > rnd_gen_())
+ selected.first = true;
+ else
+ selected.second = true;
+ return selected;
+ }
+ assert(match_para.first || match_para.second);
+ if (compensate_)
+ if ((match_para.first && first_child.missing_events() > 0) ||
+ (match_para.second && second_child.missing_events() > 0))
+ --parent.missing_events();
+ return match_para;
+ }
+
+ template<class Random>
+ bool parametric_sampling_selector<Random>::use (cell& leaf) const {
+ if (compensate_) {
+ long pmissing = leaf.info().parametric_missing(*bin_id_);
+ assert(leaf.missing_events() == pmissing);
+ if (pmissing < 0) {
+ leaf.info().increase_parametric_missing(*bin_id_);
+ ++leaf.missing_events();
+ return false;
+ }
+ if (pmissing > 0) {
+ leaf.info().decrease_parametric_missing(*bin_id_);
+ --leaf.missing_events();
+ }
+ }
+ return true;
+ }
+
+}
diff --git a/Exsample2/exsample/statistics.h b/Exsample2/exsample/statistics.h
new file mode 100644
--- /dev/null
+++ b/Exsample2/exsample/statistics.h
@@ -0,0 +1,151 @@
+// -*- C++ -*-
+//
+// statistics.h is part of ExSample -- A Library for Sampling Sudakov-Type Distributions
+//
+// Copyright (C) 2008-2011 Simon Platzer -- simon.plaetzer@desy.de
+//
+// ExSample is licenced under version 2 of the GPL, see COPYING for details.
+// Please respect the MCnet academic guidelines, see GUIDELINES for details.
+//
+//
+#ifndef EXSAMPLE_statistics_h_included
+#define EXSAMPLE_statistics_h_included
+
+#include "utility.h"
+
+namespace exsample {
+
+ /// \brief statistics is a helper class for keeping track of event
+ /// generation statistics.
+ class statistics {
+
+ public:
+
+ /// default constructor
+ statistics();
+
+ /// update the statistics for a weight encountered during
+ /// presampling
+ void presampled(double weight);
+
+ /// indicate that a weight has been selected; optionally preven
+ /// the weight from entering the caluclation of the integral
+ void select(double weight,
+ bool calculate_integral = true);
+
+ /// indicate that a point has been accepted
+ void accept(double weight) {
+ ++accepted_;
+ if (weight < 0) ++accepted_negative_;
+ }
+
+ /// reject a prviously accepted event
+ void reject(double weight) {
+ --accepted_;
+ if (weight < 0) --accepted_negative_;
+ }
+
+ /// reset the statistics object
+ void reset();
+
+ /// return the integral's estimate and its uncertainty at the
+ /// currently accumulated statistics
+ std::pair<double,double> current() const;
+
+ /// the average weight
+ double average_weight() const {
+ return (n_iterations_ == 0 ? 0. : average_weight_/n_iterations_);
+ }
+
+ /// the average absolute weight
+ double average_abs_weight() const {
+ return (n_iterations_ == 0 ? 0. : average_abs_weight_/n_iterations_);
+ }
+
+ /// the variance of the weight
+ double average_weight_variance() const {
+ return (n_iterations_ == 0 ? 0. : average_weight_variance_/n_iterations_);
+ }
+
+ /// the number of points in this iteration
+ unsigned long iteration_points() const { return iteration_points_; }
+
+ /// the number of iterations
+ unsigned long n_iterations() const { return n_iterations_; }
+
+ /// the total number of attempted in this bin
+ unsigned long attempted() const { return attempted_; }
+
+ /// the total number of finally accepted events in this bin
+ unsigned long accepted() const { return accepted_; }
+
+ /// the total number of acceptet events with negative weights
+ unsigned long accepted_negative() const { return accepted_negative_; }
+
+ /// the sum of weights
+ double sum_weights() const { return sum_weights_; }
+
+ /// the sum of absolute values of the weights
+ double sum_abs_weights() const { return sum_abs_weights_; }
+
+ /// the sum of weights squared
+ double sum_weights_squared() const { return sum_weights_squared_; }
+
+ /// the maximum weight
+ double max_weight() const { return max_weight_; }
+
+ public:
+
+ /// put ostream
+ template<class OStream>
+ void put(OStream& os) const;
+
+ /// get from istream
+ template<class IStream>
+ void get(IStream& is);
+
+ private:
+
+ /// the average weight
+ double average_weight_;
+
+ /// the average absolute weight
+ double average_abs_weight_;
+
+ /// the variance of the weight
+ double average_weight_variance_;
+
+ /// the number of points in this iteration
+ unsigned long iteration_points_;
+
+ /// the total number of attempted in this bin
+ unsigned long attempted_;
+
+ /// the total number of finally accepted events in this bin
+ unsigned long accepted_;
+
+ /// the total number of acceptet events with negative weights
+ unsigned long accepted_negative_;
+
+ /// the sum of weights
+ double sum_weights_;
+
+ /// the sum of absolute values of the weights
+ double sum_abs_weights_;
+
+ /// the sum of weights squared
+ double sum_weights_squared_;
+
+ /// the maximum weight
+ double max_weight_;
+
+ /// the number of iterations used to calculate the integral
+ unsigned long n_iterations_;
+
+ };
+
+}
+
+#include "statistics.icc"
+
+#endif // EXSAMPLE_statistics_h_included
diff --git a/Exsample2/exsample/statistics.icc b/Exsample2/exsample/statistics.icc
new file mode 100644
--- /dev/null
+++ b/Exsample2/exsample/statistics.icc
@@ -0,0 +1,108 @@
+// -*- C++ -*-
+//
+// statistics.icc is part of ExSample -- A Library for Sampling Sudakov-Type Distributions
+//
+// Copyright (C) 2008-2011 Simon Platzer -- simon.plaetzer@desy.de
+//
+// ExSample is licenced under version 2 of the GPL, see COPYING for details.
+// Please respect the MCnet academic guidelines, see GUIDELINES for details.
+//
+//
+namespace exsample {
+
+ inline statistics::statistics()
+ : average_weight_(0.), average_abs_weight_(0.), average_weight_variance_(-1.),
+ iteration_points_(0),
+ attempted_(0), accepted_(0), accepted_negative_(0),
+ sum_weights_(0.), sum_abs_weights_(0.), sum_weights_squared_(0.),
+ max_weight_(0.), n_iterations_(0) {
+ }
+
+ inline void statistics::presampled(double weight) {
+ ++iteration_points_;
+ sum_weights_ += weight;
+ sum_abs_weights_ += std::abs(weight);
+ sum_weights_squared_ += sqr(weight);
+ max_weight_ = std::max(max_weight_,std::abs(weight));
+ }
+
+ inline void statistics::select(double weight,
+ bool calculate_integral) {
+ ++attempted_;
+ if (calculate_integral) {
+ ++iteration_points_;
+ sum_weights_ += weight;
+ sum_abs_weights_ += std::abs(weight);
+ sum_weights_squared_ += sqr(weight);
+ max_weight_ = std::max(max_weight_,std::abs(weight));
+ }
+ }
+
+ inline void statistics::reset() {
+ if (iteration_points_ == 0)
+ return;
+ double average = sum_weights_/iteration_points_;
+ double average_abs = sum_abs_weights_/iteration_points_;
+ double variance =
+ std::abs(sum_weights_squared_/iteration_points_ - sqr(sum_weights_/iteration_points_)) /
+ iteration_points_;
+ if (n_iterations_ == 0 ||
+ std::sqrt(variance)/average <= std::sqrt(average_weight_variance_)/average_weight_) {
+
+ if (n_iterations_ > 0) {
+ average_weight_ = average_weight_ + average;
+ average_abs_weight_ = average_abs_weight_ + average_abs;
+ average_weight_variance_ = average_weight_variance_ + variance;
+ } else {
+ average_weight_ = average;
+ average_abs_weight_ = average_abs;
+ average_weight_variance_ = variance;
+ }
+ ++n_iterations_;
+ }
+ sum_weights_ = 0.;
+ sum_abs_weights_ = 0.;
+ sum_weights_squared_ = 0.;
+ iteration_points_ = 0;
+ }
+
+ inline std::pair<double,double> statistics::current() const {
+ double average = sum_weights_/iteration_points_;
+ double variance =
+ std::abs(sum_weights_squared_/iteration_points_ - sqr(sum_weights_/iteration_points_)) /
+ iteration_points_;
+ std::pair<double,double> res;
+ if (n_iterations_ > 0) {
+ res.first = average_weight_ + average;
+ res.second = average_weight_variance_ + variance;
+ } else {
+ res.first = average;
+ res.second = variance;
+ }
+ res.first = (n_iterations_ == 0 ? 0. : res.first/n_iterations_);
+ res.second = (n_iterations_ == 0 ? 0. : res.second/n_iterations_);
+ return res;
+ }
+
+
+ template<class OStream>
+ void statistics::put(OStream& os) const {
+ os << average_weight_;
+ ostream_traits<OStream>::separator(os);
+ os << average_abs_weight_;
+ ostream_traits<OStream>::separator(os);
+ os << average_weight_variance_;
+ ostream_traits<OStream>::separator(os);
+ os << n_iterations_;
+ ostream_traits<OStream>::separator(os);
+ }
+
+ template<class IStream>
+ void statistics::get(IStream& is) {
+ is >> average_weight_
+ >> average_abs_weight_
+ >> average_weight_variance_
+ >> n_iterations_;
+ }
+
+}
diff --git a/Exsample2/exsample/utility.h b/Exsample2/exsample/utility.h
new file mode 100644
--- /dev/null
+++ b/Exsample2/exsample/utility.h
@@ -0,0 +1,322 @@
+// -*- C++ -*-
+//
+// utility.h is part of ExSample -- A Library for Sampling Sudakov-Type Distributions
+//
+// Copyright (C) 2008-2011 Simon Platzer -- simon.plaetzer@desy.de
+//
+// ExSample is licenced under version 2 of the GPL, see COPYING for details.
+// Please respect the MCnet academic guidelines, see GUIDELINES for details.
+//
+//
+#ifndef EXSAMPLE_utility_h_included
+#define EXSAMPLE_utility_h_included
+
+#include "config.h"
+
+namespace exsample {
+
+ /// \brief Compile time conversion of unsigned long to bool
+ template<unsigned long>
+ struct static_binary {
+ enum { value = 1 };
+ };
+
+ /// \brief Compile time conversion of unsigned long to bool
+ template<>
+ struct static_binary<0> {
+ enum { value = 0 };
+ };
+
+ /// \brief Fixed-size, packed vector of bools
+ template<unsigned long bits>
+ struct bit_container {
+
+ enum {
+ /// the number of bits contained
+ n_bits = bits,
+ /// the number of bits fitting in a unsigned long
+ uint_bits = CHAR_BIT * sizeof(unsigned long),
+ /// the number of unsigned long segments needed
+ n_segments = bits / uint_bits + static_binary<bits % uint_bits>::value
+ };
+
+
+ /// the default constructor
+ bit_container() {
+ for (std::size_t i = 0; i < n_segments; ++i)
+ segments[i] = 0;
+ }
+
+ /// put all values to false
+ void reset() {
+ for (std::size_t i = 0; i < n_segments; ++i)
+ segments[i] = 0;
+ }
+
+ /// compare for equality
+ bool operator==(const bit_container& x) const {
+ for (std::size_t i = 0; i < n_segments; ++i)
+ if(segments[i] != x.segments[i])
+ return false;
+ return true;
+ }
+
+ /// compare for ordering
+ bool operator<(const bit_container& x) const {
+ for (std::size_t i = 0; i < n_segments; ++i)
+ if(segments[i] != x.segments[i])
+ return (segments[i] < x.segments[i]);
+ return false;
+ }
+
+ /// set the k'th bit
+ void bit(unsigned long k, bool value) {
+ assert(k<n_bits);
+ if (value)
+ segments[n_segments-k/uint_bits-1] |= (1ul << (k % uint_bits));
+ else
+ segments[n_segments-k/uint_bits-1] &= ~(1ul << (k % uint_bits));
+ }
+
+ /// get the k'th bit
+ bool bit(unsigned long k) {
+ assert(k<n_bits);
+ return (segments[n_segments-k/uint_bits-1] & (1ul << (k % uint_bits)));
+ }
+
+ /// print to ostream
+ template<class OStream>
+ void dump(OStream& os) const {
+ for ( unsigned int k = 0; k < n_segments; ++k )
+ os << segments[k] << " ";
+ }
+
+ private:
+
+ /// segments needed to keep the hash value
+ unsigned long segments[n_segments];
+
+ };
+
+ /// \brief square a number
+ template<class T>
+ T sqr(T x) {
+ return x*x;
+ }
+
+ /// \brief cube a number
+ template<class T>
+ T cube(T x) {
+ return x*x*x;
+ }
+
+
+ /// \brief Round a floating point value to an integer value of the
+ /// same type.
+ template<class T>
+ T round(T x) {
+ T f = std::floor(x);
+ T c = std::ceil(x);
+ if (x < (f+c)/2.)
+ return f;
+ return c;
+ }
+
+ /// \brief Calculate fast powers of two.
+ inline std::size_t two_to(std::size_t n) {
+ assert(n <= sizeof(std::size_t)*CHAR_BIT);
+ return (1 << n);
+ }
+
+ /// \brief separate quantities written to an ostream
+ template<class OStream>
+ struct ostream_traits {
+
+ /// put the separator to the ostream
+ static void separator(OStream& os) { os << "\n"; }
+
+ };
+
+#ifdef EXSAMPLE_has_ThePEG
+
+ /// \brief separate quantities written to a ThePEG::PersistentOStream
+ template<>
+ struct ostream_traits<ThePEG::PersistentOStream> {
+
+ /// put the separator to the ostream
+ static void separator(ThePEG::PersistentOStream&) { }
+
+ };
+
+#endif // EXSAMPLE_has_ThePEG
+
+ /// \brief Fast, zero memory-overhead one-dimensional
+ /// histogram with 2^n equally spaced bins
+ template<class Statistics>
+ struct fast_small_histogram {
+
+ /// default constructor
+ fast_small_histogram()
+ : depth(0), bins(0) {}
+
+ /// copy constructor
+ fast_small_histogram(const fast_small_histogram& x)
+ : depth(x.depth), bins(0) {
+ if (x.bins) {
+ bins.reset(new Statistics[two_to(depth)]);
+ for(std::size_t k = 0; k < two_to(depth); ++k)
+ bins[k] = x.bins[k];
+ }
+ }
+
+ /// assignment
+ fast_small_histogram& operator=(const fast_small_histogram& x) {
+ if (&x == this)
+ return *this;
+ depth = x.depth;
+ bins.reset(0);
+ if (x.bins) {
+ bins.reset(new Statistics[two_to(depth)]);
+ for(std::size_t k = 0; k < two_to(depth); ++k)
+ bins[k] = x.bins[k];
+ }
+ return *this;
+ }
+
+ /// construct from depth d, creating 2^d bins
+ explicit fast_small_histogram(std::size_t d)
+ : depth(d), bins(0) {
+ bins.reset(new Statistics[two_to(d)]);
+ }
+
+ /// return the bin from event belongs to given outer boundaries
+ Statistics& bin(double lower,
+ double upper,
+ double event) {
+ double thelower = lower;
+ double theupper = upper;
+ std::size_t bindex = 0;
+ std::size_t current_depth = 0;
+ while (true) {
+ double cut
+ = (thelower+theupper)/2.;
+ if (event < cut) {
+ theupper = cut;
+ } else {
+ thelower = cut;
+ bindex += two_to(depth-current_depth-1);
+ }
+ if(++current_depth == depth)
+ break;
+ }
+ return bins[bindex];
+ }
+
+ /// the depth, defining a histogram of 2^depth bins
+ std::size_t depth;
+
+ /// the contained statistics objects
+ boost::scoped_array<Statistics> bins;
+
+ /// put histogram to an ostream
+ template<class OStream>
+ void put(OStream& os) const {
+ os << depth;
+ ostream_traits<OStream>::separator(os);
+ for (std::size_t k = 0; k < two_to(depth); ++k) {
+ bins[k].put(os);
+ }
+ }
+
+ /// get histogram from an istream
+ template<class IStream>
+ void get(IStream& is) {
+ is >> depth;
+ bins.reset(new Statistics[two_to(depth)]);
+ for(std::size_t k = 0; k < two_to(depth); ++k) {
+ bins[k].get(is);
+ }
+ }
+
+ };
+
+ /// \brief Generalize the transform algorithm to only apply
+ /// depending on a range of flags accompanying the input range
+ template<class FirstInputIterator,
+ class SecondInputIterator,
+ class FlagIterator,
+ class OutputIterator,
+ class BinaryOperation>
+ OutputIterator conditional_transform(FirstInputIterator first1,
+ FirstInputIterator last1,
+ SecondInputIterator first2,
+ FlagIterator firstf,
+ OutputIterator result,
+ BinaryOperation binary_op) {
+ for (; first1 != last1; ++first1, ++first2, ++firstf, ++result)
+ if (*firstf)
+ *result = binary_op(*first1, *first2);
+ return result;
+ }
+
+ /// \brief calculate a volume given lower left and upper right
+ /// corners
+ inline double volume(const std::vector<double>& lower_left,
+ const std::vector<double>& upper_right) {
+ std::vector<double> delta;
+ std::transform(upper_right.begin(),upper_right.end(),
+ lower_left.begin(),std::back_inserter(delta),
+ std::minus<double>());
+ return
+ std::accumulate(delta.begin(),delta.end(),1.,std::multiplies<double>());
+ }
+
+ /// \brief calculate a volume given lower left and upper right
+ /// corners, taking into account only part of the dimensions, which
+ /// are flagged with true in the correspponding random access
+ /// container
+ inline double volume(const std::vector<double>& lower_left,
+ const std::vector<double>& upper_right,
+ const std::vector<bool>& flags) {
+ std::vector<double> delta;
+ conditional_transform(upper_right.begin(),upper_right.end(),
+ lower_left.begin(),flags.begin(),
+ std::back_inserter(delta),
+ std::minus<double>());
+ return
+ std::accumulate(delta.begin(),delta.end(),1.,std::multiplies<double>());
+ }
+
+
+ /// \brief Exception thrown if the maximum number of attempts to
+ /// select a cell has been reached.
+ struct selection_maxtry{};
+
+ /// \brief Exception thrown, if the maximum number of misses has
+ /// been reached.
+ struct hit_and_miss_maxtry{};
+
+ /// \brief Random generator traits.
+ template<class Random>
+ struct rnd_generator {
+
+ ///Generate uniform random number on [0,1]
+ double operator()() const {
+ return Random::rnd();
+ }
+
+ ///Generate uniform random number on [0,a]
+ double operator()(double a) const {
+ return a*Random::rnd();
+ }
+
+ ///Generate uniform random number on [a,b]
+ double operator()(double a, double b) const {
+ return (a + (b-a)*Random::rnd());
+ }
+
+ };
+
+}
+
+#endif // EXSAMPLE_utility_h_included
diff --git a/Exsample2/exsampler.cc b/Exsample2/exsampler.cc
new file mode 100644
--- /dev/null
+++ b/Exsample2/exsampler.cc
@@ -0,0 +1,312 @@
+// -*- C++ -*-
+
+// exsample2/exsampler.cc is part of matchbox
+// (C) 2008 Simon Platzer -- sp@particle.uni-karlsruhe.de
+
+#include "exsampler.h"
+#include "ThePEG/Interface/ClassDocumentation.h"
+#include "ThePEG/Interface/Parameter.h"
+
+#include "ThePEG/Handlers/StandardXComb.h"
+#include "ThePEG/PDT/ParticleData.h"
+
+#include "ThePEG/Persistency/PersistentOStream.h"
+#include "ThePEG/Persistency/PersistentIStream.h"
+
+#include <sstream>
+
+using namespace matchbox;
+using namespace exsample;
+
+exsampler::exsampler()
+ : presampling_points_(2000),
+ freeze_grid_(0),
+ efficiency_threshold_(.95),
+ gain_threshold_(.1),
+ samplers_(), eg_wrappers_(),
+ bin_selector_(), integrals_(),
+ missing_events_(), oversampling_bins_(),
+ sum_weights_(0),
+ integral_(0.), integral_abs_(0.), variance_(0.),
+ max_integral_(0.), last_bin_(-1),
+ last_weight_(0.) {}
+
+exsampler::~exsampler() {}
+
+ThePEG::IBPtr exsampler::clone() const {
+ return ThePEG::new_ptr(*this);
+}
+
+ThePEG::IBPtr exsampler::fullclone() const {
+ return ThePEG::new_ptr(*this);
+}
+
+std::string exsampler::process(int bin) const {
+ std::ostringstream os("");
+ const ThePEG::StandardEventHandler& eh = *eventHandler();
+ const ThePEG::StandardXComb& xc = *eh.xCombs()[bin];
+ os << xc.mePartonData()[0]->PDGName() << " "
+ << xc.mePartonData()[1]->PDGName() << " -> ";
+ for ( ThePEG::cPDVector::const_iterator pid =
+ xc.mePartonData().begin() + 2;
+ pid != xc.mePartonData().end(); ++pid )
+ os << (**pid).PDGName() << " ";
+ return os.str();
+}
+
+void exsampler::dofinish() {
+ ThePEG::SamplerBase::dofinish();
+
+ integral_ = 0.;
+ integral_abs_ = 0.;
+ variance_ = 0.;
+ max_integral_ = 0.;
+
+ int b = 0;
+
+ bool compensating = false;
+
+ for (std::vector<sampler_type>::iterator s = samplers_.begin();
+ s != samplers_.end(); ++s, ++b) {
+
+ std::cout << "integrated cross section for "
+ << process(b) << "is ("
+ << samplers_[b].integral() << " +/- "
+ << samplers_[b].integral_uncertainty()
+ << ") nb"
+ << (s->compensating() ? " (*)" : "") << "\n";
+
+ if ( s->compensating() )
+ compensating = true;
+
+ s->finalize();
+ integral_ += s->integral();
+ integral_abs_ += std::abs(s->integral());
+ variance_ += s->integral_variance();
+ max_integral_ = std::max(max_integral_,s->integral());
+ }
+
+ std::cout << "integrated cross section is ("
+ << integral_ << " +/- "
+ << std::sqrt(variance_) << ") nb\n" << std::flush;
+
+ if ( compensating )
+ std::cout << "warning -- samplers marked with (*) are still in compensating mode\n" << std::flush;
+
+}
+
+void exsampler::doinitrun() {
+ ThePEG::SamplerBase::doinitrun();
+ initialize();
+}
+
+void exsampler::persistentOutput(ThePEG::PersistentOStream & os) const {
+ // *** ATTENTION *** os << ; // Add all member variable which should be written persistently here.
+ os << presampling_points_
+ << freeze_grid_ << efficiency_threshold_
+ << gain_threshold_ << samplers_.size();
+
+ for (std::vector<sampler_type>::const_iterator s = samplers_.begin();
+ s != samplers_.end(); ++s)
+ s->put(os);
+
+}
+
+void exsampler::persistentInput(ThePEG::PersistentIStream & is, int) {
+ // *** ATTENTION *** is >> ; // Add all member variable which should be read persistently here.
+ is >> presampling_points_
+ >> freeze_grid_ >> efficiency_threshold_
+ >> gain_threshold_;
+ std::size_t nsamplers;
+ is >> nsamplers;
+ samplers_.resize(nsamplers);
+
+ for (std::vector<sampler_type>::iterator s = samplers_.begin();
+ s != samplers_.end(); ++s)
+ s->get(is);
+
+}
+
+ThePEG::ClassDescription<exsampler> exsampler::initexsampler;
+// Definition of the static class description member.
+
+void exsampler::Init() {
+
+ static ThePEG::ClassDocumentation<exsampler> documentation
+ ("There is no documentation for the exsampler class");
+
+ static ThePEG::Parameter<exsampler,unsigned long> interfacepresampling_points
+ ("presampling_points",
+ "Set the number of presampling points per cell",
+ &exsampler::presampling_points_, 2000, 0, 0,
+ false, false, ThePEG::Interface::lowerlim);
+
+ static ThePEG::Parameter<exsampler,unsigned long> interfacefreeze_grid
+ ("freeze_grid",
+ "Set the number of events after which the grid should be frozen",
+ &exsampler::freeze_grid_, 0, 0, 0,
+ false, false, ThePEG::Interface::lowerlim);
+
+ static ThePEG::Parameter<exsampler,double> interfaceefficiency_threshold
+ ("efficiency_threshold",
+ "Set the efficiency threshold",
+ &exsampler::efficiency_threshold_, .95, 0., 1.,
+ false, false, ThePEG::Interface::limited);
+
+ static ThePEG::Parameter<exsampler,double> interfacegain_threshold
+ ("gain_threshold",
+ "Set the gain threshold",
+ &exsampler::gain_threshold_, .1, 0., 1.,
+ false, false, ThePEG::Interface::limited);
+
+}
+
+void exsampler::initialize() {
+
+ integral_ = 0.;
+ integral_abs_ = 0.;
+ variance_ = 0.;
+ max_integral_ = 0.;
+
+ if (samplers_.empty())
+ samplers_.resize(eventHandler()->nBins());
+
+ eg_wrappers_.resize(eventHandler()->nBins());
+ integrals_.resize(eventHandler()->nBins());
+ missing_events_.resize(eventHandler()->nBins(),0);
+
+ for (int b = 0; b < eventHandler()->nBins(); ++b) {
+
+ last_bin_ = b;
+
+ eg_wrappers_[b] = eg_exsample2_wrapper(b,eventHandler());
+ samplers_[b].function(&eg_wrappers_[b]);
+
+ samplers_[b].sampling_parameters().presampling_points = presampling_points_;
+ samplers_[b].sampling_parameters().freeze_grid = freeze_grid_;
+ samplers_[b].sampling_parameters().maxtry = eventHandler()->maxLoop();
+ samplers_[b].sampling_parameters().efficiency_threshold = efficiency_threshold_;
+ samplers_[b].sampling_parameters().gain_threshold = gain_threshold_;
+
+ samplers_[b].initialize(dummy_);
+ integrals_[b] = samplers_[b].integral();
+ integral_ += samplers_[b].integral();
+ integral_abs_ += std::abs(samplers_[b].integral());
+ variance_ += samplers_[b].integral_variance();
+ max_integral_ = std::max(max_integral_,samplers_[b].integral());
+
+ std::cout << "estimated cross section for " << process(b) << "is ("
+ << samplers_[b].integral() << " +/- "
+ << samplers_[b].integral_uncertainty()
+ << ") nb\n";
+
+ }
+
+ std::cout << "estimated cross section is ("
+ << integral_ << " +/- "
+ << std::sqrt(variance_) << ") nb\n" << std::flush;
+
+ double sum = 0.;
+
+ for (int b = 0; b < eventHandler()->nBins(); ++b) {
+ sum += std::abs(samplers_[b].integral());
+ bin_selector_.insert(std::make_pair(sum/integral_abs_,b));
+ }
+
+}
+
+void exsampler::update() {
+
+ double old_integral_abs = integral_abs_;
+ std::vector<double> old_integrals = integrals_;
+
+ integral_ = 0.;
+ integral_abs_ = 0.;
+ variance_ = 0.;
+ max_integral_ = 0.;
+
+ for (std::vector<sampler_type>::iterator s = samplers_.begin();
+ s != samplers_.end(); ++s) {
+
+ integral_ += s->integral();
+ integral_abs_ += std::abs(s->integral());
+ variance_ += s->integral_variance();
+ max_integral_ = std::max(max_integral_,s->integral());
+
+ }
+
+ bin_selector_.clear();
+
+ double sum = 0.;
+
+ for (int b = 0; b < eventHandler()->nBins(); ++b) {
+
+ sum += std::abs(samplers_[b].integral());
+ integrals_[b] = samplers_[b].integral();
+ bin_selector_.insert(std::make_pair(sum/integral_abs_,b));
+
+ long missing =
+ static_cast<long>(round(samplers_[b].stats().accepted()*
+ ((old_integral_abs * std::abs(integrals_[b])) /
+ (integral_abs_ * std::abs(old_integrals[b]))-1.)));
+
+ missing_events_[b] += missing;
+ if (missing_events_[b] > 0)
+ oversampling_bins_.insert(b);
+
+ }
+
+}
+
+double exsampler::generate() {
+
+ while (true) {
+
+ try {
+
+ if (oversampling_bins_.empty()) {
+ last_bin_ = bin_selector_.upper_bound(ThePEG::UseRandom::rnd())->second;
+ if (missing_events_[last_bin_] < 0) {
+ ++missing_events_[last_bin_];
+ continue;
+ }
+ } else {
+ last_bin_ = *oversampling_bins_.begin();
+ if (--missing_events_[last_bin_] == 0)
+ oversampling_bins_.erase(last_bin_);
+ }
+
+ last_weight_ = samplers_[last_bin_].generate(dummy_);
+ lastPoint() = samplers_[last_bin_].last_point();
+ break;
+
+ } catch (selection_maxtry&) {
+
+ throw maxtry_exception()
+ << "The maximum number of attempts to select a cell was exceeded\n"
+ << "for process " << process(last_bin_)
+ << ThePEG::Exception::eventerror;
+
+ } catch (hit_and_miss_maxtry&) {
+
+ throw maxtry_exception()
+ << "The maximum number of attempts to select an event was exceeded\n"
+ << "process " << process(last_bin_)
+ << ThePEG::Exception::eventerror;
+
+ } catch (generator_update&) {
+
+ update();
+ continue;
+
+ } catch (...) {
+ throw;
+ }
+
+ }
+
+ sum_weights_ += last_weight_;
+ return last_weight_;
+
+}
+
diff --git a/Exsample2/exsampler.h b/Exsample2/exsampler.h
new file mode 100644
--- /dev/null
+++ b/Exsample2/exsampler.h
@@ -0,0 +1,353 @@
+// -*- C++ -*-
+
+// exsample2/exsampler.h is part of matchbox
+// (C) 2008 Simon Platzer -- sp@particle.uni-karlsruhe.de
+
+#ifndef matchbox_exsample2_exsampler_h
+#define matchbox_exsample2_exsampler_h
+
+#include <map>
+
+#include "ThePEG/Handlers/SamplerBase.h"
+#include "ThePEG/Handlers/StandardEventHandler.h"
+#include "ThePEG/Utilities/Exception.h"
+#include "ThePEG/Repository/UseRandom.h"
+
+#include "exsample/generator.h"
+
+namespace matchbox {
+
+ /**
+ * exsample2 function interface conforming
+ * wrapper around standard event handler
+ */
+ struct eg_exsample2_wrapper {
+
+ inline eg_exsample2_wrapper ()
+ : bin_(-1), event_handler_() {}
+
+ inline eg_exsample2_wrapper (int b,
+ ThePEG::tStdEHPtr eh)
+ : bin_(b), event_handler_(eh) {}
+
+
+ /**
+ * Evaluate with given random numbers.
+ */
+ inline double evaluate (const std::vector<double>& p) const {
+ double ret;
+ try {
+ ret = event_handler_->dSigDR(p) / ThePEG::nanobarn;
+ } catch (ThePEG::Veto&) {
+ ret = 0.0;
+ } catch (...) {
+ throw;
+ }
+ return ret;
+ }
+
+ /**
+ * Return the dimensionality in random
+ * numbers needed to generate events
+ */
+ inline std::size_t dimension () const {
+ return event_handler_->nDim(bin_);
+ }
+
+ /**
+ * Return the lower left and upper right
+ * corners of the support of this function
+ */
+ inline std::pair<std::vector<double>,std::vector<double> > support () const {
+ std::vector<double> lower(dimension(),0.);
+ std::vector<double> upper(dimension(),1.);
+ return std::make_pair(lower,upper);
+ }
+
+ /**
+ * Indicate start of presampling
+ */
+ inline void start_presampling () { }
+
+ /**
+ * Indicate end of presampling
+ */
+ inline void stop_presampling () { }
+
+ private:
+
+ int bin_;
+ ThePEG::tStdEHPtr event_handler_;
+
+ };
+
+ /**
+ * Here is the documentation of the exsampler class.
+ *
+ * @see \ref exsamplerInterfaces "The interfaces"
+ * defined for exsampler.
+ */
+ class exsampler
+ : public ThePEG::SamplerBase {
+
+ public:
+
+ /** @name Standard constructors and destructors. */
+ //@{
+ /**
+ * The default constructor.
+ */
+ exsampler();
+
+ /**
+ * The destructor.
+ */
+ virtual ~exsampler();
+ //@}
+
+ public:
+
+ typedef exsample::generator<eg_exsample2_wrapper,ThePEG::UseRandom> sampler_type;
+
+ /** @name Virtual functions from SamplerBase. */
+ //@{
+ /**
+ * Initialize the the sampler, possibly doing presampling of the
+ * phase space.
+ */
+ virtual void initialize();
+
+ /**
+ * Generarate a new phase space point and return a weight associated
+ * with it. This weight should preferably be 1.
+ */
+ virtual double generate();
+
+ /**
+ * Reject the last chosen phase space point.
+ */
+ virtual inline void rejectLast() {
+ samplers_[last_bin_].reject();
+ sum_weights_ -= last_weight_;
+ }
+
+ /**
+ * If the sampler is able to sample several different functions
+ * separately, this function should return the last chosen
+ * function. This default version always returns 0.
+ */
+ virtual inline int lastBin() const { return last_bin_; }
+
+ /**
+ * Return the total integrated cross section determined from the
+ * Monte Carlo sampling so far.
+ */
+ virtual inline ThePEG::CrossSection integratedXSec() const {
+ return integral_ * ThePEG::nanobarn;
+ }
+
+ /**
+ * Return the error on the total integrated cross section determined
+ * from the Monte Carlo sampling so far.
+ */
+ virtual ThePEG::CrossSection integratedXSecErr() const {
+ return std::sqrt(variance_) * ThePEG::nanobarn;
+ }
+
+ /**
+ * Return the overestimated integrated cross section.
+ */
+ virtual ThePEG::CrossSection maxXSec() const {
+ return max_integral_ * ThePEG::nanobarn;
+ }
+
+ /**
+ * Return the sum of the weights returned by generate() so far (of
+ * the events that were not rejeted).
+ */
+ virtual inline double sumWeights() const { return sum_weights_; }
+ //@}
+
+ public:
+
+ /** @name Functions used by the persistent I/O system. */
+ //@{
+ /**
+ * Function used to write out object persistently.
+ * @name os the persistent output stream written to.
+ */
+ void persistentOutput(ThePEG::PersistentOStream & os) const;
+
+ /**
+ * Function used to read in object persistently.
+ * @name is the persistent input stream read from.
+ * @name version the version number of the object when written.
+ */
+ void persistentInput(ThePEG::PersistentIStream & is, int version);
+ //@}
+
+ /**
+ * The standard Init function used to initialize the interfaces.
+ * Called exactly once for each class by the class description system
+ * before the main function starts or
+ * when this class is dynamically loaded.
+ */
+ static void Init();
+
+ public:
+
+ struct maxtry_exception : public ThePEG::Exception {};
+
+ protected:
+
+ /** @name Standard Interfaced functions. */
+ //@{
+
+ /**
+ * Initialize this object. Called in the run phase just before
+ * a run begins.
+ */
+ virtual void doinitrun();
+
+ /**
+ * Finalize this object. Called in the run phase just after a
+ * run has ended. Used eg. to write out statistics.
+ */
+ virtual void dofinish();
+
+ //@}
+
+ protected:
+
+ /** @name Clone Methods. */
+ //@{
+ /**
+ * Make a simple clone of this object.
+ * @return a pointer to the new object.
+ */
+ virtual ThePEG::IBPtr clone() const;
+
+ /** Make a clone of this object, possibly modifying the cloned object
+ * to make it sane.
+ * @return a pointer to the new object.
+ */
+ virtual ThePEG::IBPtr fullclone() const;
+ //@}
+
+ private:
+
+ /// update integrals and stuff
+ void update ();
+
+ /// get process by bin id
+ std::string process(int bin) const;
+
+ ///@name interface helpers to adaption_info objects
+ //@{
+
+ unsigned long presampling_points_;
+
+ unsigned long freeze_grid_;
+
+ double efficiency_threshold_;
+
+ double gain_threshold_;
+
+ //@}
+
+ /// map bin ids to generators
+ std::vector<sampler_type> samplers_;
+
+ /// map bin ids to wrappers used
+ std::vector<eg_exsample2_wrapper> eg_wrappers_;
+
+ /// map used to select bins
+ std::map<double,int> bin_selector_;
+
+ /// current integrals of the bins
+ std::vector<double> integrals_;
+
+ /// map bins to number of missing events
+ std::vector<long> missing_events_;
+
+ /// bins which do need oversampling
+ std::set<int> oversampling_bins_;
+
+ /// the sum of accepted weights
+ double sum_weights_;
+
+ /// the total integrated corss section
+ double integral_;
+
+ /// sum of absoulte values of integrals
+ double integral_abs_;
+
+ /// the ucertainty on the integrated cross section
+ double variance_;
+
+ /// the maximum integrated cross section
+ double max_integral_;
+
+ /// the last selected bin
+ int last_bin_;
+
+ /// the last generated weight
+ double last_weight_;
+
+ /// dummy statistics to fix functionality required by rewrite
+ exsample::statistics dummy_;
+
+ private:
+
+ /**
+ * The static object used to initialize the description of this class.
+ * Indicates that this is an abstract class with persistent data.
+ */
+ static ThePEG::ClassDescription<exsampler> initexsampler;
+
+ /**
+ * The assignment operator is private and must never be called.
+ * In fact, it should not even be implemented.
+ */
+ exsampler & operator=(const exsampler &);
+
+ };
+
+}
+
+#include "ThePEG/Utilities/ClassTraits.h"
+
+namespace ThePEG {
+
+ /** @cond TRAITSPECIALIZATIONS */
+
+ /** This template specialization informs ThePEG about the
+ * base classes of exsampler. */
+ template <>
+ struct BaseClassTrait<matchbox::exsampler,1> {
+ /** Typedef of the first base class of exsampler. */
+ typedef ThePEG::SamplerBase NthBase;
+ };
+
+ /** This template specialization informs ThePEG about the name of
+ * the exsampler class and the shared object where it is defined. */
+ template <>
+ struct ClassTraits<matchbox::exsampler>
+ : public ClassTraitsBase<matchbox::exsampler> {
+ /** Return a platform-independent class name */
+ static string className() { return "matchbox::exsampler"; }
+ /**
+ * The name of a file containing the dynamic library where the class
+ * exsampler is implemented. It may also include several, space-separated,
+ * libraries if the class exsampler depends on other classes (base classes
+ * excepted). In this case the listed libraries will be dynamically
+ * linked in the order they are specified.
+ */
+ static string library() { return "HwExsample2.so"; }
+ };
+
+ /** @endcond */
+
+}
+
+#endif /* matchbox_exsample2_exsampler_h */

File Metadata

Mime Type
text/x-diff
Expires
Mon, Jan 20, 11:01 PM (1 d, 17 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
4242788
Default Alt Text
(133 KB)

Event Timeline