value.hpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581
  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. * In order to enable proper provenance tracking, and at the same time keep
  58. * the ability to embed functions into values, the Function class should be
  59. * used. It is simply a wrapper around a std::function that also has a name.
  60. * This name is used when generating the name of values that use the function.
  61. * A function name is automatically prepended with "func::" to explicitly state
  62. * that the value is the result of a computation encoded within the function
  63. * object, and not from some other Value object. Unfortunately, it is up to the
  64. * user to find where that function is defined in the source code to inspect
  65. * what it is doing. But hopefully this isn't too onerous by just using grep.
  66. */
  67. template<typename> class Function; // undefined
  68. template <typename R, typename... ArgTypes>
  69. class Function<R(ArgTypes...)> {
  70. std::string name;
  71. std::function<R(ArgTypes...)> f;
  72. public:
  73. Function(const std::string& name, std::function<R(ArgTypes...)> f)
  74. :name("func::"+name),f(f){ }
  75. std::string& get_name(){
  76. return name;
  77. }
  78. R operator()(ArgTypes ...args){
  79. return f(args...);
  80. }
  81. };
  82. /**
  83. * A type-agnostic value.
  84. * It is necessary to create a type-agnostic parent class to Value so that
  85. * it is possible to handle collections of them. GenValue also provides the
  86. * rest of the type-independent interface to Value.
  87. */
  88. class GenValue;
  89. typedef std::map<std::string, GenValue*> ValueSet;
  90. class GenValue{
  91. private:
  92. /**
  93. * The name of the value.
  94. * This is used to allow for dynamic lookup of
  95. * values based on their name via GenValue::get_value.
  96. */
  97. std::string name;
  98. protected:
  99. /**
  100. * Mark the internal value as invalid. This is needed for DerivedValue
  101. * to force a recalculation of the internal value when a new
  102. * observation is loaded into memory. It is called automatically for
  103. * all GenValue objects when reset is called.
  104. */
  105. virtual void _reset() = 0;
  106. /**
  107. * A static mapping containing all created Value objects.
  108. * Every value object must have a unique name, and this name is used as
  109. * a key in values to that object. This is used to enable more dynamic
  110. * creation of objects as well as avoiding the uneccesary passing of
  111. * pointers.
  112. */
  113. inline static std::map<const std::string, GenValue*> values;
  114. inline static std::map<const std::string, GenValue*> aliases;
  115. public:
  116. GenValue(const std::string& name)
  117. :name(name) {
  118. values[name] = this;
  119. }
  120. const std::string& get_name(){
  121. return name;
  122. }
  123. static void reset(){
  124. for (auto val : values){
  125. val.second->_reset();
  126. }
  127. }
  128. static GenValue* get_value(const std::string& name){
  129. if (aliases[name] != NULL)
  130. return aliases[name];
  131. else if (values[name] != NULL)
  132. return values[name];
  133. else{
  134. std::cout << "ERROR: Could not find alias or value \"" << name << "\"" << std::endl;
  135. std::cout << "I'll tell you the ones I know about." << std::endl;
  136. summary();
  137. std::cout << "Aborting... :(" << std::endl;
  138. exit(-1);
  139. }
  140. }
  141. static void alias(const std::string& name, GenValue* value){
  142. if (aliases[name] != NULL){
  143. std::cout << "WARNING: alias \"" << name << "\" overrides previous entry." << std::endl;
  144. }
  145. aliases[name] = value;
  146. }
  147. static GenValue* alias(const std::string& name){
  148. if (values[name] != NULL){
  149. std::cout << "WARNING: alias \"" << name << "\" does not exist." << std::endl;
  150. }
  151. return aliases[name];
  152. }
  153. static void summary(){
  154. std::cout << "The following values have been created: " << std::endl;
  155. for (auto value : values){
  156. if (value.second == NULL) continue;
  157. std::cout << "\t\"" << value.first << "\" at address " << value.second << std::endl;
  158. }
  159. std::cout << "And these aliases:" << std::endl;
  160. for (auto alias : aliases){
  161. std::string orig("VOID");
  162. if (alias.second == NULL) continue;
  163. for (auto value : values){
  164. if (alias.second == value.second){
  165. orig = value.second->get_name();
  166. break;
  167. }
  168. }
  169. std::cout << "\t\"" << alias.first << "\" referring to \"" << orig << "\"" << std::endl;
  170. }
  171. }
  172. };
  173. /**
  174. * A generic value.
  175. * In order to facilitate run-time creation of analysis routines, it is
  176. * necessary to have some ability to get and store *values*. Values can either
  177. * be directly taken from some original data source (i.e. ObservedValue), or
  178. * they can be a function of some other set of values (i.e. DerivedValue). They
  179. * template class T of Value<T> is the type of thing that is returned upon
  180. * calling get_value().
  181. */
  182. template <typename T>
  183. class Value : public GenValue{
  184. public:
  185. Value(const std::string& name)
  186. :GenValue(name){ }
  187. /** Calculate, if necessary, and return the value held by this object.
  188. */
  189. virtual T& get_value() = 0;
  190. };
  191. /**
  192. * A generic, observed, value.
  193. * An ObservedValue is the interface to your dataset. Upon creation, an
  194. * ObservedValue is given a pointer to an object of type T. When an observation
  195. * is loaded into memory, the value at the location referenced by that pointer
  196. * must be updated with the associated data from that observation. This is the
  197. * responsibility of whatever DataSet implementation is being used. This object
  198. * then will read that data and return it when requested.
  199. */
  200. template <typename T>
  201. class ObservedValue : public Value<T>{
  202. private:
  203. T *val_ref;
  204. void _reset(){ }
  205. public:
  206. ObservedValue(const std::string& name, T* val_ref)
  207. :Value<T>(name),
  208. val_ref(val_ref){ }
  209. T& get_value(){
  210. return *val_ref;
  211. }
  212. };
  213. /**
  214. * A generic, derived, value.
  215. * A DerivedValue is generally defined as some function of other Value objects.
  216. * For example, a Pair is a function of two other Value objects that makes a
  217. * pair of them. Note that these other Value objects are free to be either
  218. * ObservedValues or other DerivedValues.
  219. *
  220. * It is desireable from a performance standpoint that each DerivedValue be
  221. * calculated no more than once per observation. Therefore, when a get_value is
  222. * called on a DerivedValue, it first checks whether the value that it holds is
  223. * **valid**, meaning it has already been calculated for this observation. If
  224. * so, it simply returns the value. If not, the update_value function is called
  225. * to calculate the value. and then the newly calculated value is marked as
  226. * valid and returned.
  227. */
  228. template <typename T>
  229. class DerivedValue : public Value<T>{
  230. private:
  231. void _reset(){
  232. value_valid = false;
  233. }
  234. protected:
  235. T value;
  236. bool value_valid;
  237. /**
  238. * Updates the internal value.
  239. * This function should be overridden by any child class to do the
  240. * actual work of updating value based on whatever rules the class
  241. * chooses. Normally, this consists of geting the values from some
  242. * associated Value objects, doing some calculation on them, and
  243. * storing the result in value.
  244. */
  245. virtual void update_value() = 0;
  246. public:
  247. DerivedValue(const std::string& name)
  248. :Value<T>(name),
  249. value_valid(false) { }
  250. T& get_value(){
  251. if (!value_valid){
  252. update_value();
  253. value_valid = true;
  254. }
  255. return value;
  256. }
  257. };
  258. /**
  259. * A std::vector wrapper around a C-style array.
  260. * In order to make some of the higher-level Value types easier to work with,
  261. * it is a good idea to wrap all arrays in the original data source with
  262. * std::vector objects. To do this, it is necessary to supply both a Value
  263. * object containing the array itself as well as another Value object
  264. * containing the size of that array. Currently, update_value will simply copy
  265. * the contents of the array into the interally held vector.
  266. * \todo avoid an unneccessary copy and set the vectors data directly.
  267. */
  268. template <typename T>
  269. class WrapperVector : public DerivedValue<std::vector<T> >{
  270. private:
  271. Value<int>* size;
  272. Value<T*>* data;
  273. void update_value(){
  274. int n = size->get_value();
  275. T* data_ref = data->get_value();
  276. this->value.resize(n);
  277. for (int i=0; i<n; i++){
  278. this->value[i] = *(data_ref+i);
  279. }
  280. }
  281. public:
  282. WrapperVector(Value<int>* size, Value<T*>* data)
  283. :DerivedValue<std::vector<T> >("vectorOf("+size->get_name()+","+data->get_name()+")"),
  284. size(size), data(data){ }
  285. WrapperVector(const std::string &label_size, const std::string &label_data)
  286. :WrapperVector(dynamic_cast<Value<int>*>(GenValue::values.at(label_size)),
  287. dynamic_cast<Value<T*>*>(GenValue::values.at(label_data))) { }
  288. };
  289. /**
  290. * Creates a std::pair type from a two other Value objects.
  291. */
  292. template <typename T1, typename T2>
  293. class Pair : public DerivedValue<std::pair<T1, T2> >{
  294. protected:
  295. std::pair<Value<T1>*, Value<T2>* > value_pair;
  296. void update_value(){
  297. this->value.first = value_pair.first->get_value();
  298. this->value.second = value_pair.second->get_value();
  299. }
  300. public:
  301. Pair(Value<T1> *value1, Value<T2> *value2)
  302. :DerivedValue<std::pair<T1, T2> >("pair("+value1->get_name()+","+value2->get_name()+")"),
  303. value_pair(value1, value2){ }
  304. Pair(const std::string& label1, const std::string& label2)
  305. :Pair(dynamic_cast<Value<T1>*>(GenValue::values.at(label1)),
  306. dynamic_cast<Value<T1>*>(GenValue::values.at(label2))){ }
  307. };
  308. /**
  309. * Takes a set of four Value<std::vector<T> > objects and a function of four Ts
  310. * and returns a std::vector<R>. This is used in, for instance, calculating the
  311. * energy of a set of particles when one has separate arrays containing pt,
  312. * eta, phi, and mass. These arrays are first wrapped up in VectorWrappers and
  313. * then passes along with a function to calculate the energy into a ZipMapFour.
  314. * The result of this calculation is a new vector containing the energy for
  315. * each particle. Note that if the input vectors are not all the same size,
  316. * calculations are only performed up to the size of the shortest.
  317. * \see MiniTreeDataSet
  318. * \todo find way to implement for arbitrary number(and possibly type) of
  319. * vector inputs.
  320. */
  321. template <typename R, typename T>
  322. class ZipMapFour : public DerivedValue<std::vector<R> >{
  323. private:
  324. Function<R(T, T, T, T)> f;
  325. Value<std::vector<T> >* v1;
  326. Value<std::vector<T> >* v2;
  327. Value<std::vector<T> >* v3;
  328. Value<std::vector<T> >* v4;
  329. void update_value(){
  330. std::vector<T> v1_val = v1->get_value();
  331. std::vector<T> v2_val = v2->get_value();
  332. std::vector<T> v3_val = v3->get_value();
  333. std::vector<T> v4_val = v4->get_value();
  334. int n;
  335. std::tie(n, std::ignore) = std::minmax({v1_val.size(), v2_val.size(), v3_val.size(), v4_val.size()});
  336. this->value.resize(n);
  337. for (int i=0; i<n; i++){
  338. this->value[i] = f(v1_val[i], v2_val[i], v3_val[i], v4_val[i]);
  339. }
  340. }
  341. public:
  342. ZipMapFour(Function<R(T, T, T, T)> f,
  343. Value<std::vector<T> >* v1, Value<std::vector<T> >* v2,
  344. Value<std::vector<T> >* v3, Value<std::vector<T> >* v4)
  345. :DerivedValue<std::vector<R> >("zipmap("+f.get_name()+":"+v1->get_name()+","+v2->get_name()+","+v3->get_name()+","+v4->get_name()+")"),
  346. f(f), v1(v1), v2(v2), v3(v3), v4(v4) { }
  347. ZipMapFour(Function<R(T, T, T, T)> f,
  348. const std::string &label1, const std::string &label2,
  349. const std::string &label3, const std::string &label4)
  350. :ZipMapFour(f,
  351. dynamic_cast<Value<std::vector<T> >*>(GenValue::values.at(label1)),
  352. dynamic_cast<Value<std::vector<T> >*>(GenValue::values.at(label2)),
  353. dynamic_cast<Value<std::vector<T> >*>(GenValue::values.at(label3)),
  354. dynamic_cast<Value<std::vector<T> >*>(GenValue::values.at(label4))){ }
  355. };
  356. /**
  357. * Reduce a Value of type vector<T> to just a T.
  358. * This is useful functionality to model, for instance, calculating the maximum
  359. * element of a vector, or a the mean. See child classes for specific
  360. * implementations.
  361. */
  362. template <typename T>
  363. class Reduce : public DerivedValue<T>{
  364. private:
  365. Function<T(std::vector<T>)> reduce;
  366. Value<std::vector<T> >* v;
  367. void update_value(){
  368. this->value = reduce(v->get_value());
  369. }
  370. public:
  371. Reduce(Function<T(std::vector<T>)> reduce, Value<std::vector<T> >* v)
  372. :DerivedValue<T>("reduceWith("+reduce.get_name()+":"+v->get_name()+")"),
  373. reduce(reduce), v(v) { }
  374. Reduce(Function<T(std::vector<T>)> reduce, const std::string& v_name)
  375. :Reduce(reduce, dynamic_cast<Value<std::vector<T> >*>(GenValue::get_value(v_name))) { }
  376. };
  377. /**
  378. * Find and return the maximum value of a vector.
  379. */
  380. template <typename T>
  381. class Max : public Reduce<T>{
  382. public:
  383. Max(const std::string& v_name)
  384. :Reduce<T>(Function<T(std::vector<T>)>("max", [](std::vector<T> vec){
  385. return *std::max_element(vec.begin(), vec.end());}),
  386. v_name) { }
  387. };
  388. /**
  389. * Find and return the minimum value of a vector.
  390. */
  391. template <typename T>
  392. class Min : public Reduce<T>{
  393. public:
  394. Min(const std::string& v_name)
  395. :Reduce<T>(Function<T(std::vector<T>)>("min", [](std::vector<T> vec){
  396. return *std::min_element(vec.begin(), vec.end());}),
  397. v_name) { }
  398. };
  399. /**
  400. * Calculate the mean value of a vector.
  401. */
  402. template <typename T>
  403. class Mean : public Reduce<T>{
  404. public:
  405. Mean(const std::string& v_name)
  406. :Reduce<T>(Function<T(std::vector<T>)>("mean", [](std::vector<T> vec){
  407. int n = 0; T sum = 0;
  408. for (T e : vec){ n++; sum += e; }
  409. return n>0 ? sum / n : 0; }),
  410. v_name) { }
  411. };
  412. /**
  413. * Extract the element at a specific index from a vector.
  414. */
  415. template <typename T>
  416. class ElementOf : public Reduce<T>{
  417. public:
  418. ElementOf(Value<int>* index, const std::string& v_name)
  419. :Reduce<T>(Function<T(std::vector<T>)>("elementOf", [index](std::vector<T> vec){return vec[index->get_value()];}),
  420. v_name) { }
  421. ElementOf(const std::string& name, int index, const std::string& v_name)
  422. :Reduce<T>(name, [index](std::vector<T> vec){return vec[index];}, v_name) { }
  423. };
  424. /**
  425. * Similar to Reduce, but returns a pair of a T and an int.
  426. * This is useful if you need to know where in the vector exists the element
  427. * being returned.
  428. */
  429. template <typename T>
  430. class ReduceIndex : public DerivedValue<std::pair<T, int> >{
  431. private:
  432. Function<std::pair<T,int>(std::vector<T>)> reduce;
  433. Value<std::vector<T> >* v;
  434. void update_value(){
  435. this->value = reduce(v->get_value());
  436. }
  437. public:
  438. ReduceIndex(Function<std::pair<T,int>(std::vector<T>)> reduce, Value<std::vector<T> >* v)
  439. :DerivedValue<T>("reduceIndexWith("+reduce.get_name()+":"+v->get_name()+")"),
  440. reduce(reduce), v(v) { }
  441. ReduceIndex(Function<std::pair<T,int>(std::vector<T>)> reduce, const std::string& v_name)
  442. :ReduceIndex(reduce, dynamic_cast<Value<std::vector<T> >*>(GenValue::get_value(v_name))) { }
  443. };
  444. /**
  445. * Find and return the maximum value of a vector and its index.
  446. */
  447. template <typename T>
  448. class MaxIndex : public ReduceIndex<T>{
  449. public:
  450. MaxIndex(const std::string& v_name)
  451. :ReduceIndex<T>(Function<T(std::vector<T>)>("maxIndex", [](std::vector<T> vec){
  452. auto elptr = std::max_element(vec.begin(), vec.end());
  453. return std::pair<T,int>(*elptr, int(elptr-vec.begin()));}),
  454. v_name) { }
  455. };
  456. /**
  457. * Find and return the minimum value of a vector and its index.
  458. */
  459. template <typename T>
  460. class MinIndex : public ReduceIndex<T>{
  461. public:
  462. MinIndex(const std::string& v_name)
  463. :ReduceIndex<T>(Function<T(std::vector<T>)>("minIndex", [](std::vector<T> vec){
  464. auto elptr = std::min_element(vec.begin(), vec.end());
  465. return std::pair<T,int>(*elptr, int(elptr-vec.begin()));}),
  466. v_name) { }
  467. };
  468. /**
  469. * A variadic
  470. */
  471. /* template <typename R, typename... T> */
  472. /* class MultiFunc : public DerivedValue<R>{ */
  473. /* private: */
  474. /* Function<R(T...)> f; */
  475. /* std::tuple<T...> value_tuple; */
  476. /* void update_value(){ */
  477. /* this->value = f(value_tuple); */
  478. /* } */
  479. /* public: */
  480. /* MultiFunc(const std::string& name, Function<R(std::tuple<T...>)> f, T... varargs) */
  481. /* :DerivedValue<R>(name), */
  482. /* f(f), */
  483. /* value_tuple(varargs...){ } */
  484. /* }; */
  485. /**
  486. * A generic value owning only a function object.
  487. * All necessary values upon which this value depends must be bound to the
  488. * function object.
  489. */
  490. template <typename T>
  491. class BoundValue : public DerivedValue<T>{
  492. protected:
  493. Function<T()> f;
  494. void update_value(){
  495. this->value = f();
  496. }
  497. public:
  498. BoundValue(Function<T()> f)
  499. :DerivedValue<T>(f.get_name()+"(<bound>)"),
  500. f(f) { }
  501. };
  502. /**
  503. * A Value of a pointer. The pointer is constant, however the data the pointer
  504. * points to is variable.
  505. */
  506. template <typename T>
  507. class PointerValue : public DerivedValue<T*>{
  508. protected:
  509. void update_value(){ }
  510. public:
  511. PointerValue(const std::string& name, T* ptr)
  512. :DerivedValue<T*>(name){
  513. this->value = ptr;
  514. }
  515. };
  516. /**
  517. * A Value which always returns the same value, supplied in the constructor.
  518. */
  519. template <typename T>
  520. class ConstantValue : public DerivedValue<T>{
  521. protected:
  522. T const_value;
  523. void update_value(){
  524. this->value = const_value;
  525. }
  526. public:
  527. ConstantValue(const std::string& name, T const_value)
  528. :DerivedValue<T>("const::"+name),
  529. const_value(const_value) { }
  530. };
  531. }
  532. #endif // value_hpp