From b9892dbfcde4de321f52142bec7afef1c156c4ad Mon Sep 17 00:00:00 2001 From: Andre Senna <“andre.senna@gmail.com”> Date: Tue, 1 Sep 2026 14:48:52 -0300 Subject: [PATCH 01/12] Minor fixes --- src/agents/evolution/QueryEvolutionProcessor.cc | 3 --- src/agents/link_creation_agent/LinkCreationProcessor.cc | 1 - src/agents/link_creation_agent/LinkCreationProxy.cc | 1 + 3 files changed, 1 insertion(+), 4 deletions(-) diff --git a/src/agents/evolution/QueryEvolutionProcessor.cc b/src/agents/evolution/QueryEvolutionProcessor.cc index 5862a29b9..bb64e9df4 100644 --- a/src/agents/evolution/QueryEvolutionProcessor.cc +++ b/src/agents/evolution/QueryEvolutionProcessor.cc @@ -598,7 +598,6 @@ void QueryEvolutionProcessor::evolve_query(shared_ptr monitor, #endif proxy->new_population_sampled(population); if (population.size() > 0) { - proxy->flush_answer_bundle(); STOP_WATCH_START(selection); select_best_individuals(proxy, population, selected); STOP_WATCH_FINISH(selection, "EvolutionIndividualSelection"); @@ -620,8 +619,6 @@ void QueryEvolutionProcessor::evolve_query(shared_ptr monitor, this->generation_count++; proxy->cycle_ended(); } - proxy->flush_answer_bundle(); - proxy->cycle_ended(); if (this->generation_count > 0) { LOG_INFO("--------------------"); LOG_INFO("Last generation with answer improvement: " + diff --git a/src/agents/link_creation_agent/LinkCreationProcessor.cc b/src/agents/link_creation_agent/LinkCreationProcessor.cc index 675f78cc8..a969edec3 100644 --- a/src/agents/link_creation_agent/LinkCreationProcessor.cc +++ b/src/agents/link_creation_agent/LinkCreationProcessor.cc @@ -193,7 +193,6 @@ void LinkCreationProcessor::link_creation(shared_ptr monitor, } } proxy->flush_determiners(); - proxy->flush_answer_bundle(); proxy->cycle_ended(); if (!pm_proxy->finished()) { // stopping pattern matching query diff --git a/src/agents/link_creation_agent/LinkCreationProxy.cc b/src/agents/link_creation_agent/LinkCreationProxy.cc index ee30c3c01..18d429cb4 100644 --- a/src/agents/link_creation_agent/LinkCreationProxy.cc +++ b/src/agents/link_creation_agent/LinkCreationProxy.cc @@ -45,6 +45,7 @@ LinkCreationProxy::~LinkCreationProxy() {} void LinkCreationProxy::init() { this->command = ServiceBus::LINK_CREATION; this->link_creation_function_object = shared_ptr(nullptr); + this->link_creator_function_tag = ""; this->round_count = 0; this->parameters[LOG_NEW_LINKS] = true; this->parameters += SystemParametersSingleton::get_instance()->get_link_creation_agent_params(); From f0c4fc1f4503fadec30079f0b05295cd9a169ae0 Mon Sep 17 00:00:00 2001 From: Andre Senna <“andre.senna@gmail.com”> Date: Thu, 3 Sep 2026 08:18:24 -0300 Subject: [PATCH 02/12] WIP --- .../link_creators/Customizable.cc | 84 +++++++++++++++++++ .../link_creators/Customizable.h | 30 +++++++ .../link_creators/LinkCreatorRegistry.cc | 7 +- .../link_creators/LinkCreatorRegistry.h | 1 + 4 files changed, 120 insertions(+), 2 deletions(-) create mode 100644 src/agents/link_creation_agent/link_creators/Customizable.cc create mode 100644 src/agents/link_creation_agent/link_creators/Customizable.h diff --git a/src/agents/link_creation_agent/link_creators/Customizable.cc b/src/agents/link_creation_agent/link_creators/Customizable.cc new file mode 100644 index 000000000..ae8df852d --- /dev/null +++ b/src/agents/link_creation_agent/link_creators/Customizable.cc @@ -0,0 +1,84 @@ +#include "AndTwoPredicates.h" +#include "tags.h" + +using namespace link_creators; + +string AndTwoPredicates::LOGICAL_AND_HANDLE = Hasher::node_handle(SYMBOL, LOGICAL_AND_TAG); +string AndTwoPredicates::EVALUATION_HANDLE = Hasher::node_handle(SYMBOL, EVALUATION_TAG); + +// ------------------------------------------------------------------------------------------------- +// Public methods + +AndTwoPredicates::AndTwoPredicates() { +} + +AndTwoPredicates::~AndTwoPredicates() { +} + +LinkCreationStats AndTwoPredicates::create(shared_ptr query_answer) { + STACK_TRACE(); + string concept_ = query_answer->get(CONCEPT); + string predicates[2]; + predicates[0] = query_answer->get(PREDICATE1); + predicates[1] = query_answer->get(PREDICATE2); + if (predicates[1] < predicates[0]) { + string aux = predicates[0]; + predicates[0] = predicates[1]; + predicates[1] = aux; + } + string key = predicates[0] + " " + predicates[1]; + + LinkCreationStats stats = LinkCreationStats(false, 0, 0); + if (predicates[0] != predicates[1]) { + if (! visited(key)) { + visit(key); + stats.visited = true; + set mentioned_predicates0, mentioned_predicates1; + extract_mentioned_predicates(mentioned_predicates0, predicates[0]); + extract_mentioned_predicates(mentioned_predicates1, predicates[1]); + if (! Utils::intersects(mentioned_predicates0, mentioned_predicates1)) { + vector targets = {LOGICAL_AND_HANDLE, predicates[0], predicates[1]}; + if (add_or_update_link(targets, 1.0)) { + stats.created++; + double strength = 1; + for (string& h : query_answer->get_handles_vector()) { + strength *= get_strength(h); + } + if (strength >= strength_threshold()) { + stats.created++; + string new_predicate_handle = Hasher::link_handle(EXPRESSION, targets); + add_or_update_link({EVALUATION_HANDLE, new_predicate_handle, concept_}, strength); + } else { + stats.updated++; + } + } else { + LOG_DEBUG("(" + Utils::join(vector(mentioned_predicates0.begin(), mentioned_predicates0.end()), '-') + ", " + Utils::join(vector(mentioned_predicates1.begin(), mentioned_predicates1.end()), '-') + ") " + "Skipping link building because composite predicate already exists."); + } + } else { + LOG_DEBUG("(" + Utils::join(vector(mentioned_predicates0.begin(), mentioned_predicates0.end()), '-') + ", " + Utils::join(vector(mentioned_predicates1.begin(), mentioned_predicates1.end()), '-') + ") " + "Skipping link building because predicates intersect."); + } + } else { + LOG_DEBUG("(" + predicates[0] + ", " + predicates[1] + ") " + "Skipping link building because targets have already been visited this cycle: " + key); + } + } else { + LOG_DEBUG("(" + predicates[0] + ", " + predicates[1] + ") " + "Skipping link building because predicates are the same."); + } + return stats; +} + +void AndTwoPredicates::extract_mentioned_predicates(set& mentioned, const string& handle) { + STACK_TRACE(); + shared_ptr node; + shared_ptr link = atomdb()->get_link(handle); + if (link != nullptr) { + for (string& target_handle : link->targets) { + if ((node = atomdb()->get_node(target_handle)) != nullptr) { + if ((node->name != PREDICATE_TAG) && (node->name != LOGICAL_AND_TAG)) { + mentioned.insert(node->name); + } + } else { + extract_mentioned_predicates(mentioned, target_handle); + } + } + } +} diff --git a/src/agents/link_creation_agent/link_creators/Customizable.h b/src/agents/link_creation_agent/link_creators/Customizable.h new file mode 100644 index 000000000..29ff8da28 --- /dev/null +++ b/src/agents/link_creation_agent/link_creators/Customizable.h @@ -0,0 +1,30 @@ +#pragma once +#include +#include "LinkCreator.h" + +using namespace std; + +namespace link_creators { + +/** + * + */ +class Customizable : public LinkCreator { + +public: + + enum StrengthComposition { UNDEFINED = 0, PRODUCT }; + + Customizable(); + ~Customizable(); + + LinkCreationStats create(shared_ptr query_answer); + +private: + + vector target_elements; + vector strength_elements; + StrengthComposition strenth_composition; +}; + +} // namespace link_creators diff --git a/src/agents/link_creation_agent/link_creators/LinkCreatorRegistry.cc b/src/agents/link_creation_agent/link_creators/LinkCreatorRegistry.cc index 171183c7a..bc701f386 100644 --- a/src/agents/link_creation_agent/link_creators/LinkCreatorRegistry.cc +++ b/src/agents/link_creation_agent/link_creators/LinkCreatorRegistry.cc @@ -6,6 +6,7 @@ // ------------------------------------------------------------------------------------------------- // ADD your header here #include "UnitTestLinkCreator.h" +#include "Customizable.h" #include "AndTwoPredicates.h" // ------------------------------------------------------------------------------------------------- @@ -15,11 +16,11 @@ using namespace commons; bool LinkCreatorRegistry::INITIALIZED = false; // ----------------------------------------------------------------------------------------- // ADD your function here using a unique string key -// NOTE: "remote_link_creation_function" is reserved and CAN'T be used here. -// ----------------------------------------------------------------------------------------- string LinkCreatorRegistry::REMOTE_FUNCTION = "remote_link_creation_function"; string LinkCreatorRegistry::UNIT_TEST = "unit_test"; +string LinkCreatorRegistry::CUSTOMIZABLE = "customizable"; string LinkCreatorRegistry::AND_TWO_PREDICATES = "and_two_predicates"; +// ----------------------------------------------------------------------------------------- void LinkCreatorRegistry::initialize_statics() { STACK_TRACE(); @@ -42,6 +43,8 @@ shared_ptr LinkCreatorRegistry::function(const string& tag) { // ADD an "else if" for your function here } else if (tag == UNIT_TEST) { answer = make_shared(); + } else if (tag == UNIT_TEST) { + answer = make_shared(); } else if (tag == AND_TWO_PREDICATES) { answer = make_shared(); // ----------------------------------------------------------------------------------------- diff --git a/src/agents/link_creation_agent/link_creators/LinkCreatorRegistry.h b/src/agents/link_creation_agent/link_creators/LinkCreatorRegistry.h index 9ebab08cd..73d637ee4 100644 --- a/src/agents/link_creation_agent/link_creators/LinkCreatorRegistry.h +++ b/src/agents/link_creation_agent/link_creators/LinkCreatorRegistry.h @@ -19,6 +19,7 @@ class LinkCreatorRegistry { public: static string REMOTE_FUNCTION; static string UNIT_TEST; + static string CUSTOMIZABLE; static string AND_TWO_PREDICATES; ~LinkCreatorRegistry() {} From 807d2ceca8097e4273eba94934161c53d4ef3c91 Mon Sep 17 00:00:00 2001 From: Andre Senna <“andre.senna@gmail.com”> Date: Thu, 10 Sep 2026 16:40:06 -0300 Subject: [PATCH 03/12] WIP --- .../link_creators/Customizable.cc | 86 +++++-------------- .../link_creators/Customizable.h | 23 ++++- .../link_creators/LinkCreatorRegistry.cc | 2 +- 3 files changed, 41 insertions(+), 70 deletions(-) diff --git a/src/agents/link_creation_agent/link_creators/Customizable.cc b/src/agents/link_creation_agent/link_creators/Customizable.cc index ae8df852d..73add82d0 100644 --- a/src/agents/link_creation_agent/link_creators/Customizable.cc +++ b/src/agents/link_creation_agent/link_creators/Customizable.cc @@ -1,84 +1,38 @@ -#include "AndTwoPredicates.h" +#include "Customizable.h" #include "tags.h" using namespace link_creators; -string AndTwoPredicates::LOGICAL_AND_HANDLE = Hasher::node_handle(SYMBOL, LOGICAL_AND_TAG); -string AndTwoPredicates::EVALUATION_HANDLE = Hasher::node_handle(SYMBOL, EVALUATION_TAG); - // ------------------------------------------------------------------------------------------------- // Public methods -AndTwoPredicates::AndTwoPredicates() { +Customizable::Customizable() { } -AndTwoPredicates::~AndTwoPredicates() { +Customizable::~Customizable() { } -LinkCreationStats AndTwoPredicates::create(shared_ptr query_answer) { +LinkCreationStats Customizable::create(shared_ptr query_answer) { STACK_TRACE(); - string concept_ = query_answer->get(CONCEPT); - string predicates[2]; - predicates[0] = query_answer->get(PREDICATE1); - predicates[1] = query_answer->get(PREDICATE2); - if (predicates[1] < predicates[0]) { - string aux = predicates[0]; - predicates[0] = predicates[1]; - predicates[1] = aux; - } - string key = predicates[0] + " " + predicates[1]; - - LinkCreationStats stats = LinkCreationStats(false, 0, 0); - if (predicates[0] != predicates[1]) { - if (! visited(key)) { - visit(key); - stats.visited = true; - set mentioned_predicates0, mentioned_predicates1; - extract_mentioned_predicates(mentioned_predicates0, predicates[0]); - extract_mentioned_predicates(mentioned_predicates1, predicates[1]); - if (! Utils::intersects(mentioned_predicates0, mentioned_predicates1)) { - vector targets = {LOGICAL_AND_HANDLE, predicates[0], predicates[1]}; - if (add_or_update_link(targets, 1.0)) { - stats.created++; - double strength = 1; - for (string& h : query_answer->get_handles_vector()) { - strength *= get_strength(h); - } - if (strength >= strength_threshold()) { - stats.created++; - string new_predicate_handle = Hasher::link_handle(EXPRESSION, targets); - add_or_update_link({EVALUATION_HANDLE, new_predicate_handle, concept_}, strength); - } else { - stats.updated++; - } - } else { - LOG_DEBUG("(" + Utils::join(vector(mentioned_predicates0.begin(), mentioned_predicates0.end()), '-') + ", " + Utils::join(vector(mentioned_predicates1.begin(), mentioned_predicates1.end()), '-') + ") " + "Skipping link building because composite predicate already exists."); - } - } else { - LOG_DEBUG("(" + Utils::join(vector(mentioned_predicates0.begin(), mentioned_predicates0.end()), '-') + ", " + Utils::join(vector(mentioned_predicates1.begin(), mentioned_predicates1.end()), '-') + ") " + "Skipping link building because predicates intersect."); - } - } else { - LOG_DEBUG("(" + predicates[0] + ", " + predicates[1] + ") " + "Skipping link building because targets have already been visited this cycle: " + key); + LinkCreationStats stats; + for (LinkSpecification& spec : this->link_specification) { + vector handles; + vector strength_components + handles.push_back(Hasher::type_handle(spec.link_type)); + for (QueryAnswerElement& element : spec.target_elements) { + handles.push_back(query_answer->get(element)); } - } else { - LOG_DEBUG("(" + predicates[0] + ", " + predicates[1] + ") " + "Skipping link building because predicates are the same."); + for (QueryAnswerElement& element : spec.strength_elements) { + strength_components.push_back(get_strength(query_answer->get(element))); + } + add_or_update_link(handles, compute_strength(strength_components, spec.strength_composition)); } return stats; } -void AndTwoPredicates::extract_mentioned_predicates(set& mentioned, const string& handle) { - STACK_TRACE(); - shared_ptr node; - shared_ptr link = atomdb()->get_link(handle); - if (link != nullptr) { - for (string& target_handle : link->targets) { - if ((node = atomdb()->get_node(target_handle)) != nullptr) { - if ((node->name != PREDICATE_TAG) && (node->name != LOGICAL_AND_TAG)) { - mentioned.insert(node->name); - } - } else { - extract_mentioned_predicates(mentioned, target_handle); - } - } - } +// ------------------------------------------------------------------------------------------------- +// Private methods + +bool Customizable:: + } diff --git a/src/agents/link_creation_agent/link_creators/Customizable.h b/src/agents/link_creation_agent/link_creators/Customizable.h index 29ff8da28..f6773b44b 100644 --- a/src/agents/link_creation_agent/link_creators/Customizable.h +++ b/src/agents/link_creation_agent/link_creators/Customizable.h @@ -22,9 +22,26 @@ class Customizable : public LinkCreator { private: - vector target_elements; - vector strength_elements; - StrengthComposition strenth_composition; + class LinkSpecification { + vector target_elements; + vector strength_elements; + StrengthComposition strength_composition; + string link_type; + }; + + vector link_specification; + +public: + + void add_link_specification(const vector& target_elements, + const vector& strength_elements, + StrengthComposition strength_composition, + const string& link_type) { + link_specification.emplace_back(target_elements, + strength_elements, + strength_composition, + link_type); + } }; } // namespace link_creators diff --git a/src/agents/link_creation_agent/link_creators/LinkCreatorRegistry.cc b/src/agents/link_creation_agent/link_creators/LinkCreatorRegistry.cc index 4a5a2d803..a0678db39 100644 --- a/src/agents/link_creation_agent/link_creators/LinkCreatorRegistry.cc +++ b/src/agents/link_creation_agent/link_creators/LinkCreatorRegistry.cc @@ -43,7 +43,7 @@ shared_ptr LinkCreatorRegistry::function(const string& tag) { // ADD an "else if" for your function here } else if (tag == UNIT_TEST) { answer = make_shared(); - } else if (tag == UNIT_TEST) { + } else if (tag == CUSTOMIZABLE) { answer = make_shared(); } else if (tag == AND_TWO_PREDICATES) { answer = make_shared(); From 8724f8031e1c6612050c33ed4b06b0ad8953abd9 Mon Sep 17 00:00:00 2001 From: Andre Senna <“andre.senna@gmail.com”> Date: Mon, 14 Sep 2026 12:25:41 -0300 Subject: [PATCH 04/12] Add new optional parameter LINK_CREATOR_EXTRA_PARAMETERS --- src/agents/link_creation_agent/LinkCreationProxy.cc | 3 +++ src/agents/link_creation_agent/LinkCreationProxy.h | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/agents/link_creation_agent/LinkCreationProxy.cc b/src/agents/link_creation_agent/LinkCreationProxy.cc index de81bef55..b19071e84 100644 --- a/src/agents/link_creation_agent/LinkCreationProxy.cc +++ b/src/agents/link_creation_agent/LinkCreationProxy.cc @@ -19,6 +19,7 @@ string LinkCreationProxy::MAX_ROUNDS = "max_rounds"; string LinkCreationProxy::LINK_CREATION_STRENGTH_THRESHOLD = "link_creation_strength_threshold"; string LinkCreationProxy::LINK_CREATION_LOG_FILE_NAME = "link_creation_log_file_name"; string LinkCreationProxy::LOG_NEW_LINKS = "log_new_links"; +string LinkCreationProxy::LINK_CREATOR_EXTRA_PARAMETERS = "link_creator_extra_parameters"; LinkCreationProxy::LinkCreationProxy() { // constructor typically used in processor @@ -144,6 +145,8 @@ void LinkCreationProxy::set_link_creator_function_tag(const string& tag) { this->parameters.get_or(LINK_CREATION_LOG_FILE_NAME, "")); this->link_creation_function_object->set_log_new_links( this->parameters.get(LOG_NEW_LINKS)); + this->link_creation_function_object->extra_parameters( + this->parameters.get_or(LINK_CREATOR_EXTRA_PARAMETERS, "")); } } } diff --git a/src/agents/link_creation_agent/LinkCreationProxy.h b/src/agents/link_creation_agent/LinkCreationProxy.h index fadf90a3c..db0f1b4bc 100644 --- a/src/agents/link_creation_agent/LinkCreationProxy.h +++ b/src/agents/link_creation_agent/LinkCreationProxy.h @@ -31,9 +31,9 @@ class LinkCreationProxy : public BaseQueryProxy { static string LINK_CREATION_STRENGTH_THRESHOLD; static string LINK_CREATION_LOG_FILE_NAME; - // LOG_NEW_LINKS is an optional parameter but it is not part of the configuration file as it - // is meant to be used only in tests. + // Optional parameter which are not part of the configuration file static string LOG_NEW_LINKS; + static string LINK_CREATOR_EXTRA_PARAMETERS; LinkCreationProxy(); From 20c8565a54a628f95fbd3b8dd3b3ec32cdf4d91c Mon Sep 17 00:00:00 2001 From: Andre Senna <“andre.senna@gmail.com”> Date: Mon, 14 Sep 2026 12:28:06 -0300 Subject: [PATCH 05/12] Minor fixes --- .../link_creators/AndTwoPredicates.cc | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/agents/link_creation_agent/link_creators/AndTwoPredicates.cc b/src/agents/link_creation_agent/link_creators/AndTwoPredicates.cc index 1a99feeb9..591ba4638 100644 --- a/src/agents/link_creation_agent/link_creators/AndTwoPredicates.cc +++ b/src/agents/link_creation_agent/link_creators/AndTwoPredicates.cc @@ -27,7 +27,7 @@ LinkCreationStats AndTwoPredicates::create(shared_ptr query_answer) } string key = predicates[0] + " " + predicates[1] + concept_; - LinkCreationStats stats = LinkCreationStats(false, 0, 0); + LinkCreationStats stats; if (predicates[0] != predicates[1]) { if (!visited(key)) { visit(key); @@ -37,18 +37,20 @@ LinkCreationStats AndTwoPredicates::create(shared_ptr query_answer) extract_mentioned_predicates(mentioned_predicates1, predicates[1]); if (!Utils::intersects(mentioned_predicates0, mentioned_predicates1)) { vector targets = {LOGICAL_AND_HANDLE, predicates[0], predicates[1]}; - add_or_update_link(targets, 1.0); - stats.created++; + if (add_or_update_link(targets, 1.0)) { + stats.created++; + } double strength = 1; for (string& h : query_answer->get_handles_vector()) { strength *= get_strength(h); } if (strength >= strength_threshold()) { - stats.created++; string new_predicate_handle = Hasher::link_handle(EXPRESSION, targets); - add_or_update_link({EVALUATION_HANDLE, new_predicate_handle, concept_}, strength); - } else { - stats.updated++; + if (add_or_update_link({EVALUATION_HANDLE, new_predicate_handle, concept_}, strength)) { + stats.created++; + } else { + stats.updated++; + } } } else { LOG_DEBUG("(" + From 0e663734c90068a06da0cfac4874c1047c7d4cc8 Mon Sep 17 00:00:00 2001 From: Andre Senna <“andre.senna@gmail.com”> Date: Mon, 14 Sep 2026 12:28:52 -0300 Subject: [PATCH 06/12] Minor new features - accepts string as join() delimiter --- src/commons/Utils.cc | 6 +++++- src/commons/Utils.h | 1 + src/tests/cpp/utils_test.cc | 22 ++++++++++++++++++++++ 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/src/commons/Utils.cc b/src/commons/Utils.cc index 61285f518..7bad6e26f 100644 --- a/src/commons/Utils.cc +++ b/src/commons/Utils.cc @@ -166,7 +166,7 @@ pair Utils::parse_ports_range(const string& str, char delimiter) return make_pair(start_port, end_port); } -string Utils::join(const vector& tokens, char delimiter) { +string Utils::join(const vector& tokens, const string& delimiter) { string result; for (size_t i = 0; i < tokens.size(); i++) { if (i > 0) { @@ -177,6 +177,10 @@ string Utils::join(const vector& tokens, char delimiter) { return result; } +string Utils::join(const vector& tokens, char delimiter) { + return join(tokens, string(1, delimiter)); +} + bool Utils::is_number(const string& s) { return !s.empty() && find_if(s.begin(), s.end(), [](unsigned char c) { return !isdigit(c); }) == s.end(); diff --git a/src/commons/Utils.h b/src/commons/Utils.h index 94fedfeaf..fcadf62b7 100644 --- a/src/commons/Utils.h +++ b/src/commons/Utils.h @@ -156,6 +156,7 @@ class Utils { static map parse_config(string const& config_path); static vector split(string const& str, char delimiter = ' '); static pair parse_ports_range(string const& str, char delimiter = ':'); + static string join(vector const& tokens, const string& delimiter); static string join(vector const& tokens, char delimiter = ' '); static bool is_number(const string& s); static int string_to_int(const string& s); diff --git a/src/tests/cpp/utils_test.cc b/src/tests/cpp/utils_test.cc index 5194c050d..a8579770b 100644 --- a/src/tests/cpp/utils_test.cc +++ b/src/tests/cpp/utils_test.cc @@ -112,6 +112,28 @@ TEST(LocalFileTestSuite, flip_coin) { EXPECT_THROW(Utils::flip_coin(-0.5), runtime_error); } +TEST(LocalFileTestSuite, join) { + vector v1 = {}; + vector v2 = {"1"}; + vector v3 = {"1", "2"}; + vector v4 = {"1", "2", "3"}; + + ASSERT_EQ(Utils::join(v1), ""); + ASSERT_EQ(Utils::join(v2), "1"); + ASSERT_EQ(Utils::join(v3), "1 2"); + ASSERT_EQ(Utils::join(v4), "1 2 3"); + + ASSERT_EQ(Utils::join(v1, '-'), ""); + ASSERT_EQ(Utils::join(v2, '-'), "1"); + ASSERT_EQ(Utils::join(v3, '-'), "1-2"); + ASSERT_EQ(Utils::join(v4, '-'), "1-2-3"); + + ASSERT_EQ(Utils::join(v1, ", "), ""); + ASSERT_EQ(Utils::join(v2, ", "), "1"); + ASSERT_EQ(Utils::join(v3, ", "), "1, 2"); + ASSERT_EQ(Utils::join(v4, ", "), "1, 2, 3"); +} + TEST(LocalFileTestSuite, uint_rand) { for (pair p : vector>( {{0, 1}, {0, 2}, {0, 3}, {2, 3}, {2, 4}, {2, 5}, {105, 1200}})) { From 138343186c9cf868ab1bf12e45f2a28b04328099 Mon Sep 17 00:00:00 2001 From: Andre Senna <“andre.senna@gmail.com”> Date: Mon, 14 Sep 2026 12:29:18 -0300 Subject: [PATCH 07/12] Add CustomizableLinkCreator --- .../link_creators/Customizable.cc | 38 ----- .../link_creators/Customizable.h | 47 ------ .../link_creators/CustomizableLinkCreator.cc | 134 ++++++++++++++++++ .../link_creators/CustomizableLinkCreator.h | 59 ++++++++ .../link_creators/LinkCreator.h | 9 ++ .../link_creators/LinkCreatorRegistry.cc | 10 +- src/tests/cpp/link_creation_agent_test.cc | 69 +++++++++ .../integration/cpp/lca_integration_test.cc | 133 +++++++++++++++-- 8 files changed, 395 insertions(+), 104 deletions(-) delete mode 100644 src/agents/link_creation_agent/link_creators/Customizable.cc delete mode 100644 src/agents/link_creation_agent/link_creators/Customizable.h create mode 100644 src/agents/link_creation_agent/link_creators/CustomizableLinkCreator.cc create mode 100644 src/agents/link_creation_agent/link_creators/CustomizableLinkCreator.h diff --git a/src/agents/link_creation_agent/link_creators/Customizable.cc b/src/agents/link_creation_agent/link_creators/Customizable.cc deleted file mode 100644 index 73add82d0..000000000 --- a/src/agents/link_creation_agent/link_creators/Customizable.cc +++ /dev/null @@ -1,38 +0,0 @@ -#include "Customizable.h" -#include "tags.h" - -using namespace link_creators; - -// ------------------------------------------------------------------------------------------------- -// Public methods - -Customizable::Customizable() { -} - -Customizable::~Customizable() { -} - -LinkCreationStats Customizable::create(shared_ptr query_answer) { - STACK_TRACE(); - LinkCreationStats stats; - for (LinkSpecification& spec : this->link_specification) { - vector handles; - vector strength_components - handles.push_back(Hasher::type_handle(spec.link_type)); - for (QueryAnswerElement& element : spec.target_elements) { - handles.push_back(query_answer->get(element)); - } - for (QueryAnswerElement& element : spec.strength_elements) { - strength_components.push_back(get_strength(query_answer->get(element))); - } - add_or_update_link(handles, compute_strength(strength_components, spec.strength_composition)); - } - return stats; -} - -// ------------------------------------------------------------------------------------------------- -// Private methods - -bool Customizable:: - -} diff --git a/src/agents/link_creation_agent/link_creators/Customizable.h b/src/agents/link_creation_agent/link_creators/Customizable.h deleted file mode 100644 index f6773b44b..000000000 --- a/src/agents/link_creation_agent/link_creators/Customizable.h +++ /dev/null @@ -1,47 +0,0 @@ -#pragma once -#include -#include "LinkCreator.h" - -using namespace std; - -namespace link_creators { - -/** - * - */ -class Customizable : public LinkCreator { - -public: - - enum StrengthComposition { UNDEFINED = 0, PRODUCT }; - - Customizable(); - ~Customizable(); - - LinkCreationStats create(shared_ptr query_answer); - -private: - - class LinkSpecification { - vector target_elements; - vector strength_elements; - StrengthComposition strength_composition; - string link_type; - }; - - vector link_specification; - -public: - - void add_link_specification(const vector& target_elements, - const vector& strength_elements, - StrengthComposition strength_composition, - const string& link_type) { - link_specification.emplace_back(target_elements, - strength_elements, - strength_composition, - link_type); - } -}; - -} // namespace link_creators diff --git a/src/agents/link_creation_agent/link_creators/CustomizableLinkCreator.cc b/src/agents/link_creation_agent/link_creators/CustomizableLinkCreator.cc new file mode 100644 index 000000000..b102d7924 --- /dev/null +++ b/src/agents/link_creation_agent/link_creators/CustomizableLinkCreator.cc @@ -0,0 +1,134 @@ +#include "CustomizableLinkCreator.h" +#include "Hasher.h" +#include "tags.h" + +using namespace link_creators; + +// ------------------------------------------------------------------------------------------------- +// Public methods + +CustomizableLinkCreator::CustomizableLinkCreator() { +} + +CustomizableLinkCreator::~CustomizableLinkCreator() { +} + +LinkCreationStats CustomizableLinkCreator::create(shared_ptr query_answer) { + STACK_TRACE(); + LinkCreationStats stats; + for (LinkSpecification& spec : this->link_specification) { + if ((spec.target_elements.size() == 0) || (spec.link_type == "")) { + RAISE_ERROR("Invalid empty target elements or link_type"); + return stats; + } + vector handles; + vector strength_components; + handles.push_back(Hasher::node_handle(SYMBOL, spec.link_type)); + for (QueryAnswerElement& element : spec.target_elements) { + handles.push_back(query_answer->get(element)); + } + string key = Utils::join(handles, ' '); + if (!visited(key)) { + visit(key); + stats.visited = true; + for (QueryAnswerElement& element : spec.strength_elements) { + strength_components.push_back(get_strength(query_answer->get(element))); + } + if (add_or_update_link(handles, compute_strength(strength_components, spec.strength_composition))) { + stats.created++; + } else { + stats.updated++; + } + } + } + return stats; +} + +void CustomizableLinkCreator::extra_parameters(const string& extra_parameters) { + if (extra_parameters != "") { + vector tokens = Utils::split(extra_parameters); + untokenize(tokens); + } +} + +void CustomizableLinkCreator::add_link_specification(const vector& target_elements, + const vector& strength_elements, + StrengthComposition strength_composition, + const string& link_type) { + string trimmed_type = Utils::trim(link_type); + if (trimmed_type == "") { + RAISE_ERROR("Invalid empty link_type"); + } + + link_specification.emplace_back(target_elements, + strength_elements, + strength_composition, + trimmed_type); +} + +void CustomizableLinkCreator::tokenize(vector& tokens) { + tokens.push_back(std::to_string(this->link_specification.size())); + for (LinkSpecification& spec: this->link_specification) { + tokens.push_back(std::to_string(spec.target_elements.size())); + for (QueryAnswerElement& element : spec.target_elements) { + tokens.push_back(element.to_string()); + } + tokens.push_back(std::to_string(spec.strength_elements.size())); + for (QueryAnswerElement& element : spec.strength_elements) { + tokens.push_back(element.to_string()); + } + tokens.push_back(std::to_string(spec.strength_composition)); + tokens.push_back(spec.link_type); + } +} + +static inline string& safe_get_next_token(vector& tokens, unsigned int& cursor) { + if (cursor >= tokens.size()) { + RAISE_ERROR("Invalid tokens for CustomizableLinkCreator"); + } + return tokens[cursor++]; +} + +void CustomizableLinkCreator::untokenize(vector& tokens) { + unsigned int cursor = 0; + unsigned int num_specs = Utils::string_to_uint(safe_get_next_token(tokens, cursor)); + for (unsigned int i = 0; i < num_specs; i++) { + vector _target_elements; + vector _strength_elements; + StrengthComposition _strength_composition; + string _link_type; + unsigned int num_elements = Utils::string_to_uint(safe_get_next_token(tokens, cursor)); + for (unsigned int j = 0; j < num_elements; j++) { + _target_elements.push_back(QueryAnswerElement::from_string(safe_get_next_token(tokens, cursor))); + } + num_elements = Utils::string_to_uint(safe_get_next_token(tokens, cursor)); + for (unsigned int j = 0; j < num_elements; j++) { + _strength_elements.push_back(QueryAnswerElement::from_string(safe_get_next_token(tokens, cursor))); + } + _strength_composition = (StrengthComposition) Utils::string_to_uint(safe_get_next_token(tokens, cursor)); + _link_type = safe_get_next_token(tokens, cursor); + add_link_specification(_target_elements, _strength_elements, _strength_composition, _link_type); + } + if (cursor != tokens.size()) { + RAISE_ERROR("Invalid trailing tokens for CustomizableLinkCreator"); + } +} + +// ------------------------------------------------------------------------------------------------- +// Private methods + +double CustomizableLinkCreator::compute_strength(const vector& components, StrengthComposition composition) { + double answer = 0.0; + switch (composition) { + case PRODUCT: + answer = 1.0; + for (double strength: components) { + answer *= strength; + } + break; + default: + RAISE_ERROR("Invalid strength composition: " + std::to_string(composition)); + break; + } + return answer; +} diff --git a/src/agents/link_creation_agent/link_creators/CustomizableLinkCreator.h b/src/agents/link_creation_agent/link_creators/CustomizableLinkCreator.h new file mode 100644 index 000000000..45d907127 --- /dev/null +++ b/src/agents/link_creation_agent/link_creators/CustomizableLinkCreator.h @@ -0,0 +1,59 @@ +#pragma once +#include +#include "LinkCreator.h" + +using namespace std; + +namespace link_creators { + +/** + * + */ +class CustomizableLinkCreator : public LinkCreator { + +public: + + enum StrengthComposition { UNDEFINED = 0, PRODUCT }; + + CustomizableLinkCreator(); + ~CustomizableLinkCreator(); + + LinkCreationStats create(shared_ptr query_answer); + virtual void extra_parameters(const string& extra_parameters); + + +private: + + class LinkSpecification { + public: + LinkSpecification() = default; + LinkSpecification(const vector& target_elements, + const vector& strength_elements, + StrengthComposition strength_composition, + string link_type) { + this->target_elements = target_elements; + this->strength_elements = strength_elements; + this->strength_composition = strength_composition; + this->link_type = link_type; + } + vector target_elements; + vector strength_elements; + StrengthComposition strength_composition; + string link_type; + }; + + vector link_specification; + + double compute_strength(const vector& components, StrengthComposition composition); + +public: + + void tokenize(vector& tokens); + void untokenize(vector& tokens); + void add_link_specification(const vector& target_elements, + const vector& strength_elements, + StrengthComposition strength_composition, + const string& link_type); +}; + +} // namespace link_creators diff --git a/src/agents/link_creation_agent/link_creators/LinkCreator.h b/src/agents/link_creation_agent/link_creators/LinkCreator.h index fe7619b91..9e77ad1cc 100644 --- a/src/agents/link_creation_agent/link_creators/LinkCreator.h +++ b/src/agents/link_creation_agent/link_creators/LinkCreator.h @@ -142,6 +142,15 @@ class LinkCreator { */ virtual LinkCreationStats create(shared_ptr query_answer) = 0; + /** + * Concrete subclasses may implement this in order to receive optional extra parameters passed + * to the LinkCreationProxy by caller under the tag LINK_CREATOR_EXTRA_PARAMETERS. + * + * @param extra_parameters A string which is supposed to be parsed in order to obtain the actual + * parameters. + */ + virtual void extra_parameters(const string& extra_parameters) {} + /** * Return the AttentionBroker context to be used. * diff --git a/src/agents/link_creation_agent/link_creators/LinkCreatorRegistry.cc b/src/agents/link_creation_agent/link_creators/LinkCreatorRegistry.cc index a0678db39..14c3c782b 100644 --- a/src/agents/link_creation_agent/link_creators/LinkCreatorRegistry.cc +++ b/src/agents/link_creation_agent/link_creators/LinkCreatorRegistry.cc @@ -6,7 +6,7 @@ // ------------------------------------------------------------------------------------------------- // ADD your header here #include "AndTwoPredicates.h" -#include "Customizable.h" +#include "CustomizableLinkCreator.h" #include "UnitTestLinkCreator.h" // ------------------------------------------------------------------------------------------------- @@ -39,15 +39,15 @@ shared_ptr LinkCreatorRegistry::function(const string& tag) { if (INITIALIZED) { if (tag == REMOTE_FUNCTION) { RAISE_ERROR("Invalid use of reserved link creation function tag: " + tag); - // ----------------------------------------------------------------------------------------- - // ADD an "else if" for your function here +// ----------------------------------------------------------------------------------------- +// ADD an "else if" for your function here } else if (tag == UNIT_TEST) { answer = make_shared(); } else if (tag == CUSTOMIZABLE) { - answer = make_shared(); + answer = make_shared(); } else if (tag == AND_TWO_PREDICATES) { answer = make_shared(); - // ----------------------------------------------------------------------------------------- +// ----------------------------------------------------------------------------------------- } else { RAISE_ERROR("Unkown link creation function: " + tag); } diff --git a/src/tests/cpp/link_creation_agent_test.cc b/src/tests/cpp/link_creation_agent_test.cc index 5b7ca2de3..17f88be09 100644 --- a/src/tests/cpp/link_creation_agent_test.cc +++ b/src/tests/cpp/link_creation_agent_test.cc @@ -4,6 +4,9 @@ #include "LinkCreationProcessor.h" #include "LinkCreationProxy.h" #include "LinkCreatorRegistry.h" +#include "AndTwoPredicates.h" +#include "CustomizableLinkCreator.h" +#include "UnitTestLinkCreator.h" #include "Logger.h" #include "ServiceBus.h" #include "ServiceBusSingleton.h" @@ -58,6 +61,72 @@ TEST(LinkCreation, proxy_object) { EXPECT_EQ(tokens1, tokens3); } +TEST(LinkCreation, link_creator_registry) { + ASSERT_TRUE(dynamic_pointer_cast(LinkCreatorRegistry::function(LinkCreatorRegistry::UNIT_TEST)) != nullptr); + ASSERT_TRUE(dynamic_pointer_cast(LinkCreatorRegistry::function(LinkCreatorRegistry::CUSTOMIZABLE)) != nullptr); + ASSERT_TRUE(dynamic_pointer_cast(LinkCreatorRegistry::function(LinkCreatorRegistry::AND_TWO_PREDICATES)) != nullptr); +} + +TEST(LinkCreation, customizable_tokenization) { + vector original; + vector copy1; + vector copy2; + unsigned int count = 0; + + original.emplace_back(); + original[count++].add_link_specification( + {QueryAnswerElement(1), QueryAnswerElement(2)}, + {QueryAnswerElement("v1"), QueryAnswerElement("v2")}, + CustomizableLinkCreator::PRODUCT, + " type0 "); + + original.emplace_back(); + original[count++].add_link_specification( + {QueryAnswerElement(1)}, + {QueryAnswerElement("v1"), QueryAnswerElement("v2")}, + CustomizableLinkCreator::PRODUCT, + "type0"); + + original.emplace_back(); + original[count++].add_link_specification( + {QueryAnswerElement(1), QueryAnswerElement(2)}, + {}, + CustomizableLinkCreator::PRODUCT, + "type0"); + + original.emplace_back(); + original[count++].add_link_specification( + {}, + {}, + (CustomizableLinkCreator::StrengthComposition) 0, + "blah"); + + vector tokens1, tokens2, tokens3; + for (unsigned int i = 0; i < count; i++) { + copy1.emplace_back(); + copy2.emplace_back(); + original[i].tokenize(tokens1); + string tokens_string = Utils::join(tokens1); + copy1[i].untokenize(tokens1); + copy1[i].tokenize(tokens2); + copy2[i].extra_parameters(tokens_string); + copy2[i].tokenize(tokens3); + if (i == 0) { + ASSERT_EQ(tokens_string, "1 2 _1 _2 2 $v1 $v2 1 type0"); + } + ASSERT_EQ(tokens1, tokens2); + ASSERT_EQ(tokens1, tokens3); + tokens1.clear(); + tokens2.clear(); + tokens3.clear(); + } + + original.emplace_back(); + EXPECT_THROW(original[count++].add_link_specification({}, {}, (CustomizableLinkCreator::StrengthComposition) 0, ""), runtime_error); + EXPECT_THROW(original[count++].add_link_specification({}, {}, (CustomizableLinkCreator::StrengthComposition) 0, " "), runtime_error); + EXPECT_THROW(original[count++].add_link_specification({}, {}, (CustomizableLinkCreator::StrengthComposition) 0, " "), runtime_error); +} + int main(int argc, char** argv) { ::testing::InitGoogleTest(&argc, argv); AtomDBSingleton::provide(make_shared()); diff --git a/src/tests/integration/cpp/lca_integration_test.cc b/src/tests/integration/cpp/lca_integration_test.cc index f69b0dc1f..494158867 100644 --- a/src/tests/integration/cpp/lca_integration_test.cc +++ b/src/tests/integration/cpp/lca_integration_test.cc @@ -3,6 +3,8 @@ #include "JsonConfigParser.h" #include "LinkCreationProxy.h" #include "LinkCreatorRegistry.h" +#include "CustomizableLinkCreator.h" +#include "QueryAnswer.h" #include "Logger.h" #include "PatternMatchingQueryProxy.h" #include "ServiceBusSingleton.h" @@ -19,7 +21,7 @@ using namespace link_creation_agent; static void insert_type_symbols() { STACK_TRACE(); - vector to_insert = {EQUIVALENCE_TAG, IMPLICATION_TAG, LOGICAL_AND_TAG}; + vector to_insert = {EQUIVALENCE_TAG, IMPLICATION_TAG, LOGICAL_AND_TAG, "FunctionalTest1", "FunctionalTest2", "FunctionalTest3"}; Node* node; for (string node_name : to_insert) { node = new Node(SYMBOL, node_name); @@ -67,17 +69,8 @@ static void timeout_after_minutes(unsigned int minutes) { t.detach(); } -shared_ptr make_proxy( - BaseProxy::ORCHESTRATION_SCHEMA_TYPE orchestration = BaseProxy::NONE) { - vector query_tokens = { - AND_OPERATOR, "2", LINK_TEMPLATE, EXPRESSION, "3", - NODE, SYMBOL, EVALUATION_TAG, VARIABLE, PREDICATE1, - VARIABLE, CONCEPT, LINK_TEMPLATE, EXPRESSION, "3", - NODE, SYMBOL, EVALUATION_TAG, VARIABLE, PREDICATE2, - VARIABLE, CONCEPT, - }; - auto proxy = make_shared( - query_tokens, "", LinkCreatorRegistry::AND_TWO_PREDICATES, orchestration); +shared_ptr make_proxy(const vector& query_tokens, const string& link_creator, BaseProxy::ORCHESTRATION_SCHEMA_TYPE orchestration = BaseProxy::NONE) { + auto proxy = make_shared(query_tokens, "", link_creator, orchestration); proxy->parameters[LinkCreationProxy::MAX_SUCCESSFUL_CREATION_PER_ROUND] = (unsigned int) 0; proxy->parameters[LinkCreationProxy::MAX_UNPRODUCTIVE_VISITS_PER_ROUND] = (unsigned int) 0; proxy->parameters[LinkCreationProxy::MAX_VISIT_ATTEMPTS_PER_ROUND] = (unsigned int) 0; @@ -97,7 +90,20 @@ static bool test_and_two_predicates() { string test_case = start_test_case("test_and_two_predicates()"); bool success = true; - auto proxy = make_proxy(); + // clang-format off + vector query_tokens = { + AND_OPERATOR, "2", + LINK_TEMPLATE, EXPRESSION, "3", + NODE, SYMBOL, EVALUATION_TAG, + VARIABLE, PREDICATE1, + VARIABLE, CONCEPT, + LINK_TEMPLATE, EXPRESSION, "3", + NODE, SYMBOL, EVALUATION_TAG, + VARIABLE, PREDICATE2, + VARIABLE, CONCEPT + }; + // clang-format on + auto proxy = make_proxy(query_tokens, LinkCreatorRegistry::AND_TWO_PREDICATES); ServiceBusSingleton::get_instance()->issue_bus_command(proxy); while (true) { @@ -116,6 +122,90 @@ static bool test_and_two_predicates() { return success; } +static bool test_customizable() { + string test_case = start_test_case("test_customizable()"); + bool success = true; + vector tokens; + + // clang-format off + vector query_tokens1 = { + AND_OPERATOR, "2", + LINK_TEMPLATE, EXPRESSION, "3", + NODE, SYMBOL, EVALUATION_TAG, + LINK, EXPRESSION, "2", + NODE, SYMBOL, PREDICATE_TAG, + NODE, SYMBOL, "\"contains_bbb\"", + VARIABLE, "v1", + LINK_TEMPLATE, EXPRESSION, "3", + NODE, SYMBOL, EVALUATION_TAG, + LINK, EXPRESSION, "2", + NODE, SYMBOL, PREDICATE_TAG, + NODE, SYMBOL, "\"contains_ccc\"", + VARIABLE, "v2", + }; + // clang-format on + CustomizableLinkCreator link_creator1; + link_creator1.add_link_specification({QueryAnswerElement("v1"), QueryAnswerElement("v2")}, {}, CustomizableLinkCreator::PRODUCT, "FunctionalTest1"); + link_creator1.add_link_specification({QueryAnswerElement("v2"), QueryAnswerElement("v1")}, {}, CustomizableLinkCreator::PRODUCT, "FunctionalTest2"); + tokens.clear(); + link_creator1.tokenize(tokens); + auto proxy1 = make_proxy(query_tokens1, LinkCreatorRegistry::CUSTOMIZABLE); + proxy1->parameters[LinkCreationProxy::LINK_CREATOR_EXTRA_PARAMETERS] = (string) Utils::join(tokens); + proxy1->parameters[LinkCreationProxy::MAX_SUCCESSFUL_CREATION_PER_ROUND] = (unsigned int) 200; + + ServiceBusSingleton::get_instance()->issue_bus_command(proxy1); + + while (true) { + if (proxy1->finished()) { + break; + } + shared_ptr answer = proxy1->pop(); + if (answer == nullptr) { + Utils::sleep(); + } + } + success &= assert_equal(proxy1->get_count(), 200, "link creation count"); + + // clang-format off + vector query_tokens2 = { + AND_OPERATOR, "2", + LINK_TEMPLATE, EXPRESSION, "3", + NODE, SYMBOL, "FunctionalTest1", + VARIABLE, "v1", + VARIABLE, "v2", + LINK_TEMPLATE, EXPRESSION, "3", + NODE, SYMBOL, "FunctionalTest2", + VARIABLE, "v2", + VARIABLE, "v1", + }; + // clang-format on + CustomizableLinkCreator link_creator2; + link_creator2.add_link_specification({QueryAnswerElement("v1"), QueryAnswerElement("v2")}, {}, CustomizableLinkCreator::PRODUCT, "FunctionalTest3"); + tokens.clear(); + link_creator2.tokenize(tokens); + auto proxy2 = make_proxy(query_tokens2, LinkCreatorRegistry::CUSTOMIZABLE); + proxy2->parameters[LinkCreationProxy::LINK_CREATOR_EXTRA_PARAMETERS] = (string) Utils::join(tokens); + + ServiceBusSingleton::get_instance()->issue_bus_command(proxy2); + + while (true) { + if (proxy2->finished()) { + break; + } + shared_ptr answer = proxy2->pop(); + if (answer == nullptr) { + Utils::sleep(); + } + } + success &= assert_equal(proxy2->get_count(), 200, "link creation count"); + + AtomDBSingleton::get_instance()->delete_atoms(proxy1->get_built_atoms()); + AtomDBSingleton::get_instance()->delete_atoms(proxy2->get_built_atoms()); + + finish_test_case(test_case, success); + return success; +} + static bool test_cycles() { STACK_TRACE(); @@ -130,8 +220,22 @@ static bool test_cycles() { vector creation = {0, 0, 0, 0, 0}; vector> proxy = {nullptr, nullptr, nullptr, nullptr, nullptr}; + // clang-format off + vector query_tokens = { + AND_OPERATOR, "2", + LINK_TEMPLATE, EXPRESSION, "3", + NODE, SYMBOL, EVALUATION_TAG, + VARIABLE, PREDICATE1, + VARIABLE, CONCEPT, + LINK_TEMPLATE, EXPRESSION, "3", + NODE, SYMBOL, EVALUATION_TAG, + VARIABLE, PREDICATE2, + VARIABLE, CONCEPT + }; + // clang-format on + for (unsigned int i = 0; i < proxy.size(); i++) { - proxy[i] = make_proxy(BaseProxy::SYNC_ON_CYCLE_START); + proxy[i] = make_proxy(query_tokens, LinkCreatorRegistry::AND_TWO_PREDICATES, BaseProxy::SYNC_ON_CYCLE_START); proxy[i]->parameters[LinkCreationProxy::MAX_SUCCESSFUL_CREATION_PER_ROUND] = (unsigned int) creations_per_cycle[i]; proxy[i]->parameters[LinkCreationProxy::MAX_ROUNDS] = (unsigned int) num_cycles[i]; @@ -204,6 +308,7 @@ int main(int argc, char* argv[]) { timeout_after_minutes(10); success &= test_cycles(); success &= test_and_two_predicates(); + success &= test_customizable(); LOG_INFO("================================================================================"); if (success) { LOG_INFO("OK - ALL TEST CASES PASSED"); From 95f5377cb49c2dc171c853bac18801c4b07bd05d Mon Sep 17 00:00:00 2001 From: Andre Senna <“andre.senna@gmail.com”> Date: Mon, 14 Sep 2026 13:05:40 -0300 Subject: [PATCH 08/12] Format fixes --- .../link_creators/AndTwoPredicates.cc | 3 +- .../link_creators/CustomizableLinkCreator.cc | 32 ++++++----- .../link_creators/CustomizableLinkCreator.h | 16 ++---- .../link_creators/LinkCreatorRegistry.cc | 6 +- src/tests/cpp/link_creation_agent_test.cc | 55 ++++++++++--------- .../integration/cpp/lca_integration_test.cc | 34 +++++++++--- 6 files changed, 82 insertions(+), 64 deletions(-) diff --git a/src/agents/link_creation_agent/link_creators/AndTwoPredicates.cc b/src/agents/link_creation_agent/link_creators/AndTwoPredicates.cc index 591ba4638..4ee6a0f1d 100644 --- a/src/agents/link_creation_agent/link_creators/AndTwoPredicates.cc +++ b/src/agents/link_creation_agent/link_creators/AndTwoPredicates.cc @@ -46,7 +46,8 @@ LinkCreationStats AndTwoPredicates::create(shared_ptr query_answer) } if (strength >= strength_threshold()) { string new_predicate_handle = Hasher::link_handle(EXPRESSION, targets); - if (add_or_update_link({EVALUATION_HANDLE, new_predicate_handle, concept_}, strength)) { + if (add_or_update_link({EVALUATION_HANDLE, new_predicate_handle, concept_}, + strength)) { stats.created++; } else { stats.updated++; diff --git a/src/agents/link_creation_agent/link_creators/CustomizableLinkCreator.cc b/src/agents/link_creation_agent/link_creators/CustomizableLinkCreator.cc index b102d7924..ee926538a 100644 --- a/src/agents/link_creation_agent/link_creators/CustomizableLinkCreator.cc +++ b/src/agents/link_creation_agent/link_creators/CustomizableLinkCreator.cc @@ -1,4 +1,5 @@ #include "CustomizableLinkCreator.h" + #include "Hasher.h" #include "tags.h" @@ -7,11 +8,9 @@ using namespace link_creators; // ------------------------------------------------------------------------------------------------- // Public methods -CustomizableLinkCreator::CustomizableLinkCreator() { -} +CustomizableLinkCreator::CustomizableLinkCreator() {} -CustomizableLinkCreator::~CustomizableLinkCreator() { -} +CustomizableLinkCreator::~CustomizableLinkCreator() {} LinkCreationStats CustomizableLinkCreator::create(shared_ptr query_answer) { STACK_TRACE(); @@ -34,7 +33,8 @@ LinkCreationStats CustomizableLinkCreator::create(shared_ptr query_ for (QueryAnswerElement& element : spec.strength_elements) { strength_components.push_back(get_strength(query_answer->get(element))); } - if (add_or_update_link(handles, compute_strength(strength_components, spec.strength_composition))) { + if (add_or_update_link(handles, + compute_strength(strength_components, spec.strength_composition))) { stats.created++; } else { stats.updated++; @@ -60,15 +60,13 @@ void CustomizableLinkCreator::add_link_specification(const vector& tokens) { tokens.push_back(std::to_string(this->link_specification.size())); - for (LinkSpecification& spec: this->link_specification) { + for (LinkSpecification& spec : this->link_specification) { tokens.push_back(std::to_string(spec.target_elements.size())); for (QueryAnswerElement& element : spec.target_elements) { tokens.push_back(element.to_string()); @@ -99,13 +97,16 @@ void CustomizableLinkCreator::untokenize(vector& tokens) { string _link_type; unsigned int num_elements = Utils::string_to_uint(safe_get_next_token(tokens, cursor)); for (unsigned int j = 0; j < num_elements; j++) { - _target_elements.push_back(QueryAnswerElement::from_string(safe_get_next_token(tokens, cursor))); + _target_elements.push_back( + QueryAnswerElement::from_string(safe_get_next_token(tokens, cursor))); } num_elements = Utils::string_to_uint(safe_get_next_token(tokens, cursor)); for (unsigned int j = 0; j < num_elements; j++) { - _strength_elements.push_back(QueryAnswerElement::from_string(safe_get_next_token(tokens, cursor))); + _strength_elements.push_back( + QueryAnswerElement::from_string(safe_get_next_token(tokens, cursor))); } - _strength_composition = (StrengthComposition) Utils::string_to_uint(safe_get_next_token(tokens, cursor)); + _strength_composition = + (StrengthComposition) Utils::string_to_uint(safe_get_next_token(tokens, cursor)); _link_type = safe_get_next_token(tokens, cursor); add_link_specification(_target_elements, _strength_elements, _strength_composition, _link_type); } @@ -117,12 +118,13 @@ void CustomizableLinkCreator::untokenize(vector& tokens) { // ------------------------------------------------------------------------------------------------- // Private methods -double CustomizableLinkCreator::compute_strength(const vector& components, StrengthComposition composition) { +double CustomizableLinkCreator::compute_strength(const vector& components, + StrengthComposition composition) { double answer = 0.0; switch (composition) { case PRODUCT: answer = 1.0; - for (double strength: components) { + for (double strength : components) { answer *= strength; } break; diff --git a/src/agents/link_creation_agent/link_creators/CustomizableLinkCreator.h b/src/agents/link_creation_agent/link_creators/CustomizableLinkCreator.h index 45d907127..6bce8b100 100644 --- a/src/agents/link_creation_agent/link_creators/CustomizableLinkCreator.h +++ b/src/agents/link_creation_agent/link_creators/CustomizableLinkCreator.h @@ -1,5 +1,6 @@ #pragma once #include + #include "LinkCreator.h" using namespace std; @@ -10,9 +11,7 @@ namespace link_creators { * */ class CustomizableLinkCreator : public LinkCreator { - -public: - + public: enum StrengthComposition { UNDEFINED = 0, PRODUCT }; CustomizableLinkCreator(); @@ -21,11 +20,9 @@ class CustomizableLinkCreator : public LinkCreator { LinkCreationStats create(shared_ptr query_answer); virtual void extra_parameters(const string& extra_parameters); - -private: - + private: class LinkSpecification { - public: + public: LinkSpecification() = default; LinkSpecification(const vector& target_elements, const vector& strength_elements, @@ -46,8 +43,7 @@ class CustomizableLinkCreator : public LinkCreator { double compute_strength(const vector& components, StrengthComposition composition); -public: - + public: void tokenize(vector& tokens); void untokenize(vector& tokens); void add_link_specification(const vector& target_elements, @@ -56,4 +52,4 @@ class CustomizableLinkCreator : public LinkCreator { const string& link_type); }; -} // namespace link_creators +} // namespace link_creators diff --git a/src/agents/link_creation_agent/link_creators/LinkCreatorRegistry.cc b/src/agents/link_creation_agent/link_creators/LinkCreatorRegistry.cc index 14c3c782b..87b427c1f 100644 --- a/src/agents/link_creation_agent/link_creators/LinkCreatorRegistry.cc +++ b/src/agents/link_creation_agent/link_creators/LinkCreatorRegistry.cc @@ -39,15 +39,15 @@ shared_ptr LinkCreatorRegistry::function(const string& tag) { if (INITIALIZED) { if (tag == REMOTE_FUNCTION) { RAISE_ERROR("Invalid use of reserved link creation function tag: " + tag); -// ----------------------------------------------------------------------------------------- -// ADD an "else if" for your function here + // ----------------------------------------------------------------------------------------- + // ADD an "else if" for your function here } else if (tag == UNIT_TEST) { answer = make_shared(); } else if (tag == CUSTOMIZABLE) { answer = make_shared(); } else if (tag == AND_TWO_PREDICATES) { answer = make_shared(); -// ----------------------------------------------------------------------------------------- + // ----------------------------------------------------------------------------------------- } else { RAISE_ERROR("Unkown link creation function: " + tag); } diff --git a/src/tests/cpp/link_creation_agent_test.cc b/src/tests/cpp/link_creation_agent_test.cc index 17f88be09..27b684853 100644 --- a/src/tests/cpp/link_creation_agent_test.cc +++ b/src/tests/cpp/link_creation_agent_test.cc @@ -1,17 +1,17 @@ #include +#include "AndTwoPredicates.h" +#include "CustomizableLinkCreator.h" #include "InMemoryDB.h" #include "LinkCreationProcessor.h" #include "LinkCreationProxy.h" #include "LinkCreatorRegistry.h" -#include "AndTwoPredicates.h" -#include "CustomizableLinkCreator.h" -#include "UnitTestLinkCreator.h" #include "Logger.h" #include "ServiceBus.h" #include "ServiceBusSingleton.h" #include "TestAtomDBJsonConfig.h" #include "TestSystemParams.h" +#include "UnitTestLinkCreator.h" #include "Utils.h" #include "gtest/gtest.h" @@ -62,9 +62,12 @@ TEST(LinkCreation, proxy_object) { } TEST(LinkCreation, link_creator_registry) { - ASSERT_TRUE(dynamic_pointer_cast(LinkCreatorRegistry::function(LinkCreatorRegistry::UNIT_TEST)) != nullptr); - ASSERT_TRUE(dynamic_pointer_cast(LinkCreatorRegistry::function(LinkCreatorRegistry::CUSTOMIZABLE)) != nullptr); - ASSERT_TRUE(dynamic_pointer_cast(LinkCreatorRegistry::function(LinkCreatorRegistry::AND_TWO_PREDICATES)) != nullptr); + ASSERT_TRUE(dynamic_pointer_cast( + LinkCreatorRegistry::function(LinkCreatorRegistry::UNIT_TEST)) != nullptr); + ASSERT_TRUE(dynamic_pointer_cast( + LinkCreatorRegistry::function(LinkCreatorRegistry::CUSTOMIZABLE)) != nullptr); + ASSERT_TRUE(dynamic_pointer_cast( + LinkCreatorRegistry::function(LinkCreatorRegistry::AND_TWO_PREDICATES)) != nullptr); } TEST(LinkCreation, customizable_tokenization) { @@ -74,32 +77,24 @@ TEST(LinkCreation, customizable_tokenization) { unsigned int count = 0; original.emplace_back(); - original[count++].add_link_specification( - {QueryAnswerElement(1), QueryAnswerElement(2)}, - {QueryAnswerElement("v1"), QueryAnswerElement("v2")}, - CustomizableLinkCreator::PRODUCT, - " type0 "); + original[count++].add_link_specification({QueryAnswerElement(1), QueryAnswerElement(2)}, + {QueryAnswerElement("v1"), QueryAnswerElement("v2")}, + CustomizableLinkCreator::PRODUCT, + " type0 "); original.emplace_back(); - original[count++].add_link_specification( - {QueryAnswerElement(1)}, - {QueryAnswerElement("v1"), QueryAnswerElement("v2")}, - CustomizableLinkCreator::PRODUCT, - "type0"); + original[count++].add_link_specification({QueryAnswerElement(1)}, + {QueryAnswerElement("v1"), QueryAnswerElement("v2")}, + CustomizableLinkCreator::PRODUCT, + "type0"); original.emplace_back(); original[count++].add_link_specification( - {QueryAnswerElement(1), QueryAnswerElement(2)}, - {}, - CustomizableLinkCreator::PRODUCT, - "type0"); + {QueryAnswerElement(1), QueryAnswerElement(2)}, {}, CustomizableLinkCreator::PRODUCT, "type0"); original.emplace_back(); original[count++].add_link_specification( - {}, - {}, - (CustomizableLinkCreator::StrengthComposition) 0, - "blah"); + {}, {}, (CustomizableLinkCreator::StrengthComposition) 0, "blah"); vector tokens1, tokens2, tokens3; for (unsigned int i = 0; i < count; i++) { @@ -122,9 +117,15 @@ TEST(LinkCreation, customizable_tokenization) { } original.emplace_back(); - EXPECT_THROW(original[count++].add_link_specification({}, {}, (CustomizableLinkCreator::StrengthComposition) 0, ""), runtime_error); - EXPECT_THROW(original[count++].add_link_specification({}, {}, (CustomizableLinkCreator::StrengthComposition) 0, " "), runtime_error); - EXPECT_THROW(original[count++].add_link_specification({}, {}, (CustomizableLinkCreator::StrengthComposition) 0, " "), runtime_error); + EXPECT_THROW(original[count++].add_link_specification( + {}, {}, (CustomizableLinkCreator::StrengthComposition) 0, ""), + runtime_error); + EXPECT_THROW(original[count++].add_link_specification( + {}, {}, (CustomizableLinkCreator::StrengthComposition) 0, " "), + runtime_error); + EXPECT_THROW(original[count++].add_link_specification( + {}, {}, (CustomizableLinkCreator::StrengthComposition) 0, " "), + runtime_error); } int main(int argc, char** argv) { diff --git a/src/tests/integration/cpp/lca_integration_test.cc b/src/tests/integration/cpp/lca_integration_test.cc index 494158867..3589b681f 100644 --- a/src/tests/integration/cpp/lca_integration_test.cc +++ b/src/tests/integration/cpp/lca_integration_test.cc @@ -1,12 +1,12 @@ #include "AndTwoPredicates.h" #include "AtomDBSingleton.h" +#include "CustomizableLinkCreator.h" #include "JsonConfigParser.h" #include "LinkCreationProxy.h" #include "LinkCreatorRegistry.h" -#include "CustomizableLinkCreator.h" -#include "QueryAnswer.h" #include "Logger.h" #include "PatternMatchingQueryProxy.h" +#include "QueryAnswer.h" #include "ServiceBusSingleton.h" #include "SystemParametersSingleton.h" #include "Utils.h" @@ -21,7 +21,12 @@ using namespace link_creation_agent; static void insert_type_symbols() { STACK_TRACE(); - vector to_insert = {EQUIVALENCE_TAG, IMPLICATION_TAG, LOGICAL_AND_TAG, "FunctionalTest1", "FunctionalTest2", "FunctionalTest3"}; + vector to_insert = {EQUIVALENCE_TAG, + IMPLICATION_TAG, + LOGICAL_AND_TAG, + "FunctionalTest1", + "FunctionalTest2", + "FunctionalTest3"}; Node* node; for (string node_name : to_insert) { node = new Node(SYMBOL, node_name); @@ -69,7 +74,10 @@ static void timeout_after_minutes(unsigned int minutes) { t.detach(); } -shared_ptr make_proxy(const vector& query_tokens, const string& link_creator, BaseProxy::ORCHESTRATION_SCHEMA_TYPE orchestration = BaseProxy::NONE) { +shared_ptr make_proxy( + const vector& query_tokens, + const string& link_creator, + BaseProxy::ORCHESTRATION_SCHEMA_TYPE orchestration = BaseProxy::NONE) { auto proxy = make_shared(query_tokens, "", link_creator, orchestration); proxy->parameters[LinkCreationProxy::MAX_SUCCESSFUL_CREATION_PER_ROUND] = (unsigned int) 0; proxy->parameters[LinkCreationProxy::MAX_UNPRODUCTIVE_VISITS_PER_ROUND] = (unsigned int) 0; @@ -145,8 +153,14 @@ static bool test_customizable() { }; // clang-format on CustomizableLinkCreator link_creator1; - link_creator1.add_link_specification({QueryAnswerElement("v1"), QueryAnswerElement("v2")}, {}, CustomizableLinkCreator::PRODUCT, "FunctionalTest1"); - link_creator1.add_link_specification({QueryAnswerElement("v2"), QueryAnswerElement("v1")}, {}, CustomizableLinkCreator::PRODUCT, "FunctionalTest2"); + link_creator1.add_link_specification({QueryAnswerElement("v1"), QueryAnswerElement("v2")}, + {}, + CustomizableLinkCreator::PRODUCT, + "FunctionalTest1"); + link_creator1.add_link_specification({QueryAnswerElement("v2"), QueryAnswerElement("v1")}, + {}, + CustomizableLinkCreator::PRODUCT, + "FunctionalTest2"); tokens.clear(); link_creator1.tokenize(tokens); auto proxy1 = make_proxy(query_tokens1, LinkCreatorRegistry::CUSTOMIZABLE); @@ -180,7 +194,10 @@ static bool test_customizable() { }; // clang-format on CustomizableLinkCreator link_creator2; - link_creator2.add_link_specification({QueryAnswerElement("v1"), QueryAnswerElement("v2")}, {}, CustomizableLinkCreator::PRODUCT, "FunctionalTest3"); + link_creator2.add_link_specification({QueryAnswerElement("v1"), QueryAnswerElement("v2")}, + {}, + CustomizableLinkCreator::PRODUCT, + "FunctionalTest3"); tokens.clear(); link_creator2.tokenize(tokens); auto proxy2 = make_proxy(query_tokens2, LinkCreatorRegistry::CUSTOMIZABLE); @@ -235,7 +252,8 @@ static bool test_cycles() { // clang-format on for (unsigned int i = 0; i < proxy.size(); i++) { - proxy[i] = make_proxy(query_tokens, LinkCreatorRegistry::AND_TWO_PREDICATES, BaseProxy::SYNC_ON_CYCLE_START); + proxy[i] = make_proxy( + query_tokens, LinkCreatorRegistry::AND_TWO_PREDICATES, BaseProxy::SYNC_ON_CYCLE_START); proxy[i]->parameters[LinkCreationProxy::MAX_SUCCESSFUL_CREATION_PER_ROUND] = (unsigned int) creations_per_cycle[i]; proxy[i]->parameters[LinkCreationProxy::MAX_ROUNDS] = (unsigned int) num_cycles[i]; From 88987df8657edba1babc350e76cee9754e8ecc86 Mon Sep 17 00:00:00 2001 From: Andre Senna <“andre.senna@gmail.com”> Date: Mon, 14 Sep 2026 13:54:21 -0300 Subject: [PATCH 09/12] Peer review fixes --- .../link_creators/CustomizableLinkCreator.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/agents/link_creation_agent/link_creators/CustomizableLinkCreator.cc b/src/agents/link_creation_agent/link_creators/CustomizableLinkCreator.cc index ee926538a..a682dbde5 100644 --- a/src/agents/link_creation_agent/link_creators/CustomizableLinkCreator.cc +++ b/src/agents/link_creation_agent/link_creators/CustomizableLinkCreator.cc @@ -56,8 +56,8 @@ void CustomizableLinkCreator::add_link_specification(const vector Date: Wed, 16 Sep 2026 09:27:11 -0300 Subject: [PATCH 10/12] Peer review fixes --- .../link_creators/AndTwoPredicates.cc | 13 +++++-------- .../link_creators/CustomizableLinkCreator.cc | 2 +- .../link_creators/LinkCreator.cc | 3 +++ 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/agents/link_creation_agent/link_creators/AndTwoPredicates.cc b/src/agents/link_creation_agent/link_creators/AndTwoPredicates.cc index 4ee6a0f1d..8d4baa1e5 100644 --- a/src/agents/link_creation_agent/link_creators/AndTwoPredicates.cc +++ b/src/agents/link_creation_agent/link_creators/AndTwoPredicates.cc @@ -44,14 +44,11 @@ LinkCreationStats AndTwoPredicates::create(shared_ptr query_answer) for (string& h : query_answer->get_handles_vector()) { strength *= get_strength(h); } - if (strength >= strength_threshold()) { - string new_predicate_handle = Hasher::link_handle(EXPRESSION, targets); - if (add_or_update_link({EVALUATION_HANDLE, new_predicate_handle, concept_}, - strength)) { - stats.created++; - } else { - stats.updated++; - } + string new_predicate_handle = Hasher::link_handle(EXPRESSION, targets); + if (add_or_update_link({EVALUATION_HANDLE, new_predicate_handle, concept_}, strength)) { + stats.created++; + } else { + stats.updated++; } } else { LOG_DEBUG("(" + diff --git a/src/agents/link_creation_agent/link_creators/CustomizableLinkCreator.cc b/src/agents/link_creation_agent/link_creators/CustomizableLinkCreator.cc index a682dbde5..a8b3cedc8 100644 --- a/src/agents/link_creation_agent/link_creators/CustomizableLinkCreator.cc +++ b/src/agents/link_creation_agent/link_creators/CustomizableLinkCreator.cc @@ -18,7 +18,7 @@ LinkCreationStats CustomizableLinkCreator::create(shared_ptr query_ for (LinkSpecification& spec : this->link_specification) { if ((spec.target_elements.size() == 0) || (spec.link_type == "")) { RAISE_ERROR("Invalid empty target elements or link_type"); - return stats; + break; } vector handles; vector strength_components; diff --git a/src/agents/link_creation_agent/link_creators/LinkCreator.cc b/src/agents/link_creation_agent/link_creators/LinkCreator.cc index a04acae9d..19e5c6546 100644 --- a/src/agents/link_creation_agent/link_creators/LinkCreator.cc +++ b/src/agents/link_creation_agent/link_creators/LinkCreator.cc @@ -17,6 +17,9 @@ LinkCreator::LinkCreator() { bool LinkCreator::add_or_update_link(const vector& targets, double strength) { STACK_TRACE(); + if (strength < this->_strength_threshold) { + return false; + } auto db = atomdb(); bool new_link_created_flag = false; shared_ptr new_link = From 090d4eba7fafdbfc3c85932705b6611c15bda384 Mon Sep 17 00:00:00 2001 From: Andre Senna <“andre.senna@gmail.com”> Date: Wed, 16 Sep 2026 09:55:51 -0300 Subject: [PATCH 11/12] Peer review fixes --- .../link_creation_agent/link_creators/AndTwoPredicates.cc | 7 ++++--- .../link_creators/CustomizableLinkCreator.cc | 6 +++--- .../link_creation_agent/link_creators/LinkCreator.cc | 6 +++--- src/agents/link_creation_agent/link_creators/LinkCreator.h | 3 ++- 4 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/agents/link_creation_agent/link_creators/AndTwoPredicates.cc b/src/agents/link_creation_agent/link_creators/AndTwoPredicates.cc index 8d4baa1e5..e02954fc5 100644 --- a/src/agents/link_creation_agent/link_creators/AndTwoPredicates.cc +++ b/src/agents/link_creation_agent/link_creators/AndTwoPredicates.cc @@ -37,7 +37,7 @@ LinkCreationStats AndTwoPredicates::create(shared_ptr query_answer) extract_mentioned_predicates(mentioned_predicates1, predicates[1]); if (!Utils::intersects(mentioned_predicates0, mentioned_predicates1)) { vector targets = {LOGICAL_AND_HANDLE, predicates[0], predicates[1]}; - if (add_or_update_link(targets, 1.0)) { + if (add_or_update_link(targets, 1.0) == CREATED) { stats.created++; } double strength = 1; @@ -45,9 +45,10 @@ LinkCreationStats AndTwoPredicates::create(shared_ptr query_answer) strength *= get_strength(h); } string new_predicate_handle = Hasher::link_handle(EXPRESSION, targets); - if (add_or_update_link({EVALUATION_HANDLE, new_predicate_handle, concept_}, strength)) { + AddLinkStatus add_status = add_or_update_link({EVALUATION_HANDLE, new_predicate_handle, concept_}, strength); + if (add_status == CREATED) { stats.created++; - } else { + } else if (add_status == UPDATED) { stats.updated++; } } else { diff --git a/src/agents/link_creation_agent/link_creators/CustomizableLinkCreator.cc b/src/agents/link_creation_agent/link_creators/CustomizableLinkCreator.cc index a8b3cedc8..8d525f5a1 100644 --- a/src/agents/link_creation_agent/link_creators/CustomizableLinkCreator.cc +++ b/src/agents/link_creation_agent/link_creators/CustomizableLinkCreator.cc @@ -33,10 +33,10 @@ LinkCreationStats CustomizableLinkCreator::create(shared_ptr query_ for (QueryAnswerElement& element : spec.strength_elements) { strength_components.push_back(get_strength(query_answer->get(element))); } - if (add_or_update_link(handles, - compute_strength(strength_components, spec.strength_composition))) { + AddLinkStatus add_status = add_or_update_link(handles, compute_strength(strength_components, spec.strength_composition)); + if (add_status == CREATED) { stats.created++; - } else { + } else if (add_status == UPDATED) { stats.updated++; } } diff --git a/src/agents/link_creation_agent/link_creators/LinkCreator.cc b/src/agents/link_creation_agent/link_creators/LinkCreator.cc index 19e5c6546..18c0cf003 100644 --- a/src/agents/link_creation_agent/link_creators/LinkCreator.cc +++ b/src/agents/link_creation_agent/link_creators/LinkCreator.cc @@ -15,10 +15,10 @@ LinkCreator::LinkCreator() { this->_log_new_links = false; } -bool LinkCreator::add_or_update_link(const vector& targets, double strength) { +LinkCreator::AddLinkStatus LinkCreator::add_or_update_link(const vector& targets, double strength) { STACK_TRACE(); if (strength < this->_strength_threshold) { - return false; + return REJECTED; } auto db = atomdb(); bool new_link_created_flag = false; @@ -50,7 +50,7 @@ bool LinkCreator::add_or_update_link(const vector& targets, double stren save_link_metta(new_link); } } - return new_link_created_flag; + return (new_link_created_flag ? CREATED : UPDATED); } string LinkCreator::get_node_name(const string& handle) { diff --git a/src/agents/link_creation_agent/link_creators/LinkCreator.h b/src/agents/link_creation_agent/link_creators/LinkCreator.h index 9e77ad1cc..ab3ac720d 100644 --- a/src/agents/link_creation_agent/link_creators/LinkCreator.h +++ b/src/agents/link_creation_agent/link_creators/LinkCreator.h @@ -54,6 +54,7 @@ class LinkCreationStats { */ class LinkCreator { public: + enum AddLinkStatus { REJECTED = 0, UPDATED, CREATED }; LinkCreator(); virtual ~LinkCreator() {} @@ -168,7 +169,7 @@ class LinkCreator { inline HandleDecoder* decoder() { return static_pointer_cast(atomdb()).get(); } inline void add_determiners(vector& entry) { this->_buffer_determiners.push_back(entry); } - bool add_or_update_link(const vector& targets, double strength); + AddLinkStatus add_or_update_link(const vector& targets, double strength); double get_strength(const string& handle); string get_node_name(const string& handle); void save_link_metta(shared_ptr link); From aa211ec3ddacdd772e32de894016fda8942e0b6e Mon Sep 17 00:00:00 2001 From: Andre Senna <“andre.senna@gmail.com”> Date: Wed, 16 Sep 2026 10:08:49 -0300 Subject: [PATCH 12/12] Format fixes --- .../link_creation_agent/link_creators/AndTwoPredicates.cc | 3 ++- .../link_creators/CustomizableLinkCreator.cc | 3 ++- src/agents/link_creation_agent/link_creators/LinkCreator.cc | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/agents/link_creation_agent/link_creators/AndTwoPredicates.cc b/src/agents/link_creation_agent/link_creators/AndTwoPredicates.cc index e02954fc5..c92642521 100644 --- a/src/agents/link_creation_agent/link_creators/AndTwoPredicates.cc +++ b/src/agents/link_creation_agent/link_creators/AndTwoPredicates.cc @@ -45,7 +45,8 @@ LinkCreationStats AndTwoPredicates::create(shared_ptr query_answer) strength *= get_strength(h); } string new_predicate_handle = Hasher::link_handle(EXPRESSION, targets); - AddLinkStatus add_status = add_or_update_link({EVALUATION_HANDLE, new_predicate_handle, concept_}, strength); + AddLinkStatus add_status = + add_or_update_link({EVALUATION_HANDLE, new_predicate_handle, concept_}, strength); if (add_status == CREATED) { stats.created++; } else if (add_status == UPDATED) { diff --git a/src/agents/link_creation_agent/link_creators/CustomizableLinkCreator.cc b/src/agents/link_creation_agent/link_creators/CustomizableLinkCreator.cc index 8d525f5a1..0a4388eb9 100644 --- a/src/agents/link_creation_agent/link_creators/CustomizableLinkCreator.cc +++ b/src/agents/link_creation_agent/link_creators/CustomizableLinkCreator.cc @@ -33,7 +33,8 @@ LinkCreationStats CustomizableLinkCreator::create(shared_ptr query_ for (QueryAnswerElement& element : spec.strength_elements) { strength_components.push_back(get_strength(query_answer->get(element))); } - AddLinkStatus add_status = add_or_update_link(handles, compute_strength(strength_components, spec.strength_composition)); + AddLinkStatus add_status = add_or_update_link( + handles, compute_strength(strength_components, spec.strength_composition)); if (add_status == CREATED) { stats.created++; } else if (add_status == UPDATED) { diff --git a/src/agents/link_creation_agent/link_creators/LinkCreator.cc b/src/agents/link_creation_agent/link_creators/LinkCreator.cc index 18c0cf003..0f5c2fc1b 100644 --- a/src/agents/link_creation_agent/link_creators/LinkCreator.cc +++ b/src/agents/link_creation_agent/link_creators/LinkCreator.cc @@ -15,7 +15,8 @@ LinkCreator::LinkCreator() { this->_log_new_links = false; } -LinkCreator::AddLinkStatus LinkCreator::add_or_update_link(const vector& targets, double strength) { +LinkCreator::AddLinkStatus LinkCreator::add_or_update_link(const vector& targets, + double strength) { STACK_TRACE(); if (strength < this->_strength_threshold) { return REJECTED;