diff --git a/Trigger/TrigHypothesis/TrigHLTJetHypo/src/CombinationsGenerator.cxx b/Trigger/TrigHypothesis/TrigHLTJetHypo/src/CombinationsGenerator.cxx new file mode 100644 index 0000000000000000000000000000000000000000..d833eaf7ef1970c0c9801b179d1ea0145fc3cf89 --- /dev/null +++ b/Trigger/TrigHypothesis/TrigHLTJetHypo/src/CombinationsGenerator.cxx @@ -0,0 +1,24 @@ +/* + Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration +*/ + +#include "./CombinationsGenerator.h" + +std::ostream& operator << (std::ostream& os, const CombinationsGenerator& cg){ + os << "CombinationsGenerator m_invalid " <<std::boolalpha << cg.m_invalid + << " bitmask len " << cg.m_bitmask.size() + << " m_bitmask: "; + for (const auto& c : cg.m_bitmask) { + if (c == 0) { + os << 0 << " "; + } else if (c == 1) { + os << 1 << " "; + } else { + os << '?' << " "; + } + } + os << " m_N " << cg.m_N << " m_K " << cg.m_K; + + os << '\n'; + return os; +} diff --git a/Trigger/TrigHypothesis/TrigHLTJetHypo/src/CombinationsGenerator.h b/Trigger/TrigHypothesis/TrigHLTJetHypo/src/CombinationsGenerator.h new file mode 100644 index 0000000000000000000000000000000000000000..b7ea1d09048943c510d158ba3c7ab42377e96e53 --- /dev/null +++ b/Trigger/TrigHypothesis/TrigHLTJetHypo/src/CombinationsGenerator.h @@ -0,0 +1,86 @@ +/* + Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef TRIG_HLTJETHYPO_COMBINATIONSGENERATOR_H +#define TRIG_HLTJETHYPO_COMBINATIONSGENERATOR_H + +#include <algorithm> +#include <string> +#include <vector> +#include <sstream> + +/* +Combinations generator. Given n, k > 0, n>= k, bump() calculate sets +a bit mask of length n with k set values and n-k unset values. + +get() uses the bitmask to return the postions of the k set values. + +When all combinations havebeen exhausted by succesive calls to bump +the process cycles. At the point of recycling a bool flag is set. +This flag is unset on the next call to bump(). +*/ + +class CombinationsGenerator { + public: + + friend std::ostream& operator << (std::ostream&, const CombinationsGenerator&); + + CombinationsGenerator(std::size_t n, std::size_t k): + m_invalid{false}, m_N{n}, m_K(k){ + + // if n==k, std::prev_permutations never returns false, + // so treat as a special case + if (m_N == 0 or m_K > m_N) { + m_invalid = true; + } else if (m_N==m_K) { + m_NequalsKvec.reserve(m_K); + for(std::size_t i = 0u; i != m_K; ++i){ + m_NequalsKvec.push_back(i); + } + } else if (m_K < m_N){ + m_bitmask = std::string(m_K, 1); + m_bitmask.resize(m_N, 0); + } else { + m_invalid = true; + } + } + + + std::vector<std::size_t> get() const { + + if (m_K < m_N and m_K > 0) { + std::vector<std::size_t> comb; + for(std::size_t i = 0; i < m_bitmask.size(); ++i){ + if(m_bitmask[i]){comb.push_back(i);} + } + return comb; + } + + if(m_K == m_N) {return m_NequalsKvec;} + + return std::vector<std::size_t>(); + } + + bool bump() { + // returns true if have cycled + + if (m_K < m_N and m_K > 0) { + return ! std::prev_permutation(m_bitmask.begin(), m_bitmask.end()); + } + return true; + } + +private: + + bool m_invalid; + std::string m_bitmask; + + std::size_t m_N; + std::size_t m_K; + std::vector<std::size_t> m_NequalsKvec; +}; + +std::ostream& operator << (std::ostream& os, const CombinationsGenerator& cg); + +#endif diff --git a/Trigger/TrigHypothesis/TrigHLTJetHypo/src/CombinationsJetStream.cxx b/Trigger/TrigHypothesis/TrigHLTJetHypo/src/CombinationsJetStream.cxx new file mode 100644 index 0000000000000000000000000000000000000000..ca64fa05da4ef2f08fb90baa6b042a12dbf06ece --- /dev/null +++ b/Trigger/TrigHypothesis/TrigHLTJetHypo/src/CombinationsJetStream.cxx @@ -0,0 +1,22 @@ +/* + Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration +*/ + + +#include "CombinationsJetStream.h" + +std::ostream& operator << (std::ostream& os, const CombinationsJetStream& str){ + os << "CombinationsJetStream m_combgen " << str.m_id << '\n' + << *str.m_combgen << '\n'; + return os; +} + +std::stringstream& operator << (std::stringstream& os, const CombinationsJetStream& str){ + os << "CombinationsJetStream id: " << str.m_id + << " m_combgen: " << *str.m_combgen + <<" data: "; + for (const auto& d : str.m_data){os << d << " ";} + os <<'\n'; + + return os; +} diff --git a/Trigger/TrigHypothesis/TrigHLTJetHypo/src/CombinationsJetStream.h b/Trigger/TrigHypothesis/TrigHLTJetHypo/src/CombinationsJetStream.h new file mode 100644 index 0000000000000000000000000000000000000000..b8fbba68c0627049666cb4ca0c3e76a7f040d426 --- /dev/null +++ b/Trigger/TrigHypothesis/TrigHLTJetHypo/src/CombinationsJetStream.h @@ -0,0 +1,143 @@ +/* + Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef TRIGHLTJETHYPO_COMBINATIONSJETSTREAM_H +#define TRIGHLTJETHYPO_COMBINATIONSJETSTREAM_H + +/* + * CompoundJetStream is an implementation of IJetStream. + * on every call to bump(), it makes available a vector of k + * indices chosen from a vector of n indices. + * + * The positions in the k chosen jets in the jet indices list + * is claculated by an instance of CombinationsGenerator, held + * as attribute of this class. + * + * On each call to bump(), the right neighbor is checked for + * having cycled. If this is rthe case, or if there is no such neighbor, + * the instance will bump itself by + * asking its CombinationsGenerator which positions to + * use, and makes these values availble for collection. + * When all combinations have been exhausted by succesive calls to + * bump, the bump() returns true, and the cycle is restarted. + * + */ + + +#include "IJetStream.h" +#include "CombinationsGenerator.h" +#include <vector> +#include <sstream> +#include <memory> +#include <string> + +class CombinationsJetStream: public IJetStream { + + public: + friend std::ostream& operator << (std::ostream&, + const CombinationsJetStream&); + friend std::stringstream& operator << (std::stringstream&, + const CombinationsJetStream&); + + CombinationsJetStream(const std::vector<std::size_t>& jets, + std::unique_ptr<IJetStream> neigh, + std::size_t k, + std::size_t id): + m_jets(jets), + m_neigh(std::move(neigh)), + m_k(k), + m_id{id} + { + auto n = m_jets.size(); + + m_valid = k <= n and !jets.empty(); + if (m_valid) { + m_combgen.reset(new CombinationsGenerator(n, k)); + auto indices = m_combgen->get(); + m_data.clear(); + for (const auto i : indices) {m_data.push_back(m_jets.at(i));} + } + } + + virtual std::vector<std::size_t> get() override { + + + auto result = m_neigh ? m_neigh->get() : std::vector<std::size_t>(); + result.insert(result.end(), m_data.begin(), m_data.end()); + return result; + } + + + virtual bool bump() override { + + // if there is a neighor, bump it. If it returns + // true, it has cycled, in which case try bumping this stream + + bool cycled{false}; + if (m_neigh) { + bool neigh_cycled = m_neigh->bump(); + if (!neigh_cycled) {return false;} + + cycled = m_combgen->bump(); + + auto indices = m_combgen->get(); + m_data.clear(); + for (const auto i : indices) {m_data.push_back(m_jets.at(i));} + return cycled; + } else { + // no neighbor + cycled = m_combgen->bump(); + + auto indices = m_combgen->get(); + m_data.clear(); + for (const auto& i : indices) { + m_data.push_back(m_jets.at(i)); + } + return cycled; + } + } + + + virtual bool valid() const override { + if (!m_valid){return false;} + + if (m_neigh) {return m_neigh->valid();} + return true; + } + + virtual std::string dump() const override { + + auto result = m_neigh ? m_neigh->dump() : ""; + + std::stringstream ss; + ss << *this; + result += ss.str(); + + return result; + } + +private: + std::vector<std::size_t> m_jets; + std::unique_ptr<IJetStream> m_neigh{nullptr}; + std::size_t m_k; // n choose k... + std::size_t m_id; + std::vector<std::size_t> m_data; + std::unique_ptr<CombinationsGenerator> m_combgen{nullptr}; + bool m_valid{false}; + + + + bool empty() const { + return m_jets.empty(); + } + + }; + +std::ostream& operator << (std::ostream&, + const CombinationsJetStream&); + +std::stringstream& operator << (std::stringstream&, + const CombinationsJetStream&); + + #endif diff --git a/Trigger/TrigHypothesis/TrigHLTJetHypo/src/IJetStream.h b/Trigger/TrigHypothesis/TrigHLTJetHypo/src/IJetStream.h new file mode 100644 index 0000000000000000000000000000000000000000..2e49923d678620e09d62a500275be4530ca7bc80 --- /dev/null +++ b/Trigger/TrigHypothesis/TrigHLTJetHypo/src/IJetStream.h @@ -0,0 +1,40 @@ +/* + Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef TRIGHLTJETHYPO_IJETSTREAM_H +#define TRIGHLTJETHYPO_IJETSTREAM_H + +/* + * PABC Interface to trigger jet hypo JetStream classes + * In this context, jets are represented by integer indices. + * a jet stream steps through the available indices in a manner + * that is implemnented in the concrete classes. The selected + * indices are returned in a vector. + * + * Checks on the validity of the stream can be made after construction + * + * Concrete implementations a pointer to a right neighbor + * of typeIJetStream object, and so can be an element of a linked list. + * + * Cycling is used by the left neighbor to decide whether the left + * neigbor should be bumped. + * + * When the state of all elements of the list is cycled, the caller is + * informed, and will normally stop the iteration, + * + */ + +#include <vector> +#include <string> + +class IJetStream { + public: + virtual ~IJetStream(){} + virtual std::vector<std::size_t> get() = 0; + virtual bool valid() const = 0; + virtual bool bump() = 0; + virtual std::string dump() const= 0; +}; + +#endif diff --git a/Trigger/TrigHypothesis/TrigHLTJetHypo/src/JetGroupProduct.cxx b/Trigger/TrigHypothesis/TrigHLTJetHypo/src/JetGroupProduct.cxx index 6d6f8ec79ee7df5e63a3ec0647122c855e77207b..4d0672e88c86182caa75c1c6f49b754e2b2e3360 100644 --- a/Trigger/TrigHypothesis/TrigHLTJetHypo/src/JetGroupProduct.cxx +++ b/Trigger/TrigHypothesis/TrigHLTJetHypo/src/JetGroupProduct.cxx @@ -3,6 +3,9 @@ */ #include "./JetGroupProduct.h" +#include "./JetStreamer.h" +#include "./make_jetstream.h" + #include <set> #include <string> @@ -10,11 +13,29 @@ JetGroupProduct::JetGroupProduct(const std::vector<std::size_t>& siblings, const CondInd2JetGroupsInds& satisfiedBy, const std::vector<std::size_t>& condMult) { - // copy the parts od satisfiedBy corresponding to the sibling indices + m_valid = !siblings.empty() or satisfiedBy.size() != condMult.size(); + if (m_valid) {init(siblings, satisfiedBy, condMult);} +} + +void JetGroupProduct::init(const std::vector<std::size_t>& siblings, + const CondInd2JetGroupsInds& satisfiedBy, + const std::vector<std::size_t>& condMult) { + + // copy the parts of satisfiedBy corresponding to the sibling indices // into m_condIndices. The number of copies made per sibling is the // given by the sibling multiplicity. + + + + std::vector<std::vector<std::size_t>> condIndices; + condIndices.reserve(siblings.size()); + std::vector<std::size_t> repeats; + condIndices.reserve(siblings.size()); + for(const auto& isib : siblings){ auto mult = condMult[isib]; // jet groups indices of satisying jgs. + repeats.push_back(mult); + condIndices.push_back(satisfiedBy.at(isib)); // find the greatest jet index we will deal with const auto& sibjets = satisfiedBy.at(isib); @@ -25,24 +46,15 @@ JetGroupProduct::JetGroupProduct(const std::vector<std::size_t>& siblings, m_jetMask.reserve(m_jetEnd); // no of copies = multiplicity of the Condition + for (std::size_t im = 0; im != mult; ++im){ m_condIndices.push_back(satisfiedBy.at(isib)); } } - // find the size for the satisfying jet group vectors. - // these values will be used ot generate indexes into m_condIndices. - std::vector<std::size_t> ends; - ends.reserve(m_condIndices.size()); - for(const auto& s : m_condIndices){ - ends.push_back(s.size()); - } - // ProductGen is a device for calculating a tuple of indices - // into a vector of vectors of indices. The length of the tuple - // is the length of m_condIndices. The values of the tuple - // are indices into the inner vectors. - m_productGen = ProductGen(ends); + auto stream = make_jetstream(condIndices, repeats, 0); + m_jetstreamer.reset(new JetStreamer(std::move(stream))); } std::vector<std::size_t> JetGroupProduct::next(const Collector& collector){ @@ -57,6 +69,8 @@ std::vector<std::size_t> JetGroupProduct::next(const Collector& collector){ // already been generated. If this is the first time the sequece has // been generated, it will be added to m_seenJetIndices, and then requrned // to the caller. If it has already been seen, it will be abandoned. + + if (!m_valid) {return std::vector<std::size_t>();} unsigned int ipass{0}; std::vector<std::size_t> jg_indices; @@ -66,26 +80,25 @@ std::vector<std::size_t> JetGroupProduct::next(const Collector& collector){ if(collector){ collector->collect("JetGroupProduct::next()", - "loop start pass" + std::to_string(ipass++)); + "loop start pass " + std::to_string(ipass++)); } - auto indices = m_productGen.next(); - if(indices.empty()){ - return indices; //an empty vector of size_t ints - } - // select indices from the child jet group indicies. Form a vector - // of indices. bool blocked{false}; - for(std::size_t i = 0; i < indices.size(); ++i){ - auto idx = (m_condIndices.at(i)).at(indices[i]); - if (m_jetMask[idx]) { + auto jet_indices = m_jetstreamer->next(); + if (jet_indices.empty()) { + if(collector){ + collector->collect("JetGroupProduct::next()", + "end of iteration "); + } + return jet_indices; + } + for (const auto& ind : jet_indices) { + if (m_jetMask[ind]) { blocked = true; break; } - - - m_jetMask[idx] = true; + m_jetMask[ind] = true; } if (blocked){continue;} diff --git a/Trigger/TrigHypothesis/TrigHLTJetHypo/src/JetGroupProduct.h b/Trigger/TrigHypothesis/TrigHLTJetHypo/src/JetGroupProduct.h index 2347b1ec06b27e5d4ac6f405b6dbdf87ec10a5bc..35f8fbeb03fec05da19ed9a481f675692b1fa787 100644 --- a/Trigger/TrigHypothesis/TrigHLTJetHypo/src/JetGroupProduct.h +++ b/Trigger/TrigHypothesis/TrigHLTJetHypo/src/JetGroupProduct.h @@ -7,6 +7,7 @@ #include "./IJetGroupProduct.h" #include "./ProductGen.h" +#include "./JetStreamer.h" #include "./DebugInfoCollector.h" #include "TrigHLTJetHypo/TrigHLTJetHypoUtils/HypoJetDefs.h" #include <vector> @@ -42,8 +43,15 @@ class JetGroupProduct: public IJetGroupProduct{ std::vector<std::vector<std::size_t>> m_condIndices; std::vector<bool> m_jetMask; std::size_t m_jetEnd{0}; - ProductGen m_productGen; + // ProductGen m_productGen; std::vector<std::vector<std::size_t>> m_seenIndices; + std::unique_ptr<JetStreamer> m_jetstreamer{nullptr}; + bool m_valid{false}; + + void init(const std::vector<std::size_t>& siblings, + const CondInd2JetGroupsInds& satisfiedBy, + const std::vector<std::size_t>& condMult + ); }; diff --git a/Trigger/TrigHypothesis/TrigHLTJetHypo/src/JetStreamer.cxx b/Trigger/TrigHypothesis/TrigHLTJetHypo/src/JetStreamer.cxx new file mode 100644 index 0000000000000000000000000000000000000000..6672d8a466151cb5a41e01b4229c3893f7b792ca --- /dev/null +++ b/Trigger/TrigHypothesis/TrigHLTJetHypo/src/JetStreamer.cxx @@ -0,0 +1,13 @@ +/* + Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration +*/ + + +#include "./JetStreamer.h" + + +std::ostream& operator << (std::ostream& os, const JetStreamer& js){ + os << "JetStreamer\n" << js.m_stream->dump() << '\n'; + return os; +} + diff --git a/Trigger/TrigHypothesis/TrigHLTJetHypo/src/JetStreamer.h b/Trigger/TrigHypothesis/TrigHLTJetHypo/src/JetStreamer.h new file mode 100644 index 0000000000000000000000000000000000000000..7c84da64ca1c75a46ca664ed74b00dd5b366808d --- /dev/null +++ b/Trigger/TrigHypothesis/TrigHLTJetHypo/src/JetStreamer.h @@ -0,0 +1,64 @@ +/* + Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef TRIGHLTJETHYPO_JETSTEAMER_H +#define TRIGHLTJETHYPO_JETSTEAMER_H + +/* + * JetStreamer owns a linked list of IJetStream objects. + * These provide vectors of indices according to the conrete types. + * The stream objects cycle, which allows for stepping through + * all possible combinations of jets. On each call to bump an element + * in the list informs its left neigbor if the fact. The + * the cycle state is relayed back to JetStreamer: when all elements + * in the list have cycled, the iteration stops. + */ + +#include "./IJetStream.h" +#include "./SimpleJetStream.h" +#include "./CombinationsJetStream.h" + +#include <sstream> +#include <ostream> + +class JetStreamer { + + public: + + friend std::ostream& operator << (std::ostream&, const JetStreamer&); + friend std::ostream& operator << (std::stringstream&, const JetStreamer&); + + + JetStreamer(std::unique_ptr<IJetStream>&& stream) : + m_stream(std::move(stream)) + { + m_valid = m_stream != nullptr and m_stream->valid(); + } + + + std::vector<std::size_t> next() { + + if (!m_valid) { + return std::vector<std::size_t>(); + } + + if (m_done) {return std::vector<std::size_t>();} + auto result = m_stream->get(); // stream always as legal data + + m_done = m_stream->bump(); + + return result; + } + + bool isValid() const {return m_valid;} + + private: + std::unique_ptr<IJetStream> m_stream; + bool m_done{false}; + bool m_valid{false}; +}; + +std::ostream& operator << (std::ostream&, const JetStreamer&); + +#endif diff --git a/Trigger/TrigHypothesis/TrigHLTJetHypo/src/SimpleJetStream.cxx b/Trigger/TrigHypothesis/TrigHLTJetHypo/src/SimpleJetStream.cxx new file mode 100644 index 0000000000000000000000000000000000000000..99bfe5e0410913e5729cc096c27d749dc9823b81 --- /dev/null +++ b/Trigger/TrigHypothesis/TrigHLTJetHypo/src/SimpleJetStream.cxx @@ -0,0 +1,26 @@ +/* + Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration +*/ + +#include "./SimpleJetStream.h" + +std::ostream& operator << (std::ostream& os , + const SimpleJetStream& js) { + + os << "SimpleJetStream id " << js.m_id + << " m_valid " << std::boolalpha << js.m_valid + << " no of jets: " << js.m_jets.size() + << " m_ind " << js.m_ind; + return os; +} + +std::stringstream& operator << (std::stringstream& os , + const SimpleJetStream& js) { + + os << "SimpleJetStream id " << js.m_id + << " m_valid " << std::boolalpha << js.m_valid + << " no of jets: " << js.m_jets.size() + << " m_ind " << js.m_ind; + return os; +} + diff --git a/Trigger/TrigHypothesis/TrigHLTJetHypo/src/SimpleJetStream.h b/Trigger/TrigHypothesis/TrigHLTJetHypo/src/SimpleJetStream.h new file mode 100644 index 0000000000000000000000000000000000000000..352661ab4a9962e7bf21e2fe4f9daa20334d7f14 --- /dev/null +++ b/Trigger/TrigHypothesis/TrigHLTJetHypo/src/SimpleJetStream.h @@ -0,0 +1,126 @@ +/* + Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef TRIGHLTJETHYPO_SIMPLEJETSTREAM_H +#define TRIGHLTJETHYPO_SIMPLEJETSTREAM_H + + +/* + * SimpleJetStream is an implementation of IJetStream. + + * On each call to bump(), it steps through its container of jet indices, + * making the current value + * available for collection. When it reaches the end, and moves + * back to the begining of its list. bump() returns the true when it has + * cycled, otherwise it returns false + * + */ + +#include "IJetStream.h" +#include <vector> +#include <sstream> +#include <memory> +#include <string> + +class SimpleJetStream: public IJetStream { + + public: + + + friend std::ostream& operator << (std::ostream&, + const SimpleJetStream&); + friend std::stringstream& operator << (std::stringstream&, + const SimpleJetStream&); + + SimpleJetStream(const std::vector<std::size_t>& jets, + std::unique_ptr<IJetStream> neigh, + std::size_t id): + m_jets(jets), + m_neigh(std::move(neigh)), + m_id{id} + { + m_valid = !jets.empty(); + if(m_valid) { + m_data = m_jets.at(0); + m_ind = 0; + } + } + + + virtual std::vector<std::size_t> get() override { + + auto result = m_neigh ? m_neigh->get() : std::vector<std::size_t>(); + result.push_back(m_data); + + return result; + } + + virtual bool bump() override { + // if there is a neighbor, try bumping it. + bool cycled{false}; + if (m_neigh) { + bool neigh_cycled = m_neigh->bump(); + + if (!neigh_cycled) {return false;} + + // neighbor has cycled as a result of bumping. + ++m_ind; + cycled = m_ind == m_jets.size(); + + if (cycled) {m_ind = 0;} + + m_data = m_jets.at(m_ind); + return cycled; + } else { + + // no neighbor + + ++m_ind; + + cycled = m_ind == m_jets.size(); + + if(cycled) { + m_ind = 0; + } + m_data = m_jets.at(m_ind); + return cycled; + } + } + + + + virtual bool valid() const override { + if (!m_valid) {return false;} + + if (m_neigh) {return m_neigh->valid();} + return true; + } + + virtual std::string dump() const override { + std::stringstream ss; + + auto result = m_neigh ? m_neigh->dump() : ""; + + ss<< *this << '\n'; + result += ss.str(); + + return result; + } + +private: + std::vector<std::size_t> m_jets; + std::size_t m_ind{0}; + std::unique_ptr<IJetStream> m_neigh{nullptr}; + std::size_t m_id; + std::size_t m_data; + bool m_valid{false}; + +}; + +std::ostream& operator << (std::ostream& os , + const SimpleJetStream& js); +std::stringstream& operator << (std::stringstream& os , + const SimpleJetStream& js); + +#endif diff --git a/Trigger/TrigHypothesis/TrigHLTJetHypo/src/make_jetstream.h b/Trigger/TrigHypothesis/TrigHLTJetHypo/src/make_jetstream.h new file mode 100644 index 0000000000000000000000000000000000000000..ec46fec8a166a4dc7f5c5554de91e7c55d9e5807 --- /dev/null +++ b/Trigger/TrigHypothesis/TrigHLTJetHypo/src/make_jetstream.h @@ -0,0 +1,72 @@ +/* + Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef TRIGHLTJETHYPO_MAKE_JETSTREAM_H +#define TRIGHLTJETHYPO_MAKE_JETSTREAM_H + +/* + * make_jetstream creates a linled list of IJetStreams. + * The first arguement of type vector<vector<std::size>> contains + * jet indices that pass a RepeatedCondition. There is one entry in the outer + * vector per Condition being considered. + * + * The vector<std:size_t> contains the repeat values of the RepeatedConditions. + * + * The concrete types in the list + * will be a SimpleJetStream if the repeat value for the corresponding + * Condition is 1, and a CombinationsJetStream otherwise. + */ + +#include "SimpleJetStream.h" +#include "CombinationsJetStream.h" +#include "JetStreamer.h" +#include <memory> +#include <vector> + +std::unique_ptr<IJetStream> +make_jetstream(std::vector<std::vector<std::size_t>> indices, + std::vector<std::size_t> repeats, + std::size_t sid) { + if (indices.size()==1) { + auto null_stream = std::unique_ptr<IJetStream>{nullptr}; + auto base_case = std::unique_ptr<IJetStream>(nullptr); + auto repeat = repeats.at(0); + if (repeat == 1) { + base_case.reset(new SimpleJetStream(indices.at(0), + std::move(null_stream), + sid)); + } else { + base_case.reset(new CombinationsJetStream(indices.at(0), + std::move(null_stream), + repeat, + sid)); + } + return base_case; + + } + + auto inds = indices.back(); + indices.pop_back(); + + auto repeat = repeats.back(); + repeats.pop_back(); + + auto n_sid = sid; + auto right_stream = make_jetstream(indices, repeats, ++n_sid); + auto stream = std::unique_ptr<IJetStream>(nullptr); + if (repeat == 1) { + stream.reset(new SimpleJetStream(inds, + std::move(right_stream), + sid)); + } else { + stream.reset(new CombinationsJetStream(inds, + std::move(right_stream), + repeat, + sid)); + } + + return stream; +} + +#endif diff --git a/Trigger/TrigHypothesis/TrigHLTJetHypoUnitTests/CMakeLists.txt b/Trigger/TrigHypothesis/TrigHLTJetHypoUnitTests/CMakeLists.txt index 7a86a159f64f0e97cfd695024676c9caa9164b97..4618282a5b57717406df07de6de54ac8f47df874 100644 --- a/Trigger/TrigHypothesis/TrigHLTJetHypoUnitTests/CMakeLists.txt +++ b/Trigger/TrigHypothesis/TrigHLTJetHypoUnitTests/CMakeLists.txt @@ -23,7 +23,7 @@ atlas_add_component( TrigHLTJetHypoUnitTests # Test(s) in the package: atlas_add_test( TrigHLTJetHypoUnitTests SOURCES tests/all_tests.cxx - tests/CombinationsGenTest.cxx + tests/CombinationsGeneratorTest.cxx tests/ProductGenTest.cxx tests/JetGroupProductTest.cxx tests/JetGroupUnionTest.cxx @@ -35,6 +35,8 @@ atlas_add_test( TrigHLTJetHypoUnitTests tests/PassThroughFilterTest.cxx tests/ConditionFilterTest.cxx tests/MultiFilterTest.cxx + tests/JetStreamerTest.cxx + tests/make_jetstreamTest.cxx INCLUDE_DIRS ${GMOCK_INCLUDE_DIRS} ${GTEST_INCLUDE_DIRS} ${ROOT_INCLUDE_DIRS} LINK_LIBRARIES ${GMOCK_LIBRARIES} ${GTEST_LIBRARIES} ${ROOT_LIBRARIES} TrigHLTJetHypoLib TrigHLTJetHypoUnitTestsLib xAODJet POST_EXEC_SCRIPT nopost.sh ) diff --git a/Trigger/TrigHypothesis/TrigHLTJetHypoUnitTests/tests/CombinationsGenTest.cxx b/Trigger/TrigHypothesis/TrigHLTJetHypoUnitTests/tests/CombinationsGenTest.cxx deleted file mode 100644 index d4effc409ba3023936b99251f07303cdc9d10412..0000000000000000000000000000000000000000 --- a/Trigger/TrigHypothesis/TrigHLTJetHypoUnitTests/tests/CombinationsGenTest.cxx +++ /dev/null @@ -1,48 +0,0 @@ -/* - Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration -*/ - -#include "gtest/gtest.h" -#include "TrigHLTJetHypo/TrigHLTJetHypoUtils/CombinationsGen.h" -#include <vector> - -using res = std::pair<std::vector<unsigned int>, bool>; -using vec = std::vector<unsigned int>; - -TEST(CombinationsGenTester, n3k1) { - CombinationsGen gen(3,1); - EXPECT_EQ (res(vec{0}, true), gen.next()); - EXPECT_EQ (res(vec{1}, true), gen.next()); - EXPECT_EQ (res(vec{2}, true), gen.next()); - res r = gen.next(); - EXPECT_EQ (r.second, false); -} - -TEST(CombinationsGenTester, n3k2) { - CombinationsGen gen(3,2); - EXPECT_EQ (res(vec{0,1}, true), gen.next()); - EXPECT_EQ (res(vec{0,2}, true), gen.next()); - EXPECT_EQ (res(vec{1,2}, true), gen.next()); - res r = gen.next(); - EXPECT_EQ (r.second, false); -} - - -TEST(CombinationsGenTester, n3k3) { - CombinationsGen gen(3,3); - EXPECT_EQ (res(vec{0,1, 2}, true), gen.next()); - res r = gen.next(); - EXPECT_EQ (r.second, false); -} - -TEST(CombinationsGenTester, n3k0) { - CombinationsGen gen(3,0); - EXPECT_EQ (res(vec{}, true), gen.next()); - res r = gen.next(); - EXPECT_EQ (r.second, false); -} - -TEST(CombinationsGenTester, n3kgtn) { - CombinationsGen gen(3,4); - EXPECT_FALSE(gen.next().second); -} diff --git a/Trigger/TrigHypothesis/TrigHLTJetHypoUnitTests/tests/CombinationsGeneratorTest.cxx b/Trigger/TrigHypothesis/TrigHLTJetHypoUnitTests/tests/CombinationsGeneratorTest.cxx new file mode 100644 index 0000000000000000000000000000000000000000..c472146adfdc133b8b7ff548c98772da7d9ac19d --- /dev/null +++ b/Trigger/TrigHypothesis/TrigHLTJetHypoUnitTests/tests/CombinationsGeneratorTest.cxx @@ -0,0 +1,57 @@ +/* + Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration +*/ + +#include "gtest/gtest.h" +#include "TrigHLTJetHypo/../src/CombinationsGenerator.h" +#include <vector> + +using vec = std::vector<size_t>; + +TEST(CombinationsGeneratorTester, n3k1) { + CombinationsGenerator gen(3,1); + // return value from bump() says whether the generator has cycled. + EXPECT_EQ (vec{0}, gen.get()); + EXPECT_EQ (false, gen.bump()); + EXPECT_EQ (vec{1}, gen.get()); + EXPECT_EQ (false, gen.bump()); + EXPECT_EQ (vec{2}, gen.get()); + EXPECT_EQ (true, gen.bump()); +} + +TEST(CombinationsGeneratorTester, n3k2) { + CombinationsGenerator gen(3,2); + vec v0 {0,1}; + vec v1 {0,2}; + vec v2 {1,2}; + EXPECT_EQ (v0, gen.get()); + EXPECT_EQ (false, gen.bump()); + EXPECT_EQ (v1, gen.get()); + EXPECT_EQ (false, gen.bump()); + EXPECT_EQ (v2, gen.get()); + EXPECT_EQ (true, gen.bump()); +} + +TEST(CombinationsGeneratorTester, n3k3) { + CombinationsGenerator gen(3,3); + vec v0 {0,1,2}; + EXPECT_EQ (v0, gen.get()); + EXPECT_EQ (true, gen.bump()); +} + +TEST(CombinationsGeneratorTester, n3k0) { + CombinationsGenerator gen(3,0); + vec v0 {}; + EXPECT_EQ (v0, gen.get()); + EXPECT_EQ (true, gen.bump()); +} + +TEST(CombinationsGeneratorTester, n3k4) { + CombinationsGenerator gen(3,4); + vec v0 {}; + EXPECT_EQ (v0, gen.get()); + EXPECT_EQ (true, gen.bump()); +} + + + diff --git a/Trigger/TrigHypothesis/TrigHLTJetHypoUnitTests/tests/JetGroupProductTest.cxx b/Trigger/TrigHypothesis/TrigHLTJetHypoUnitTests/tests/JetGroupProductTest.cxx index 03b8d76f59fd69503832805617fec5ee084c7a6c..3d099f22b032a72940e29c1a1277d524a663e258 100644 --- a/Trigger/TrigHypothesis/TrigHLTJetHypoUnitTests/tests/JetGroupProductTest.cxx +++ b/Trigger/TrigHypothesis/TrigHLTJetHypoUnitTests/tests/JetGroupProductTest.cxx @@ -24,7 +24,7 @@ TEST(JetGroupProductTester, empty) { -TEST(JetGroupProductTester, onecond) { +TEST(JetGroupProductTester, onecondition) { std::vector<std::size_t> siblings{0}; CondInd2JetGroupsInds satisfiedBy; diff --git a/Trigger/TrigHypothesis/TrigHLTJetHypoUnitTests/tests/JetStreamerTest.cxx b/Trigger/TrigHypothesis/TrigHLTJetHypoUnitTests/tests/JetStreamerTest.cxx new file mode 100644 index 0000000000000000000000000000000000000000..517e1d6c677b27e77be81d70dae9df6d57f7e7bc --- /dev/null +++ b/Trigger/TrigHypothesis/TrigHLTJetHypoUnitTests/tests/JetStreamerTest.cxx @@ -0,0 +1,337 @@ +/* + Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration +*/ + +#include "gtest/gtest.h" +#include "TrigHLTJetHypo/../src/JetStreamer.h" +#include "TrigHLTJetHypo/../src/IJetStream.h" +#include <vector> +#include <memory> + +using vec = std::vector<std::size_t>; + +std::unique_ptr<JetStreamer> make_streamer(int test){ + + auto null_stream = std::unique_ptr<IJetStream>{nullptr}; + + auto streamer = std::unique_ptr<JetStreamer> (nullptr); + + if (test == 0) { + std::vector<std::size_t> jets0 {1, 2}; + + std::cerr <<"test0\n"; + + auto stream0 = std::make_unique<SimpleJetStream>(jets0, + std::move(null_stream), + 0 + ); + streamer = std::make_unique<JetStreamer>(std::move(stream0)); + + return streamer; + } else if (test == 1) { + + std::vector<std::size_t> jets_cs {5, 6, 7}; + std::size_t k2{2}; + + auto stream0 = + std::make_unique<CombinationsJetStream>(jets_cs, + std::move(null_stream), + k2, + 0 + ); + streamer.reset(new JetStreamer(std::move(stream0))); + return streamer; + } else if (test == 2) { + + std::vector<std::size_t> jets0 {1, 2}; + std::vector<std::size_t> jets1 {3, 4}; + auto stream1 = + std::make_unique<SimpleJetStream>(jets1, + std::move(null_stream), + 1 + ); + + + auto stream0 = + std::make_unique<SimpleJetStream>(jets0, + std::move(stream1), + 0 + ); + + streamer.reset(new JetStreamer(std::move(stream0))); + return streamer; + } else if (test == 3) { + + std::vector<std::size_t> jets_cs {5, 6, 7}; + std::size_t k2{2}; + std::vector<std::size_t> jets0 {1, 2}; + + + + auto stream1 = + std::make_unique<CombinationsJetStream>(jets_cs, + std::move(null_stream), + k2, + 1 + ); + + + auto stream0 = + std::make_unique<SimpleJetStream>(jets0, + std::move(stream1), + 0 + ); + + streamer.reset(new JetStreamer(std::move(stream0))); + return streamer; + } else if (test == 4) { + + std::vector<std::size_t> jets_cs {5, 6, 7}; + std::size_t k2{2}; + std::vector<std::size_t> jets0 {1, 2}; + + + auto stream1 = + std::make_unique<SimpleJetStream>(jets0, + std::move(null_stream), + 1 + ); + + + auto stream0 = + std::make_unique<CombinationsJetStream>(jets_cs, + std::move(stream1), + k2, + 0 + ); + + streamer.reset(new JetStreamer(std::move(stream0))); + return streamer; + } else if (test == 5) { + + + std::vector<std::size_t> jets_cs {5, 6, 7}; + std::size_t k2{2}; + std::vector<std::size_t> jets0 {1, 2}; + std::vector<std::size_t> jets1 {3, 4}; + + auto stream2 = + std::make_unique<SimpleJetStream>(jets1, + std::move(null_stream), + 2 + ); + + auto stream1 = + std::make_unique<CombinationsJetStream>(jets_cs, + std::move(stream2), + k2, + 1 + ); + + + auto stream0 = + std::make_unique<SimpleJetStream>(jets0, + std::move(stream1), + 0 + ); + + streamer.reset(new JetStreamer(std::move(stream0))); + + return streamer; + } else if (test == 6) { + + + std::vector<std::size_t> jets_cs {}; + std::size_t k2{2}; + std::vector<std::size_t> jets0 {1, 2}; + std::vector<std::size_t> jets1 {3, 4}; + + auto stream2 = + std::make_unique<SimpleJetStream>(jets1, + std::move(null_stream), + 2 + ); + + auto stream1 = + std::make_unique<CombinationsJetStream>(jets_cs, + std::move(stream2), + k2, + 1 + ); + + + auto stream0 = + std::make_unique<SimpleJetStream>(jets0, + std::move(stream1), + 0 + ); + + streamer.reset(new JetStreamer(std::move(stream0))); + + return streamer; + } else if (test == 7) { + + + std::vector<std::size_t> jets_cs {5, 6, 7}; + std::size_t k4{4}; + std::vector<std::size_t> jets0 {1, 2}; + std::vector<std::size_t> jets1 {3, 4}; + + auto stream2 = + std::make_unique<SimpleJetStream>(jets1, + std::move(null_stream), + 2 + ); + + auto stream1 = + std::make_unique<CombinationsJetStream>(jets_cs, + std::move(stream2), + k4, + 1 + ); + + + auto stream0 = + std::make_unique<SimpleJetStream>(jets0, + std::move(stream1), + 0 + ); + + streamer.reset(new JetStreamer(std::move(stream0))); + + return streamer; + } else if (test == 8) { + + auto stream0 = std::unique_ptr<IJetStream>(nullptr); + streamer.reset(new JetStreamer(std::move(stream0))); + return streamer; + } else { + std::cerr << "unknown test << " << test << '\n'; + return streamer; + } +} + +TEST(JetStreamerTester, oneSimpleJetStream) { + // Cycle around the input vector + auto streamer = make_streamer(0); + EXPECT_EQ (vec{1}, streamer->next()); + EXPECT_EQ (vec{2}, streamer->next()); + EXPECT_EQ (vec{}, streamer->next()); +} + + +TEST(JetStreamerTester, oneCombinationsJetStream) { + // Cycle around the input vector + auto streamer = make_streamer(1); + vec v0{5, 6}; + vec v1{5, 7}; + vec v2{6, 7}; + EXPECT_EQ (v0, streamer->next()); + EXPECT_EQ (v1, streamer->next()); + EXPECT_EQ (v2, streamer->next()); + EXPECT_EQ (vec{}, streamer->next()); +} + + +TEST(JetStreamerTester, twoSimpleJetStreams) { + // Cycle around the input vector + auto streamer = make_streamer(2); + vec v0{3, 1}; + vec v1{4, 1}; + vec v2{3, 2}; + vec v3{4, 2}; + + EXPECT_EQ (v0, streamer->next()); + EXPECT_EQ (v1, streamer->next()); + EXPECT_EQ (v2, streamer->next()); + EXPECT_EQ (v3, streamer->next()); + EXPECT_EQ (vec{}, streamer->next()); +} + +TEST(JetStreamerTester, SimpleThenCombinationsJetStreams) { + // Cycle around the input vector + auto streamer = make_streamer(3); + vec v0{5, 6, 1}; + vec v1{5, 7, 1}; + vec v2{6, 7, 1}; + vec v3{5, 6, 2}; + vec v4{5, 7, 2}; + vec v5{6, 7, 2}; + + EXPECT_EQ (v0, streamer->next()); + EXPECT_EQ (v1, streamer->next()); + EXPECT_EQ (v2, streamer->next()); + EXPECT_EQ (v3, streamer->next()); + EXPECT_EQ (v4, streamer->next()); + EXPECT_EQ (v5, streamer->next()); + EXPECT_EQ (vec{}, streamer->next()); +} + +TEST(JetStreamerTester, CombinationsThenSimpleJetStreams) { + // Cycle around the input vector + auto streamer = make_streamer(4); + vec v0{1, 5, 6}; + vec v1{2, 5, 6}; + vec v2{1, 5, 7}; + vec v3{2, 5, 7}; + vec v4{1, 6, 7}; + vec v5{2, 6, 7}; + + EXPECT_EQ (v0, streamer->next()); + EXPECT_EQ (v1, streamer->next()); + EXPECT_EQ (v2, streamer->next()); + EXPECT_EQ (v3, streamer->next()); + EXPECT_EQ (v4, streamer->next()); + EXPECT_EQ (v5, streamer->next()); + EXPECT_EQ (vec{}, streamer->next()); +} + +TEST(JetStreamerTester, SimmpleThenCombinationsThenSimpleJetStreams) { + // Cycle around the input vector + auto streamer = make_streamer(5); + vec v0{3, 5, 6, 1}; + vec v1{4, 5, 6, 1}; + vec v2{3, 5, 7, 1}; + vec v3{4, 5, 7, 1}; + vec v4{3, 6, 7, 1}; + vec v5{4, 6, 7, 1}; + vec v6{3, 5, 6, 2}; + vec v7{4, 5, 6, 2}; + vec v8{3, 5, 7, 2}; + vec v9{4, 5, 7, 2}; + vec v10{3, 6, 7, 2}; + vec v11{4, 6, 7, 2}; + + EXPECT_EQ (v0, streamer->next()); + EXPECT_EQ (v1, streamer->next()); + EXPECT_EQ (v2, streamer->next()); + EXPECT_EQ (v3, streamer->next()); + EXPECT_EQ (v4, streamer->next()); + EXPECT_EQ (v5, streamer->next()); + EXPECT_EQ (v6, streamer->next()); + EXPECT_EQ (v7, streamer->next()); + EXPECT_EQ (v8, streamer->next()); + EXPECT_EQ (v9, streamer->next()); + EXPECT_EQ (v10, streamer->next()); + EXPECT_EQ (v11, streamer->next()); + EXPECT_EQ (vec{}, streamer->next()); +} + +TEST(JetStreamerTester, InvalidJetIndices) { + // Cycle around the input vector + auto streamer = make_streamer(6); + EXPECT_EQ (vec{}, streamer->next()); +} + + +TEST(JetStreamerTester, InvalidNchooseK) { + // Cycle around the input vector + auto streamer = make_streamer(7); + EXPECT_EQ (vec{}, streamer->next()); +} + +TEST(JetStreamerTester, InvalidJetStream) { + // Cycle around the input vector + auto streamer = make_streamer(8); + EXPECT_EQ (vec{}, streamer->next()); +} diff --git a/Trigger/TrigHypothesis/TrigHLTJetHypoUnitTests/tests/make_jetstreamTest.cxx b/Trigger/TrigHypothesis/TrigHLTJetHypoUnitTests/tests/make_jetstreamTest.cxx new file mode 100644 index 0000000000000000000000000000000000000000..2b5c5c4b4f9c6bf6b1b8708a7e141bff475c107c --- /dev/null +++ b/Trigger/TrigHypothesis/TrigHLTJetHypoUnitTests/tests/make_jetstreamTest.cxx @@ -0,0 +1,100 @@ +/* + Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration +*/ + +#include "gtest/gtest.h" +#include "TrigHLTJetHypo/../src/make_jetstream.h" +#include <vector> +#include <memory> + +using vec = std::vector<std::size_t>; + +TEST(make_jetstreamTester, SimpleSimpleSimpleChain) { + + std::vector<std::vector<std::size_t>> v; + v.push_back(std::vector<std::size_t>{1,2}); + v.push_back(std::vector<std::size_t>{3,4, 5}); + v.push_back(std::vector<std::size_t>{6,7}); + + std::vector<std::size_t> repeats{1,1,1}; + + std::size_t sid{0}; + + auto stream = make_jetstream(v, repeats, sid); + + JetStreamer streamer(std::move(stream)); + + vec v0{1, 3, 6}; + vec v1{2, 3, 6}; + vec v2{1, 4, 6}; + vec v3{2, 4, 6}; + vec v4{1, 5, 6}; + vec v5{2, 5, 6}; + vec v6{1, 3, 7}; + vec v7{2, 3, 7}; + vec v8{1, 4, 7}; + vec v9{2, 4, 7}; + vec v10{1, 5, 7}; + vec v11{2, 5, 7}; + + + EXPECT_EQ (v0, streamer.next()); + EXPECT_EQ (v1, streamer.next()); + EXPECT_EQ (v2, streamer.next()); + EXPECT_EQ (v3, streamer.next()); + EXPECT_EQ (v4, streamer.next()); + EXPECT_EQ (v5, streamer.next()); + EXPECT_EQ (v6, streamer.next()); + EXPECT_EQ (v7, streamer.next()); + EXPECT_EQ (v8, streamer.next()); + EXPECT_EQ (v9, streamer.next()); + EXPECT_EQ (v10, streamer.next()); + EXPECT_EQ (v11, streamer.next()); + + EXPECT_EQ (vec{}, streamer.next()); +} + + +TEST(make_jetstreamTester, SimpleCompoundSimpleChain) { + std::vector<std::vector<std::size_t>> v; + v.push_back(std::vector<std::size_t>{1,2}); + v.push_back(std::vector<std::size_t>{3,4, 5}); + v.push_back(std::vector<std::size_t>{6,7}); + + std::vector<std::size_t> repeats{1,2,1}; + + std::size_t sid{0}; + + auto stream = make_jetstream(v, repeats, sid); + + JetStreamer streamer(std::move(stream)); + + vec v0{1, 3, 4, 6}; + vec v1{2, 3, 4, 6}; + vec v2{1, 3, 5, 6}; + vec v3{2, 3, 5, 6}; + vec v4{1, 4, 5, 6}; + vec v5{2, 4, 5, 6}; + vec v6{1, 3, 4, 7}; + vec v7{2, 3, 4, 7}; + vec v8{1, 3, 5, 7}; + vec v9{2, 3, 5, 7}; + vec v10{1, 4, 5, 7}; + vec v11{2, 4, 5, 7}; + + EXPECT_EQ (v0, streamer.next()); + EXPECT_EQ (v1, streamer.next()); + EXPECT_EQ (v2, streamer.next()); + EXPECT_EQ (v3, streamer.next()); + EXPECT_EQ (v4, streamer.next()); + EXPECT_EQ (v5, streamer.next()); + EXPECT_EQ (v6, streamer.next()); + EXPECT_EQ (v7, streamer.next()); + EXPECT_EQ (v8, streamer.next()); + EXPECT_EQ (v9, streamer.next()); + EXPECT_EQ (v10, streamer.next()); + EXPECT_EQ (v11, streamer.next()); + + EXPECT_EQ (vec{}, streamer.next()); +} +