ATLAS Offline Software
Loading...
Searching...
No Matches
Combinators.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4#include <algorithm>
5#include <numeric>
6#include <iostream>
7#include <iterator>
9
10
11using namespace HLT;
12CombinationGenerator::CombinationGenerator( const std::initializer_list<size_t>& collectionSizes )
13 : m_maxes( collectionSizes ),
15 reset();
16
17}
18
20 // no combinations when at least one the sizes is 0 ( empty collection )
21 if ( std::any_of( m_maxes.begin(), m_maxes.end(),
22 []( size_t m ){ return m == 0; } ) )
23 m_current.clear();
24 else {
25 fill( m_current.begin(), m_current.end(), 0 );
26 }
27}
28
30 if ( m_current.empty() ) return;
31 for ( size_t i = 0, imax = m_current.size(); i < imax; ++i ) { // iterate over current indices and find the index which can be increased
32 if ( m_maxes[i] - m_current[i] == 1 ) { // reached end of the range of i-th collection, return to the beginning
33 m_current[i] = 0;
34 } else {
35 m_current[i]++;
36 return;
37 }
38 }
39
40 // unsuccessful index increase == we need to make op bool returning false and next ++ should not happen
41 m_current.clear();
42}
43
45 : m_nElements(nelems),
46 m_combLen(comblen),
48 reset();
49 }
50
51
52CombinationGenerator::operator bool() const {
53 return not m_current.empty();
54}
55
57 m_bitmask.resize(m_combLen, true);
58 m_bitmask.resize(m_nElements, false);
59 m_current.resize(m_combLen);
60 std::iota(m_current.begin(), m_current.end(), 0);
61}
62
63UniqueCombinationGenerator::operator bool() const {
64 return not m_current.empty();
65}
66
68 if ( m_current.empty() ) return;
69
70 const bool exists = std::prev_permutation( m_bitmask.begin(), m_bitmask.end());
71 if ( exists ) {
72 m_current.clear();
73 for (size_t i = 0; i < m_nElements; ++i) {
74 if ( m_bitmask[i] )
75 m_current.push_back(i);
76 }
77 return;
78 }
79 m_current.clear();
80}
81
82
88 m_current.clear();
89 for ( auto& gen: m_generators) {
90 gen.reset();
91 }
92 cache();
93}
94
96 size_t sz = 0;
97 for ( const auto& gen: m_generators) { sz += gen.size(); }
98 return sz;
99}
100
101
103 m_current.clear();
104 for ( auto& gen: m_generators ) {
105 ++gen;
106 if ( gen ) {
107 cache();
108 return;
109 } else if ( &gen != &m_generators.back()) {
110 gen.reset();
111 }
112 }
113 m_current.clear();
114}
115
116NestedUniqueCombinationGenerator::operator bool() const {
117 return not m_current.empty();
118}
119
121 m_current.clear();
122 for ( auto& gen: m_generators) {
123 m_current.insert(m_current.end(), gen.current().begin(), gen.current().end());
124 }
125}
126
127namespace {
128
129 void combMaker( const Index2DVec& indices, const std::function<void (const Index1DVec&) >& handle, const std::function<bool (const Index1DVec&) >& filter, size_t rank=0, Index1DVec combination={} ) {
130
131 for ( auto position: indices[rank] ) {
132 // found an element matching to this combination
133 if ( std::find( combination.begin(), combination.end(), position ) == combination.end() ) {
134 // std::cout << "rank " << rank << " adding or replacing " << position << " to a combination containing so far ";
135 // std::copy( combination.begin(), combination.end(), std::ostream_iterator<size_t>(std::cout, " ") );
136 // std::cout << "\n";
137 if ( combination.size() == rank ) {
138 combination.push_back( position );
139 } else {
140 combination[rank] = position;
141 }
142 if ( combination.size() == indices.size() ) { // end of recursion
143 if ( filter( combination ) ){
144 handle( combination );
145 }
146 } else {
147 combMaker( indices, handle, filter, rank+1, combination);
148 }
149 }
150 }
151 }
152}
153
154namespace HLT {
155 void elementsInUniqueCombinations( const Index2DVec& indices, std::set<size_t>& participants, const std::function<bool(const Index1DVec&)>& filter ) {
156 const auto handle = [&](const Index1DVec& combination ) { for ( auto el: combination ) participants.insert(participants.begin(), el); };
157 combMaker( indices, handle, filter );
158 }
159
160 void findUniqueCombinations( const Index2DVec& indices, std::vector<std::vector<size_t> >& combinations, const std::function<bool(const Index1DVec&)>& filter ) {
161 auto handle = [&](const Index1DVec& combination ) { combinations.push_back( combination ); };
162 combMaker( indices, handle, filter );
163 }
164}
int imax(int i, int j)
CombinationGenerator(const std::initializer_list< size_t > &collectionSizes)
construct combnations maker with the sizes of collection to which it should be applied
void operator++()
moves to the next combination
void add(const UniqueCombinationGenerator &gen)
Generator of unique combinations (no indices are repeated) API description.
UniqueCombinationGenerator(size_t nelems, size_t comblen)
bool exists(const std::string &filename)
does a file exist
It used to be useful piece of code for replacing actual SG with other store of similar functionality ...
void elementsInUniqueCombinations(const Index2DVec &indices, std::set< size_t > &participants, const std::function< bool(const Index1DVec &)> &filter)
std::vector< Index1DVec > Index2DVec
std::vector< size_t > Index1DVec
Unique combinations for case when one can not repeat the index (i.e.
void findUniqueCombinations(const Index2DVec &indices, std::vector< std::vector< size_t > > &combinations, const std::function< bool(const Index1DVec &)> &filter)
Creates unique combinations of elements.
std::pair< long int, long int > indices
void fill(H5::Group &out_file, size_t iterations)