Skip to content
Merged
4 changes: 0 additions & 4 deletions examples/mnist-learn/annotated_network.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,6 @@ struct AnnotatedNetwork
/// WTA borders, for example 2,4,6.
// cppcheck-suppress unusedStructMember
std::vector<size_t> wta_borders_;

/// Map of population names.
// cppcheck-suppress unusedStructMember
std::map<knp::core::UID, std::string> population_names_;
}
/// Annotation to network.
// cppcheck-suppress unusedStructMember
Expand Down
9 changes: 7 additions & 2 deletions examples/mnist-learn/inference.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include <knp/framework/model_executor.h>
#include <knp/framework/monitoring/model.h>
#include <knp/framework/projection/wta.h>
#include <knp/framework/tags/name.h>

#include <map>
#include <memory>
Expand All @@ -50,6 +51,12 @@ std::vector<knp::core::messaging::SpikeMessage> infer_network(
const std::shared_ptr<knp::core::Backend>& backend, AnnotatedNetwork& network, const ModelDescription& model_desc,
const Dataset& dataset)
{
// Save populations names.
std::map<knp::core::UID, std::string> pop_names;
for (const auto& pop : network.network_.get_populations())
std::visit(
[&pop_names](const auto& pop) { pop_names[pop.get_uid()] = knp::framework::tags::get_name(pop); }, pop);

// Online Help link: https://click.kaspersky.com/?hl=en-US&version=2.0&pid=KNP&link=online_help&helpid=235849
knp::framework::Model model(std::move(network.network_));

Expand Down Expand Up @@ -85,8 +92,6 @@ std::vector<knp::core::messaging::SpikeMessage> infer_network(
std::vector<knp::core::UID> wta_uids = knp::framework::projection::add_wta_handlers(
model_executor, wta_winners_amount, network.data_.wta_borders_, network.data_.wta_data_);

auto pop_names = network.data_.population_names_;

// Add WTA populations for logging.
for (auto const& uid : wta_uids) pop_names[uid] = "WTA";

Expand Down
10 changes: 7 additions & 3 deletions examples/mnist-learn/models/network_constructor.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,11 @@
*/

#pragma once
#include <knp/framework/tags/name.h>

#include <list>
#include <string>
#include <utility>

// cppcheck-suppress missingInclude
#include "annotated_network.h"
Expand Down Expand Up @@ -79,9 +82,10 @@ class NetworkConstructor
bool keep_in_inference, const std::string &name)
{
PopulationInfo pop_info{role, keep_in_inference, neurons_amount, {}, name};
network_.network_.add_population(knp::core::Population<Neuron>(
pop_info.uid_, [&neuron](size_t index) { return neuron; }, pop_info.neurons_amount_));
network_.data_.population_names_[pop_info.uid_] = pop_info.name_;
auto pop = knp::core::Population<Neuron>(
pop_info.uid_, [&neuron](size_t index) { return neuron; }, pop_info.neurons_amount_);
knp::framework::tags::set_name(pop, pop_info.name_);
network_.network_.add_population(std::move(pop));
if (pop_info.keep_in_inference_) network_.data_.inference_population_uids_.insert(pop_info.uid_);
if (PopulationRole::OUTPUT == pop_info.role_) network_.data_.output_uids_.push_back(pop_info.uid_);
return pops_.emplace_back(pop_info);
Expand Down
10 changes: 7 additions & 3 deletions examples/mnist-learn/training.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include <knp/framework/model_executor.h>
#include <knp/framework/monitoring/model.h>
#include <knp/framework/projection/wta.h>
#include <knp/framework/tags/name.h>

#include <map>
#include <memory>
Expand Down Expand Up @@ -89,6 +90,12 @@ void train_network(
const std::shared_ptr<knp::core::Backend>& backend, AnnotatedNetwork& network, const ModelDescription& model_desc,
const Dataset& dataset)
{
// Save populations names.
std::map<knp::core::UID, std::string> pop_names;
for (const auto& pop : network.network_.get_populations())
std::visit(
[&pop_names](const auto& pop) { pop_names[pop.get_uid()] = knp::framework::tags::get_name(pop); }, pop);

// Online Help link: https://click.kaspersky.com/?hl=en-US&version=2.0&pid=KNP&link=online_help&helpid=235849
knp::framework::Model model(std::move(network.network_));

Expand All @@ -109,9 +116,6 @@ void train_network(
// Online Help link: https://click.kaspersky.com/?hl=en-US&version=2.0&pid=KNP&link=online_help&helpid=301132
std::vector<knp::core::UID> wta_uids = knp::framework::projection::add_wta_handlers(
model_executor, wta_winners_amount, network.data_.wta_borders_, network.data_.wta_data_);

auto pop_names = network.data_.population_names_;

// Add WTA populations for logging.
for (auto const& uid : wta_uids) pop_names[uid] = "WTA";

Expand Down
69 changes: 69 additions & 0 deletions knp/base-framework/include/knp/framework/tags/name.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/**
* @file name.h
* @brief Functions for working with name tag.
* @kaspersky_support Postnikov D.
* @date 03.04.2026
* @license Apache 2.0
* @copyright © 2026 AO Kaspersky Lab
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#pragma once

#include <string>


/**
* @brief Tags namespace.
*/
namespace knp::framework::tags
{

/**
* @brief Tag name for setting names.
*/
constexpr char name_tag[]{"name"};


/**
* @brief Get name tag.
* @tparam Type Object type.
* @param object Object from which we want to retrieve name.
* @return If name was specified in object, it is returned, otherwise UID is returned.
*
*/
template <typename Type>
[[nodiscard]] std::string get_name(const Type& object)
{
if (object.get_tags().exists(name_tag))
{
return object.get_tags().template get_tag<std::string>(name_tag);
}
return std::string(object.get_uid());
}


/**
* @brief Set name tag.
* @tparam Type Object type.
* @param object Object in which we want to set name.
* @param name Name.
*/
template <typename Type>
void set_name(Type& object, std::string_view name)
{
object.get_tags()[name_tag] = std::string(name);
}

} //namespace knp::framework::tags
40 changes: 39 additions & 1 deletion knp/core-library/include/knp/core/tag.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,14 @@ class TagMap
*/
[[nodiscard]] std::any &get_tag(const std::string &name) { return tags_[name]; }

/**
* @brief Get tag value by tag name.
* @note Const function.
* @param name tag name.
* @return tag value.
*/
[[nodiscard]] const std::any &get_tag(const std::string &name) const { return tags_.at(name); }

/**
* @brief Get tag value by tag name and value type.
* @tparam T tag value type.
Expand All @@ -59,6 +67,19 @@ class TagMap
return std::any_cast<std::decay_t<T> &>(tags_[name]);
}

/**
* @brief Get tag value by tag name and value type.
* @note Const function.
* @tparam T tag value type.
* @param name tag name.
* @return tag value.
*/
template <typename T>
[[nodiscard]] const std::decay_t<T> &get_tag(const std::string &name) const
{
return std::any_cast<const std::decay_t<T> &>(tags_.at(name));
}

/**
* @brief Return tag value.
* @param name tag name.
Expand All @@ -67,11 +88,28 @@ class TagMap
auto &operator[](const std::string &name) { return get_tag(name); }

/**
* @brief Check if tag is specified.
* @brief Return tag value.
* @note Const function.
* @param name tag name.
* @return tag value.
*/
const auto &operator[](const std::string &name) const { return get_tag(name); }

/**
* @brief Check if no tag is specified.
* @return `true` if no tag is specified, `false` otherwise.
*/
[[nodiscard]] bool empty() const noexcept { return tags_.empty(); }


/**
* @brief Check if tag is specified.
* @param name Tag name that will be searched.
* @return `true` if tag is specified, `false` otherwise.
*/
[[nodiscard]] bool exists(const std::string &name) const noexcept { return tags_.find(name) != tags_.end(); }


private:
std::map<std::string, std::any> tags_{};
};
Expand Down
43 changes: 43 additions & 0 deletions knp/tests/framework/name_tag_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/**
* @file name_tag_test.cpp
* @brief Tests for name tag.
* @kaspersky_support David P.
* @date 06.04.2026
* @license Apache 2.0
* @copyright © 2026 AO Kaspersky Lab
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include <knp/framework/population/neuron_parameters_generators.h>
#include <knp/framework/tags/name.h>

#include <tests_common.h>


TEST(NameTag, DefaultName)
{
knp::core::UID uid;
knp::core::Population<knp::neuron_traits::BLIFATNeuron> pop(
uid, knp::framework::population::neurons_generators::make_default<knp::neuron_traits::BLIFATNeuron>(), 0);
ASSERT_EQ(knp::framework::tags::get_name(pop), std::string(uid));
}


TEST(NameTag, SetGetName)
{
knp::core::Population<knp::neuron_traits::BLIFATNeuron> pop(
knp::framework::population::neurons_generators::make_default<knp::neuron_traits::BLIFATNeuron>(), 0);
knp::framework::tags::set_name(pop, "test_name");
ASSERT_EQ(knp::framework::tags::get_name(pop), "test_name");
}
Loading