value.hpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494
  1. /**
  2. * @file
  3. * @author Caleb Fangmeier <caleb@fangmeier.tech>
  4. * @version 0.1
  5. *
  6. * @section LICENSE
  7. *
  8. *
  9. * MIT License
  10. *
  11. * Copyright (c) 2017 Caleb Fangmeier
  12. *
  13. * Permission is hereby granted, free of charge, to any person obtaining a copy
  14. * of this software and associated documentation files (the "Software"), to deal
  15. * in the Software without restriction, including without limitation the rights
  16. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  17. * copies of the Software, and to permit persons to whom the Software is
  18. * furnished to do so, subject to the following conditions:
  19. *
  20. * The above copyright notice and this permission notice shall be included in all
  21. * copies or substantial portions of the Software.
  22. *
  23. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  24. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  25. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  26. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  27. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  28. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  29. * SOFTWARE.
  30. *
  31. * @section DESCRIPTION
  32. * This header defines a set of generic classes that wrap up "values". In
  33. * essence, a Value<T> object is just something that contains a value of type T
  34. * and can provide it when requested. The usefulness stems from composing
  35. * values together with calculations. This enables very clear dependency
  36. * mapping and a way to know clearly how every value was arrived at. This could
  37. * be used to, for example, automatically generate commentary for plots that
  38. * explain the exect calculation used to create it. Or easily making a series
  39. * of plots contrasting different values that have been composed slightly
  40. * differently.
  41. */
  42. #ifndef value_hpp
  43. #define value_hpp
  44. #include <iostream>
  45. #include <utility>
  46. #include <algorithm>
  47. #include <map>
  48. #include <vector>
  49. #include <tuple>
  50. #include <initializer_list>
  51. #include <functional>
  52. /**
  53. * The namespace containing all filval classes and functions.
  54. */
  55. namespace filval{
  56. /**
  57. * A type-agnostic value.
  58. * It is necessary to create a type-agnostic parent class to Value so that
  59. * it is possible to handle collections of them. GenValue also provides the
  60. * rest of the type-independent interface to Value.
  61. */
  62. class GenValue{
  63. private:
  64. /**
  65. * The name of the value.
  66. * This is used to allow for dynamic lookup of
  67. * values based on their name via GenValue::get_value.
  68. */
  69. std::string name;
  70. protected:
  71. /**
  72. * Mark the internal value as invalid. This is needed for DerivedValue
  73. * to force a recalculation of the internal value when a new
  74. * observation is loaded into memory. It is called automatically for
  75. * all GenValue objects when reset is called.
  76. */
  77. virtual void _reset() = 0;
  78. /**
  79. * A static mapping containing all created Value objects.
  80. * Every value object must have a unique name, and this name is used as
  81. * a key in values to that object. This is used to enable more dynamic
  82. * creation of objects as well as avoiding the uneccesary passing of
  83. * pointers.
  84. */
  85. inline static std::map<const std::string, GenValue*> values;
  86. public:
  87. GenValue(const std::string& name)
  88. :name(name) {
  89. values[name] = this;
  90. }
  91. const std::string& get_name(){
  92. return name;
  93. }
  94. static void reset(){
  95. for (auto val : values){
  96. val.second->_reset();
  97. }
  98. }
  99. static GenValue* get_value(const std::string& name){
  100. return values.at(name);
  101. }
  102. static void summary(){
  103. std::cout << "The following values have been created: " << std::endl;
  104. for (auto value : values){
  105. std::cout << "\t\"" << value.first << "\" at address " << value.second << std::endl;
  106. }
  107. }
  108. };
  109. typedef std::map<std::string, GenValue*> ValueSet;
  110. /**
  111. * A generic value.
  112. * In order to facilitate run-time creation of analysis routines, it is
  113. * necessary to have some ability to get and store *values*. Values can either
  114. * be directly taken from some original data source (i.e. ObservedValue), or
  115. * they can be a function of some other set of values (i.e. DerivedValue). They
  116. * template class T of Value<T> is the type of thing that is returned upon
  117. * calling get_value().
  118. */
  119. template <typename T>
  120. class Value : public GenValue{
  121. public:
  122. Value(const std::string& name)
  123. :GenValue(name){ }
  124. /** Calculate, if necessary, and return the value held by this object.
  125. */
  126. virtual T& get_value() = 0;
  127. };
  128. /**
  129. * A generic, observed, value.
  130. * An ObservedValue is the interface to your dataset. Upon creation, an
  131. * ObservedValue is given a pointer to an object of type T. When an observation
  132. * is loaded into memory, the value at the location referenced by that pointer
  133. * must be updated with the associated data from that observation. This is the
  134. * responsibility of whatever DataSet implementation is being used. This object
  135. * then will read that data and return it when requested.
  136. */
  137. template <typename T>
  138. class ObservedValue : public Value<T>{
  139. private:
  140. T *val_ref;
  141. void _reset(){ }
  142. public:
  143. ObservedValue(const std::string& name, T* val_ref)
  144. :Value<T>(name),
  145. val_ref(val_ref){ }
  146. T& get_value(){
  147. return *val_ref;
  148. }
  149. };
  150. /**
  151. * A generic, derived, value.
  152. * A DerivedValue is generally defined as some function of other Value objects.
  153. * For example, a Pair is a function of two other Value objects that makes a
  154. * pair of them. Note that these other Value objects are free to be either
  155. * ObservedValues or other DerivedValues.
  156. *
  157. * It is desireable from a performance standpoint that each DerivedValue be
  158. * calculated no more than once per observation. Therefore, when a get_value is
  159. * called on a DerivedValue, it first checks whether the value that it holds is
  160. * **valid**, meaning it has already been calculated for this observation. If
  161. * so, it simply returns the value. If not, the update_value function is called
  162. * to calculate the value. and then the newly calculated value is marked as
  163. * valid and returned.
  164. */
  165. template <typename T>
  166. class DerivedValue : public Value<T>{
  167. private:
  168. void _reset(){
  169. value_valid = false;
  170. }
  171. protected:
  172. T value;
  173. bool value_valid;
  174. /**
  175. * Updates the internal value.
  176. * This function should be overridden by any child class to do the
  177. * actual work of updating value based on whatever rules the class
  178. * chooses. Normally, this consists of geting the values from some
  179. * associated Value objects, doing some calculation on them, and
  180. * storing the result in value.
  181. */
  182. virtual void update_value() = 0;
  183. public:
  184. DerivedValue(const std::string& name)
  185. :Value<T>(name),
  186. value_valid(false) { }
  187. T& get_value(){
  188. if (!value_valid){
  189. update_value();
  190. value_valid = true;
  191. }
  192. return value;
  193. }
  194. };
  195. /**
  196. * A std::vector wrapper around a C-style array.
  197. * In order to make some of the higher-level Value types easier to work with,
  198. * it is a good idea to wrap all arrays in the original data source with
  199. * std::vector objects. To do this, it is necessary to supply both a Value
  200. * object containing the array itself as well as another Value object
  201. * containing the size of that array. Currently, update_value will simply copy
  202. * the contents of the array into the interally held vector.
  203. * \todo avoid an unneccessary copy and set the vectors data directly.
  204. */
  205. template <typename T>
  206. class WrapperVector : public DerivedValue<std::vector<T> >{
  207. private:
  208. Value<int>* size;
  209. Value<T*>* data;
  210. void update_value(){
  211. int n = size->get_value();
  212. T* data_ref = data->get_value();
  213. this->value.resize(n);
  214. for (int i=0; i<n; i++){
  215. this->value[i] = *(data_ref+i);
  216. }
  217. }
  218. public:
  219. WrapperVector(const std::string& name, Value<int>* _size, Value<T*>* _data)
  220. :DerivedValue<std::vector<T> >(name),
  221. size(_size), data(_data){ }
  222. WrapperVector(const std::string& name, const std::string &label_size, const std::string &label_data)
  223. :WrapperVector(name,
  224. dynamic_cast<Value<int>*>(GenValue::values.at(label_size)),
  225. dynamic_cast<Value<T*>*>(GenValue::values.at(label_data))) { }
  226. };
  227. /**
  228. * Creates a std::pair type from a two other Value objects.
  229. */
  230. template <typename T1, typename T2>
  231. class Pair : public DerivedValue<std::pair<T1, T2> >{
  232. protected:
  233. std::pair<Value<T1>*, Value<T2>* > value_pair;
  234. void update_value(){
  235. this->value.first = value_pair.first->get_value();
  236. this->value.second = value_pair.second->get_value();
  237. }
  238. public:
  239. Pair(const std::string name, Value<T1> *value1, Value<T2> *value2)
  240. :DerivedValue<std::pair<T1, T2> >(name),
  241. value_pair(value1, value2){ }
  242. Pair(const std::string& name, const std::string& label1, const std::string& label2)
  243. :Pair(name,
  244. dynamic_cast<Value<T1>*>(GenValue::values.at(label1)),
  245. dynamic_cast<Value<T1>*>(GenValue::values.at(label2))){ }
  246. };
  247. /**
  248. * Takes a set of four Value<std::vector<T> > objects and a function of four Ts
  249. * and returns a std::vector<R>. This is used in, for instance, calculating the
  250. * energy of a set of particles when one has separate arrays containing pt,
  251. * eta, phi, and mass. These arrays are first wrapped up in VectorWrappers and
  252. * then passes along with a function to calculate the energy into a ZipMapFour.
  253. * The result of this calculation is a new vector containing the energy for
  254. * each particle. Note that if the input vectors are not all the same size,
  255. * calculations are only performed up to the size of the shortest.
  256. * \see MiniTreeDataSet
  257. * \todo find way to implement for arbitrary number(and possibly type) of
  258. * vector inputs.
  259. */
  260. template <typename R, typename T>
  261. class ZipMapFour : public DerivedValue<std::vector<R> >{
  262. private:
  263. std::function<R(T, T, T, T)> f;
  264. Value<std::vector<T> >* v1;
  265. Value<std::vector<T> >* v2;
  266. Value<std::vector<T> >* v3;
  267. Value<std::vector<T> >* v4;
  268. void update_value(){
  269. std::vector<T> v1_val = v1->get_value();
  270. std::vector<T> v2_val = v2->get_value();
  271. std::vector<T> v3_val = v3->get_value();
  272. std::vector<T> v4_val = v4->get_value();
  273. int n;
  274. std::tie(n, std::ignore) = std::minmax({v1_val.size(), v2_val.size(), v3_val.size(), v4_val.size()});
  275. this->value.resize(n);
  276. for (int i=0; i<n; i++){
  277. this->value[i] = f(v1_val[i], v2_val[i], v3_val[i], v4_val[i]);
  278. }
  279. }
  280. public:
  281. ZipMapFour(const std::string& name, std::function<R(T, T, T, T)> f,
  282. Value<std::vector<T> >* v1, Value<std::vector<T> >* v2,
  283. Value<std::vector<T> >* v3, Value<std::vector<T> >* v4)
  284. :DerivedValue<std::vector<R> >(name),
  285. f(f), v1(v1), v2(v2), v3(v3), v4(v4) { }
  286. ZipMapFour(const std::string& name,
  287. std::function<R(T, T, T, T)> f,
  288. const std::string &label1, const std::string &label2,
  289. const std::string &label3, const std::string &label4)
  290. :ZipMapFour(name, f,
  291. dynamic_cast<Value<std::vector<T> >*>(GenValue::values.at(label1)),
  292. dynamic_cast<Value<std::vector<T> >*>(GenValue::values.at(label2)),
  293. dynamic_cast<Value<std::vector<T> >*>(GenValue::values.at(label3)),
  294. dynamic_cast<Value<std::vector<T> >*>(GenValue::values.at(label4))){ }
  295. };
  296. /**
  297. * Reduce a Value of type vector<T> to just a T.
  298. * This is useful functionality to model, for instance, calculating the maximum
  299. * element of a vector, or a the mean. See child classes for specific
  300. * implementations.
  301. */
  302. template <typename T>
  303. class Reduce : public DerivedValue<T>{
  304. private:
  305. std::function<T(std::vector<T>)> reduce;
  306. Value<std::vector<T> >* v;
  307. void update_value(){
  308. this->value = reduce(v->get_value());
  309. }
  310. public:
  311. Reduce(const std::string& name, std::function<T(std::vector<T>)> reduce, Value<std::vector<T> >* v)
  312. :DerivedValue<T>(name),
  313. reduce(reduce), v(v) { }
  314. Reduce(const std::string& name, std::function<T(std::vector<T>)> reduce, const std::string& v_name)
  315. :Reduce(name, reduce, dynamic_cast<Value<std::vector<T> >*>(GenValue::get_value(v_name))) { }
  316. };
  317. /**
  318. * Find and return the maximum value of a vector.
  319. */
  320. template <typename T>
  321. class Max : public Reduce<T>{
  322. public:
  323. Max(const std::string& name, const std::string& v_name)
  324. :Reduce<T>(name, [](std::vector<T> vec){ return std::max(vec.begin(), vec.end());}, v_name) { }
  325. };
  326. /**
  327. * Find and return the minimum value of a vector.
  328. */
  329. template <typename T>
  330. class Min : public Reduce<T>{
  331. public:
  332. Min(const std::string& name, const std::string& v_name)
  333. :Reduce<T>(name, [](std::vector<T> vec){ return std::min(vec.begin(), vec.end());}, v_name) { }
  334. };
  335. /**
  336. * Calculate the mean value of a vector.
  337. */
  338. template <typename T>
  339. class Mean : public Reduce<T>{
  340. public:
  341. Mean(const std::string& name, const std::string& v_name)
  342. :Reduce<T>(name,
  343. [](std::vector<T> vec){
  344. int n = 0; T sum = 0;
  345. for (T e : vec){ n++; sum += e; }
  346. return n>0 ? sum / n : 0; },
  347. v_name) { }
  348. };
  349. /**
  350. * Extract the element at a specific index from a vector.
  351. */
  352. template <typename T>
  353. class ElementOf : public Reduce<T>{
  354. public:
  355. ElementOf(const std::string& name, Value<int>* index, const std::string& v_name)
  356. :Reduce<T>(name, [index](std::vector<T> vec){return vec[index->get_value()];}, v_name) { }
  357. ElementOf(const std::string& name, int index, const std::string& v_name)
  358. :Reduce<T>(name, [index](std::vector<T> vec){return vec[index];}, v_name) { }
  359. };
  360. /**
  361. * Similar to Reduce, but returns a pair of a T and an int.
  362. * This is useful if you need to know where in the vector exists the element
  363. * being returned.
  364. */
  365. template <typename T>
  366. class ReduceIndex : public DerivedValue<std::pair<T, int> >{
  367. private:
  368. std::function<std::pair<T,int>(std::vector<T>)> reduce;
  369. Value<std::vector<T> >* v;
  370. void update_value(){
  371. this->value = reduce(v->get_value());
  372. }
  373. public:
  374. ReduceIndex(const std::string& name, std::function<std::pair<T,int>(std::vector<T>)> reduce, Value<std::vector<T> >* v)
  375. :DerivedValue<T>(name),
  376. reduce(reduce), v(v) { }
  377. ReduceIndex(const std::string& name, std::function<std::pair<T,int>(std::vector<T>)> reduce, const std::string& v_name)
  378. :ReduceIndex(name, reduce, dynamic_cast<Value<std::vector<T> >*>(GenValue::get_value(v_name))) { }
  379. };
  380. /**
  381. * Find and return the maximum value of a vector and its index.
  382. */
  383. template <typename T>
  384. class MaxIndex : public ReduceIndex<T>{
  385. public:
  386. MaxIndex(const std::string& name, const std::string& v_name)
  387. :ReduceIndex<T>(name,
  388. [](std::vector<T> vec){
  389. auto elptr = std::max_element(vec.begin(), vec.end());
  390. return std::pair<T,int>(*elptr, int(elptr-vec.begin()));},
  391. v_name) { }
  392. };
  393. /**
  394. * Find and return the minimum value of a vector and its index.
  395. */
  396. template <typename T>
  397. class MinIndex : public ReduceIndex<T>{
  398. public:
  399. MinIndex(const std::string& name, const std::string& v_name)
  400. :ReduceIndex<T>(name,
  401. [](std::vector<T> vec){
  402. auto elptr = std::min_element(vec.begin(), vec.end());
  403. return std::pair<T,int>(*elptr, int(elptr-vec.begin()));},
  404. v_name) { }
  405. };
  406. /**
  407. * A variadic
  408. */
  409. template <typename R, typename... T>
  410. class MultiFunc : public DerivedValue<R>{
  411. private:
  412. std::function<R(T...)> f;
  413. std::tuple<T...> value_tuple;
  414. void update_value(){
  415. this->value = f(value_tuple);
  416. }
  417. public:
  418. MultiFunc(const std::string& name, std::function<R(std::tuple<T...>)> f, T... varargs)
  419. :DerivedValue<R>(name),
  420. f(f),
  421. value_tuple(varargs...){ }
  422. };
  423. /**
  424. * A generic value owning only a function object.
  425. * All necessary values upon which this value depends must be bound to the
  426. * function object.
  427. */
  428. template <typename T>
  429. class BoundValue : public DerivedValue<T>{
  430. protected:
  431. std::function<T()> f;
  432. void update_value(){
  433. this->value = f();
  434. }
  435. public:
  436. BoundValue(const std::string& name, std::function<T()> f)
  437. :DerivedValue<T>(name),
  438. f(f) { }
  439. };
  440. /**
  441. * A Value which always returns the same value, supplied in the constructor.
  442. */
  443. template <typename T>
  444. class ConstantValue : public DerivedValue<T>{
  445. protected:
  446. T const_value;
  447. void update_value(){
  448. this->value = const_value;
  449. }
  450. public:
  451. ConstantValue(const std::string& name, T const_value)
  452. :DerivedValue<T>(name),
  453. const_value(const_value) { }
  454. };
  455. }
  456. #endif // value_hpp