From 9a3d2c742f79502cf8b37b64dbdce2f1f323b6d2 Mon Sep 17 00:00:00 2001 From: Linas Vepstas Date: Thu, 15 Dec 2022 20:53:41 -0600 Subject: [PATCH] Revert "Merge pull request #2500 from linas/anchor-link" Linking results to the AnchorNode idea now seems like a bad idea, in retrospect. The ideas in #2911 seem superior. So trash the AnchorNode support in the query subsystem. FWIW, if this kind of thing was wanted, a better solution would be a new kind of Value, that dequeued from a QueueValue, and plopped the results onto an AnchorNode. ***This*** is the real reason for stripping away this code: its not generic enough. This reverts commit 46dea8ea1fe8f81c079bc770861d59aad448f2bb, reversing changes made to 5ec84bbe77daa06af72e39bb5b2e04e72c7ddcf8. --- examples/pattern-matcher/README.md | 1 - examples/pattern-matcher/anchor.scm | 66 ----------- opencog/atoms/core/Variables.cc | 28 ++++- opencog/atoms/core/Variables.h | 5 + opencog/atoms/pattern/BindLink.cc | 10 -- opencog/atoms/pattern/DualLink.cc | 15 --- opencog/atoms/pattern/GetLink.cc | 10 -- opencog/atoms/pattern/SatisfactionLink.cc | 6 - tests/query/AnchorUTest.cxxtest | 138 ---------------------- tests/query/CMakeLists.txt | 2 - tests/query/anchor.scm | 39 ------ 11 files changed, 31 insertions(+), 289 deletions(-) delete mode 100644 examples/pattern-matcher/anchor.scm delete mode 100644 tests/query/AnchorUTest.cxxtest delete mode 100644 tests/query/anchor.scm diff --git a/examples/pattern-matcher/README.md b/examples/pattern-matcher/README.md index 0bf26599ba..7bfc6437c0 100644 --- a/examples/pattern-matcher/README.md +++ b/examples/pattern-matcher/README.md @@ -84,7 +84,6 @@ Basic Examples The first five examples provide a basic introduction to basic pattern matching. -* `anchor.scm` -- Obtaining results incrementally. * `satisfaction.scm` -- Determining satisfiability of a query. * `unify.scm` -- Basic term unification. * `glob.scm` -- Matching multiple atoms at once. diff --git a/examples/pattern-matcher/anchor.scm b/examples/pattern-matcher/anchor.scm deleted file mode 100644 index 52e611b523..0000000000 --- a/examples/pattern-matcher/anchor.scm +++ /dev/null @@ -1,66 +0,0 @@ -; -; anchor.scm - Obtaining search results incrementally. -; -; Both GetLink and BindLink return all search results wrapped in -; a SetLink. This can be inconvenient in several ways. First, -; in most typical uses, the contents of the SetLink are examined, -; and the set itself is promptly discarded. If it is not discarded, -; then one risks that it just hangs out in the AtomSpace, using up -; storage, but otherwise forgetten and useless. Another downside -; is that it is impossible to report any results, until all of them -; are found. This can be a problem for extremely long-running searches. -; -; To avoid both of the above issues, one can specify a "drop-off -; location" for the searches; as results arrive, they are attached -; to these drop-off points with MemberLinks, and other parts of the -; system can then grab results from there, and continue. (There are -; also proposals for a promise/future-type mechanis in the same vein, -; but it has not been implemented yet.) -; -; This example shows how to declare a drop-off point. Its actually -; almost trivial. -; -(use-modules (opencog) (opencog exec)) - -; Some data that we will query over. -(Evaluation (Predicate "foo") (List (Concept "A") (Concept "alpha"))) -(Evaluation (Predicate "foo") (List (Concept "B") (Concept "alpha"))) -(Evaluation (Predicate "foo") (List (Concept "C") (Concept "alpha"))) - -; ---------------------------------- -; Define a search query. Just an ordinary GetLink - with one twist: -; there is an AnchorNode in the variable declaration. This AnchorNode -; will be used as the drop-off point. -(define get-link - (Get - (VariableList - (TypedVariable (Variable "$x") (Type 'ConceptNode)) - (Anchor "get-results")) - (Present - (Evaluation (Predicate "foo") - (List (Variable "$x") (Concept "alpha")))))) - -; Perform the query. This will return the Anchor, instead of a SetLink. -; (cog-execute! get-link) - -; Verify that the expected results showed up. They will be attached -; to the AnchorNode, with MemberLinks. -; (cog-incoming-by-type (AnchorNode "get-results") 'MemberLink) -; ---------------------------------- - -; Very nearly identical to the above, this shows that the BindLink -; can be used in a similar fashion. -(define bind-link - (Bind - (VariableList - (TypedVariable (Variable "$z") (Type 'ConceptNode)) - (Anchor "bind-results")) - (Present - (Evaluation (Predicate "foo") - (List (Variable "$z") (Concept "alpha")))) - (Inheritance (Variable "$z") (Concept "letters")))) - -; As above: perform the query, and verify that the results showed up. -; (cog-execute! bind-link) -; (cog-incoming-by-type (AnchorNode "bind-results") 'MemberLink) -; ---------------------------------- diff --git a/opencog/atoms/core/Variables.cc b/opencog/atoms/core/Variables.cc index 412d2a151d..0a4c598bb8 100644 --- a/opencog/atoms/core/Variables.cc +++ b/opencog/atoms/core/Variables.cc @@ -354,7 +354,7 @@ static const GlobInterval& default_interval(Type t) var_def_interval; } -const GlobInterval Variables::get_interval(const Handle& var) const +const GlobInterval& Variables::get_interval(const Handle& var) const { const auto& decl = _typemap.find(var); @@ -668,10 +668,34 @@ Handle Variables::get_vardecl() const if (_ordered) return HandleCast(createVariableList(std::move(vardecls))); - return HandleCast(createVariableSet(std::move(vardecls))); } +void Variables::validate_vardecl(const HandleSeq& oset) +{ + for (const Handle& h: oset) + { + Type t = h->get_type(); + if (VARIABLE_NODE == t or GLOB_NODE == t) + { + varset.insert(h); + varseq.emplace_back(h); + } + else if (TYPED_VARIABLE_LINK == t) + { + get_vartype(h); + } + else + { + throw InvalidParamException(TRACE_INFO, + "Expected a VariableNode or a TypedVariableLink, got: %s" + "\nVariableList is %s", + nameserver().getTypeName(t).c_str(), + to_string().c_str()); + } + } +} + /* ================================================================= */ std::string Variables::to_string(const std::string& indent) const diff --git a/opencog/atoms/core/Variables.h b/opencog/atoms/core/Variables.h index 1f99197572..a0d06d2600 100644 --- a/opencog/atoms/core/Variables.h +++ b/opencog/atoms/core/Variables.h @@ -68,8 +68,13 @@ struct Variables : public FreeVariables /// _typemap holds back-ponters to TypedVariableLinkPtrs VariableTypeMap _typemap; +<<<<<<< HEAD /// Anchor, if present, else undefined. Handle _anchor; +======= + // See VariableList.cc for comments + void get_vartype(const Handle&); +>>>>>>> parent of 46dea8ea1 (Merge pull request #2500 from linas/anchor-link) // Validate the variable decls void validate_vardecl(const Handle&); diff --git a/opencog/atoms/pattern/BindLink.cc b/opencog/atoms/pattern/BindLink.cc index 6662ee1d55..ea51afcfd0 100644 --- a/opencog/atoms/pattern/BindLink.cc +++ b/opencog/atoms/pattern/BindLink.cc @@ -69,16 +69,6 @@ ValuePtr BindLink::execute(AtomSpace* as, bool silent) OC_ASSERT(qv->is_closed(), "Unexpected queue state!"); HandleSeq rslt(qv->to_handle_seq()); - // If there is an anchor, then attach results to the anchor. - // Otherwise, create a SetLink and return that. - if (_variables._anchor and as) - { - for (const Handle& h: rslt) - as->add_link(MEMBER_LINK, h, _variables._anchor); - - return _variables._anchor; - } - // The result_set contains a list of the grounded expressions. // (The order of the list has no significance, so it's really a set.) // Put the set into a SetLink, cache it, and return that. diff --git a/opencog/atoms/pattern/DualLink.cc b/opencog/atoms/pattern/DualLink.cc index 3c30f6e852..57f59f8cc6 100644 --- a/opencog/atoms/pattern/DualLink.cc +++ b/opencog/atoms/pattern/DualLink.cc @@ -79,21 +79,6 @@ ValuePtr DualLink::execute(AtomSpace* as, bool silent) if (nullptr == as) as = _atom_space; Recognizer reco(as); reco.satisfy(PatternLinkCast(get_handle())); - - // If there is an anchor, then attach results to the anchor. - // Otherwise, create a SetLink and return that. - // XXX FIXME ... at this time, there is no documented way of - // squeezing an AnchorLink into a DualLink. So the below - // if-statement is never taken. Some additional design work - // is needed. - if (_variables._anchor and as) - { - for (const Handle& h : reco._rules) - as->add_link(MEMBER_LINK, h, _variables._anchor); - - return _variables._anchor; - } - return as->add_atom(createUnorderedLink(reco._rules, SET_LINK)); } diff --git a/opencog/atoms/pattern/GetLink.cc b/opencog/atoms/pattern/GetLink.cc index 15a7015dda..efa3b6b740 100644 --- a/opencog/atoms/pattern/GetLink.cc +++ b/opencog/atoms/pattern/GetLink.cc @@ -53,16 +53,6 @@ ValuePtr GetLink::execute(AtomSpace* as, bool silent) OC_ASSERT(qv->is_closed(), "Unexpected queue state!"); HandleSet hs(qv->to_handle_set()); - // If there is an anchor, then attach results to the anchor. - // Otherwise, create a SetLink and return that. - if (_variables._anchor and as) - { - for (const Handle& h : hs) - as->add_link(MEMBER_LINK, h, _variables._anchor); - - return _variables._anchor; - } - // Create the satisfying set, and cache it. Handle satset(createUnorderedLink(std::move(hs), SET_LINK)); diff --git a/opencog/atoms/pattern/SatisfactionLink.cc b/opencog/atoms/pattern/SatisfactionLink.cc index cc81951d00..5bad667524 100644 --- a/opencog/atoms/pattern/SatisfactionLink.cc +++ b/opencog/atoms/pattern/SatisfactionLink.cc @@ -52,12 +52,6 @@ TruthValuePtr SatisfactionLink::evaluate(AtomSpace* as, bool silent) Satisfier sater(as); sater.satisfy(PatternLinkCast(get_handle())); - // If there is an anchor, then attach results to the anchor. - if (_variables._anchor and as) - { - as->add_link(MEMBER_LINK, sater._ground, _variables._anchor); - } - return sater._result; } diff --git a/tests/query/AnchorUTest.cxxtest b/tests/query/AnchorUTest.cxxtest deleted file mode 100644 index f83ef319e9..0000000000 --- a/tests/query/AnchorUTest.cxxtest +++ /dev/null @@ -1,138 +0,0 @@ -/* - * tests/query/AnchorUTest.cxxtest - * - * Copyright (C) 2020 Linas Vepstas - * All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License v3 as - * published by the Free Software Foundation and including the exceptions - * at http://opencog.org/wiki/Licenses - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program; if not, write to: - * Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include - -#include -#include -#include -#include -#include - -using namespace opencog; - -#define al as->add_link -#define an as->add_node - -class AnchorUTest: public CxxTest::TestSuite -{ -private: - AtomSpacePtr as; - -public: - AnchorUTest(void) - { - // logger().set_level(Logger::FINE); - logger().set_print_to_stdout_flag(true); - logger().set_timestamp_flag(false); - - as = createAtomSpace(); - SchemeEval* eval = SchemeEval::get_evaluator(as); - eval->eval("(use-modules (opencog exec))"); - eval->eval("(add-to-load-path \"" PROJECT_SOURCE_DIR "\")"); - } - - ~AnchorUTest() - { - // Erase the log file if no assertions failed. - if (!CxxTest::TestTracker::tracker().suiteFailed()) - std::remove(logger().get_filename().c_str()); - } - - void setUp(void); - void tearDown(void); - - void Setter(void); - void Getter(void); - - void test_get(void); - void test_bind(void); - void xtest_dual(void); -}; - -void AnchorUTest::tearDown(void) -{ -} - -void AnchorUTest::setUp(void) -{ -} - -/* - * GetLink unit test. - */ -void AnchorUTest::test_get(void) -{ - logger().debug("BEGIN TEST: %s", __FUNCTION__); - - SchemeEval* eval = SchemeEval::get_evaluator(as); - eval->eval("(load-from-path \"tests/query/anchor.scm\")"); - - Handle anchor = eval->eval_h("(cog-execute! getli)"); - - IncomingSet results = anchor->getIncomingSetByType(MEMBER_LINK); - - TSM_ASSERT_EQUALS("Expecting three answers", results.size(), 3); - - logger().debug("END TEST: %s", __FUNCTION__); -} - -/* - * BindLink unit test. - */ -void AnchorUTest::test_bind(void) -{ - logger().debug("BEGIN TEST: %s", __FUNCTION__); - - SchemeEval* eval = SchemeEval::get_evaluator(as); - eval->eval("(load-from-path \"tests/query/anchor.scm\")"); - - Handle anchor = eval->eval_h("(cog-execute! bindli)"); - - IncomingSet results = anchor->getIncomingSetByType(MEMBER_LINK); - - TSM_ASSERT_EQUALS("Expecting three answers", results.size(), 3); - - logger().debug("END TEST: %s", __FUNCTION__); -} - -/* - * DualLink unit test. - * XXX FIXME -- there is currently no documented way of squeezing - * an AnchorNode into an SRAI search, and so the unit test below - * cannot possibly pass until that design issue is fixed... - */ -void AnchorUTest::xtest_dual(void) -{ - logger().debug("BEGIN TEST: %s", __FUNCTION__); - - SchemeEval* eval = SchemeEval::get_evaluator(as); - eval->eval("(load-from-path \"tests/query/anchor.scm\")"); - - Handle anchor = eval->eval_h("(cog-execute! (Dual srai))"); - - IncomingSet results = anchor->getIncomingSetByType(MEMBER_LINK); - - TSM_ASSERT_EQUALS("Expecting two answers", results.size(), 2); - - logger().debug("END TEST: %s", __FUNCTION__); -} diff --git a/tests/query/CMakeLists.txt b/tests/query/CMakeLists.txt index d9888762b8..e9a7220f2b 100644 --- a/tests/query/CMakeLists.txt +++ b/tests/query/CMakeLists.txt @@ -59,7 +59,6 @@ ADD_CXXTEST(RecognizerUTest) ADD_CXXTEST(ArcanaUTest) ADD_CXXTEST(SubstitutionUTest) ADD_CXXTEST(GetLinkUTest) -ADD_CXXTEST(AnchorUTest) ADD_CXXTEST(NotLinkUTest) ADD_CXXTEST(GetStateUTest) ADD_CXXTEST(ClassicalBooleanUTest) @@ -150,7 +149,6 @@ TARGET_LINK_LIBRARIES(SparseUTest ) # ------------------------------------------------------------- - # Run only the tests in this subdirectory ADD_CUSTOM_TARGET (qtest DEPENDS tests diff --git a/tests/query/anchor.scm b/tests/query/anchor.scm deleted file mode 100644 index f6cf76d8c8..0000000000 --- a/tests/query/anchor.scm +++ /dev/null @@ -1,39 +0,0 @@ -; -; AnchorLink unit test -; -(use-modules (opencog) (opencog exec)) - -(Evaluation (Predicate "foo") (List (Concept "A") (Concept "alpha"))) -(Evaluation (Predicate "foo") (List (Concept "B") (Concept "alpha"))) -(Evaluation (Predicate "foo") (List (Concept "C") (Concept "alpha"))) - -(define getli - (Get (VariableList - (TypedVariable (Variable "$x") (Type 'ConceptNode)) - (Anchor "get-results")) - (Present - (Evaluation (Predicate "foo") - (List (Variable "$x") (Concept "alpha")))))) - -; (cog-execute! getli) -; (cog-incoming-by-type (AnchorNode "get-results") 'MemberLink) -; ---------------------------------- - -(define bindli - (Bind (VariableList - (TypedVariable (Variable "$z") (Type 'ConceptNode)) - (Anchor "bind-results")) - (Present - (Evaluation (Predicate "foo") - (List (Variable "$z") (Concept "alpha")))) - (Inheritance (Variable "$z") (Concept "letters")))) - -; (cog-execute! bindli) -; (cog-incoming-by-type (AnchorNode "bind-results") 'MemberLink) -; ---------------------------------- - -; Stimulous-Response-style AI -(define srai - (Evaluation (Predicate "foo") (List (Concept "C") (Concept "alpha")))) - -; (cog-execute! (Dual srai))