From 7ed62d7ff819b31b2217bf65be5995cbb3bef42d Mon Sep 17 00:00:00 2001 From: Peter Sherwood <peter.sherwood@cern.ch> Date: Sat, 5 Mar 2022 18:22:13 +0100 Subject: [PATCH 1/4] Jet hypo change the algorithm to calculate jet combinations Before this commit - take all combinations sfter unrolling The jets associated with a RepeatedCondition with repeat value > 1. For such Conditions, now use an NchooseK index generator. This reduces, sometimes drastically the number of combaintions due to duplicate jet indices, or due to regenerating the same cmbination many times. The new system uses a link list of jet indices selectors (JetStreams). The chain is driben ba a JetStreamer instance. The elements of the list are of type SimpleJetStream if the Condition repeat value is 1, and a CombinationsJetStreamer otherwise. New streamer code: new file: TrigHLTJetHypo/src/CombinationsGenerator.cxx new file: TrigHLTJetHypo/src/CombinationsGenerator.h new file: TrigHLTJetHypo/src/CombinationsJetStream.cxx new file: TrigHLTJetHypo/src/CombinationsJetStream.h new file: TrigHLTJetHypo/src/IJetStream.h new file: TrigHLTJetHypo/src/JetStreamer.cxx new file: TrigHLTJetHypo/src/JetStreamer.h new file: TrigHLTJetHypo/src/SimpleJetStream.cxx new file: TrigHLTJetHypo/src/SimpleJetStream.h new file: TrigHLTJetHypo/src/make_jetstream.h Modified Jet hypo code: modified: TrigHLTJetHypo/src/JetGroupProduct.cxx modified: TrigHLTJetHypo/src/JetGroupProduct.h New unit testing code modified: TrigHLTJetHypoUnitTests/CMakeLists.txt deleted: TrigHLTJetHypoUnitTests/tests/CombinationsGenTest.cxx new file: TrigHLTJetHypoUnitTests/tests/CombinationsGeneratorTest.cxx modified: TrigHLTJetHypoUnitTests/tests/JetGroupProductTest.cxx new file: TrigHLTJetHypoUnitTests/tests/JetStreamerTest.cxx new file: TrigHLTJetHypoUnitTests/tests/make_jetstreamTest.cxx Updated/fixed Unit testing code modified: TrigHLTJetHypoUnitTests/tests/JetGroupProductTest.cxx deleted: TrigHLTJetHypoUnitTests/tests/CombinationsGenTest.cxx --- .../python/TrigJetHypoToolConfig.py | 2 +- .../src/CombinationsGenerator.cxx | 24 ++ .../src/CombinationsGenerator.h | 87 +++++ .../src/CombinationsJetStream.cxx | 22 ++ .../src/CombinationsJetStream.h | 151 ++++++++ .../TrigHLTJetHypo/src/IJetStream.h | 40 +++ .../TrigHLTJetHypo/src/JetGroupProduct.cxx | 87 +++-- .../TrigHLTJetHypo/src/JetGroupProduct.h | 10 +- .../TrigHLTJetHypo/src/JetStreamer.cxx | 13 + .../TrigHLTJetHypo/src/JetStreamer.h | 64 ++++ .../TrigHLTJetHypo/src/SimpleJetStream.cxx | 26 ++ .../TrigHLTJetHypo/src/SimpleJetStream.h | 126 +++++++ .../TrigHLTJetHypo/src/make_jetstream.h | 72 ++++ .../TrigHLTJetHypoUnitTests/CMakeLists.txt | 4 +- .../tests/CombinationsGenTest.cxx | 48 --- .../tests/CombinationsGeneratorTest.cxx | 76 ++++ .../tests/JetGroupProductTest.cxx | 2 +- .../tests/JetStreamerTest.cxx | 337 ++++++++++++++++++ .../tests/make_jetstreamTest.cxx | 100 ++++++ 19 files changed, 1219 insertions(+), 72 deletions(-) create mode 100644 Trigger/TrigHypothesis/TrigHLTJetHypo/src/CombinationsGenerator.cxx create mode 100644 Trigger/TrigHypothesis/TrigHLTJetHypo/src/CombinationsGenerator.h create mode 100644 Trigger/TrigHypothesis/TrigHLTJetHypo/src/CombinationsJetStream.cxx create mode 100644 Trigger/TrigHypothesis/TrigHLTJetHypo/src/CombinationsJetStream.h create mode 100644 Trigger/TrigHypothesis/TrigHLTJetHypo/src/IJetStream.h create mode 100644 Trigger/TrigHypothesis/TrigHLTJetHypo/src/JetStreamer.cxx create mode 100644 Trigger/TrigHypothesis/TrigHLTJetHypo/src/JetStreamer.h create mode 100644 Trigger/TrigHypothesis/TrigHLTJetHypo/src/SimpleJetStream.cxx create mode 100644 Trigger/TrigHypothesis/TrigHLTJetHypo/src/SimpleJetStream.h create mode 100644 Trigger/TrigHypothesis/TrigHLTJetHypo/src/make_jetstream.h delete mode 100644 Trigger/TrigHypothesis/TrigHLTJetHypoUnitTests/tests/CombinationsGenTest.cxx create mode 100644 Trigger/TrigHypothesis/TrigHLTJetHypoUnitTests/tests/CombinationsGeneratorTest.cxx create mode 100644 Trigger/TrigHypothesis/TrigHLTJetHypoUnitTests/tests/JetStreamerTest.cxx create mode 100644 Trigger/TrigHypothesis/TrigHLTJetHypoUnitTests/tests/make_jetstreamTest.cxx diff --git a/Trigger/TrigHypothesis/TrigHLTJetHypo/python/TrigJetHypoToolConfig.py b/Trigger/TrigHypothesis/TrigHLTJetHypo/python/TrigJetHypoToolConfig.py index ffb1c6be9b63..fd9133baf121 100644 --- a/Trigger/TrigHypothesis/TrigHLTJetHypo/python/TrigJetHypoToolConfig.py +++ b/Trigger/TrigHypothesis/TrigHLTJetHypo/python/TrigJetHypoToolConfig.py @@ -10,7 +10,7 @@ from AthenaCommon.Logging import logging logger = logging.getLogger(__name__) -debug = False # SET TO FALSE WHEN COMMITTING +debug = True # SET TO FALSE WHEN COMMITTING if debug: from AthenaCommon.Constants import DEBUG logger.setLevel(DEBUG) diff --git a/Trigger/TrigHypothesis/TrigHLTJetHypo/src/CombinationsGenerator.cxx b/Trigger/TrigHypothesis/TrigHLTJetHypo/src/CombinationsGenerator.cxx new file mode 100644 index 000000000000..d833eaf7ef19 --- /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 000000000000..70977e13c40a --- /dev/null +++ b/Trigger/TrigHypothesis/TrigHLTJetHypo/src/CombinationsGenerator.h @@ -0,0 +1,87 @@ +/* + 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){ + // m_cycled{false}, m_invalid{false}{ + + // 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 000000000000..ca64fa05da4e --- /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 000000000000..41920b92fed7 --- /dev/null +++ b/Trigger/TrigHypothesis/TrigHLTJetHypo/src/CombinationsJetStream.h @@ -0,0 +1,151 @@ +/* + 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(); + // cycled = m_combgen->cycled(); + + // if (cycled) { + // m_combgen->reset(); + // } + 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(); + // cycled = m_combgen->cycled(); + // if (cycled) { + // m_combgen->reset(); + // } + + 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 000000000000..2e49923d6786 --- /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 6d6f8ec79ee7..b301218327a6 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,6 +46,7 @@ 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)); } @@ -32,17 +54,23 @@ JetGroupProduct::JetGroupProduct(const std::vector<std::size_t>& siblings, // 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()); - } + // 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); + // m_productGen = ProductGen(ends); + + //std::vector<std::size_t> repeats(m_condIndices.size(), 1); + + + 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 +85,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 +96,43 @@ 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 - } + // 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]) { + // blocked = true; + // break; + // } + // + // + // m_jetMask[idx] = true; + // } - // 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 2347b1ec06b2..35f8fbeb03fe 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 000000000000..6672d8a46615 --- /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 000000000000..7c84da64ca1c --- /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 000000000000..99bfe5e04109 --- /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 000000000000..352661ab4a99 --- /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 000000000000..ec46fec8a166 --- /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 7a86a159f64f..4618282a5b57 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 d4effc409ba3..000000000000 --- 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 000000000000..ac959e1ae02b --- /dev/null +++ b/Trigger/TrigHypothesis/TrigHLTJetHypoUnitTests/tests/CombinationsGeneratorTest.cxx @@ -0,0 +1,76 @@ +/* + 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()); +} + + +/* +TEST(CombinationsGeneratorTester, n3k3) { + CombinationsGenerator gen(3,3); + EXPECT_EQ (res(vec{0,1, 2}, true), gen.next()); + res r = gen.next(); + EXPECT_EQ (r.second, false); +cd} + +TEST(CombinationsGeneratorTester, n3k0) { + CombinationsGenerator gen(3,0); + EXPECT_EQ (res(vec{}, true), gen.next()); + res r = gen.next(); + EXPECT_EQ (r.second, false); +} + +TEST(CombinationsGeneratorTester, n3kgtn) { + CombinationsGenerator gen(3,4); + EXPECT_FALSE(gen.next().second); +} +*/ diff --git a/Trigger/TrigHypothesis/TrigHLTJetHypoUnitTests/tests/JetGroupProductTest.cxx b/Trigger/TrigHypothesis/TrigHLTJetHypoUnitTests/tests/JetGroupProductTest.cxx index 03b8d76f59fd..3d099f22b032 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 000000000000..517e1d6c677b --- /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 000000000000..2b5c5c4b4f9c --- /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()); +} + -- GitLab From f91b24f76e04a435b1f00c2bf7454c1452d1a75a Mon Sep 17 00:00:00 2001 From: Peter Sherwood <peter.sherwood@cern.ch> Date: Sat, 5 Mar 2022 21:52:12 +0100 Subject: [PATCH 2/4] set the jet hypo debug flag to False --- .../TrigHLTJetHypo/python/TrigJetHypoToolConfig.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Trigger/TrigHypothesis/TrigHLTJetHypo/python/TrigJetHypoToolConfig.py b/Trigger/TrigHypothesis/TrigHLTJetHypo/python/TrigJetHypoToolConfig.py index fd9133baf121..ffb1c6be9b63 100644 --- a/Trigger/TrigHypothesis/TrigHLTJetHypo/python/TrigJetHypoToolConfig.py +++ b/Trigger/TrigHypothesis/TrigHLTJetHypo/python/TrigJetHypoToolConfig.py @@ -10,7 +10,7 @@ from AthenaCommon.Logging import logging logger = logging.getLogger(__name__) -debug = True # SET TO FALSE WHEN COMMITTING +debug = False # SET TO FALSE WHEN COMMITTING if debug: from AthenaCommon.Constants import DEBUG logger.setLevel(DEBUG) -- GitLab From b608f45813fef1bf77627066667acfdcd80e6caa Mon Sep 17 00:00:00 2001 From: Peter Sherwood <peter.sherwood@cern.ch> Date: Mon, 7 Mar 2022 15:55:05 +0100 Subject: [PATCH 3/4] jet hypo - remove commented-out code --- .../src/CombinationsGenerator.h | 3 +- .../src/CombinationsJetStream.h | 4 --- .../TrigHLTJetHypo/src/JetGroupProduct.cxx | 34 ------------------- .../tests/CombinationsGeneratorTest.cxx | 19 ----------- 4 files changed, 1 insertion(+), 59 deletions(-) diff --git a/Trigger/TrigHypothesis/TrigHLTJetHypo/src/CombinationsGenerator.h b/Trigger/TrigHypothesis/TrigHLTJetHypo/src/CombinationsGenerator.h index 70977e13c40a..b7ea1d090489 100644 --- a/Trigger/TrigHypothesis/TrigHLTJetHypo/src/CombinationsGenerator.h +++ b/Trigger/TrigHypothesis/TrigHLTJetHypo/src/CombinationsGenerator.h @@ -28,9 +28,8 @@ class CombinationsGenerator { CombinationsGenerator(std::size_t n, std::size_t k): m_invalid{false}, m_N{n}, m_K(k){ - // m_cycled{false}, m_invalid{false}{ - // if n==k, std::prev_permutations never returns false, + // 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; diff --git a/Trigger/TrigHypothesis/TrigHLTJetHypo/src/CombinationsJetStream.h b/Trigger/TrigHypothesis/TrigHLTJetHypo/src/CombinationsJetStream.h index 41920b92fed7..163b82fe01aa 100644 --- a/Trigger/TrigHypothesis/TrigHLTJetHypo/src/CombinationsJetStream.h +++ b/Trigger/TrigHypothesis/TrigHLTJetHypo/src/CombinationsJetStream.h @@ -80,11 +80,7 @@ class CombinationsJetStream: public IJetStream { if (!neigh_cycled) {return false;} cycled = m_combgen->bump(); - // cycled = m_combgen->cycled(); - // if (cycled) { - // m_combgen->reset(); - // } auto indices = m_combgen->get(); m_data.clear(); for (const auto i : indices) {m_data.push_back(m_jets.at(i));} diff --git a/Trigger/TrigHypothesis/TrigHLTJetHypo/src/JetGroupProduct.cxx b/Trigger/TrigHypothesis/TrigHLTJetHypo/src/JetGroupProduct.cxx index b301218327a6..4d0672e88c86 100644 --- a/Trigger/TrigHypothesis/TrigHLTJetHypo/src/JetGroupProduct.cxx +++ b/Trigger/TrigHypothesis/TrigHLTJetHypo/src/JetGroupProduct.cxx @@ -52,22 +52,6 @@ void JetGroupProduct::init(const std::vector<std::size_t>& siblings, } } - // 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); - - //std::vector<std::size_t> repeats(m_condIndices.size(), 1); - auto stream = make_jetstream(condIndices, repeats, 0); m_jetstreamer.reset(new JetStreamer(std::move(stream))); @@ -99,24 +83,6 @@ std::vector<std::size_t> JetGroupProduct::next(const Collector& collector){ "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]) { - // blocked = true; - // break; - // } - // - // - // m_jetMask[idx] = true; - // } bool blocked{false}; auto jet_indices = m_jetstreamer->next(); diff --git a/Trigger/TrigHypothesis/TrigHLTJetHypoUnitTests/tests/CombinationsGeneratorTest.cxx b/Trigger/TrigHypothesis/TrigHLTJetHypoUnitTests/tests/CombinationsGeneratorTest.cxx index ac959e1ae02b..c472146adfdc 100644 --- a/Trigger/TrigHypothesis/TrigHLTJetHypoUnitTests/tests/CombinationsGeneratorTest.cxx +++ b/Trigger/TrigHypothesis/TrigHLTJetHypoUnitTests/tests/CombinationsGeneratorTest.cxx @@ -54,23 +54,4 @@ TEST(CombinationsGeneratorTester, n3k4) { } -/* -TEST(CombinationsGeneratorTester, n3k3) { - CombinationsGenerator gen(3,3); - EXPECT_EQ (res(vec{0,1, 2}, true), gen.next()); - res r = gen.next(); - EXPECT_EQ (r.second, false); -cd} - -TEST(CombinationsGeneratorTester, n3k0) { - CombinationsGenerator gen(3,0); - EXPECT_EQ (res(vec{}, true), gen.next()); - res r = gen.next(); - EXPECT_EQ (r.second, false); -} -TEST(CombinationsGeneratorTester, n3kgtn) { - CombinationsGenerator gen(3,4); - EXPECT_FALSE(gen.next().second); -} -*/ -- GitLab From 65115514b7aa12ae7b94f2d146e9e80167ab8def Mon Sep 17 00:00:00 2001 From: Peter Sherwood <peter.sherwood@cern.ch> Date: Mon, 7 Mar 2022 16:03:08 +0100 Subject: [PATCH 4/4] jet hypo commit file overlooked in the last commit (dead code removal) --- .../TrigHypothesis/TrigHLTJetHypo/src/CombinationsJetStream.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Trigger/TrigHypothesis/TrigHLTJetHypo/src/CombinationsJetStream.h b/Trigger/TrigHypothesis/TrigHLTJetHypo/src/CombinationsJetStream.h index 163b82fe01aa..b8fbba68c062 100644 --- a/Trigger/TrigHypothesis/TrigHLTJetHypo/src/CombinationsJetStream.h +++ b/Trigger/TrigHypothesis/TrigHLTJetHypo/src/CombinationsJetStream.h @@ -88,10 +88,6 @@ class CombinationsJetStream: public IJetStream { } else { // no neighbor cycled = m_combgen->bump(); - // cycled = m_combgen->cycled(); - // if (cycled) { - // m_combgen->reset(); - // } auto indices = m_combgen->get(); m_data.clear(); -- GitLab