diff --git a/src/agents/evolution/QueryEvolutionProcessor.cc b/src/agents/evolution/QueryEvolutionProcessor.cc index a051cb0b..51921d91 100644 --- a/src/agents/evolution/QueryEvolutionProcessor.cc +++ b/src/agents/evolution/QueryEvolutionProcessor.cc @@ -597,7 +597,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"); diff --git a/src/agents/link_creation_agent/LinkCreationProcessor.cc b/src/agents/link_creation_agent/LinkCreationProcessor.cc index 8c4a0199..93d77d58 100644 --- a/src/agents/link_creation_agent/LinkCreationProcessor.cc +++ b/src/agents/link_creation_agent/LinkCreationProcessor.cc @@ -210,7 +210,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 7547c4d9..b19071e8 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 @@ -44,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(); @@ -143,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 fadf90a3..db0f1b4b 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(); diff --git a/src/agents/link_creation_agent/link_creators/AndTwoPredicates.cc b/src/agents/link_creation_agent/link_creators/AndTwoPredicates.cc index 1a99feeb..c9264252 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,17 +37,19 @@ 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) == CREATED) { + 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); + string new_predicate_handle = Hasher::link_handle(EXPRESSION, targets); + AddLinkStatus add_status = add_or_update_link({EVALUATION_HANDLE, new_predicate_handle, concept_}, strength); - } else { + if (add_status == CREATED) { + stats.created++; + } 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 new file mode 100644 index 00000000..0a4388eb --- /dev/null +++ b/src/agents/link_creation_agent/link_creators/CustomizableLinkCreator.cc @@ -0,0 +1,137 @@ +#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"); + break; + } + 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))); + } + 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) { + 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 == "") || (trimmed_type.find(' ') != std::string::npos)) { + RAISE_ERROR("Invalid link_type: " + 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 00000000..6bce8b10 --- /dev/null +++ b/src/agents/link_creation_agent/link_creators/CustomizableLinkCreator.h @@ -0,0 +1,55 @@ +#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.cc b/src/agents/link_creation_agent/link_creators/LinkCreator.cc index a04acae9..0f5c2fc1 100644 --- a/src/agents/link_creation_agent/link_creators/LinkCreator.cc +++ b/src/agents/link_creation_agent/link_creators/LinkCreator.cc @@ -15,8 +15,12 @@ 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 REJECTED; + } auto db = atomdb(); bool new_link_created_flag = false; shared_ptr new_link = @@ -47,7 +51,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 fe7619b9..ab3ac720 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() {} @@ -142,6 +143,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. * @@ -159,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); diff --git a/src/agents/link_creation_agent/link_creators/LinkCreatorRegistry.cc b/src/agents/link_creation_agent/link_creators/LinkCreatorRegistry.cc index 52e02aff..87b427c1 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 "AndTwoPredicates.h" +#include "CustomizableLinkCreator.h" #include "UnitTestLinkCreator.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 == CUSTOMIZABLE) { + 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 9ebab08c..73d637ee 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() {} diff --git a/src/commons/Utils.cc b/src/commons/Utils.cc index 61285f51..7bad6e26 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 94fedfea..fcadf62b 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/link_creation_agent_test.cc b/src/tests/cpp/link_creation_agent_test.cc index 5b7ca2de..27b68485 100644 --- a/src/tests/cpp/link_creation_agent_test.cc +++ b/src/tests/cpp/link_creation_agent_test.cc @@ -1,5 +1,7 @@ #include +#include "AndTwoPredicates.h" +#include "CustomizableLinkCreator.h" #include "InMemoryDB.h" #include "LinkCreationProcessor.h" #include "LinkCreationProxy.h" @@ -9,6 +11,7 @@ #include "ServiceBusSingleton.h" #include "TestAtomDBJsonConfig.h" #include "TestSystemParams.h" +#include "UnitTestLinkCreator.h" #include "Utils.h" #include "gtest/gtest.h" @@ -58,6 +61,73 @@ 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/cpp/utils_test.cc b/src/tests/cpp/utils_test.cc index 5194c050..a8579770 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}})) { diff --git a/src/tests/integration/cpp/lca_integration_test.cc b/src/tests/integration/cpp/lca_integration_test.cc index f69b0dc1..3589b681 100644 --- a/src/tests/integration/cpp/lca_integration_test.cc +++ b/src/tests/integration/cpp/lca_integration_test.cc @@ -1,10 +1,12 @@ #include "AndTwoPredicates.h" #include "AtomDBSingleton.h" +#include "CustomizableLinkCreator.h" #include "JsonConfigParser.h" #include "LinkCreationProxy.h" #include "LinkCreatorRegistry.h" #include "Logger.h" #include "PatternMatchingQueryProxy.h" +#include "QueryAnswer.h" #include "ServiceBusSingleton.h" #include "SystemParametersSingleton.h" #include "Utils.h" @@ -19,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}; + 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); @@ -68,16 +75,10 @@ static void timeout_after_minutes(unsigned int minutes) { } shared_ptr make_proxy( + const vector& query_tokens, + const string& link_creator, 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); + 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 +98,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 +130,99 @@ 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 +237,23 @@ 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 +326,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");