ATLAS Offline Software
conifer.h
Go to the documentation of this file.
1 #ifndef CONIFER_CPP_H__
2 #define CONIFER_CPP_H__
3 #include "nlohmann/json.hpp"
4 #include <cassert>
5 #include <fstream>
6 
7 namespace conifer {
8 
9 /* ---
10  * Balanced tree reduce implementation.
11  * Reduces an array of inputs to a single value using the template binary
12  * operator 'Op', for example summing all elements with Op_add, or finding the
13  * maximum with Op_max Use only when the input array is fully unrolled. Or,
14  * slice out a fully unrolled section before applying and accumulate the result
15  * over the rolled dimension. Required for emulation to guarantee equality of
16  * ordering.
17  * --- */
18 constexpr int floorlog2(int x) { return (x < 2) ? 0 : 1 + floorlog2(x / 2); }
19 
20 template <int B> constexpr int pow(int x) {
21  return x == 0 ? 1 : B * pow<B>(x - 1);
22 }
23 
24 constexpr int pow2(int x) { return pow<2>(x); }
25 
26 template <class T, class Op> T reduce(std::vector<T> x, Op op) {
27  int N = x.size();
28  int leftN = pow2(floorlog2(N - 1)) > 0 ? pow2(floorlog2(N - 1)) : 0;
29  // static constexpr int rightN = N - leftN > 0 ? N - leftN : 0;
30  if (N == 1) {
31  return x.at(0);
32  } else if (N == 2) {
33  return op(x.at(0), x.at(1));
34  } else {
35  std::vector<T> left(x.begin(), x.begin() + leftN);
36  std::vector<T> right(x.begin() + leftN, x.end());
37  return op(reduce<T, Op>(left, op), reduce<T, Op>(right, op));
38  }
39 }
40 
41 template <class T> class OpAdd {
42 public:
43  T operator()(T a, T b) { return a + b; }
44 };
45 
46 template <class T, class U> class DecisionTree {
47 
48 private:
49  std::vector<int> m_feature;
50  std::vector<int> m_children_left;
51  std::vector<int> m_children_right;
52  std::vector<T> m_threshold_;
53  std::vector<U> m_value_;
54  std::vector<double> m_threshold;
55  std::vector<double> m_value;
56 
57 public:
58  U decision_function(const std::vector<T>& x) const {
59  /* Do the prediction */
60  int i = 0;
61  while (m_feature[i] != -2) { // continue until reaching leaf
62  bool comparison = x[m_feature[i]] <= m_threshold_[i];
63  i = comparison ? m_children_left[i] : m_children_right[i];
64  }
65  return m_value_[i];
66  }
67 
68  void init_() {
69  /* Since T, U types may not be readable from the JSON, read them to double
70  * and the cast them here */
71  std::transform(m_threshold.begin(), m_threshold.end(),
72  std::back_inserter(m_threshold_),
73  [](double t) -> T { return (T)t; });
74  std::transform(m_value.begin(), m_value.end(), std::back_inserter(m_value_),
75  [](double v) -> U { return (U)v; });
76  }
77 
78  // Define how to read this class to/from JSON
79  friend void from_json(const nlohmann::json &j, DecisionTree &o) {
80  j.at("feature").get_to(o.m_feature);
81  j.at("children_left").get_to(o.m_children_left);
82  j.at("children_right").get_to(o.m_children_right);
83  j.at("threshold").get_to(o.m_threshold);
84  j.at("value").get_to(o.m_value);
85  }
86 
87 }; // class DecisionTree
88 
89 template <class T, class U, bool useAddTree = false> class BDT {
90 
91 private:
93  int m_n_trees;
95  std::vector<double> m_init_predict;
96  std::vector<U> m_init_predict_;
97  // vector of decision trees: outer dimension tree, inner dimension class
98  std::vector<std::vector<DecisionTree<T, U>>> m_trees;
100 
101 public:
102  void init(/*std::string filename*/) {
103  /* Construct the BDT from conifer cpp backend JSON file */
104  // std::ifstream ifs(filename);
105  // nlohmann::json j = nlohmann::json::parse(ifs);
106  // from_json(j, *this);
107  /* Do some transformation to initialise things into the proper emulation T,
108  * U types */
109  if (m_n_classes == 2)
110  m_n_classes = 1;
112  std::back_inserter(m_init_predict_),
113  [](double ip) -> U { return (U)ip; });
114  for (int i = 0; i < m_n_trees; i++) {
115  for (int j = 0; j < m_n_classes; j++) {
116  m_trees.at(i).at(j).init_();
117  }
118  }
119  }
120 
121  std::vector<U> decision_function(std::vector<T> x) const {
122  /* Do the prediction */
123  assert("Size of feature vector mismatches expected m_n_features" &&
124  x.size() == static_cast<size_t>(m_n_features));
125  std::vector<U> values;
126  std::vector<std::vector<U>> values_trees;
127  values_trees.resize(m_n_classes);
128  values.resize(m_n_classes, U(0));
129  for (int i = 0; i < m_n_classes; i++) {
131  m_trees.begin(), m_trees.end(),
132  std::back_inserter(values_trees.at(i)),
133  [&i, &x](auto tree_v) { return tree_v.at(i).decision_function(x); });
134  if (useAddTree) {
135  values.at(i) = m_init_predict_.at(i);
136  values.at(i) += reduce<U, OpAdd<U>>(values_trees.at(i), m_add);
137  } else {
138  values.at(i) =
139  std::accumulate(values_trees.at(i).begin(),
140  values_trees.at(i).end(), U(m_init_predict_.at(i)));
141  }
142  }
143 
144  return values;
145  }
146 
147  // Define how to read this class to/from JSON
148  friend void from_json(const nlohmann::json &j, BDT &o) {
149  j.at("n_classes").get_to(o.m_n_classes);
150  j.at("n_trees").get_to(o.m_n_trees);
151  j.at("n_features").get_to(o.m_n_features);
152  j.at("init_predict").get_to(o.m_init_predict);
153  j.at("trees").get_to(o.m_trees);
154  }
155 }; // class BDT
156 
157 } // namespace conifer
158 
159 #endif
conifer::DecisionTree::m_threshold_
std::vector< T > m_threshold_
Definition: conifer.h:52
conifer::BDT::from_json
friend void from_json(const nlohmann::json &j, BDT &o)
Definition: conifer.h:148
conifer::BDT::m_n_features
int m_n_features
Definition: conifer.h:94
conifer::DecisionTree::m_threshold
std::vector< double > m_threshold
Definition: conifer.h:54
json
nlohmann::json json
Definition: HistogramDef.cxx:9
conifer::DecisionTree::m_feature
std::vector< int > m_feature
Definition: conifer.h:49
accumulate
bool accumulate(AccumulateMap &map, std::vector< module_t > const &modules, FPGATrackSimMatrixAccumulator const &acc)
Accumulates an accumulator (e.g.
Definition: FPGATrackSimMatrixAccumulator.cxx:22
conifer::pow
constexpr int pow(int x)
Definition: conifer.h:20
conifer::OpAdd::operator()
T operator()(T a, T b)
Definition: conifer.h:43
conifer::DecisionTree::decision_function
U decision_function(const std::vector< T > &x) const
Definition: conifer.h:58
conifer
Definition: conifer.h:7
JetTiledMap::N
@ N
Definition: TiledEtaPhiMap.h:44
read_hist_ntuple.t
t
Definition: read_hist_ntuple.py:5
conifer::BDT::m_init_predict_
std::vector< U > m_init_predict_
Definition: conifer.h:96
conifer::DecisionTree::m_value
std::vector< double > m_value
Definition: conifer.h:55
x
#define x
python.Bindings.values
values
Definition: Control/AthenaPython/python/Bindings.py:805
conifer::floorlog2
constexpr int floorlog2(int x)
Definition: conifer.h:18
conifer::BDT::m_n_classes
int m_n_classes
Definition: conifer.h:92
conifer::pow2
constexpr int pow2(int x)
Definition: conifer.h:24
lumiFormat.i
int i
Definition: lumiFormat.py:85
conifer::BDT
Definition: conifer.h:89
conifer::BDT::decision_function
std::vector< U > decision_function(std::vector< T > x) const
Definition: conifer.h:121
Amg::transform
Amg::Vector3D transform(Amg::Vector3D &v, Amg::Transform3D &tr)
Transform a point from a Trasformation3D.
Definition: GeoPrimitivesHelpers.h:156
find_tgc_unfilled_channelids.ip
ip
Definition: find_tgc_unfilled_channelids.py:3
conifer::DecisionTree::m_value_
std::vector< U > m_value_
Definition: conifer.h:53
conifer::BDT::init
void init()
Definition: conifer.h:102
conifer::BDT::m_add
OpAdd< U > m_add
Definition: conifer.h:99
conifer::reduce
T reduce(std::vector< T > x, Op op)
Definition: conifer.h:26
plotBeamSpotMon.b
b
Definition: plotBeamSpotMon.py:77
conifer::DecisionTree::m_children_right
std::vector< int > m_children_right
Definition: conifer.h:51
conifer::BDT::m_n_trees
int m_n_trees
Definition: conifer.h:93
conifer::DecisionTree::from_json
friend void from_json(const nlohmann::json &j, DecisionTree &o)
Definition: conifer.h:79
conifer::DecisionTree::m_children_left
std::vector< int > m_children_left
Definition: conifer.h:50
python.PyAthena.v
v
Definition: PyAthena.py:154
conifer::OpAdd
Definition: conifer.h:41
a
TList * a
Definition: liststreamerinfos.cxx:10
conifer::DecisionTree
Definition: conifer.h:46
conifer::DecisionTree::init_
void init_()
Definition: conifer.h:68
conifer::BDT::m_trees
std::vector< std::vector< DecisionTree< T, U > > > m_trees
Definition: conifer.h:98
conifer::BDT::m_init_predict
std::vector< double > m_init_predict
Definition: conifer.h:95