Skip to content
Snippets Groups Projects
Commit 2548003a authored by Rainer Kartmann's avatar Rainer Kartmann
Browse files

Revise interface of memory id lookups

parent f9f57d48
No related branches found
No related tags found
1 merge request!244Improve armem prediction interface
...@@ -32,10 +32,18 @@ namespace armarx::armem ...@@ -32,10 +32,18 @@ namespace armarx::armem
namespace detail namespace detail
{ {
template <class KeyT, class ValueT>
struct MapRef
{
KeyT* key;
ValueT* value;
};
/** /**
* @brief Get the key-value pair from the map for which the returned key * @brief Get the entry in the map for which the returned key is the longest prefix
* is the longest prefix of the given key among the keys in the map. * of the given key among the keys in the map.
* *
* `prefixFunc` is used to successively calculate the prefixes of the given key. * `prefixFunc` is used to successively calculate the prefixes of the given key.
* It must be pure and return an empty optional when there is no shorter * It must be pure and return an empty optional when there is no shorter
...@@ -44,35 +52,36 @@ namespace armarx::armem ...@@ -44,35 +52,36 @@ namespace armarx::armem
* @param keyValMap the map that contains the key-value-pairs to search * @param keyValMap the map that contains the key-value-pairs to search
* @param prefixFunc the function that returns the longest non-identical prefix of the key * @param prefixFunc the function that returns the longest non-identical prefix of the key
* @param key the key to calculate the prefixes of * @param key the key to calculate the prefixes of
*
* @return The iterator pointing to the found entry, or `keyValMap.end()`.
*/ */
template <typename KeyT, typename ValueT> template <typename KeyT, typename ValueT>
std::optional<std::pair<KeyT, ValueT>> typename std::map<KeyT, ValueT>::const_iterator
getWithLongestPrefix(const std::map<KeyT, ValueT>& keyValMap, findEntryWithLongestPrefix(const std::map<KeyT, ValueT>& keyValMap,
const std::function<std::optional<KeyT>(KeyT&)>& prefixFunc, const std::function<std::optional<KeyT>(KeyT&)>& prefixFunc,
const KeyT& key) const KeyT& key)
{ {
std::optional<KeyT> curKey = key; std::optional<KeyT> curKey = key;
std::optional<ValueT> value;
typename std::map<KeyT, ValueT>::const_iterator result = keyValMap.end();
do do
{ {
auto iterator = keyValMap.find(curKey.value()); auto iterator = keyValMap.find(curKey.value());
if (iterator != keyValMap.end()) if (iterator != keyValMap.end())
{ {
value = iterator->second; result = iterator;
} }
else else
{ {
curKey = prefixFunc(curKey.value()); curKey = prefixFunc(curKey.value());
} }
} while (!value.has_value() && curKey.has_value());
if (value.has_value())
{
return {{curKey.value(), value.value()}};
} }
return {}; while (result == keyValMap.end() and curKey.has_value());
return result;
} }
/** /**
* @brief Accumulate all the values in a map for which the keys are prefixes of the given key. * @brief Accumulate all the values in a map for which the keys are prefixes of the given key.
* *
...@@ -91,26 +100,27 @@ namespace armarx::armem ...@@ -91,26 +100,27 @@ namespace armarx::armem
template <typename KeyT, typename ValueT, typename AccumulateT> template <typename KeyT, typename ValueT, typename AccumulateT>
AccumulateT AccumulateT
accumulateFromPrefixes(const std::map<KeyT, ValueT>& keyValMap, accumulateFromPrefixes(const std::map<KeyT, ValueT>& keyValMap,
const std::function<std::optional<KeyT>(KeyT&)>& prefixFunc, const std::function<std::optional<KeyT>(const KeyT&)>& prefixFunc,
const std::function<void(AccumulateT&, ValueT&)> accumulateFunc, const std::function<void(AccumulateT&, const ValueT&)> accumulateFunc,
const KeyT& key) const KeyT& key)
{ {
std::optional<KeyT> curKey = key; std::optional<KeyT> curKey = key;
AccumulateT values; AccumulateT values;
do do
{ {
std::optional<std::pair<KeyT, ValueT>> nextPair = const auto nextEntry =
getWithLongestPrefix<KeyT, ValueT>(keyValMap, prefixFunc, curKey.value()); findEntryWithLongestPrefix<KeyT, ValueT>(keyValMap, prefixFunc, curKey.value());
if (nextPair.has_value()) if (nextEntry != keyValMap.end())
{ {
curKey = prefixFunc(nextPair.value().first); curKey = prefixFunc(nextEntry->first);
accumulateFunc(values, nextPair.value().second); accumulateFunc(values, nextEntry->second);
} }
else else
{ {
curKey.reset(); curKey.reset();
} }
} while (curKey.has_value()); }
while (curKey.has_value());
return values; return values;
} }
...@@ -129,13 +139,13 @@ namespace armarx::armem ...@@ -129,13 +139,13 @@ namespace armarx::armem
template <typename KeyT, typename ValueT> template <typename KeyT, typename ValueT>
std::vector<ValueT> std::vector<ValueT>
accumulateFromPrefixes(const std::map<KeyT, ValueT>& keyValMap, accumulateFromPrefixes(const std::map<KeyT, ValueT>& keyValMap,
const std::function<std::optional<KeyT>(KeyT&)>& prefixFunc, const std::function<std::optional<KeyT>(const KeyT&)>& prefixFunc,
const KeyT& key) const KeyT& key)
{ {
return accumulateFromPrefixes<KeyT, ValueT, std::vector<ValueT>>( return accumulateFromPrefixes<KeyT, ValueT, std::vector<ValueT>>(
keyValMap, keyValMap,
prefixFunc, prefixFunc,
[](std::vector<ValueT>& values, ValueT& val) { values.push_back(val); }, [](std::vector<ValueT>& values, const ValueT& val) { values.push_back(val); },
key); key);
} }
...@@ -153,57 +163,70 @@ namespace armarx::armem ...@@ -153,57 +163,70 @@ namespace armarx::armem
template <typename KeyT, typename ValueT> template <typename KeyT, typename ValueT>
std::vector<ValueT> std::vector<ValueT>
accumulateFromPrefixes(const std::map<KeyT, std::vector<ValueT>>& keyValMap, accumulateFromPrefixes(const std::map<KeyT, std::vector<ValueT>>& keyValMap,
const std::function<std::optional<KeyT>(KeyT&)>& prefixFunc, const std::function<std::optional<KeyT>(const KeyT&)>& prefixFunc,
const KeyT& key) const KeyT& key)
{ {
return accumulateFromPrefixes<KeyT, std::vector<ValueT>, std::vector<ValueT>>( return accumulateFromPrefixes<KeyT, std::vector<ValueT>, std::vector<ValueT>>(
keyValMap, keyValMap,
prefixFunc, prefixFunc,
[](std::vector<ValueT>& values, std::vector<ValueT>& val) [](std::vector<ValueT>& values, const std::vector<ValueT>& val)
{ values.insert(values.end(), val.begin(), val.end()); }, { values.insert(values.end(), val.begin(), val.end()); },
key); key);
} }
} // namespace detail } // namespace detail
std::optional<MemoryID> inline getMemoryIDParent(MemoryID& memID)
std::optional<MemoryID> inline getMemoryIDParent(const MemoryID& memID)
{ {
if (!memID.hasMemoryName()) if (!memID.hasMemoryName())
{ {
return {}; return std::nullopt;
} }
MemoryID parent = memID.removeLeafItem(); MemoryID parent = memID.removeLeafItem();
return {parent}; return {parent};
} }
/** /**
* @see `getWithLongestPrefix` * @brief Find the entry with the most specific key that contains the given ID,
* or `idMap.end()` if no key contains the ID.
*
* @see `detail::findEntryWithLongestPrefix()`
*/ */
template <typename ValueT> template <typename ValueT>
std::optional<std::pair<MemoryID, ValueT>> typename std::map<MemoryID, ValueT>::const_iterator
getWithMostSpecificContainer(const std::map<MemoryID, ValueT>& idMap, const MemoryID& key) findMostSpecificEntryContainingID(const std::map<MemoryID, ValueT>& idMap, const MemoryID& id)
{ {
return detail::getWithLongestPrefix<MemoryID, ValueT>(idMap, &getMemoryIDParent, key); return detail::findEntryWithLongestPrefix<MemoryID, ValueT>(idMap, &getMemoryIDParent, id);
} }
/** /**
* @see `accumulateFromPrefixes` * @brief Return all values of keys containing the given ID.
*
* @see `detail::accumulateFromPrefixes()`
*/ */
template <typename ValueT> template <typename ValueT>
std::vector<ValueT> std::vector<ValueT>
accumulateFromContainers(const std::map<MemoryID, ValueT>& idMap, const MemoryID& key) accumulateEntriesContainingID(const std::map<MemoryID, ValueT>& idMap, const MemoryID& id)
{ {
return detail::accumulateFromPrefixes<MemoryID, ValueT>(idMap, &getMemoryIDParent, key); return detail::accumulateFromPrefixes<MemoryID, ValueT>(idMap, &getMemoryIDParent, id);
} }
/** /**
* @see `accumulateFromPrefixes` * @brief Return all values of keys containing the given ID in a flattened vector.
*
* @see `detail::accumulateFromPrefixes()`
*/ */
template <typename ValueT> template <typename ValueT>
std::vector<ValueT> std::vector<ValueT>
accumulateFromContainers(const std::map<MemoryID, std::vector<ValueT>>& idMap, accumulateEntriesContainingID(const std::map<MemoryID, std::vector<ValueT>>& idMap,
const MemoryID& key) const MemoryID& key)
{ {
return detail::accumulateFromPrefixes<MemoryID, ValueT>(idMap, &getMemoryIDParent, key); return detail::accumulateFromPrefixes<MemoryID, ValueT>(idMap, &getMemoryIDParent, key);
} }
} // namespace armarx::armem } // namespace armarx::armem
...@@ -42,14 +42,13 @@ BOOST_AUTO_TEST_CASE(test_MemoryID_prefixes) ...@@ -42,14 +42,13 @@ BOOST_AUTO_TEST_CASE(test_MemoryID_prefixes)
BOOST_TEST_CONTEXT(VAROUT(idMap)) BOOST_TEST_CONTEXT(VAROUT(idMap))
{ {
BOOST_CHECK(not armem::getWithMostSpecificContainer(idMap, empty).has_value()); BOOST_CHECK(armem::findMostSpecificEntryContainingID(idMap, empty) == idMap.end());
BOOST_CHECK(not armem::getWithMostSpecificContainer(idMap, complete).has_value()); BOOST_CHECK(armem::findMostSpecificEntryContainingID(idMap, complete) == idMap.end());
BOOST_CHECK(armem::accumulateFromContainers(idMap, empty).empty()); BOOST_CHECK(armem::accumulateEntriesContainingID(idMap, empty).empty());
BOOST_CHECK(armem::accumulateFromContainers(idMap, complete).empty()); BOOST_CHECK(armem::accumulateEntriesContainingID(idMap, complete).empty());
BOOST_CHECK(armem::accumulateEntriesContainingID(idListMap, empty).empty());
BOOST_CHECK(armem::accumulateFromContainers(idListMap, empty).empty()); BOOST_CHECK(armem::accumulateEntriesContainingID(idListMap, complete).empty());
BOOST_CHECK(armem::accumulateFromContainers(idListMap, complete).empty());
} }
idMap[armem::MemoryID()] = 0; idMap[armem::MemoryID()] = 0;
...@@ -60,21 +59,23 @@ BOOST_AUTO_TEST_CASE(test_MemoryID_prefixes) ...@@ -60,21 +59,23 @@ BOOST_AUTO_TEST_CASE(test_MemoryID_prefixes)
BOOST_TEST_CONTEXT(VAROUT(idMap)) BOOST_TEST_CONTEXT(VAROUT(idMap))
{ {
BOOST_CHECK(armem::getWithMostSpecificContainer(idMap, empty) auto it = armem::findMostSpecificEntryContainingID(idMap, empty);
.value_or(std::make_pair(armem::MemoryID("inv"), -1)) BOOST_CHECK(it != idMap.end());
.second == 0); BOOST_CHECK_EQUAL(it->second, 0);
BOOST_CHECK(armem::getWithMostSpecificContainer(idMap, complete.getCoreSegmentID())
.value_or(std::make_pair(armem::MemoryID("inv"), -1)) it = armem::findMostSpecificEntryContainingID(idMap, complete.getCoreSegmentID());
.second == 2); BOOST_CHECK(it != idMap.end());
BOOST_CHECK(armem::getWithMostSpecificContainer(idMap, complete) BOOST_CHECK_EQUAL(it->second, 2);
.value_or(std::make_pair(armem::MemoryID("inv"), -1))
.second == 3); it = armem::findMostSpecificEntryContainingID(idMap, complete);
BOOST_CHECK(it != idMap.end());
BOOST_CHECK((armem::accumulateFromContainers(idMap, empty) == std::vector<int>{0})); BOOST_CHECK_EQUAL(it->second, 3);
BOOST_CHECK((armem::accumulateFromContainers(idMap, complete.getCoreSegmentID()) ==
BOOST_CHECK((armem::accumulateEntriesContainingID(idMap, empty) == std::vector<int>{0}));
BOOST_CHECK((armem::accumulateEntriesContainingID(idMap, complete.getCoreSegmentID()) ==
std::vector<int>{2, 1, 0})); std::vector<int>{2, 1, 0}));
BOOST_CHECK( BOOST_CHECK(
(armem::accumulateFromContainers(idMap, complete) == std::vector<int>{3, 2, 1, 0})); (armem::accumulateEntriesContainingID(idMap, complete) == std::vector<int>{3, 2, 1, 0}));
} }
idListMap.emplace("mem", std::vector<int>{1, 2}); idListMap.emplace("mem", std::vector<int>{1, 2});
...@@ -84,10 +85,10 @@ BOOST_AUTO_TEST_CASE(test_MemoryID_prefixes) ...@@ -84,10 +85,10 @@ BOOST_AUTO_TEST_CASE(test_MemoryID_prefixes)
BOOST_TEST_CONTEXT(VAROUT(idListMap)) BOOST_TEST_CONTEXT(VAROUT(idListMap))
{ {
BOOST_CHECK((armem::accumulateFromContainers(idListMap, empty).empty())); BOOST_CHECK((armem::accumulateEntriesContainingID(idListMap, empty).empty()));
BOOST_CHECK((armem::accumulateFromContainers(idListMap, complete.getCoreSegmentID()) == BOOST_CHECK((armem::accumulateEntriesContainingID(idListMap, complete.getCoreSegmentID()) ==
std::vector<int>{3, 4, 5, 1, 2})); std::vector<int>{3, 4, 5, 1, 2}));
BOOST_CHECK((armem::accumulateFromContainers(idListMap, complete) == BOOST_CHECK((armem::accumulateEntriesContainingID(idListMap, complete) ==
std::vector<int>{6, 7, 8, 3, 4, 5, 1, 2})); std::vector<int>{6, 7, 8, 3, 4, 5, 1, 2}));
} }
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment