Belle II Software  light-2212-foldex
select_subset.cc
1 /**************************************************************************
2  * basf2 (Belle II Analysis Software Framework) *
3  * Author: The Belle II Collaboration *
4  * *
5  * See git log for contributors and copyright holders. *
6  * This file is licensed under LGPL-3.0, see LICENSE.md. *
7  **************************************************************************/
8 #include <framework/datastore/SelectSubset.h>
9 #include <framework/datastore/StoreArray.h>
10 #include <framework/datastore/RelationsObject.h>
11 #include <framework/datastore/RelationArray.h>
12 
13 
14 #include <gtest/gtest.h>
15 
16 #include <string>
17 #include <vector>
18 #include <cstdlib>
19 #include <iostream>
20 #include <map>
21 #include <unordered_map>
22 #include <algorithm>
23 
24 using namespace std;
25 using namespace Belle2;
26 
27 
28 namespace {
30  class SelectSubsetTest : public ::testing::Test {
31 
32  public:
33 
34  using KeyElementType = UInt_t;
35  using StoredElement = RelationsObject;
36 
37 
38  static bool SelectionCriterium(const KeyElementType a)
39  {
40  // The elements whose UniqueID is prime are selected (well, if the UniqueID
41  // is equal or greather than 1369 the sieve is too coarse)
42  return (a % 2) != 0 && (a % 3) != 0 && (a % 5) != 0 && (a % 7) != 0 &&
43  (a % 11) != 0 && (a % 13) != 0 && (a % 17) != 0 && (a % 19) != 0 && (a % 23) != 0 &&
44  (a % 29) != 0 && (a % 31) != 0 ;
45  }
46 
47  static bool SelectionCriteriumOnElement(const StoredElement* a)
48  {
49  return SelectionCriterium(a->GetUniqueID());
50  }
51 
52  // The following map type is ment as a container of all the relations
53  // from m_fromElement to al other elements in all the store arrays.
54  // It maps the "To" KeyElement to the weight of Relation.
55  using FromTargetElementsToWeight = map< KeyElementType, double >;
56 
57 
58  class Relations {
59 
60  // This class is a container of all the
61  // relations from m_elementKey to all other elements
62  // in all the store arrays of the TestBench
63 
64  public:
65 
66  // the following map is ment to map the name of StoreArray to the
67  // map linking the target "to" element to the weight of the relation.
68  using FromStringToArrows = unordered_map< string, FromTargetElementsToWeight >;
69 
70  private:
71  KeyElementType m_fromElement;
72  FromStringToArrows m_allRelations;
73 
74  public:
75 
76  // constructor
77  explicit Relations(const KeyElementType& from):
78  m_fromElement(from)
79  {
80  }
81 
82  const FromStringToArrows&
83  getConstSetOfAllRelations() const
84  {
85  return m_allRelations;
86  }
87 
88  FromStringToArrows::const_iterator
89  getConstSetOfToRelations(const string& toSetName) const
90  {
91  return m_allRelations.find(toSetName) ;
92  }
93 
94 
95  FromStringToArrows::iterator
96  getSetOfToRelations(const string& toSetName)
97  {
98  return m_allRelations.find(toSetName) ;
99  }
100 
101  FromStringToArrows::const_iterator
102  getSetOfToRelations(const string& toSetName) const
103  {
104  return m_allRelations.find(toSetName) ;
105  }
106 
107 
108  void
109  print()
110  {
111  cout << "From KeyElement " << m_fromElement << "to:" << endl;
112  for (const auto& toSet : m_allRelations) {
113  for (auto pair : toSet.second)
114  cout << "Set name: "
115  << toSet.first << " "
116  << pair.first
117  << " ( " << pair.second << " ) " << endl;
118 
119  cout << "-----------------------------------------------------------------" << endl;
120  }
121  }
122 
123  bool
124  isPresentRelationTo(const string& toSetName, KeyElementType to) const
125  {
126  auto toRelations = getConstSetOfToRelations(toSetName);
127  if (toRelations == m_allRelations.end())
128  return false;
129  return toRelations->second.find(to) != toRelations->second.end();
130  }
131 
132  void
133  appendNewRelationTo(const string& toName, KeyElementType to,
134  double weight)
135  {
136  auto toRelations = getSetOfToRelations(toName);
137  if (toRelations == m_allRelations.end()) {
138  // add the new named set to the relation
139  m_allRelations.insert(pair <string, FromTargetElementsToWeight>
140  (toName,
141  FromTargetElementsToWeight({ {to, weight} })));
142  return;
143  }
144  pair< KeyElementType, double > relation(to, weight);
145  toRelations->second.insert(relation);
146 
147  }
148 
149  const FromTargetElementsToWeight&
150  getAllRelations(const string& toOtherSetName) const
151  {
152  static FromTargetElementsToWeight nothing;
153  auto toRelations = getSetOfToRelations(toOtherSetName);
154  if (toRelations == m_allRelations.end()) {
155  return nothing;
156  };
157  return toRelations->second;
158  }
159 
160  };
161 
162 //disable warnings about unused functions
163 #if defined(__INTEL_COMPILER)
164 #pragma warning disable 177
165 #endif
166 
167  class NamedSet {
168 
169  // The class NamedSet provides two representantions of the same entity.
170  // The entity has a name, a set, and some relations with other sets.
171  // The entity name is m_name.
172  // The set is stored both as a StoreArray named m_name and as an unordered_map
173  // The relations are stored both as relation and as unordered_map so that
174  // one can check the correctness of the SelectSubset utility.
175 
176  string m_name; // My name
177  map< KeyElementType, Relations > m_set; // What I am
178  StoreArray< StoredElement > m_storeArray; // How I am stored
179  RelationArray* to{nullptr}; // How my relation to the original set is stored
180  RelationArray* from{nullptr}; // How my relation from the original set is stored
181  RelationArray* self{nullptr}; // How the relation with myself is stored (yes, I am
182  // the original set)
183  public:
184 
185 
186  void print()
187  {
188  cout << "The NamedSet: " << m_name << " contains:" << endl ;
189  for (auto set : m_set) {
190  cout << set.first << endl;
191  set.second.print();
192  }
193  cout << "~~~~~~~~~~~~~~~~~~~~~~~" << endl;
194  }
195 
196  // constructor
197  explicit NamedSet(const string& name = "") :
198  m_name(name), m_storeArray(name) {}
199 
200  // order relation
201  bool operator()(const NamedSet& a, const NamedSet& b) const
202  {
203  return a.getName() < b.getName();
204  }
205 
206  // accessors
207  [[nodiscard]] const string getName() const
208  {
209  return m_name;
210  }
211 
212  StoreArray< StoredElement >& storedArray()
213  {
214  return m_storeArray;
215  }
216 
217 
218  void initializeDatastore()
219  {
220  // this method take care of the initialization of the
221  // StoreArray
222  DataStore::Instance().setInitializeActive(true);
223 
224  StoreArray< StoredElement > array(getName());
225  array.registerInDataStore();
226  array.registerRelationTo(array);
227 
228  DataStore::Instance().setInitializeActive(false);
229  }
230 
231  void initializeDatastore(const string& SetName)
232  {
233  // this method take care of the initialization of the
234  // store array and of the RelationArrays from and to
235  // the StoreArray named SetName
236 
237  DataStore::Instance().setInitializeActive(true);
238 
239  StoreArray< StoredElement > array(getName());
240  StoreArray< StoredElement > otherSet(SetName);
241  array.registerInDataStore();
242  array.registerRelationTo(otherSet);
243  otherSet.registerRelationTo(array);
244  //TODO one of these is wrong! -> getRelationsWith() would return both directions
245 
246  DataStore::Instance().setInitializeActive(false);
247  }
248 
249  void consolidate()
250  {
251  // this method consolidate the StoreArray and the RelationArrays
252  // to and from the set
253  if (self != nullptr)
254  self->consolidate();
255  if (from != nullptr)
256  from->consolidate();
257  if (to != nullptr)
258  to->consolidate();
259  }
260 
261 
262  void appendNewElement(KeyElementType element)
263  {
264  m_set.insert(pair< KeyElementType, Relations > (element, Relations(element)));
265  }
266 
267  void appendNewRelationTo(KeyElementType fromKey, const string& toName, KeyElementType toKey,
268  double weight)
269  {
270  auto fromElement = m_set.find(fromKey);
271  if (fromElement == m_set.end()) {
272  cout << "??" << endl;
273  return; // quietly skip
274  }
275  fromElement->second.appendNewRelationTo(toName, toKey, weight);
276  }
277 
278  [[nodiscard]] bool isPresentRelationFromTo(const KeyElementType& fromKey, const string& otherSetName,
279  const KeyElementType& toKey) const
280  {
281  auto fromElement = m_set.find(fromKey);
282  if (fromElement != m_set.end()) {
283  return fromElement->second.isPresentRelationTo(otherSetName, toKey);
284  } else {
285  cout << "Error: from: " << getName() << " id " << fromKey <<
286  " -> " << otherSetName << " id " << toKey << endl;
287  for (const auto& element : m_set)
288  cout << element.first << "\t";
289  cout << endl;
290  for (const auto& element : m_storeArray)
291  cout << element.GetUniqueID() << "\t";
292  cout << endl;
293  return false;
294  }
295  }
296 
297  [[nodiscard]] const FromTargetElementsToWeight& getAllRelations(const KeyElementType& fromKey, const string& toOtherSetName) const
298  {
299  auto fromElement = m_set.find(fromKey);
300  return fromElement->second.getAllRelations(toOtherSetName);
301  }
302 
303  using StlRelationArray = map< KeyElementType, FromTargetElementsToWeight >;
304 
305  [[nodiscard]] StlRelationArray getRestrictedDomainRelationTo(const string& toOtherSetName)const
306  {
307  StlRelationArray theInducedRelation;
308  for (const auto& element : m_set) {
309  if (SelectionCriterium(element.first) &&
310  element.second.getAllRelations(toOtherSetName).size() != 0)
311  theInducedRelation.insert(pair< KeyElementType, FromTargetElementsToWeight>
312  (element.first, element.second.getAllRelations(toOtherSetName)));
313  }
314  return theInducedRelation;
315  }
316 
317  [[nodiscard]] StlRelationArray getRestrictedCodomainRelationTo(const string& setName)const
318  {
319  StlRelationArray theInducedRelation;
320  for (const auto& element : m_set) {
321  if (element.second.getConstSetOfToRelations(setName) ==
322  element.second.getConstSetOfAllRelations().end())
323  continue;
324  for (auto image : element.second.getConstSetOfToRelations(setName)->second) {
325  if (SelectionCriterium(image.first)) {
326  if (theInducedRelation.find(element.first) == theInducedRelation.end())
327  theInducedRelation.insert(pair< KeyElementType, FromTargetElementsToWeight>
328  (element.first, FromTargetElementsToWeight()));
329  theInducedRelation.find(element.first)->second.
330  insert(FromTargetElementsToWeight::value_type
331  (image.first, image.second));
332  }
333  }
334  }
335  return theInducedRelation;
336  }
337 
338  [[nodiscard]] StlRelationArray getRestrictedSelfRelation() const
339  {
340  StlRelationArray theInducedRelation;
341  for (const auto& element : m_set) {
342  if (! SelectionCriterium(element.first) ||
343  element.second.getAllRelations(m_name).size() == 0)
344  continue;
345  for (auto image : element.second.getConstSetOfToRelations(m_name)->second) {
346  if (SelectionCriterium(image.first)) {
347  if (theInducedRelation.find(element.first) == theInducedRelation.end())
348  theInducedRelation.insert(pair< KeyElementType, FromTargetElementsToWeight>
349  (element.first, FromTargetElementsToWeight()));
350  theInducedRelation.find(element.first)->second.
351  insert(FromTargetElementsToWeight::value_type
352  (image.first, image.second));
353  }
354  }
355  }
356  return theInducedRelation;
357 
358  }
359  };
360 
361  class CollectionOfSets {
362 
363  // This is the actual test bench. It contains the set to be subsetted
364  // together with the subset and the other sets in relation with the subset
365  private:
366  string m_setName; // We start from this set
367  string m_subsetName; // we will select this subset
368  NamedSet m_set;
369  NamedSet m_subset;
370 
371  vector< string > m_otherSetsNames; // other sets in the universe
372  unordered_map< string, NamedSet > m_otherSets;
373 
374  public:
375  // constructor
376  CollectionOfSets(): m_set("theSet"),
377  m_subset("theSubset"),
378  m_otherSetsNames {string("G"), string("F"), string("E"),
379  string("D"), string("C"), string("B"), string("A")
380  }
381  {
382  m_setName = m_set.getName();
383  m_subsetName = m_subset.getName();
384  for (const auto& aSetName : m_otherSetsNames)
385  m_otherSets.insert(pair<string, NamedSet> (aSetName, NamedSet(aSetName)));
386  };
387 
388  //accessors
389  const string&
390  getSetName() const
391  {
392  return m_setName ;
393  };
394 
396  getSet()
397  {
398  return m_set.storedArray();
399  };
400 
401  NamedSet&
402  getNamedSet()
403  {
404  return m_set;
405  };
406 
407 
408  const string&
409  getSubsetName() const
410  {
411  return m_subsetName ;
412  };
413 
415  getSubset()
416  {
417  return m_subset.storedArray();
418  };
419 
420  int
421  getNSets() const
422  {
423  return m_otherSets.size() ;
424  }
425 
426  const vector< string >&
427  getOtherSetsNames() const
428  {
429  return m_otherSetsNames ;
430  }
431 
432  const string&
433  getOtherSetsNames(int i) const
434  {
435  return m_otherSetsNames[i] ;
436  }
437 
439  getOtherSet(int i)
440  {
441  auto otherSet = m_otherSets.find(m_otherSetsNames[ i ]);
442  if (otherSet != m_otherSets.end())
443  return otherSet->second.storedArray();
444  else
445  cout << " ???????????? " << i << endl;
446  throw std::runtime_error("invalid set access");
447  }
448 
449  pair< const string, NamedSet>&
450  getOtherNamedSet(int i)
451  {
452  return * m_otherSets.find(m_otherSetsNames[ i ]);
453  }
454 
455  unordered_map< string, NamedSet >&
456  getOtherSets()
457  {
458  return m_otherSets;
459  }
460 
461  void
462  initializeDatastore()
463  {
464  // initialitation phase
465 
466  m_set.initializeDatastore();
467 
468  for (auto namedSet : m_otherSets)
469  namedSet.second.initializeDatastore(getSetName());
470 
471  }
472 
473  void
474  populateDatastore()
475  {
476  unsigned int nElements = 1368;
477  for (unsigned int i = 0; i < nElements ; i++)
478  appendNewElement(m_set);
479 
480  int n(0);
481 
482  for (auto& set : m_otherSets) {
483  unsigned int nOtherElements = nElements - n * 100;
484 
485  for (unsigned int i = 0; i < nOtherElements ; i++)
486  appendNewElement(set.second);
487 
488  }
489 
490  int j(2);
491  for (auto& set : m_otherSets) {
492 
493 
494  unsigned int nArrows = nElements * j;
495  j++;
496 
497  for (unsigned int arrow = 0; arrow < nArrows ; arrow ++) {
498  appendNewRelationToOther(set);
499  appendNewRelationFromOther(set);
500  }
501 
502  }
503 
504 
505  for (unsigned int arrow = 0; arrow < 5 * nElements; arrow ++)
506  appendNewSelfRelation();
507 
508 #ifdef DEBUG
509  m_set.print();
510 #endif
511 
512  }
513 
514 
515  double
516  getWeight()
517  {
518  static double counter(0.0);
519  return counter += 1.;
520  };
521 
522  unsigned int
523  flat_random(unsigned int max)
524  {
525  /* This algorithm is mentioned in the ISO C standard, here extended for 32 bits.
526  the initial seed is arbitrary set to 11036
527  the seed is 11036 and is fixed i.e. it is strictly reproducible and does
528  not interact with other random generators*/
529  static unsigned int next = 11036;
530  int result;
531 
532  next *= 1103515245;
533  next += 12345;
534  result = (unsigned int)(next / 65536) % 2048;
535 
536  next *= 1103515245;
537  next += 12345;
538  result <<= 10;
539  result ^= (unsigned int)(next / 65536) % 1024;
540 
541  next *= 1103515245;
542  next += 12345;
543  result <<= 10;
544  result ^= (unsigned int)(next / 65536) % 1024;
545 
546  return result % max;
547 
548  }
549 
550  void
551  appendNewElement(NamedSet& namedSet)
552  {
553  StoreArray< StoredElement >& set = namedSet.storedArray();
554  int i = set.getEntries() ;
555  static int uniqueId(0);
556 
557  namedSet.appendNewElement(uniqueId);
558  set.appendNew();
559  set[ i ]->SetUniqueID(uniqueId);
560  uniqueId++;
561  }
562 
563 
564  void
565  appendNewRelationToOther(pair< const string, NamedSet>& set)
566  {
567 
568  int from_index = flat_random(getSet().getEntries());
569  KeyElementType from_key = getSet()[from_index]->GetUniqueID();
570  int to_index = flat_random(set.second.storedArray().getEntries());
571  KeyElementType to_key = set.second.storedArray()[to_index]->GetUniqueID();
572 
573 
574  if (getNamedSet().isPresentRelationFromTo(from_key, set.first, to_key))
575  return; // Arrow already drawn
576 
577 
578  double weight = getWeight();
579 
580  getNamedSet().appendNewRelationTo(from_key, set.first, to_key, weight);
581 
582  RelationArray setToOtherSet(getSet(), set.second.storedArray());
583  setToOtherSet.add(from_index, to_index, weight);
584 
585  }
586 
587 
588  void
589  appendNewRelationFromOther(pair< const string, NamedSet>& otherSet)
590  {
591 
592  //cout << otherSet.first << "\t";
593  unsigned int from_index = flat_random(otherSet.second.storedArray().getEntries());
594  //cout << from_index << "\t";
595  KeyElementType from_key = otherSet.second.storedArray()[from_index]->GetUniqueID();
596  //cout << from_key << endl;
597  unsigned int to_index = flat_random(getSet().getEntries());
598  KeyElementType to_key = getSet()[to_index]->GetUniqueID();
599 
600  if (otherSet.second.isPresentRelationFromTo(from_key, getSetName(), to_key))
601 
602  return; // Arrow already drawn
603 
604  double weight = getWeight();
605 
606  otherSet.second.appendNewRelationTo(from_key, getSetName(), to_key, weight);
607 
608  //otherSet.second.storedArray()[ from_index ]->SetBinContent( 0 , to_index , weight);
609 
610  RelationArray otherSetToSet(otherSet.second.storedArray(), getSet());
611  otherSetToSet.add(from_index, to_index, weight);
612 
613  }
614 
615  void
616  appendNewSelfRelation()
617  {
618  unsigned int from_index = flat_random(getSet().getEntries());
619  KeyElementType from_key = getSet()[from_index]->GetUniqueID();
620  unsigned int to_index = flat_random(getSet().getEntries());
621  KeyElementType to_key = getSet()[to_index]->GetUniqueID();
622 
623 
624  if (getNamedSet().isPresentRelationFromTo(from_key, getSetName(), to_key))
625  return; // Arrow already drawn
626 
627  double weight = getWeight();
628 
629  getNamedSet().appendNewRelationTo(from_key, getSetName(), to_key, weight);
630 
631  RelationArray setToSet(getSet(), getSet());
632 
633  setToSet.add(from_index, to_index, weight);
634 
635 
636  }
637 
638 
639  };
640 
641 
642  protected:
643 
644  CollectionOfSets m_TestBench;
645 
646  void SetUp() override
647  {
648  }
649 
651  void TearDown() override
652  {
653  DataStore::Instance().reset();
654  }
655 
656 
657  bool
658  testRelationToOther(pair< const string, NamedSet>& otherSet)
659  {
660 
661  StoreArray< StoredElement > theSet(m_TestBench.getSetName());
662  StoreArray< StoredElement > subset(m_TestBench.getSubsetName());
663  RelationArray subsetToOtherSet(subset,
664  otherSet.second.storedArray());
665 
666 
667  NamedSet::StlRelationArray theInducedRelation;
668 
669  for (int relation = 0 ; relation < subsetToOtherSet.getEntries() ; relation++) {
670  size_t relationSize = subsetToOtherSet[ relation ].getSize();
671 
672  RelationElement::index_type from = subsetToOtherSet[ relation ].getFromIndex();
673  KeyElementType fromElementKey = subset[from]->GetUniqueID();
674  if (theInducedRelation.find(fromElementKey) == theInducedRelation.end())
675  theInducedRelation.insert(pair< KeyElementType, FromTargetElementsToWeight>
676  (fromElementKey, FromTargetElementsToWeight()));
677 
678  for (unsigned int to_index = 0 ; to_index < relationSize ; to_index++) {
679  RelationElement::index_type to = subsetToOtherSet[ relation ].getToIndex(to_index);
680  double weight = subsetToOtherSet[ relation ].getWeight(to_index);
681  KeyElementType toElementKey = otherSet.second.storedArray()[to]->GetUniqueID();
682 
683  theInducedRelation.find(fromElementKey)->second.insert(pair< KeyElementType, double> (toElementKey, weight));
684 
685  }
686  }
687 
688 
689  NamedSet::StlRelationArray theExpectedRelation = m_TestBench.getNamedSet().
690  getRestrictedDomainRelationTo(otherSet.first) ;
691 
692  bool OKorKO = equal(theExpectedRelation.begin(), theExpectedRelation.end(), theInducedRelation.begin(),
693  [](const NamedSet::StlRelationArray::value_type & a,
694  const NamedSet::StlRelationArray::value_type & b) {
695 #ifdef DEBUG
696  cout << a.first << " vs " << b.first << endl;
697 #endif
698  return a.first == b.first &&
699  equal(a.second.begin(), a.second.end(), b.second.begin(),
700  [](const FromTargetElementsToWeight::value_type & x,
701  const FromTargetElementsToWeight::value_type & y) {
702 #ifdef DEBUG
703  cout
704  << x.first << "," << x.second
705  << " <-> "
706  << y.first << "," << y.second << "\t";
707  cout << (x.first == y.first) << " , " << (x.second == y.second) << endl;
708 #endif
709  return x.first == y.first && x.second == y.second;
710  }
711  ) ;
712  });
713 
714 #ifdef DEBUG
715  for (auto relation : theExpectedRelation)
716  for (auto to : relation.second)
717  cout << relation.first << " -> " << to.first << " ( " << to.second << " )" << endl;
718 
719  for (auto relation : theInducedRelation)
720  for (auto to : relation.second)
721  cout << relation.first << " --> " << to.first << " ( " << to.second << " )" << endl;
722 #endif
723 
724 
725  return OKorKO;
726  }
727 
728  bool
729  testRelationFromOther(pair< const string, NamedSet>& otherNamedSet)
730  {
731 
732  StoreArray< StoredElement > subset(m_TestBench.getSubsetName());
733  StoreArray< StoredElement > other = otherNamedSet.second.storedArray();
734 
735 
736  RelationArray subsetFromOtherSet(otherNamedSet.second.storedArray(), subset);
737 
738 
739  NamedSet::StlRelationArray theInducedRelation;
740 
741  for (int relation = 0 ; relation < subsetFromOtherSet.getEntries() ; relation++) {
742  size_t relationSize = subsetFromOtherSet[ relation ].getSize();
743  RelationElement::index_type from = subsetFromOtherSet[ relation ].getFromIndex();
744  KeyElementType fromElementKey = other[from]->GetUniqueID();
745  if (theInducedRelation.find(fromElementKey) == theInducedRelation.end()) {
746  theInducedRelation.insert(pair< KeyElementType, FromTargetElementsToWeight>
747  (fromElementKey, FromTargetElementsToWeight()));
748  }
749 
750  for (unsigned int to_index = 0 ; to_index < relationSize ; to_index++) {
752  subsetFromOtherSet[ relation ].getToIndex(to_index);
753  double weight = subsetFromOtherSet[ relation ].getWeight(to_index);
754  KeyElementType toElementKey = subset[to]->GetUniqueID();
755 
756  theInducedRelation.find(fromElementKey)->second.insert(pair< KeyElementType, double> (toElementKey, weight));
757 
758  }
759  }
760 
761 
762  NamedSet::StlRelationArray theExpectedRelation
763  = otherNamedSet.second.getRestrictedCodomainRelationTo(m_TestBench.getSetName());
764  bool OKorKO = equal(theExpectedRelation.begin(), theExpectedRelation.end(), theInducedRelation.begin(),
765  [](const NamedSet::StlRelationArray::value_type & a,
766  const NamedSet::StlRelationArray::value_type & b) {
767 #ifdef DEBUG
768  cout << a.first << " vs " << b.first << endl;
769 #endif
770  return a.first == b.first &&
771  equal(a.second.begin(), a.second.end(), b.second.begin(),
772  [](const FromTargetElementsToWeight::value_type & x,
773  const FromTargetElementsToWeight::value_type & y) {
774 #ifdef DEBUG
775  cout
776  << x.first << "," << x.second
777  << " <-> "
778  << y.first << "," << y.second << "\t";
779  cout << (x.first == y.first) << " , " << (x.second == y.second) << endl;
780 #endif
781  return x.first == y.first && x.second == y.second;
782  }
783  ) ;
784  });
785 
786 #ifdef DEBUG
787  for (auto relation : theExpectedRelation)
788  for (auto to : relation.second)
789  cout << relation.first << " -> " << to.first << " ( " << to.second << " )" << endl;
790 
791  for (auto relation : theInducedRelation)
792  for (auto to : relation.second)
793  cout << relation.first << " --> " << to.first << " ( " << to.second << " )" << endl;
794 #endif
795 
796 
797  return OKorKO;
798  }
799 
800 
801  bool
802  testSelfRelation()
803  {
804 
805  StoreArray< StoredElement > subset(m_TestBench.getSubsetName());
806  RelationArray selfRelation(subset, subset);
807 
808 
809  NamedSet::StlRelationArray theInducedRelation;
810 
811  for (int relation = 0 ; relation < selfRelation.getEntries() ; relation++) {
812  size_t relationSize = selfRelation[ relation ].getSize();
813  RelationElement::index_type from = selfRelation[ relation ].getFromIndex();
814  KeyElementType fromElementKey = subset[from]->GetUniqueID();
815  if (theInducedRelation.find(fromElementKey) == theInducedRelation.end()) {
816  theInducedRelation.insert(pair< KeyElementType, FromTargetElementsToWeight>
817  (fromElementKey, FromTargetElementsToWeight()));
818  }
819 
820  for (unsigned int to_index = 0 ; to_index < relationSize ; to_index++) {
822  selfRelation[ relation ].getToIndex(to_index);
823  double weight = selfRelation[ relation ].getWeight(to_index);
824  KeyElementType toElementKey = subset[to]->GetUniqueID();
825 
826  theInducedRelation.find(fromElementKey)->second.insert(pair< KeyElementType, double> (toElementKey, weight));
827 
828  }
829  }
830 
831 
832  NamedSet::StlRelationArray theExpectedRelation = m_TestBench.getNamedSet().
833  getRestrictedSelfRelation();
834 
835  bool OKorKO = equal(theExpectedRelation.begin(), theExpectedRelation.end(), theInducedRelation.begin(),
836  [](const NamedSet::StlRelationArray::value_type & a,
837  const NamedSet::StlRelationArray::value_type & b) {
838 
839 #ifdef DEBUG
840  cout << a.first << " vs " << b.first << endl;
841 #endif
842  return (true || a.first == b.first) &&
843  equal(a.second.begin(), a.second.end(), b.second.begin(),
844  [](const FromTargetElementsToWeight::value_type & x,
845  const FromTargetElementsToWeight::value_type & y) {
846 #ifdef DEBUG
847  cout
848  << x.first << "," << x.second
849  << " <-> "
850  << y.first << "," << y.second << "\t";
851  cout << (x.first == y.first) << " , " << (x.second == y.second) << endl;
852 #endif
853  return x.first == y.first && x.second == y.second;
854  }
855  ) ;
856  });
857 
858 #ifdef DEBUG
859 
860  cout << "We do expect the following set of relations" << endl;
861  for (auto relation : theExpectedRelation)
862  for (auto to : relation.second)
863  cout << relation.first << " -> " << to.first << " ( " << to.second << " )" << endl;
864 
865  cout << "We found the following ones" << endl;
866  for (auto relation : theInducedRelation)
867  for (auto to : relation.second)
868  cout << relation.first << " --> " << to.first << " ( " << to.second << " )" << endl;
869  cout << "~~~~";
870 #endif
871 
872 
873  return OKorKO;
874  }
875  };
876 
877 
878 
879 
880 
881  TEST_F(SelectSubsetTest, ExtensiveTest)
882  {
883  m_TestBench.initializeDatastore();
884  m_TestBench.populateDatastore();
885 
887  StoreArray< StoredElement > set(m_TestBench.getSetName());
888 
889  DataStore::Instance().setInitializeActive(true);
890 
891  selector.registerSubset(set, m_TestBench.getSubsetName());
892 
893  for (auto other : m_TestBench.getOtherSets()) {
894  selector.inheritRelationsTo(other.second.storedArray());
895  selector.inheritRelationsFrom(other.second.storedArray());
896  }
897 
898  //inherit set <-> set relations
899  selector.inheritRelationsFrom(set);
900 
901  DataStore::Instance().setInitializeActive(false);
902 
903  selector.select(SelectionCriteriumOnElement);
904 
905  StoreArray< StoredElement > subset(m_TestBench.getSubsetName());
906 
907  bool allSubsetElementsAreGood(true);
908 
909 
910  // First of all let us check that all the elements in the subset
911  // do satisfy the SelectionCriterium and that
912  for (const auto& element : subset) {
913  if (! SelectionCriteriumOnElement(& element))
914  allSubsetElementsAreGood = false;
915 
916 
917  }
918 
919  EXPECT_TRUE(allSubsetElementsAreGood);
920 
921 
922  // Then we check that the size of the subset equals the number
923  // of elements in the set satisfiing the SelectionCriterium
924  int NSelected(0);
925  for (const auto& element : set)
926  NSelected += SelectionCriteriumOnElement(&element) ? 1 : 0;
927 
928  EXPECT_TRUE(NSelected == subset.getEntries());
929 
930 
931  // Then we test that all the relations are correct
932  EXPECT_TRUE(testSelfRelation());
933 
934  for (int i = 0 ; i < m_TestBench.getNSets(); i++) {
935 
936  auto otherSet = m_TestBench.getOtherNamedSet(i);
937  EXPECT_TRUE(testRelationToOther(otherSet));
938  EXPECT_TRUE(testRelationFromOther(otherSet));
939 
940  }
941  }
942 
943  bool hasOddIndex(const RelationsObject* a)
944  {
945  return (a->getArrayIndex() % 2) == 1;
946  }
947 
948  TEST_F(SelectSubsetTest, TestWithManyRelations)
949  {
950  //array 'main' with relations: a -> main -> b
951  //create subset: a -> subsetOfMain -> b
952 
953  DataStore::Instance().setInitializeActive(true);
954  StoreArray< RelationsObject > arrayMain("main");
955  StoreArray< RelationsObject > arrayA("a");
956  StoreArray< RelationsObject > arrayB("b");
957  arrayMain.registerInDataStore();
958  arrayA.registerInDataStore();
959  arrayB.registerInDataStore();
960  arrayA.registerRelationTo(arrayMain);
961  arrayMain.registerRelationTo(arrayB);
962 
963  //create subset and relations
964  SelectSubset< RelationsObject > selectorMain;
965  selectorMain.registerSubset(arrayMain, "subsetOfMain");
966 
967  selectorMain.inheritRelationsFrom(arrayA);
968  selectorMain.inheritRelationsTo(arrayB);
969 
970  DataStore::Instance().setInitializeActive(false);
971 
972  //fill some data
973  for (int i = 0; i < 10; i++) {
974  auto* mainObj = arrayMain.appendNew();
975  for (int j = 0; j < 2; j++) {
976  auto* aObj = arrayA.appendNew();
977  aObj->addRelationTo(mainObj);
978  }
979  for (int j = 0; j < 10; j++) {
980  auto* bObj = arrayB.appendNew();
981  mainObj->addRelationTo(bObj);
982  }
983  }
984 
985  //run selector
986  selectorMain.select(hasOddIndex);
987 
988 
989  //verify original contents
990  EXPECT_EQ(10, arrayMain.getEntries());
991  EXPECT_EQ(20, arrayA.getEntries());
992  EXPECT_EQ(100, arrayB.getEntries());
993 
994 
995  StoreArray< RelationsObject > arraySubset("subsetOfMain");
996 
997  //verify subset
998  EXPECT_EQ(5, arraySubset.getEntries());
999  for (const RelationsObject& r : arraySubset) {
1000  EXPECT_EQ(2u, r.getRelationsFrom<RelationsObject>("a").size());
1001  EXPECT_EQ(0u, r.getRelationsFrom<RelationsObject>("b").size());
1002  EXPECT_EQ(10u, r.getRelationsTo<RelationsObject>("b").size());
1003  EXPECT_EQ(0u, r.getRelationsTo<RelationsObject>("a").size());
1004  EXPECT_TRUE(nullptr == r.getRelatedTo<RelationsObject>("main"));
1005 
1006  //go back to main set, check selection condidition holds
1007  EXPECT_EQ(1u, r.getRelationsWith<RelationsObject>("main").size());
1008  const RelationsObject* originalObject = r.getRelatedFrom<RelationsObject>("main");
1009  EXPECT_TRUE(hasOddIndex(originalObject));
1010  }
1011  }
1012 
1013  TEST_F(SelectSubsetTest, InheritAll)
1014  {
1015  //array 'main' with relations: a -> main -> b
1016  //create subset: a -> subsetOfMain -> b
1017 
1018  DataStore::Instance().setInitializeActive(true);
1019  StoreArray< RelationsObject > arrayMain("main");
1020  StoreArray< RelationsObject > arrayA("a");
1021  StoreArray< RelationsObject > arrayB("b");
1022  arrayMain.registerInDataStore();
1023  arrayA.registerInDataStore();
1024  arrayB.registerInDataStore();
1025  arrayA.registerRelationTo(arrayMain);
1026  arrayMain.registerRelationTo(arrayB);
1027 
1028  //create subset and relations
1029  SelectSubset< RelationsObject > selectorMain;
1030  selectorMain.registerSubset(arrayMain, "subsetOfMain");
1031 
1032  selectorMain.inheritAllRelations();
1033 
1034  DataStore::Instance().setInitializeActive(false);
1035 
1036  //check if the state matches what we expect
1037  EXPECT_FALSE(selectorMain.getInheritToSelf());
1038  EXPECT_EQ(std::vector<string>({"a"}), selectorMain.getInheritFromArrays());
1039  EXPECT_EQ(std::vector<string>({"b"}), selectorMain.getInheritToArrays());
1040  }
1041 
1042  TEST_F(SelectSubsetTest, TestExistingSetWithManyRelations)
1043  {
1044  //array 'main' with relations: a -> main -> b
1045  //then remove half of main.
1046 
1047  DataStore::Instance().setInitializeActive(true);
1048  StoreArray< RelationsObject > arrayMain("main");
1049  StoreArray< RelationsObject > arrayA("a");
1050  StoreArray< RelationsObject > arrayB("b");
1051  arrayMain.registerInDataStore();
1052  arrayA.registerInDataStore();
1053  arrayB.registerInDataStore();
1054  arrayA.registerRelationTo(arrayMain);
1055  arrayMain.registerRelationTo(arrayB);
1056 
1057  //create subset and relations
1058  SelectSubset< RelationsObject > selectorMain;
1059  selectorMain.registerSubset(arrayMain);
1060 
1061  DataStore::Instance().setInitializeActive(false);
1062 
1063  //fill some data
1064  for (int i = 0; i < 10; i++) {
1065  auto* mainObj = arrayMain.appendNew();
1066  for (int j = 0; j < 2; j++) {
1067  auto* aObj = arrayA.appendNew();
1068  aObj->addRelationTo(mainObj);
1069  }
1070  for (int j = 0; j < 10; j++) {
1071  auto* bObj = arrayB.appendNew();
1072  mainObj->addRelationTo(bObj);
1073  }
1074  }
1075 
1076  //verify original contents
1077  EXPECT_EQ(10, arrayMain.getEntries());
1078  EXPECT_EQ(20, arrayA.getEntries());
1079  EXPECT_EQ(100, arrayB.getEntries());
1080 
1081  //run selector
1082  selectorMain.select(hasOddIndex);
1083 
1084 
1085  //verify subset
1086  EXPECT_EQ(5, arrayMain.getEntries());
1087  for (const RelationsObject& r : arrayMain) {
1088  EXPECT_EQ(2u, r.getRelationsFrom<RelationsObject>("a").size());
1089  EXPECT_EQ(0u, r.getRelationsFrom<RelationsObject>("b").size());
1090  EXPECT_EQ(10u, r.getRelationsTo<RelationsObject>("b").size());
1091  EXPECT_EQ(0u, r.getRelationsTo<RelationsObject>("a").size());
1092  EXPECT_TRUE(nullptr == r.getRelatedTo<RelationsObject>("main"));
1093  }
1094  int i = 0;
1095  for (const RelationsObject& r : arrayA) {
1096  EXPECT_EQ((i / 2 % 2 == 1) ? 1u : 0u, r.getRelationsTo<RelationsObject>("main").size());
1097  i++;
1098  }
1099  }
1100 
1101  TEST_F(SelectSubsetTest, TestEmptyArray)
1102  {
1103  //array 'main' with relations: a -> main -> b
1104  //then remove half of main.
1105 
1106  DataStore::Instance().setInitializeActive(true);
1107  StoreArray< RelationsObject > arrayMain("main");
1108  StoreArray< RelationsObject > arrayA("a");
1109  StoreArray< RelationsObject > arrayB("b");
1110  arrayMain.registerInDataStore();
1111  arrayA.registerInDataStore();
1112  arrayB.registerInDataStore();
1113  arrayA.registerRelationTo(arrayMain);
1114  arrayMain.registerRelationTo(arrayB);
1115 
1116  //create subset and relations
1117  SelectSubset< RelationsObject > selectorMain;
1118  selectorMain.registerSubset(arrayMain);
1119 
1120  DataStore::Instance().setInitializeActive(false);
1121 
1122  //test with empty inputs
1123  EXPECT_EQ(0, arrayMain.getEntries());
1124  selectorMain.select(hasOddIndex);
1125  EXPECT_EQ(0, arrayMain.getEntries());
1126 
1127  //fill some data
1128  for (int i = 0; i < 10; i++) {
1129  auto* mainObj = arrayMain.appendNew();
1130  for (int j = 0; j < 2; j++) {
1131  auto* aObj = arrayA.appendNew();
1132  aObj->addRelationTo(mainObj);
1133  }
1134  for (int j = 0; j < 10; j++) {
1135  auto* bObj = arrayB.appendNew();
1136  mainObj->addRelationTo(bObj);
1137  }
1138  }
1139 
1140  //verify original contents
1141  EXPECT_EQ(10, arrayMain.getEntries());
1142  EXPECT_EQ(20, arrayA.getEntries());
1143  EXPECT_EQ(100, arrayB.getEntries());
1144 
1145  //delete all contents
1146  auto never = [](const RelationsObject*) -> bool { return false; };
1147  selectorMain.select(never);
1148 
1149 
1150  //verify subset
1151  EXPECT_EQ(0, arrayMain.getEntries());
1152  for (const RelationsObject& r : arrayA) {
1153  EXPECT_EQ(0u, r.getRelationsTo<RelationsObject>("main").size());
1154  }
1155  }
1156 
1157 } // namespace
Low-level class to create/modify relations between StoreArrays.
Definition: RelationArray.h:62
unsigned int index_type
type used for indices.
Defines interface for accessing relations of objects in StoreArray.
std::vector< std::string > getInheritToArrays() const
Get list of arrays we inherit relations to.
Definition: SelectSubset.h:34
std::vector< std::string > getInheritFromArrays() const
Get list of arrays we inherit relations from.
Definition: SelectSubset.h:32
bool getInheritToSelf() const
Do we inherit relations from original set to itself?
Definition: SelectSubset.h:36
Class to create a subset of a given StoreArray together with the relations with other StoreArrays.
Definition: SelectSubset.h:193
void inheritRelationsTo(const StoreArray< T > &array, MoreArguments... moreArgs)
Inherit relations pointing from objects selected into this subset to Other.
Definition: SelectSubset.h:275
void inheritRelationsFrom(const StoreArray< T > &array, MoreArguments... moreArgs)
Inherit relations pointing from Other to objects selected into this subset.
Definition: SelectSubset.h:250
void inheritAllRelations()
Automatically inherit all relations to or from the original set (if registered when calling this func...
Definition: SelectSubset.h:301
void registerSubset(const StoreArray< StoredClass > &set, DataStore::EStoreFlags storeFlags=DataStore::c_ErrorIfAlreadyRegistered)
Remove all non-selected objects from set.
Definition: SelectSubset.h:215
Accessor to arrays stored in the data store.
Definition: StoreArray.h:113
T * appendNew()
Construct a new T object at the end of the array.
Definition: StoreArray.h:246
int getEntries() const
Get the number of objects in the array.
Definition: StoreArray.h:216
TEST_F(ChargedParticleIdentificatorTest, TestDBRep)
Test correct storage of weightfiles in the database representation inner structure.
void select(const std::function< bool(const StoredClass *)> &f)
This method is the actual worker.
Definition: SelectSubset.h:414
RelationsInterface< TObject > RelationsObject
Provides interface for getting/adding relations to objects in StoreArrays.
Abstract base class for different kinds of events.
Definition: ClusterUtils.h:23