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