diff --git a/src/BUILD b/src/BUILD index 7d96c4cd..f42bc37e 100644 --- a/src/BUILD +++ b/src/BUILD @@ -176,6 +176,18 @@ cc_binary( ], ) +cc_binary( + name = "evaluation_evolution", + srcs = [], + defines = ["BAZEL_BUILD"], + linkstatic = 1, + deps = [ + "//commons:commons_lib", + "//tests/main:evaluation_evolution_main_lib", + "@mbedtls", + ], +) + cc_binary( name = "busnode", srcs = [], diff --git a/src/agents/context_broker/ContextBrokerProcessor.cc b/src/agents/context_broker/ContextBrokerProcessor.cc index 3000282e..9ff65342 100644 --- a/src/agents/context_broker/ContextBrokerProcessor.cc +++ b/src/agents/context_broker/ContextBrokerProcessor.cc @@ -122,8 +122,8 @@ void ContextBrokerProcessor::create_context(shared_ptr monitor, proxy->parameters.get_or(BaseQueryProxy::ATTENTION_UPDATE_FLAG, false); pattern_proxy->parameters[BaseQueryProxy::USE_LINK_TEMPLATE_CACHE] = proxy->parameters.get_or(BaseQueryProxy::USE_LINK_TEMPLATE_CACHE, false); - pattern_proxy->parameters[PatternMatchingQueryProxy::POSITIVE_IMPORTANCE_FLAG] = - proxy->parameters.get_or(PatternMatchingQueryProxy::POSITIVE_IMPORTANCE_FLAG, false); + pattern_proxy->parameters[PatternMatchingQueryProxy::POSITIVE_IMPORTANCE_FLAG] = false; + pattern_proxy->parameters[PatternMatchingQueryProxy::DISREGARD_IMPORTANCE_FLAG] = true; pattern_proxy->parameters[BaseQueryProxy::USE_METTA_AS_QUERY_TOKENS] = proxy->parameters.get_or(BaseQueryProxy::USE_METTA_AS_QUERY_TOKENS, false); diff --git a/src/agents/evolution/QueryEvolutionProcessor.cc b/src/agents/evolution/QueryEvolutionProcessor.cc index 92d3c7e7..2984ec7b 100644 --- a/src/agents/evolution/QueryEvolutionProcessor.cc +++ b/src/agents/evolution/QueryEvolutionProcessor.cc @@ -292,7 +292,7 @@ float eval_word(const string& handle, string& word) { void QueryEvolutionProcessor::correlate_similar(shared_ptr proxy, shared_ptr correlation_query_answer) { vector query_tokens; - vector handle_list; + map> handle_lists; vector> correlation_queries = proxy->get_correlation_queries(); vector> correlation_replacements = proxy->get_correlation_replacements(); @@ -349,24 +349,30 @@ void QueryEvolutionProcessor::correlate_similar(shared_ptr } // Update AttentionBroker - handle_list.clear(); - handle_list.push_back(correlation_query_answer->get(correlation_mappings[0].first)); + handle_lists.clear(); auto pm_query = issue_correlation_query(proxy, query_tokens); while (!pm_query->finished()) { shared_ptr answer = pm_query->pop(); string word; if (answer != NULL) { for (auto pair : correlation_mappings) { - string handle = answer->get(pair.second); - if (handle != "") { - handle_list.push_back(handle); + string key = answer->get(pair.first, true); + string handle = answer->get(pair.second, true); + if ((key != "") && (handle != "")) { + if (handle_lists.find(key) == handle_lists.end()) { + handle_lists[key] = {key}; + } else { + handle_lists[key].push_back(handle); + } } } } else { Utils::sleep(); } } - AttentionBrokerClient::asymmetric_correlate(handle_list, proxy->get_context()); + for (auto pair : handle_lists) { + AttentionBrokerClient::asymmetric_correlate(pair.second, proxy->get_context()); + } } } diff --git a/src/agents/query_engine/MettaParserActions.cc b/src/agents/query_engine/MettaParserActions.cc index aa473166..f17899bc 100644 --- a/src/agents/query_engine/MettaParserActions.cc +++ b/src/agents/query_engine/MettaParserActions.cc @@ -124,13 +124,15 @@ void MettaParserActions::expression_end(bool toplevel, const string& metta_expre this->element_stack.push(make_shared(MettaMapping::EXPRESSION_LINK_TYPE, targets)); } else { LOG_DEBUG("Pushing LINK_TEMPLATE"); - this->element_stack.push(make_shared( + auto new_link_template = make_shared( MettaMapping::EXPRESSION_LINK_TYPE, targets, this->proxy->get_context(), this->proxy->parameters.get(PatternMatchingQueryProxy::POSITIVE_IMPORTANCE_FLAG), + this->proxy->parameters.get(PatternMatchingQueryProxy::DISREGARD_IMPORTANCE_FLAG), this->proxy->parameters.get(PatternMatchingQueryProxy::UNIQUE_VALUE_FLAG), - this->proxy->parameters.get(BaseQueryProxy::USE_LINK_TEMPLATE_CACHE))); + this->proxy->parameters.get(BaseQueryProxy::USE_LINK_TEMPLATE_CACHE)); + this->element_stack.push(new_link_template); } } else if ((this->current_expression_type == AND) || (this->current_expression_type == OR)) { if (element_stack.size() >= 2) { diff --git a/src/agents/query_engine/PatternMatchingQueryProcessor.cc b/src/agents/query_engine/PatternMatchingQueryProcessor.cc index b6b51417..22b53272 100644 --- a/src/agents/query_engine/PatternMatchingQueryProcessor.cc +++ b/src/agents/query_engine/PatternMatchingQueryProcessor.cc @@ -85,9 +85,9 @@ void PatternMatchingQueryProcessor::update_attention_broker_single_answer( for (auto pair : answer->assignment.table) { single_answer.insert(pair.second); joint_answer.insert(pair.second); - single_answer.insert(pair.second); } + /* // Correlate handles which are the query answer for (string handle : answer->handles) { execution_stack.push(handle); @@ -109,6 +109,7 @@ void PatternMatchingQueryProcessor::update_attention_broker_single_answer( } } } + */ if (single_answer.size() > 1) { AttentionBrokerClient::correlate(single_answer, proxy->get_context()); } else { @@ -342,6 +343,7 @@ shared_ptr PatternMatchingQueryProcessor::build_link_template( targets, proxy->get_context(), proxy->parameters.get(PatternMatchingQueryProxy::POSITIVE_IMPORTANCE_FLAG), + proxy->parameters.get(PatternMatchingQueryProxy::DISREGARD_IMPORTANCE_FLAG), proxy->parameters.get(PatternMatchingQueryProxy::UNIQUE_VALUE_FLAG), proxy->parameters.get(BaseQueryProxy::USE_LINK_TEMPLATE_CACHE)); return link_template; diff --git a/src/agents/query_engine/PatternMatchingQueryProxy.cc b/src/agents/query_engine/PatternMatchingQueryProxy.cc index 0460fc4d..0170c5d4 100644 --- a/src/agents/query_engine/PatternMatchingQueryProxy.cc +++ b/src/agents/query_engine/PatternMatchingQueryProxy.cc @@ -13,6 +13,7 @@ using namespace query_engine; string PatternMatchingQueryProxy::COUNT = "count"; string PatternMatchingQueryProxy::POSITIVE_IMPORTANCE_FLAG = "positive_importance_flag"; +string PatternMatchingQueryProxy::DISREGARD_IMPORTANCE_FLAG = "disregard_importance_flag"; string PatternMatchingQueryProxy::UNIQUE_VALUE_FLAG = "unique_value_flag"; string PatternMatchingQueryProxy::COUNT_FLAG = "count_flag"; @@ -32,6 +33,7 @@ PatternMatchingQueryProxy::PatternMatchingQueryProxy(const vector& token void PatternMatchingQueryProxy::set_default_parameters() { this->parameters[POSITIVE_IMPORTANCE_FLAG] = false; + this->parameters[DISREGARD_IMPORTANCE_FLAG] = false; this->parameters[UNIQUE_VALUE_FLAG] = false; this->parameters[COUNT_FLAG] = false; } diff --git a/src/agents/query_engine/PatternMatchingQueryProxy.h b/src/agents/query_engine/PatternMatchingQueryProxy.h index 65ebd944..f9b4c663 100644 --- a/src/agents/query_engine/PatternMatchingQueryProxy.h +++ b/src/agents/query_engine/PatternMatchingQueryProxy.h @@ -32,17 +32,21 @@ class PatternMatchingQueryProxy : public BaseQueryProxy { static string COUNT; // Delivery of the final result of a count_only query // Query command's optional parameters - static string POSITIVE_IMPORTANCE_FLAG; // Indicates that only answers whose importance > 0 - // are supposed to be returned - - static string UNIQUE_VALUE_FLAG; // When true, QueryAnswers won't be allowed to have the same - // handle assigned to different values. For instance, if a - // variable V1 is assigned to a handle H1, if this parameter - // is true then it's assured that no other variable will be - // assigned with the same value H1. When this parameter is - // false (which is the default value, btw), it's possible - // to have a QueryAnswer with an assignment like this, for - // example: V1: H1, V2: H2, V3, H1. + static string POSITIVE_IMPORTANCE_FLAG; // Indicates that only answers whose importance > 0 + // are supposed to be returned + + static string DISREGARD_IMPORTANCE_FLAG; // When set true, importance values are not fetched from + // Attention Broker, thus the order of query answers + // are not determined by importance. + + static string UNIQUE_VALUE_FLAG; // When true, QueryAnswers won't be allowed to have the same + // handle assigned to different values. For instance, if a + // variable V1 is assigned to a handle H1, if this parameter + // is true then it's assured that no other variable will be + // assigned with the same value H1. When this parameter is + // false (which is the default value, btw), it's possible + // to have a QueryAnswer with an assignment like this, for + // example: V1: H1, V2: H2, V3, H1. static string COUNT_FLAG; // Indicates that this query is supposed to count the results and not // actually provide the query answers (i.e. no QueryAnswer is sent diff --git a/src/agents/query_engine/query_element/LinkTemplate.cc b/src/agents/query_engine/query_element/LinkTemplate.cc index 8f3996d6..cf2eb7de 100644 --- a/src/agents/query_engine/query_element/LinkTemplate.cc +++ b/src/agents/query_engine/query_element/LinkTemplate.cc @@ -21,12 +21,17 @@ LinkTemplate::LinkTemplate(const string& type, const vector>& targets, const string& context, bool positive_importance_flag, + bool disregard_importance_flag, bool unique_value_flag, bool use_cache) : link_schema(type, targets.size()) { this->targets = targets; this->context = context; + if (positive_importance_flag && disregard_importance_flag) { + Utils::error("Conficting settings for positive_importance_flag and disregard_importance_flag"); + } this->positive_importance_flag = positive_importance_flag; + this->disregard_importance_flag = disregard_importance_flag; this->unique_value_flag = unique_value_flag; this->use_cache = use_cache; this->inner_flag = true; @@ -34,6 +39,13 @@ LinkTemplate::LinkTemplate(const string& type, this->processor = nullptr; this->random_generator = new std::mt19937(std::chrono::system_clock::now().time_since_epoch().count()); + unsigned int max_reverse_nesting = 0; + for (auto element : targets) { + if (element->reverse_nesting_level > max_reverse_nesting) { + max_reverse_nesting = element->reverse_nesting_level; + } + } + this->reverse_nesting_level = max_reverse_nesting + 1; } LinkTemplate::~LinkTemplate() { @@ -135,8 +147,12 @@ void LinkTemplate::processor_method(shared_ptr monitor) { handles = db->query_for_pattern(this->link_schema); LinkTemplate::fetched_links_cache().set(link_schema_handle, handles); } + bool flat_pattern_flag = (this->reverse_nesting_level <= 1); LOG_DEBUG("Positive importance flag: " + string(this->positive_importance_flag ? "true" : "false")); + LOG_DEBUG("Disregard importance flag: " + + string(this->disregard_importance_flag ? "true" : "false")); LOG_DEBUG("Unique value flag: " + string(this->unique_value_flag ? "true" : "false")); + LOG_DEBUG("Flat pattern flag: " + string(flat_pattern_flag ? "true" : "false")); LOG_INFO("Fetched " + std::to_string(handles->size()) + " atoms in " + link_schema_handle); vector> tagged_handles; @@ -146,9 +162,12 @@ void LinkTemplate::processor_method(shared_ptr monitor) { while ((handle = iterator->next()) != nullptr) { tagged_handles.push_back(make_pair((char*) handle, 0)); } - compute_importance(tagged_handles); + if (!this->disregard_importance_flag) { + compute_importance(tagged_handles); + } } unsigned int pending = tagged_handles.size(); + unsigned int processed = 0; unsigned int cursor = 0; Assignment assignment(this->unique_value_flag); unsigned int count_matched = 0; @@ -165,13 +184,20 @@ void LinkTemplate::processor_method(shared_ptr monitor) { handles->get_assignments_by_handle(tagged_handle.first), handles->get_metta_expressions_by_handle(tagged_handle.first)); count_matched++; - } else if (this->link_schema.match(string(tagged_handle.first), assignment, *db.get())) { - this->source_element->add_handle( - tagged_handle.first, tagged_handle.second, assignment); - assignment.clear(); - count_matched++; + } else { + if (this->link_schema.match(string(tagged_handle.first), assignment, *db.get())) { + this->source_element->add_handle( + tagged_handle.first, tagged_handle.second, assignment); + assignment.clear(); + count_matched++; + } } } + if (!(++processed % 1000000)) { + LOG_INFO("Processed " + std::to_string(processed) + "/" + + std::to_string(tagged_handles.size()) + ". " + std::to_string(count_matched) + + " matched so far."); + } pending--; } } diff --git a/src/agents/query_engine/query_element/LinkTemplate.h b/src/agents/query_engine/query_element/LinkTemplate.h index a6a25fa0..38651581 100644 --- a/src/agents/query_engine/query_element/LinkTemplate.h +++ b/src/agents/query_engine/query_element/LinkTemplate.h @@ -55,6 +55,7 @@ class LinkTemplate : public QueryElement { vector> targets; string context; bool positive_importance_flag; + bool disregard_importance_flag; bool unique_value_flag; bool use_cache; bool inner_flag; @@ -75,6 +76,7 @@ class LinkTemplate : public QueryElement { const vector>& targets, const string& context, bool positive_importance_flag, + bool disregard_importance_flag, bool unique_value_flag, bool use_cache); diff --git a/src/agents/query_engine/query_element/QueryElement.cc b/src/agents/query_engine/query_element/QueryElement.cc index 0fa348e2..cb1881b6 100644 --- a/src/agents/query_engine/query_element/QueryElement.cc +++ b/src/agents/query_engine/query_element/QueryElement.cc @@ -10,6 +10,7 @@ QueryElement::QueryElement() { this->is_terminal = false; this->is_operator = false; this->arity = 0; + this->reverse_nesting_level = 0; } QueryElement::~QueryElement() {} diff --git a/src/agents/query_engine/query_element/QueryElement.h b/src/agents/query_engine/query_element/QueryElement.h index 566b25c6..3012095d 100644 --- a/src/agents/query_engine/query_element/QueryElement.h +++ b/src/agents/query_engine/query_element/QueryElement.h @@ -53,6 +53,7 @@ class QueryElement { string id; string subsequent_id; unsigned int arity; + unsigned int reverse_nesting_level; /** * Basic constructor which solely initialize variables. diff --git a/src/attention_broker/AttentionBrokerServer.h b/src/attention_broker/AttentionBrokerServer.h index 695a23b5..80b1e8f4 100644 --- a/src/attention_broker/AttentionBrokerServer.h +++ b/src/attention_broker/AttentionBrokerServer.h @@ -1,7 +1,5 @@ #pragma once -#define DEBUG - #include #include diff --git a/src/scripts/bazel_build.sh b/src/scripts/bazel_build.sh index 90adc752..06efc044 100755 --- a/src/scripts/bazel_build.sh +++ b/src/scripts/bazel_build.sh @@ -41,6 +41,7 @@ if [ "$BUILD_BINARIES" = true ]; then BUILD_TARGETS+=" //:word_query" BUILD_TARGETS+=" //:word_query_evolution" BUILD_TARGETS+=" //:implication_query_evolution" + BUILD_TARGETS+=" //:evaluation_evolution" BUILD_TARGETS+=" //:tests_db_loader" # Move targets @@ -54,6 +55,7 @@ if [ "$BUILD_BINARIES" = true ]; then MOVE_BIN_TARGETS+=" bazel-bin/word_query" MOVE_BIN_TARGETS+=" bazel-bin/word_query_evolution" MOVE_BIN_TARGETS+=" bazel-bin/implication_query_evolution" + MOVE_BIN_TARGETS+=" bazel-bin/evaluation_evolution" MOVE_BIN_TARGETS+=" bazel-bin/tests_db_loader" diff --git a/src/tests/cpp/iterator_test.cc b/src/tests/cpp/iterator_test.cc index f0cc63d1..cf89dd6f 100644 --- a/src/tests/cpp/iterator_test.cc +++ b/src/tests/cpp/iterator_test.cc @@ -84,7 +84,7 @@ TEST(Iterator, link_template_integration) { auto human = make_shared(symbol, "\"human\""); LinkTemplate* link_template = - new LinkTemplate("Expression", {similarity, human, v1}, "", false, false, false); + new LinkTemplate("Expression", {similarity, human, v1}, "", false, false, false, false); link_template->build(); Iterator query_answer_iterator(link_template->get_source_element()); diff --git a/src/tests/cpp/link_template_test.cc b/src/tests/cpp/link_template_test.cc index 30bea8f1..30794f5d 100644 --- a/src/tests/cpp/link_template_test.cc +++ b/src/tests/cpp/link_template_test.cc @@ -30,7 +30,7 @@ TEST(LinkTemplate, basics) { similarity->handle = Hasher::node_handle(symbol, "Similarity"); auto human = make_shared(symbol, "\"human\""); - LinkTemplate link_template1("Expression", {similarity, human, v1}, "", false, false, false); + LinkTemplate link_template1("Expression", {similarity, human, v1}, "", false, false, false, false); link_template1.build(); link_template1.get_source_element()->subsequent_id = server_node_id; link_template1.get_source_element()->setup_buffers(); diff --git a/src/tests/cpp/nested_link_template_test.cc b/src/tests/cpp/nested_link_template_test.cc index 086568da..083b13cc 100644 --- a/src/tests/cpp/nested_link_template_test.cc +++ b/src/tests/cpp/nested_link_template_test.cc @@ -28,10 +28,10 @@ TEST(LinkTemplate, basics) { auto odd_link = make_shared(symbol, "OddLink"); LinkTemplate* inner_template_ptr = - new LinkTemplate(expression, {similarity, v1, v2}, "", false, false, false); + new LinkTemplate(expression, {similarity, v1, v2}, "", false, false, false, false); shared_ptr inner_template(inner_template_ptr); LinkTemplate* outter_template_ptr = - new LinkTemplate(expression, {odd_link, inner_template}, "", false, false, false); + new LinkTemplate(expression, {odd_link, inner_template}, "", false, false, false, false); outter_template_ptr->build(); Iterator iterator(outter_template_ptr->get_source_element()); @@ -59,13 +59,13 @@ TEST(LinkTemplate, nested_variables) { auto human = make_shared(symbol, "\"human\""); LinkTemplate* inner_template_ptr = - new LinkTemplate(expression, {similarity, v1, v2}, "", false, false, false); + new LinkTemplate(expression, {similarity, v1, v2}, "", false, false, false, false); shared_ptr inner_template(inner_template_ptr); LinkTemplate* outter_template = - new LinkTemplate(expression, {odd_link, inner_template}, "", false, false, false); + new LinkTemplate(expression, {odd_link, inner_template}, "", false, false, false, false); outter_template->build(); LinkTemplate* human_template = - new LinkTemplate(expression, {similarity, v1, human}, "", false, false, false); + new LinkTemplate(expression, {similarity, v1, human}, "", false, false, false, false); human_template->build(); auto and_operator = make_shared>(array, 2>( {human_template->get_source_element(), outter_template->get_source_element()})); diff --git a/src/tests/main/BUILD b/src/tests/main/BUILD index 78f7c737..6c98cb7d 100644 --- a/src/tests/main/BUILD +++ b/src/tests/main/BUILD @@ -57,3 +57,15 @@ cc_library( "//service_bus:service_bus_lib", ], ) + +cc_library( + name = "evaluation_evolution_main_lib", + srcs = ["evaluation_evolution.cc"], + deps = [ + "//agents/context_broker:context_broker_lib", + "//agents/evolution:evolution_lib", + "//atomdb:atomdb_singleton", + "//hasher:hasher_lib", + "//service_bus:service_bus_lib", + ], +) diff --git a/src/tests/main/evaluation_evolution.cc b/src/tests/main/evaluation_evolution.cc new file mode 100644 index 00000000..73d2a6fc --- /dev/null +++ b/src/tests/main/evaluation_evolution.cc @@ -0,0 +1,818 @@ +#include + +#define LOG_LEVEL INFO_LEVEL + +#include +#include +#include +#include + +#include "AtomDBSingleton.h" +#include "AtomSpace.h" +#include "AttentionBrokerClient.h" +#include "Context.h" +#include "ContextBrokerProxy.h" +#include "CountLetterFunction.h" +#include "FitnessFunctionRegistry.h" +#include "Hasher.h" +#include "Logger.h" +#include "MettaParser.h" +#include "QueryAnswer.h" +#include "QueryEvolutionProxy.h" +#include "ServiceBusSingleton.h" +#include "Utils.h" +#include "commons/atoms/MettaParserActions.h" + +#define MAX_QUERY_ANSWERS ((unsigned int) 100000) + +// Symbols +#define AND_OPERATOR "AND" +#define OR_OPERATOR "OR" +#define LINK_TEMPLATE "LINK_TEMPLATE" +#define LINK "LINK" +#define NODE "NODE" +#define VARIABLE "VARIABLE" +#define ATOM "ATOM" +#define EXPRESSION "Expression" +#define SYMBOL "Symbol" +#define SENTENCE "Sentence" +#define WORD "Word" +#define CONTAINS "Contains" +#define EVALUATION "Evaluation" +#define PREDICATE "Predicate" +#define CONCEPT "Concept" +#define EQUIVALENCE "Equivalence" +#define IMPLICATION "Implication" + +// Variables +#define V1 "V1" +#define V2 "V2" +#define V3 "V3" +#define PREDICATE1 "Predicate1" +#define PREDICATE2 "Predicate2" +#define PREDICATE3 "Predicate3" +#define CONCEPT1 "Concept1" +#define CONCEPT2 "Concept2" +#define CONCEPT3 "Concept3" + +// Misc +#define STRENGTH "strength" +#define IS_LITERAL "is_literal" +#define FITNESS_FUNCTION "multiply_strength" + +static string IMPLICATION_HANDLE = Hasher::node_handle(SYMBOL, IMPLICATION); +static string EQUIVALENCE_HANDLE = Hasher::node_handle(SYMBOL, EQUIVALENCE); +static string PREDICATE_HANDLE = Hasher::node_handle(SYMBOL, PREDICATE); +static string EVALUATION_HANDLE = Hasher::node_handle(SYMBOL, EVALUATION); +static float RENT_RATE = 0.25; +static float SPREADING_RATE_LOWERBOUND = 0.90; +static float SPREADING_RATE_UPPERBOUND = 0.90; +static double SELECTION_RATE = 0.10; +static double ELITISM_RATE = 0.08; +static unsigned int LINK_BUILDING_QUERY_SIZE = 50; +static unsigned int POPULATION_SIZE = 50; +static unsigned int MAX_GENERATIONS = 20; +static unsigned int NUM_ITERATIONS = 10; + +static string CONTEXT_FILE_NAME = "_CONTEXT_DUMP"; +static string NEW_LINKS_FILE_NAME = "newly_created_links.txt"; +static bool WRITE_CREATED_LINKS_TO_DB = true; +static bool WRITE_CREATED_LINKS_TO_FILE = true; +static bool PRINT_CREATED_LINKS_METTA = true; + +using namespace std; +using namespace atomdb; +using namespace atom_space; +using namespace query_engine; +using namespace evolution; +using namespace service_bus; +using namespace attention_broker; +using namespace context_broker; + +static shared_ptr db; +static shared_ptr bus; +static vector> buffer_determiners; +static map> weight_calculation_cache; + +static void save_link(Link& link) { + ofstream file; + file.open(NEW_LINKS_FILE_NAME, std::ios::app); + if (file.is_open()) { + vector tokens; + link.tokenize(tokens); + for (unsigned int i = 0; i < tokens.size(); i++) { + file << tokens[i]; + if (i != tokens.size() - 1) { + file << " "; + } + } + file << endl; + file.close(); + } else { + Utils::error("Couldn't open file for writing: " + NEW_LINKS_FILE_NAME); + } +} + +/* +static double get_strength(string handle) { + shared_ptr atom = db->get_atom(handle); + double strength = 0; + if (atom != nullptr) { + strength = atom->custom_attributes.get_or(STRENGTH, 0); + } + return strength; +} +*/ + +static shared_ptr issue_link_building_query( + const vector& query_tokens, const string& context, unsigned int max_answers) { + auto proxy = make_shared(query_tokens, context); + proxy->parameters[BaseQueryProxy::UNIQUE_ASSIGNMENT_FLAG] = true; + proxy->parameters[BaseQueryProxy::ATTENTION_UPDATE_FLAG] = false; + // proxy->parameters[BaseQueryProxy::USE_LINK_TEMPLATE_CACHE] = true; // Use the default value + proxy->parameters[PatternMatchingQueryProxy::MAX_ANSWERS] = (unsigned int) max_answers; + proxy->parameters[PatternMatchingQueryProxy::POSITIVE_IMPORTANCE_FLAG] = (max_answers != 0); + proxy->parameters[BaseQueryProxy::USE_METTA_AS_QUERY_TOKENS] = false; + proxy->parameters[BaseQueryProxy::POPULATE_METTA_MAPPING] = false; + proxy->parameters[PatternMatchingQueryProxy::UNIQUE_VALUE_FLAG] = true; + + ServiceBusSingleton::get_instance()->issue_bus_command(proxy); + return proxy; +} + +// Fazer um cache que permita lembrar dos handles da resposta do QA e recalcular apenas os counts (que +// dependem dos weight) +static shared_ptr issue_weight_count_query(const vector& query_tokens, + const string& context) { + auto proxy = make_shared(query_tokens, context); + proxy->parameters[BaseQueryProxy::UNIQUE_ASSIGNMENT_FLAG] = true; + proxy->parameters[BaseQueryProxy::ATTENTION_UPDATE_FLAG] = false; + proxy->parameters[BaseQueryProxy::USE_LINK_TEMPLATE_CACHE] = true; + proxy->parameters[PatternMatchingQueryProxy::POSITIVE_IMPORTANCE_FLAG] = false; + proxy->parameters[BaseQueryProxy::USE_METTA_AS_QUERY_TOKENS] = false; + proxy->parameters[BaseQueryProxy::POPULATE_METTA_MAPPING] = false; + + ServiceBusSingleton::get_instance()->issue_bus_command(proxy); + return proxy; +} + +static void attention_allocation_query(const vector& query_tokens, const string& context) { + auto proxy = make_shared(query_tokens, context); + proxy->parameters[BaseQueryProxy::UNIQUE_ASSIGNMENT_FLAG] = true; + proxy->parameters[BaseQueryProxy::ATTENTION_UPDATE_FLAG] = true; + proxy->parameters[BaseQueryProxy::USE_LINK_TEMPLATE_CACHE] = false; + proxy->parameters[PatternMatchingQueryProxy::POSITIVE_IMPORTANCE_FLAG] = false; + proxy->parameters[PatternMatchingQueryProxy::COUNT_FLAG] = true; + proxy->parameters[BaseQueryProxy::USE_METTA_AS_QUERY_TOKENS] = false; + proxy->parameters[BaseQueryProxy::POPULATE_METTA_MAPPING] = false; + + ServiceBusSingleton::get_instance()->issue_bus_command(proxy); + while (!proxy->finished()) { + Utils::sleep(); + } +} + +static void insert_or_update(map& count_map, const string& key, double value) { + auto iterator = count_map.find(key); + if (iterator == count_map.end()) { + count_map[key] = value; + } else { + if (value > iterator->second) { + count_map[key] = value; + } + } +} + +static void compute_counts(const vector>& query_tokens, + const string& context, + const QueryAnswerElement& target_element, + const string& handle0, + const string& handle1, + double& count_0, + double& count_1, + double& count_intersection, + double& count_union) { + LOG_LOCAL_DEBUG("Computing counts for " + handle0 + " and " + handle1); + shared_ptr proxy[2]; + + count_0 = 0.0; + count_1 = 0.0; + count_intersection = 0.0; + count_union = 0.0; + + map count_map[2]; + map count_map_union; + map count_map_intersection; + + double d; + string handle; + for (unsigned int i = 0; i < 2; i++) { + proxy[i] = issue_weight_count_query(query_tokens[i], context); + } + LOG_LOCAL_DEBUG("Queries issued"); + shared_ptr query_answer; + for (unsigned int i = 0; i < 2; i++) { + LOG_LOCAL_DEBUG("i: " + to_string(i)); + ServiceBusSingleton::get_instance()->issue_bus_command(proxy[i]); + while (!proxy[i]->finished()) { + if ((query_answer = proxy[i]->pop()) == NULL) { + Utils::sleep(); + } else { + if (query_answer->handles.size() == 1) { + d = 1.0; + } else { + string link_handle = query_answer->handles[1]; + auto link = db->get_atom(link_handle); + d = link->custom_attributes.get(STRENGTH); + } + handle = query_answer->get(target_element); + insert_or_update(count_map[i], handle, d); + } + } + } + LOG_LOCAL_DEBUG("Query answers processed"); + count_map_union = count_map[0]; + for (auto pair : count_map[1]) { + auto iterator = count_map[0].find(pair.first); + if (iterator == count_map[0].end()) { + insert_or_update(count_map_union, pair.first, pair.second); + } else { + insert_or_update(count_map_union, pair.first, pair.second); + insert_or_update(count_map_intersection, pair.first, min(pair.second, iterator->second)); + } + } + + for (auto pair : count_map_intersection) { + count_intersection += pair.second; + } + for (auto pair : count_map_union) { + count_union += pair.second; + } + for (auto pair : count_map[0]) { + count_0 += pair.second; + } + for (auto pair : count_map[1]) { + count_1 += pair.second; + } + LOG_DEBUG("Counts: " + to_string(count_0) + " " + to_string(count_1) + " " + + to_string(count_intersection) + " " + to_string(count_union)); +} + +static Link add_or_update_link(const string& type_handle, + const string& target1, + const string& target2, + double strength) { + LOG_DEBUG("add_or_update_link(" + type_handle + ", " + target1 + ", " + target2 + ", " + + to_string(strength) + ")"); + Link new_link(EXPRESSION, {type_handle, target1, target2}, true, {{STRENGTH, strength}}); + LOG_DEBUG("Add or update: " + new_link.to_string()); + if (PRINT_CREATED_LINKS_METTA) { + LOG_INFO("ADD LINK: " + + new_link.metta_representation(*static_pointer_cast(db).get())); + } + string handle = new_link.handle(); + if (db->link_exists(handle)) { + auto old_link = db->get_atom(handle); + LOG_DEBUG("Link already exists: " + old_link->to_string()); + if (strength > old_link->custom_attributes.get(STRENGTH)) { + if (WRITE_CREATED_LINKS_TO_DB) { + LOG_DEBUG("Updating Link in AtomDB"); + db->delete_link(handle, false); + db->add_link(&new_link); + } + if (WRITE_CREATED_LINKS_TO_FILE) { + LOG_DEBUG("Writing Link to file: " + NEW_LINKS_FILE_NAME); + save_link(new_link); + } + } + } else { + if (WRITE_CREATED_LINKS_TO_DB) { + LOG_DEBUG("Creating Link in AtomDB"); + db->add_link(&new_link); + } + buffer_determiners.push_back({handle, target1, target2}); + if (WRITE_CREATED_LINKS_TO_FILE) { + LOG_DEBUG("Writing Link to file: " + NEW_LINKS_FILE_NAME); + save_link(new_link); + } + } + return new_link; +} + +static Link add_predicate(const string& handle1, const string& handle2) { + Link new_link(EXPRESSION, {handle1, handle2}, false); + if (!db->link_exists(new_link.handle())) { + db->add_link(&new_link); + } + return new_link; +} + +static void build_implication_link(shared_ptr query_answer, + const string& context, + const string& custom_handle) { + string predicates[2]; + if (custom_handle == "") { + predicates[0] = query_answer->get(PREDICATE1); + predicates[1] = query_answer->get(PREDICATE2); + } else { + predicates[0] = custom_handle; + predicates[1] = query_answer->get(0); + } + + if (predicates[0] == predicates[1]) { + LOG_DEBUG("Skipping link building because targets are the same: " + predicates[0]); + return; + } + + vector> query; + for (unsigned int i = 0; i < 2; i++) { + // clang-format off + query.push_back({ + OR_OPERATOR, "2", + LINK_TEMPLATE, EXPRESSION, "3", + NODE, SYMBOL, EVALUATION, + ATOM, predicates[i], + VARIABLE, CONCEPT1, + AND_OPERATOR, "2", + LINK_TEMPLATE, EXPRESSION, "3", + NODE, SYMBOL, EVALUATION, + ATOM, predicates[i], + VARIABLE, CONCEPT2, + LINK_TEMPLATE, EXPRESSION, "3", + NODE, SYMBOL, EQUIVALENCE, + VARIABLE, CONCEPT2, + VARIABLE, CONCEPT1, + }); + // clang-format on + } + double count_0, count_1, count_intersection, count_union; + QueryAnswerElement target_element(CONCEPT1); + compute_counts(query, + context, + target_element, + predicates[0], + predicates[1], + count_0, + count_1, + count_intersection, + count_union); + if (count_intersection > 0) { + if (count_0 > 0) { + double strength = count_intersection / count_0; + add_or_update_link(IMPLICATION_HANDLE, predicates[0], predicates[1], strength); + } + if (count_1 > 0) { + double strength = count_intersection / count_1; + add_or_update_link(IMPLICATION_HANDLE, predicates[1], predicates[0], strength); + } + } +} + +static void build_and_predicate_link(shared_ptr query_answer, + const string& context, + const string& custom_handle) { + string predicate1 = query_answer->get(PREDICATE1); + string predicate2 = query_answer->get(PREDICATE2); + string concept1 = query_answer->get(CONCEPT); + + if (predicate1 == predicate2) { + LOG_DEBUG("Skipping link building because targets are the same: " + predicate1); + return; + } + + Link new_predicate = add_predicate(predicate1, predicate2); + add_or_update_link(EVALUATION_HANDLE, new_predicate.handle(), concept1, 1.0); +} + +static void build_equivalence_link(shared_ptr query_answer, + const string& context, + const string& custom_handle) { + string concepts[2]; + if (custom_handle == "") { + concepts[0] = query_answer->get(CONCEPT1); + concepts[1] = query_answer->get(CONCEPT2); + } else { + concepts[0] = custom_handle; + concepts[1] = query_answer->get(0); + } + + if (concepts[0] == concepts[1]) { + LOG_DEBUG("Skipping link building because targets are the same: " + concepts[0]); + return; + } + + vector> query; + for (unsigned int i = 0; i < 2; i++) { + // clang-format off + query.push_back({ + OR_OPERATOR, "2", + LINK_TEMPLATE, EXPRESSION, "3", + NODE, SYMBOL, EVALUATION, + VARIABLE, PREDICATE1, + ATOM, concepts[i], + AND_OPERATOR, "2", + LINK_TEMPLATE, EXPRESSION, "3", + NODE, SYMBOL, EVALUATION, + VARIABLE, PREDICATE2, + ATOM, concepts[i], + LINK_TEMPLATE, EXPRESSION, "3", + NODE, SYMBOL, IMPLICATION, + VARIABLE, PREDICATE2, + VARIABLE, PREDICATE1, + }); + // clang-format on + } + double count_0, count_1, count_intersection, count_union; + QueryAnswerElement target_element(PREDICATE1); + compute_counts(query, + context, + target_element, + concepts[0], + concepts[1], + count_0, + count_1, + count_intersection, + count_union); + if ((count_intersection > 0) && (count_union > 0)) { + double strength = count_intersection / count_union; + add_or_update_link(EQUIVALENCE_HANDLE, concepts[0], concepts[1], strength); + add_or_update_link(EQUIVALENCE_HANDLE, concepts[1], concepts[0], strength); + } +} + +static void build_links(const vector& query, + const string& context, + unsigned int num_links, + const string& custom_handle, + void (*build_link)(shared_ptr query_answer, + const string& context, + const string& custom_handle)) { + auto proxy = issue_link_building_query(query, context, num_links); + unsigned int count = 0; + shared_ptr query_answer; + while (!proxy->finished()) { + if ((query_answer = proxy->pop()) == nullptr) { + Utils::sleep(); + } else { + if (++count <= num_links) { + if (query_answer->handles.size() == 2) { + LOG_DEBUG("Processing query answer " + to_string(count) + ": " + + query_answer->to_string()); + build_link(query_answer, context, custom_handle); + } + } else { + Utils::sleep(); + if (!proxy->finished()) { + proxy->abort(); + } + break; + } + } + } +} + +static void print_answer(shared_ptr query_answer) { + unsigned int answer_arity = query_answer->handles.size(); + cout << fixed << setw(6) << setprecision(4) << setfill('0'); + cout << query_answer->strength << " [" << to_string(answer_arity) << "]"; + cout << endl; +} + +// clang-format off +static void query_evolution( + const vector& query_to_evolve, + const vector>& correlation_query_template, + const vector>& correlation_query_constants, + const vector>& correlation_mapping, + const string& context) { + + QueryEvolutionProxy* proxy_ptr = new QueryEvolutionProxy( + query_to_evolve, + correlation_query_template, + correlation_query_constants, + correlation_mapping, + context, + FITNESS_FUNCTION); + + shared_ptr proxy(proxy_ptr); + proxy->parameters[BaseQueryProxy::USE_METTA_AS_QUERY_TOKENS] = false; + proxy->parameters[BaseQueryProxy::POPULATE_METTA_MAPPING] = false; + proxy->parameters[QueryEvolutionProxy::POPULATION_SIZE] = (unsigned int) POPULATION_SIZE; + proxy->parameters[QueryEvolutionProxy::MAX_GENERATIONS] = (unsigned int) MAX_GENERATIONS; + proxy->parameters[QueryEvolutionProxy::ELITISM_RATE] = (double) ELITISM_RATE; + proxy->parameters[QueryEvolutionProxy::SELECTION_RATE] = (double) SELECTION_RATE; + proxy->parameters[QueryEvolutionProxy::TOTAL_ATTENTION_TOKENS] = (unsigned int) 100000; + proxy->parameters[BaseQueryProxy::MAX_BUNDLE_SIZE] = (unsigned int) 1000; + bus->issue_bus_command(proxy); + + shared_ptr query_answer; + unsigned int count_answers = 0; + static double best_fitness = 0.0; + static unsigned int count_iterations = 1; + + while (!proxy->finished()) { + if ((query_answer = proxy->pop()) == NULL) { + Utils::sleep(); + } else { + count_answers++; + if (query_answer->strength > best_fitness) { + best_fitness = query_answer->strength; + print_answer(query_answer); + } + } + } + cout << "Total answers in iteration " << count_iterations++ << ": " << count_answers << endl; +} +// clang-format on + +static void run(const string& target_predicate_handle, + const string& target_concept_handle, + const string& context_tag) { + // clang-format off + + vector implication_query = { + AND_OPERATOR, "2", + LINK_TEMPLATE, EXPRESSION, "3", + NODE, SYMBOL, EVALUATION, + VARIABLE, PREDICATE1, + VARIABLE, CONCEPT, + LINK_TEMPLATE, EXPRESSION, "3", + NODE, SYMBOL, EVALUATION, + VARIABLE, PREDICATE2, + VARIABLE, CONCEPT, + }; + + vector equivalence_query = { + AND_OPERATOR, "2", + LINK_TEMPLATE, EXPRESSION, "3", + NODE, SYMBOL, EVALUATION, + VARIABLE, PREDICATE, + VARIABLE, CONCEPT1, + LINK_TEMPLATE, EXPRESSION, "3", + NODE, SYMBOL, EVALUATION, + VARIABLE, PREDICATE, + VARIABLE, CONCEPT2, + }; + + vector and_predicate_query = { + AND_OPERATOR, "2", + LINK_TEMPLATE, EXPRESSION, "3", + NODE, SYMBOL, EVALUATION, + VARIABLE, PREDICATE1, + VARIABLE, CONCEPT, + LINK_TEMPLATE, EXPRESSION, "3", + NODE, SYMBOL, EVALUATION, + VARIABLE, PREDICATE2, + VARIABLE, CONCEPT, + }; + + vector query_to_evolve = { + OR_OPERATOR, "3", + AND_OPERATOR, "2", + LINK_TEMPLATE, EXPRESSION, "3", + NODE, SYMBOL, EVALUATION, + ATOM, target_predicate_handle, + VARIABLE, CONCEPT, + LINK_TEMPLATE, EXPRESSION, "3", + NODE, SYMBOL, EQUIVALENCE, + VARIABLE, CONCEPT, + ATOM, target_concept_handle, + AND_OPERATOR, "2", + LINK_TEMPLATE, EXPRESSION, "3", + NODE, SYMBOL, EVALUATION, + VARIABLE, PREDICATE, + ATOM, target_concept_handle, + LINK_TEMPLATE, EXPRESSION, "3", + NODE, SYMBOL, IMPLICATION, + VARIABLE, PREDICATE, + ATOM, target_predicate_handle, + AND_OPERATOR, "3", + LINK_TEMPLATE, EXPRESSION, "3", + NODE, SYMBOL, EVALUATION, + VARIABLE, PREDICATE, + VARIABLE, CONCEPT, + LINK_TEMPLATE, EXPRESSION, "3", + NODE, SYMBOL, EQUIVALENCE, + VARIABLE, CONCEPT, + ATOM, target_concept_handle, + LINK_TEMPLATE, EXPRESSION, "3", + NODE, SYMBOL, IMPLICATION, + VARIABLE, PREDICATE, + ATOM, target_predicate_handle, + }; + + vector> correlation_query_template = {{ + OR_OPERATOR, "2", + LINK_TEMPLATE, EXPRESSION, "3", + NODE, SYMBOL, EVALUATION, + VARIABLE, V1, + VARIABLE, CONCEPT, + LINK_TEMPLATE, EXPRESSION, "3", + NODE, SYMBOL, EVALUATION, + VARIABLE, PREDICATE, + VARIABLE, V2, + }}; + + vector context_query = { + LINK_TEMPLATE, EXPRESSION, "3", + NODE, SYMBOL, EVALUATION, + VARIABLE, V2, + VARIABLE, V3, + }; + + vector initialization_STI_query = { + OR_OPERATOR, "2", + LINK_TEMPLATE, EXPRESSION, "3", + NODE, SYMBOL, EVALUATION, + ATOM, target_predicate_handle, + VARIABLE, CONCEPT, + LINK_TEMPLATE, EXPRESSION, "3", + NODE, SYMBOL, EVALUATION, + VARIABLE, PREDICATE, + ATOM, target_concept_handle, + }; + + vector custom_initial_equivalence_query = { + LINK_TEMPLATE, EXPRESSION, "2", + NODE, SYMBOL, CONCEPT, + VARIABLE, V1, + }; + + vector custom_initial_implication_query = { + LINK_TEMPLATE, EXPRESSION, "2", + NODE, SYMBOL, PREDICATE, + VARIABLE, V1, + }; + + QueryAnswerElement qa_predicate(PREDICATE); + QueryAnswerElement qa_concept(CONCEPT); + + vector> correlation_query_constants = { + {{V1, qa_predicate}, {V2, qa_concept}} + }; + + vector>> correlation_mapping = { + {{qa_predicate, qa_predicate}, {qa_concept, qa_concept}} + }; + + // clang-format on + + LOG_INFO("Setting up context for tag: " + context_tag); + QueryAnswerElement target2(V2); + QueryAnswerElement target3(V3); + QueryAnswerElement toplevel_link(0); + // For some reason, make_shared was not compiling so I'm explicitly creating the shared_ptr + shared_ptr context_proxy(new ContextBrokerProxy( + context_tag, context_query, {{toplevel_link, target2}, {toplevel_link, target3}}, {})); + context_proxy->parameters[ContextBrokerProxy::USE_CACHE] = (bool) true; + context_proxy->parameters[ContextBrokerProxy::ENFORCE_CACHE_RECREATION] = (bool) false; + context_proxy->parameters[ContextBrokerProxy::INITIAL_RENT_RATE] = (double) RENT_RATE; + context_proxy->parameters[ContextBrokerProxy::INITIAL_SPREADING_RATE_LOWERBOUND] = + (double) SPREADING_RATE_LOWERBOUND; + context_proxy->parameters[ContextBrokerProxy::INITIAL_SPREADING_RATE_UPPERBOUND] = + (double) SPREADING_RATE_UPPERBOUND; + // Issue the ContextBrokerProxy to create context + ServiceBusSingleton::get_instance()->issue_bus_command(context_proxy); + // Wait for ContextBrokerProxy to finish context creation + LOG_INFO("Waiting for context creation to finish..."); + while (!context_proxy->is_context_created()) { + Utils::sleep(); + } + string context = context_proxy->get_key(); + LOG_INFO("Context " + context + " is ready"); + + LOG_INFO("Pre-processing..."); + LOG_INFO("Initializing STI"); + attention_allocation_query(initialization_STI_query, context); + LOG_INFO("Building initial custom links"); + build_links( + custom_initial_equivalence_query, context, 0, target_concept_handle, build_equivalence_link); + build_links( + custom_initial_implication_query, context, 0, target_predicate_handle, build_implication_link); + LOG_INFO("Pre-processing complete"); + + for (unsigned int i = 0; i < NUM_ITERATIONS; i++) { + LOG_INFO("--------------------------------------------------------------------------------"); + LOG_INFO("Iteration " + to_string(i + 1)); + LOG_INFO("--------------------------------------------------------------------------------"); + LOG_INFO("----- Building links"); + LOG_INFO("Building AND predicates"); + build_links( + and_predicate_query, context, LINK_BUILDING_QUERY_SIZE, "", build_and_predicate_link); + LOG_INFO("Building Equivalence links"); + build_links(equivalence_query, context, LINK_BUILDING_QUERY_SIZE, "", build_equivalence_link); + LOG_INFO("Building Implication links"); + build_links(implication_query, context, LINK_BUILDING_QUERY_SIZE, "", build_implication_link); + LOG_INFO("----- Updating AttentionBroker"); + AttentionBrokerClient::set_determiners(buffer_determiners, context); + buffer_determiners.clear(); + LOG_INFO("----- Evolving query"); + query_evolution(query_to_evolve, + correlation_query_template, + correlation_query_constants, + correlation_mapping[0], + context); + } +} + +void insert_type_symbols() { + vector to_insert = {EQUIVALENCE, IMPLICATION}; + Node* node; + for (string node_name : to_insert) { + node = new Node(SYMBOL, node_name); + if (!db->node_exists(node->handle())) { + db->add_node(node); + } + delete (node); + } +} + +int main(int argc, char* argv[]) { + // clang-format off + if (argc < 15) { + cerr << "Usage: " << argv[0] + << " " + " " + " " + " [--use-mork]" << endl; + cerr << endl; + cerr << " are MeTTa expressions" << endl; + cerr << endl; + cerr << endl; + cerr << "Suggested safe parameters:" << endl; + cerr << endl; + cerr << " RENT_RATE: 0.25" << endl; + cerr << " SPREADING_RATE_LOWERBOUND: 0.90" << endl; + cerr << " SPREADING_RATE_UPPERBOUND: 0.90" << endl; + cerr << " ELITISM_RATE: 0.08" << endl; + cerr << " SELECTION_RATE: 0.10" << endl; + cerr << " POPULATION_SIZE: 500" << endl; + cerr << " MAX_GENERATIONS: 20" << endl; + cerr << " NUM_ITERATIONS: 10" << endl; + exit(1); + } + // clang-format on + + int cursor = 0; + + string client_endpoint = argv[++cursor]; + string server_endpoint = argv[++cursor]; + auto ports_range = Utils::parse_ports_range(argv[++cursor]); + + string context_tag = argv[++cursor]; + string target_predicate = argv[++cursor]; + string target_concept = argv[++cursor]; + + RENT_RATE = Utils::string_to_float(string(argv[++cursor])); + SPREADING_RATE_LOWERBOUND = Utils::string_to_float(string(argv[++cursor])); + SPREADING_RATE_UPPERBOUND = Utils::string_to_float(string(argv[++cursor])); + + ELITISM_RATE = (double) Utils::string_to_float(string(argv[++cursor])); + SELECTION_RATE = (double) Utils::string_to_float(string(argv[++cursor])); + POPULATION_SIZE = (unsigned int) Utils::string_to_int(string(argv[++cursor])); + MAX_GENERATIONS = (unsigned int) Utils::string_to_int(string(argv[++cursor])); + NUM_ITERATIONS = (unsigned int) Utils::string_to_int(string(argv[++cursor])); + + if (cursor != 14) { + Utils::error("Error setting up parameters"); + } + + if ((++cursor < argc) && (string(argv[cursor]) == string("--use-mork"))) { + AtomDBSingleton::init(atomdb_api_types::ATOMDB_TYPE::MORKDB); + } else { + AtomDBSingleton::init(); + } + + db = AtomDBSingleton::get_instance(); + ServiceBusSingleton::init(client_endpoint, server_endpoint, ports_range.first, ports_range.second); + FitnessFunctionRegistry::initialize_statics(); + bus = ServiceBusSingleton::get_instance(); + AttentionBrokerClient::set_parameters( + RENT_RATE, SPREADING_RATE_LOWERBOUND, SPREADING_RATE_UPPERBOUND); + insert_type_symbols(); + + LOG_INFO("ELITISM_RATE: " + to_string(ELITISM_RATE)); + LOG_INFO("RENT_RATE: " + to_string(RENT_RATE)); + LOG_INFO("SPREADING_RATE_LOWERBOUND: " + to_string(SPREADING_RATE_LOWERBOUND)); + LOG_INFO("SPREADING_RATE_UPPERBOUND: " + to_string(SPREADING_RATE_UPPERBOUND)); + LOG_INFO("ELITISM_RATE: " + to_string(ELITISM_RATE)); + LOG_INFO("SELECTION_RATE: " + to_string(SELECTION_RATE)); + LOG_INFO("POPULATION_SIZE: " + to_string(POPULATION_SIZE)); + LOG_INFO("MAX_GENERATIONS: " + to_string(MAX_GENERATIONS)); + LOG_INFO("NUM_ITERATIONS: " + to_string(NUM_ITERATIONS)); + + shared_ptr predicate_pa = make_shared(); + shared_ptr concept_pa = make_shared(); + MettaParser predicate_p(target_predicate, predicate_pa); + MettaParser concept_p(target_concept, concept_pa); + predicate_p.parse(); + concept_p.parse(); + + LOG_INFO("Target predicate: " + target_predicate + + " Handle: " + predicate_pa->metta_expression_handle); + LOG_INFO("Target concept: " + target_concept + " Handle: " + concept_pa->metta_expression_handle); + + run(predicate_pa->metta_expression_handle, concept_pa->metta_expression_handle, context_tag); + + return 0; +}