/*
* tests/atoms/PutLinkUTest.cxxtest
*
* Copyright (C) 2015,2017 Linas Vepstas
* Copyright (C) 2016 Nil Geisweiller
* 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 <opencog/util/exceptions.h>
#include <opencog/guile/SchemeEval.h>
#include <opencog/atoms/base/Atom.h>
#include <opencog/atomspace/AtomSpace.h>
#include <opencog/atoms/scope/PutLink.h>
#include <cxxtest/TestSuite.h>
using namespace opencog;
// Test the PutLink.
//
class PutLinkUTest: public CxxTest::TestSuite
{
private:
AtomSpacePtr _asp;
SchemeEval* _eval;
public:
PutLinkUTest() : _asp(createAtomSpace()), _eval(SchemeEval::get_scheme_evaluator(_asp))
{
logger().set_print_to_stdout_flag(true);
logger().set_level(Logger::INFO);
logger().set_timestamp_flag(false);
logger().set_sync_flag(true); // interleave with printf correctly
_eval->eval("(add-to-load-path \"" PROJECT_SOURCE_DIR "\")");
}
void setUp() {}
void tearDown() {}
void test_define();
void test_define_glob();
void test_define_mixed_1();
void test_define_mixed_2();
void test_filtering();
void test_free_var_renaming();
void test_function();
void test_lambda();
void test_lambda_partial_substitution();
void test_eta();
void test_alpha();
void test_compose();
void test_inject_compose();
void test_simple_alpha();
void test_simple_replace();
void test_typed_compose();
void test_ident_compose();
void test_again_compose_ident();
void test_recursive_compose();
void test_eval_inheritance();
void test_eval_implication_1();
void test_eval_implication_2();
void test_ill_unquote();
void test_nested_1();
void test_nested_2();
void test_nested_3();
void test_nested_4();
void test_nested_5();
void test_and_compose_1();
void test_and_compose_2();
void test_quoted_put();
void test_tricky_put_1();
void test_tricky_put_2();
void test_tricky_put_3();
void test_tricky_put_4();
void test_tricky_put_5();
void xtest_tricky_put_6();
void test_tricky_put_7();
void test_quoted_exec();
void test_quoted_eval();
void test_quoted_lambda();
void test_get();
void test_get_lambda();
void test_get_multi();
void test_multi_set();
void test_full_quotation();
};
#define N _asp->add_node
#define L _asp->add_link
// Test to make sure that PutLink filters.
void PutLinkUTest::test_define()
{
logger().info("BEGIN TEST: %s", __FUNCTION__);
L(DEFINE_LINK,
N(DEFINED_SCHEMA_NODE, "foobar"),
L(LAMBDA_LINK,
L(INHERITANCE_LINK,
N(CONCEPT_NODE, "aaa"),
N(VARIABLE_NODE, "$zzz"))));
Handle put =
L(PUT_LINK,
N(DEFINED_SCHEMA_NODE, "foobar"),
N(CONCEPT_NODE, "bbb"));
Handle putted = _asp->add_atom(HandleCast(put->execute(_asp.get())));
Handle pat =
L(INHERITANCE_LINK,
N(CONCEPT_NODE, "aaa"),
N(CONCEPT_NODE, "bbb"));
printf("Expecting %s\n", pat->to_string().c_str());
printf("Got %s\n", putted->to_string().c_str());
TS_ASSERT_EQUALS(putted, pat);
logger().info("END TEST: %s", __FUNCTION__);
}
void PutLinkUTest::test_define_glob()
{
logger().info("BEGIN TEST: %s", __FUNCTION__);
Handle put =
L(PUT_LINK,
N(GLOB_NODE, "$g"),
L(DONT_EXEC_LINK,
L(AND_LINK,
N(GLOB_NODE, "$g"))),
L(SET_LINK,
L(LIST_LINK,
N(PREDICATE_NODE, "P"),
N(PREDICATE_NODE, "Q")),
L(LIST_LINK,
N(PREDICATE_NODE, "R"),
N(PREDICATE_NODE, "K"))));
Handle putted = _asp->add_atom(HandleCast(put->execute(_asp.get())));
Handle expected =
L(SET_LINK,
L(AND_LINK,
N(PREDICATE_NODE, "P"),
N(PREDICATE_NODE, "Q")),
L(AND_LINK,
N(PREDICATE_NODE, "R"),
N(PREDICATE_NODE, "K")));
printf("Expecting %s\n", expected->to_string().c_str());
printf("Got %s\n", putted->to_string().c_str());
TS_ASSERT(content_eq(expected, putted))
}
void PutLinkUTest::test_define_mixed_1()
{
logger().info("BEGIN TEST: %s", __FUNCTION__);
Handle put =
L(PUT_LINK,
L(VARIABLE_LIST,
N(GLOB_NODE, "$g"),
N(VARIABLE_NODE, "$v")),
L(LIST_LINK,
N(GLOB_NODE, "$g"),
N(VARIABLE_NODE, "$v"),
N(PREDICATE_NODE, "J")),
L(SET_LINK,
L(LIST_LINK,
N(PREDICATE_NODE, "P"),
N(PREDICATE_NODE, "Q")),
L(LIST_LINK,
N(PREDICATE_NODE, "R"),
N(PREDICATE_NODE, "K"))));
Handle putted = _asp->add_atom(HandleCast(put->execute(_asp.get())));
Handle expected =
L(SET_LINK,
L(LIST_LINK,
N(PREDICATE_NODE, "P"),
N(PREDICATE_NODE, "Q"),
N(PREDICATE_NODE, "J")),
L(LIST_LINK,
N(PREDICATE_NODE, "R"),
N(PREDICATE_NODE, "K"),
N(PREDICATE_NODE, "J")));
printf("Expecting %s\n", expected->to_string().c_str());
printf("Got %s\n", putted->to_string().c_str());
TS_ASSERT(content_eq(expected, putted))
}
void PutLinkUTest::test_define_mixed_2()
{
logger().info("BEGIN TEST: %s", __FUNCTION__);
Handle put =
L(PUT_LINK,
L(VARIABLE_LIST,
N(GLOB_NODE, "$g"),
N(VARIABLE_NODE, "$v")),
L(DONT_EXEC_LINK,
L(AND_LINK,
N(GLOB_NODE, "$g"),
N(VARIABLE_NODE, "$v"))),
L(SET_LINK,
L(LIST_LINK,
L(LIST_LINK,
N(PREDICATE_NODE, "P"),
N(PREDICATE_NODE, "Q")),
N(PREDICATE_NODE, "R")),
L(LIST_LINK,
L(INHERITANCE_LINK,
N(PREDICATE_NODE, "P"),
N(PREDICATE_NODE, "Q")),
N(PREDICATE_NODE, "R"))));
Handle putted = _asp->add_atom(HandleCast(put->execute(_asp.get())));
Handle expected =
L(SET_LINK,
L(AND_LINK,
N(PREDICATE_NODE, "P"),
N(PREDICATE_NODE, "Q"),
N(PREDICATE_NODE, "R")),
L(AND_LINK,
L(INHERITANCE_LINK,
N(PREDICATE_NODE, "P"),
N(PREDICATE_NODE, "Q")),
N(PREDICATE_NODE, "R")));
printf("Expecting %s\n", expected->to_string().c_str());
printf("Got %s\n", putted->to_string().c_str());
TS_ASSERT(content_eq(expected, putted))
}
// Test to make sure that PutLink filters.
void PutLinkUTest::test_filtering()
{
logger().info("BEGIN TEST: %s", __FUNCTION__);
// Copied from /examples/guile/filter.scm
// This test must pass; it is used in multiple wiki pages
// as an example, including PutLink, LambdaLink,
// DefinedSchemaLink, etc.
Handle foo, bar;
Handle filt =
L(PUT_LINK,
L(LAMBDA_LINK,
L(TYPED_VARIABLE_LINK,
N(VARIABLE_NODE, "$x"),
N(TYPE_NODE, "ConceptNode")),
N(VARIABLE_NODE, "$x")),
L(SET_LINK,
N(NUMBER_NODE, "42"),
foo = N(CONCEPT_NODE, "foo"),
N(PREDICATE_NODE, "biffle"),
L(EDGE_LINK,
N(CONCEPT_NODE, "thingy")),
N(SCHEMA_NODE, "finagle"),
bar = N(CONCEPT_NODE, "bar")));
// Test that execution filters as desired...
Handle cncpts = _asp->add_atom(HandleCast(filt->execute(_asp.get())));
printf("Filtered %s\n", cncpts->to_string().c_str());
TS_ASSERT_EQUALS(SET_LINK, cncpts->get_type());
TS_ASSERT_EQUALS(2, cncpts->get_arity());
Handle a = cncpts->getOutgoingAtom(0);
Handle b = cncpts->getOutgoingAtom(1);
TS_ASSERT(foo == a or foo == b);
TS_ASSERT(bar == a or bar == b);
TS_ASSERT(a != b);
logger().info("END TEST: %s", __FUNCTION__);
}
void PutLinkUTest::test_function()
{
logger().info("BEGIN TEST: %s", __FUNCTION__);
// Test that 2+2 = 4
// (Put (Plus) (List (Number 2) (Number 2)))
Handle want_four =
L(PUT_LINK,
L(PLUS_LINK),
L(LIST_LINK, N(NUMBER_NODE, "2"), N(NUMBER_NODE, "2")));
Handle four = _asp->add_atom(HandleCast(want_four->execute(_asp.get())));
Handle expected_four = N(NUMBER_NODE, "4");
printf("Expecting %s\n", expected_four->to_string().c_str());
printf("Got %s\n", four->to_string().c_str());
TS_ASSERT_EQUALS(four, expected_four);
// Test that 2 = 2
// (Put (Plus) (Number 2))
Handle want_two =
L(PUT_LINK, L(PLUS_LINK), N(NUMBER_NODE, "2"));
Handle two = _asp->add_atom(HandleCast(want_two->execute(_asp.get())));
Handle expected_two = N(NUMBER_NODE, "2");
printf("Expecting %s\n", expected_two->to_string().c_str());
printf("Got %s\n", two->to_string().c_str());
TS_ASSERT_EQUALS(two, expected_two);
// Test the combinator (+9) (2+2) = 13
// (Put (Plus (Number 9)) (List (Number 2) (Number 2)))
Handle want_thirteen =
L(PUT_LINK,
L(PLUS_LINK, N(NUMBER_NODE, "9")),
L(LIST_LINK, N(NUMBER_NODE, "2"), N(NUMBER_NODE, "2")));
Handle thirteen = _asp->add_atom(HandleCast(want_thirteen->execute(_asp.get())));
Handle expected_thirteen = N(NUMBER_NODE, "13");
printf("Expecting %s\n", expected_thirteen->to_string().c_str());
printf("Got %s\n", thirteen->to_string().c_str());
TS_ASSERT_EQUALS(thirteen, expected_thirteen);
// Test the combinator (+ 3 5) (2+2) = 12
// (Put (Plus (Number 3) (Number 5)) (List (Number 2) (Number 2)))
Handle want_twelve =
L(PUT_LINK,
L(PLUS_LINK, N(NUMBER_NODE, "3"), N(NUMBER_NODE, "5")),
L(LIST_LINK, N(NUMBER_NODE, "2"), N(NUMBER_NODE, "2")));
Handle twelve = _asp->add_atom(HandleCast(want_twelve->execute(_asp.get())));
Handle expected_twelve = N(NUMBER_NODE, "12");
printf("Expecting %s\n", expected_twelve->to_string().c_str());
printf("Got %s\n", twelve->to_string().c_str());
TS_ASSERT_EQUALS(twelve, expected_twelve);
// Test a complex set.
// (Put (Times) (Set
// (Number 1)
// (List (Number 2) (Number 2))
// (List (Number 3) (Number 3) (Number 3))
// (List (Number 4) (Number 4) (Number 4) (Number 4))
// )))
//
Handle want_set =
L(PUT_LINK,
L(TIMES_LINK),
L(SET_LINK,
N(NUMBER_NODE, "1"),
L(LIST_LINK, N(NUMBER_NODE, "2"), N(NUMBER_NODE, "2")),
L(LIST_LINK, N(NUMBER_NODE, "3"),
N(NUMBER_NODE, "3"),
N(NUMBER_NODE, "3")),
L(LIST_LINK, N(NUMBER_NODE, "4"),
N(NUMBER_NODE, "4"),
N(NUMBER_NODE, "4"),
N(NUMBER_NODE, "4"))));
Handle set = _asp->add_atom(HandleCast(want_set->execute(_asp.get())));
Handle expected_set =
L(SET_LINK,
N(NUMBER_NODE, "1"),
N(NUMBER_NODE, "4"),
N(NUMBER_NODE, "27"),
N(NUMBER_NODE, "256"));
printf("Expecting %s\n", expected_set->to_string().c_str());
printf("Got %s\n", set->to_string().c_str());
TS_ASSERT_EQUALS(set, expected_set);
logger().info("END TEST: %s", __FUNCTION__);
}
void PutLinkUTest::test_free_var_renaming()
{
logger().info("BEGIN TEST: %s", __FUNCTION__);
// Test simple substitution of free variable names.
Handle inh =
L(INHERITANCE_LINK,
N(VARIABLE_NODE, "$x"),
N(VARIABLE_NODE, "$y"));
Handle put =
L(PUT_LINK,
inh,
L(LIST_LINK,
N(VARIABLE_NODE, "$a"),
N(VARIABLE_NODE, "$b")));
Handle putted = _asp->add_atom(HandleCast(put->execute(_asp.get())));
Handle expected_putted =
L(INHERITANCE_LINK,
N(VARIABLE_NODE, "$a"),
N(VARIABLE_NODE, "$b"));
printf("Expecting %s\n", expected_putted->to_string().c_str());
printf("Got %s\n", putted->to_string().c_str());
TS_ASSERT_EQUALS(putted, expected_putted);
logger().info("END TEST: %s", __FUNCTION__);
}
void PutLinkUTest::test_lambda()
{
logger().info("BEGIN TEST: %s", __FUNCTION__);
// Test that the substitution follows the order of variables
// provided in the lambda rather than left-to-right in the body.
Handle lam =
L(LAMBDA_LINK,
L(VARIABLE_LIST,
N(VARIABLE_NODE, "$x"),
N(VARIABLE_NODE, "$y")),
L(INHERITANCE_LINK,
N(VARIABLE_NODE, "$y"),
N(VARIABLE_NODE, "$x")));
Handle put =
L(PUT_LINK,
lam,
L(LIST_LINK,
N(CONCEPT_NODE, "animal"),
N(CONCEPT_NODE, "coyote")));
Handle putted = _asp->add_atom(HandleCast(put->execute(_asp.get())));
Handle expected_putted =
L(INHERITANCE_LINK,
N(CONCEPT_NODE, "coyote"),
N(CONCEPT_NODE, "animal"));
printf("Expecting %s\n", expected_putted->to_string().c_str());
printf("Got %s\n", putted->to_string().c_str());
TS_ASSERT_EQUALS(putted, expected_putted);
logger().info("END TEST: %s", __FUNCTION__);
}
void PutLinkUTest::test_lambda_partial_substitution()
{
logger().info("BEGIN TEST: %s", __FUNCTION__);
// Test partial substitution
// (Put
// (Lambda (Variable "$x")
// (Inheritance (Variable "$x") (Variable "$y")))
// (Concept "animal"))
Handle lam =
L(LAMBDA_LINK,
N(VARIABLE_NODE, "$x"),
L(INHERITANCE_LINK,
N(VARIABLE_NODE, "$y"),
N(VARIABLE_NODE, "$x")));
Handle put =
L(PUT_LINK,
lam,
N(CONCEPT_NODE, "animal"));
Handle putted = _asp->add_atom(HandleCast(put->execute(_asp.get())));
// (Inheritance (Concept "animal") (Variable "$y"))
Handle expected_putted =
L(INHERITANCE_LINK,
N(VARIABLE_NODE, "$y"),
N(CONCEPT_NODE, "animal"));
printf("Expecting %s\n", expected_putted->to_string().c_str());
printf("Got %s\n", putted->to_string().c_str());
TS_ASSERT_EQUALS(putted, expected_putted);
logger().info("END TEST: %s", __FUNCTION__);
}
// Test eta-reduction of the values
void PutLinkUTest::test_eta()
{
logger().info("BEGIN TEST: %s", __FUNCTION__);
// Test that eta-reduction can be performed on the values. (This is
// actually a test of function composition)
//
// (define func-with-three-args (Lambda
// (VariableList (Variable "$x")(Variable "$y")(Variable "$z"))
// (Inheritance (Variable "$z") (Variable "$x"))))
//
//
// The above is a function that expects three arguments: x,y,z.
// Lets compose it with a function that takes one argument, but
// returns three values (function coposition):
//
// (define func-returns-three-values
// (Lambda (Variable "$w")
// (List (Concept "animal") (Concept "foobar") (Variable"$w"))))
//
// Composing these two should return a function that takes one
// argument, namely $w.
//
// (Put func-with-three-args func-returns-three-values)
//
// We expect as a result:
//
// (Lambda (Variable "$w") (Inheritance (Variable "$w") (Concept "animal")))
//
// Note that this is NOT compatible with beta-reduction in classical
// lambda calculus, which would leave $w free. We really want to
// eta-convert this, and keep $w bound, so that it looks like
// ordinary function composition. Atomese is not lambda calculus.
//
Handle lam =
L(LAMBDA_LINK,
L(VARIABLE_LIST,
N(VARIABLE_NODE, "$x"),
N(VARIABLE_NODE, "$y"),
N(VARIABLE_NODE, "$z")),
L(INHERITANCE_LINK,
N(VARIABLE_NODE, "$z"),
N(VARIABLE_NODE, "$x")));
Handle put =
L(PUT_LINK,
lam,
L(LAMBDA_LINK,
N(VARIABLE_NODE, "$w"),
L(LIST_LINK,
N(CONCEPT_NODE, "animal"),
N(CONCEPT_NODE, "foobar"),
N(VARIABLE_NODE, "$w"))));
Handle putted = _asp->add_atom(HandleCast(put->execute(_asp.get())));
Handle expected_putted =
L(LAMBDA_LINK,
N(VARIABLE_NODE, "$w"),
L(INHERITANCE_LINK,
N(VARIABLE_NODE, "$w"),
N(CONCEPT_NODE, "animal")));
printf("Expecting %s\n", expected_putted->to_string().c_str());
printf("Got %s\n", putted->to_string().c_str());
TS_ASSERT_EQUALS(putted, expected_putted);
logger().info("END TEST: %s", __FUNCTION__);
}
// Test alpha-renaming, where values are variables. Similar to
// the test_eta, except the input is pointless (aka tacit).
void PutLinkUTest::test_alpha()
{
logger().info("BEGIN TEST: %s", __FUNCTION__);
// Test that alpha-renaming can be performed on the values.
// (define lam (Lambda
// (VariableList (Variable "$x")(Variable "$y")(Variable "$z"))
// (Inheritance (Variable "$z") (Variable "$x"))))
//
// (define put (Put lam
// (List (Concept "animal") (Concept "foobar") (Variable "$w"))))
//
// We expect the below, with $w bound, because this is how beta
// reduction is defined in atomese. Note that it is NOT compatible
// with beta-reduction is classical lambda calculus! In lambda calc,
// the result would leave $w free, not bound.
//
// (Lambda (Variable "$w") (Inheritance (Variable "$w") (Concept "animal")))
//
// Note that this is very similar to the test-eta, immediately above.
// It differs because the arguments are not a function.
//
Handle lam =
L(LAMBDA_LINK,
L(VARIABLE_LIST,
N(VARIABLE_NODE, "$x"),
N(VARIABLE_NODE, "$y"),
N(VARIABLE_NODE, "$z")),
L(INHERITANCE_LINK,
N(VARIABLE_NODE, "$z"),
N(VARIABLE_NODE, "$x")));
Handle put =
L(PUT_LINK,
lam,
L(LIST_LINK,
N(CONCEPT_NODE, "animal"),
N(CONCEPT_NODE, "foobar"),
N(VARIABLE_NODE, "$w")));
Handle putted = _asp->add_atom(HandleCast(put->execute(_asp.get())));
Handle expected_putted =
L(LAMBDA_LINK,
N(VARIABLE_NODE, "$w"),
L(INHERITANCE_LINK,
N(VARIABLE_NODE, "$w"),
N(CONCEPT_NODE, "animal")));
printf("Expecting %s\n", expected_putted->to_string().c_str());
printf("Got %s\n", putted->to_string().c_str());
TS_ASSERT_EQUALS(putted, expected_putted);
logger().info("END TEST: %s", __FUNCTION__);
}
// Test simple function composition.
void PutLinkUTest::test_compose()
{
logger().info("BEGIN TEST: %s", __FUNCTION__);
// Test that simple function compostion can be performed.
//
// (define g (Lambda (Evaluation (Predicate "P") (Variable "X"))))
// (define f (Lambda (Inheritance (Variable "X") (Variable "Y"))))
// (cog-execute! (Put g f))
//
// We expect the result to be in prenex form.
//
Handle gee =
L(LAMBDA_LINK,
L(EDGE_LINK,
N(PREDICATE_NODE, "P"),
N(VARIABLE_NODE, "$x")));
Handle eff =
L(LAMBDA_LINK,
L(INHERITANCE_LINK,
N(VARIABLE_NODE, "$x"),
N(VARIABLE_NODE, "$y")));
Handle put =
L(PUT_LINK, gee, eff);
Handle putted = _asp->add_atom(HandleCast(put->execute(_asp.get())));
Handle expected_putted =
L(LAMBDA_LINK,
L(EDGE_LINK,
N(PREDICATE_NODE, "P"),
L(INHERITANCE_LINK,
N(VARIABLE_NODE, "$x"),
N(VARIABLE_NODE, "$y"))));
printf("Expecting %s\n", expected_putted->to_string().c_str());
printf("Got %s\n", putted->to_string().c_str());
TS_ASSERT_EQUALS(putted, expected_putted);
logger().info("END TEST: %s", __FUNCTION__);
}
// Test function composition.
void PutLinkUTest::test_inject_compose()
{
logger().info("BEGIN TEST: %s", __FUNCTION__);
// Test function compostion with injection
//
// (define X (Variable "X"))
// (define Y (Variable "Y"))
// (define Z (Variable "Z"))
// (define W (Variable "W"))
//
// (define g (Lambda
// (VariableList X Y W Z)
// (And
// (Inheritance X Y)
// (Inheritance W Z))))
//
// (define f (Lambda (VariableList X Y Z) (List X Y Y Z)))
//
// (cog-execute! (Put g f))
//
// We expect the result to be in prenex form.
//
Handle X = N(VARIABLE_NODE, "X");
Handle Y = N(VARIABLE_NODE, "Y");
Handle Z = N(VARIABLE_NODE, "Z");
Handle W = N(VARIABLE_NODE, "W");
Handle gee =
L(LAMBDA_LINK,
L(VARIABLE_LIST, X, Y, Z, W),
L(AND_LINK,
L(INHERITANCE_LINK, X, Y),
L(INHERITANCE_LINK, Z, W)));
Handle eff =
L(LAMBDA_LINK,
L(VARIABLE_LIST, X, Y, Z),
L(LIST_LINK, X, Y, Y, Z));
Handle put = L(PUT_LINK, gee, eff);
Handle putted = _asp->add_atom(HandleCast(put->execute(_asp.get())));
Handle expected_putted =
L(LAMBDA_LINK,
L(VARIABLE_LIST, X, Y, Z),
L(AND_LINK,
L(INHERITANCE_LINK, X, Y),
L(INHERITANCE_LINK, Y, Z)));
printf("Expecting %s\n", expected_putted->to_string().c_str());
printf("Got %s\n", putted->to_string().c_str());
TS_ASSERT_EQUALS(putted, expected_putted);
logger().info("END TEST: %s", __FUNCTION__);
}
// Test basic alpha conversion
void PutLinkUTest::test_simple_alpha()
{
logger().info("BEGIN TEST: %s", __FUNCTION__);
// Test function compostion with injection
//
// (define X (Variable "X"))
// (define Y (Variable "Y"))
// (define Z (Variable "Z"))
// (define W (Variable "W"))
//
// (define g (Lambda
// (VariableList X Y W Z)
// (And
// (Inheritance X Y)
// (Inheritance W Z))))
//
// (define f (List X Y Y Z))
//
// (cog-execute! (Put g f))
//
// We expect the result to be in prenex form.
//
Handle X = N(VARIABLE_NODE, "X");
Handle Y = N(VARIABLE_NODE, "Y");
Handle Z = N(VARIABLE_NODE, "Z");
Handle W = N(VARIABLE_NODE, "W");
Handle gee =
L(LAMBDA_LINK,
L(VARIABLE_LIST, X, Y, Z, W),
L(AND_LINK,
L(INHERITANCE_LINK, X, Y),
L(INHERITANCE_LINK, Z, W)));
Handle eff = L(LIST_LINK, X, Y, Y, Z);
Handle put = L(PUT_LINK, gee, eff);
Handle putted = _asp->add_atom(HandleCast(put->execute(_asp.get())));
Handle expected_putted =
L(LAMBDA_LINK,
L(VARIABLE_LIST, X, Y, Z),
L(AND_LINK,
L(INHERITANCE_LINK, X, Y),
L(INHERITANCE_LINK, Y, Z)));
printf("Expecting %s\n", expected_putted->to_string().c_str());
printf("Got %s\n", putted->to_string().c_str());
TS_ASSERT_EQUALS(putted, expected_putted);
logger().info("END TEST: %s", __FUNCTION__);
}
// Test basic insertion.
// A lot like test_inject_compose, but simpler.
void PutLinkUTest::test_simple_replace()
{
logger().info("BEGIN TEST: %s", __FUNCTION__);
// Test function compostion with injection
//
// (define X (Variable "X"))
// (define Y (Variable "Y"))
// (define Z (Variable "Z"))
// (define W (Variable "W"))
//
// (define g (Lambda
// (VariableList X Y W Z)
// (And
// (Inheritance X Y)
// (Inheritance W Z))))
//
// (define A (Concept "A"))
// (define B (Concept "B"))
// (define C (Concept "C"))
//
// (define f (List A B B C)))
//
// (cog-execute! (Put g f))
//
Handle X = N(VARIABLE_NODE, "X");
Handle Y = N(VARIABLE_NODE, "Y");
Handle Z = N(VARIABLE_NODE, "Z");
Handle W = N(VARIABLE_NODE, "W");
Handle gee =
L(LAMBDA_LINK,
L(VARIABLE_LIST, X, Y, Z, W),
L(UNORDERED_LINK,
L(INHERITANCE_LINK, X, Y),
L(INHERITANCE_LINK, Z, W)));
Handle A = N(CONCEPT_NODE, "A");
Handle B = N(CONCEPT_NODE, "B");
Handle C = N(CONCEPT_NODE, "C");
Handle eff = L(LIST_LINK, A, B, B, C);
Handle put = L(PUT_LINK, gee, eff);
Handle putted = _asp->add_atom(HandleCast(put->execute(_asp.get())));
Handle expected_putted =
L(UNORDERED_LINK,
L(INHERITANCE_LINK, A, B),
L(INHERITANCE_LINK, B, C));
printf("Expecting %s\n", expected_putted->to_string().c_str());
printf("Got %s\n", putted->to_string().c_str());
TS_ASSERT_EQUALS(putted, expected_putted);
logger().info("END TEST: %s", __FUNCTION__);
}
// Test function composition with types.
void PutLinkUTest::test_typed_compose()
{
logger().info("BEGIN TEST: %s", __FUNCTION__);
// Test typed function compostion
//
// (define g (Lambda
// (TypedVariable (Variable "X") (TypeNode "InheritanceLink"))
// (Evaluation (Predicate "P") (Variable "X"))))
// (define f (Lambda
// (VariableList
// (TypedVariable (Variable "X") (TypeNode "ConceptNode"))
// (TypedVariable (Variable "Y") (TypeNode "ConceptNode")))
// (Inheritance (Variable "X") (Variable "Y"))))
//
// (cog-execute! (Put g f))
//
// We expect the result to be in prenex form.
//
Handle gee =
L(LAMBDA_LINK,
L(TYPED_VARIABLE_LINK,
N(VARIABLE_NODE, "$x"),
N(TYPE_NODE, "InheritanceLink")),
L(EDGE_LINK,
N(PREDICATE_NODE, "P"),
N(VARIABLE_NODE, "$x")));
Handle eff =
L(LAMBDA_LINK,
L(VARIABLE_LIST,
L(TYPED_VARIABLE_LINK,
N(VARIABLE_NODE, "$x"),
N(TYPE_NODE, "ConceptNode")),
L(TYPED_VARIABLE_LINK,
N(VARIABLE_NODE, "$y"),
N(TYPE_NODE, "ConceptNode"))),
L(INHERITANCE_LINK,
N(VARIABLE_NODE, "$x"),
N(VARIABLE_NODE, "$y")));
Handle put =
L(PUT_LINK, gee, eff);
Handle putted = _asp->add_atom(HandleCast(put->execute(_asp.get())));
Handle expected_putted =
L(LAMBDA_LINK,
L(VARIABLE_LIST,
L(TYPED_VARIABLE_LINK,
N(VARIABLE_NODE, "$u"),
N(TYPE_NODE, "ConceptNode")),
L(TYPED_VARIABLE_LINK,
N(VARIABLE_NODE, "$v"),
N(TYPE_NODE, "ConceptNode"))),
L(EDGE_LINK,
N(PREDICATE_NODE, "P"),
L(INHERITANCE_LINK,
N(VARIABLE_NODE, "$u"),
N(VARIABLE_NODE, "$v"))));
printf("Expecting %s\n", expected_putted->to_string().c_str());
printf("Got %s\n", putted->to_string().c_str());
TS_ASSERT_EQUALS(putted, expected_putted);
Handle gahhh =
L(LAMBDA_LINK,
L(TYPED_VARIABLE_LINK,
N(VARIABLE_NODE, "$x"),
N(TYPE_NODE, "SimilarityLink")), // type mismatch here!
L(EDGE_LINK,
N(PREDICATE_NODE, "P"),
N(VARIABLE_NODE, "$x")));
bool caught = false;
try
{
put = L(PUT_LINK, gahhh, eff);
HandleCast(put->execute(_asp.get()));
}
catch(const StandardException& ex)
{
caught = true;
}
printf("Expecting throw, got %d\n", caught);
TSM_ASSERT("Failed to catch expected exception", caught);
logger().info("END TEST: %s", __FUNCTION__);
}
// Test function composition with identity function
void PutLinkUTest::test_ident_compose()
{
logger().info("BEGIN TEST: %s", __FUNCTION__);
// Test function compostion with a cartesian product
//
// (define g (Lambda (Evaluation (Variable "X") (Variable "Y"))))
// (define f2 (Lambda
// (VariableList (Variable "X") (Variable "Y") (Variable "Z"))
// (Inheritance (Variable "Y")(Variable "Z")) ))
//
// (define ident (Lambda (Variable "W") (Variable "W")))
// (cog-execute! (Put g (List ident f2)))
//
// We expect the result to be in prenex form.
//
Handle gee =
L(LAMBDA_LINK,
L(EDGE_LINK,
N(VARIABLE_NODE, "$x"),
N(VARIABLE_NODE, "$y")));
Handle eff =
L(LAMBDA_LINK,
L(VARIABLE_LIST,
N(VARIABLE_NODE, "$x"),
N(VARIABLE_NODE, "$y"),
N(VARIABLE_NODE, "$z")),
L(INHERITANCE_LINK,
N(VARIABLE_NODE, "$y"),
N(VARIABLE_NODE, "$z")));
Handle ident =
L(LAMBDA_LINK,
N(VARIABLE_NODE, "$x"), N(VARIABLE_NODE, "$x"));
Handle put =
L(PUT_LINK, gee, L(LIST_LINK, ident, eff));
Handle putted = _asp->add_atom(HandleCast(put->execute(_asp.get())));
Handle expected_putted =
L(LAMBDA_LINK,
L(VARIABLE_LIST,
N(VARIABLE_NODE, "$w"),
N(VARIABLE_NODE, "$x"),
N(VARIABLE_NODE, "$y"),
N(VARIABLE_NODE, "$z")),
L(EDGE_LINK,
N(VARIABLE_NODE, "$w"),
L(INHERITANCE_LINK,
N(VARIABLE_NODE, "$y"),
N(VARIABLE_NODE, "$z"))));
printf("Expecting %s\n", expected_putted->to_string().c_str());
printf("Got %s\n", putted->to_string().c_str());
TS_ASSERT_EQUALS(putted, expected_putted);
logger().info("END TEST: %s", __FUNCTION__);
}
// Test function composition with identity function
void PutLinkUTest::test_again_compose_ident()
{
logger().info("BEGIN TEST: %s", __FUNCTION__);
// A non-empty atomspace throws off alpha-conversion collions bugs.
// retest with an empty atomspace.
_asp->clear();
test_ident_compose();
logger().info("END TEST: %s", __FUNCTION__);
}
// Test recursive function composition
void PutLinkUTest::test_recursive_compose()
{
logger().info("BEGIN TEST: %s", __FUNCTION__);
// Test that recursive function composition is performed correctly.
//
// (define g (Lambda (Evaluation (Variable "X") (Variable "Y"))))
// (define f2 (Lambda
// (VariableList (Variable "X") (Variable "Y") (Variable "Z"))
// (Inheritance (Variable "Y")(Variable "Z")) ))
//
// (define inject ;; knock out first argument
// (List (Concept "junk") (Variable "S")(Variable "T")))
//
// (define ident (Lambda (Variable "W") (Variable "W")))
// (cog-execute! (Put g (List ident (Put f2 inject))))
//
// We expect the result to be in prenex form.
//
Handle gee =
L(LAMBDA_LINK,
L(EDGE_LINK,
N(VARIABLE_NODE, "$x"),
N(VARIABLE_NODE, "$y")));
Handle eff =
L(LAMBDA_LINK,
L(VARIABLE_LIST,
N(VARIABLE_NODE, "$x"),
N(VARIABLE_NODE, "$y"),
N(VARIABLE_NODE, "$z")),
L(INHERITANCE_LINK,
N(VARIABLE_NODE, "$y"),
N(VARIABLE_NODE, "$z")));
Handle inject =
L(LIST_LINK,
N(CONCEPT_NODE, "junk"),
N(VARIABLE_NODE, "$x"),
N(VARIABLE_NODE, "$y"));
Handle ident =
L(LAMBDA_LINK,
N(VARIABLE_NODE, "$x"), N(VARIABLE_NODE, "$x"));
Handle put =
L(PUT_LINK, gee,
L(LIST_LINK, ident, L(PUT_LINK, eff, inject)));
Handle putted = _asp->add_atom(HandleCast(put->execute(_asp.get())));
Handle expected_putted =
L(LAMBDA_LINK,
L(VARIABLE_LIST,
N(VARIABLE_NODE, "A"),
N(VARIABLE_NODE, "B"),
N(VARIABLE_NODE, "C")),
L(EDGE_LINK,
N(VARIABLE_NODE, "A"),
L(INHERITANCE_LINK,
N(VARIABLE_NODE, "B"),
N(VARIABLE_NODE, "C"))));
printf("Expecting %s\n", expected_putted->to_string().c_str());
printf("Got %s\n", putted->to_string().c_str());
TS_ASSERT_EQUALS(putted, expected_putted);
logger().info("END TEST: %s", __FUNCTION__);
}
/**
* This test is for the case where PutLink has to evaluate the beta
* reduced pattern and this pattern contains an inheritance link. For
* instance
*
* (PutLink
* (LambdaLink
* (VariableList
* (TypedVariableLink
* (VariableNode "$X")
* (TypeNode "ConceptNode")
* )
* (TypedVariableLink
* (VariableNode "$Y")
* (TypeNode "ConceptNode")
* )
* )
* (AndLink
* (InheritanceLink
* (VariableNode "$X")
* (ConceptNode "human")
* )
* (InheritanceLink
* (VariableNode "$Y")
* (ConceptNode "human")
* )
* (EvaluationLink
* (PredicateNode "acquainted")
* (ListLink
* (VariableNode "$X")
* (VariableNode "$Y")
* )
* )
* )
* )
* (ListLink
* (ConceptNode "Self")
* (ConceptNode "Bob")
* )
* )
*/
void PutLinkUTest::test_eval_inheritance()
{
logger().info("BEGIN TEST: %s", __FUNCTION__);
Handle X = N(VARIABLE_NODE, "$X"),
Y = N(VARIABLE_NODE, "$Y"),
Concept = N(TYPE_NODE, "ConceptNode"),
human = N(CONCEPT_NODE, "human"),
Self = N(CONCEPT_NODE, "Self"),
Bob = N(CONCEPT_NODE, "Bob"),
acquainted = N(PREDICATE_NODE, "acquainted"),
X_human = L(INHERITANCE_LINK, X, human),
Y_human = L(INHERITANCE_LINK, Y, human),
Self_human = L(INHERITANCE_LINK, Self, human),
Bob_human = L(INHERITANCE_LINK, Bob, human),
X_Y_acquainted = L(EDGE_LINK,
acquainted,
L(LIST_LINK, X, Y)),
Self_Bob_acquainted = L(EDGE_LINK,
acquainted,
L(LIST_LINK, Self, Bob)),
vardecl = L(VARIABLE_LIST,
L(TYPED_VARIABLE_LINK, X, Concept),
L(TYPED_VARIABLE_LINK, Y, Concept)),
body = L(UNORDERED_LINK, X_human, Y_human, X_Y_acquainted),
args = L(LIST_LINK, Self, Bob),
put = L(PUT_LINK, L(LAMBDA_LINK, vardecl, body), args);
Handle putted = _asp->add_atom(HandleCast(put->execute(_asp.get())));
Handle expected = L(UNORDERED_LINK, Self_human, Bob_human, Self_Bob_acquainted);
printf("Expecting %s\n", expected->to_string().c_str());
printf("Got %s\n", putted->to_string().c_str());
TS_ASSERT_EQUALS(putted, expected);
logger().info("END TEST: %s", __FUNCTION__);
}
/**
* Another test for the case where PutLink has to evaluate the beta
* reduced pattern and this pattern contains an implication link. For
* instance
*
* (PutLink
* (LambdaLink
* (TypedVariableLink
* (VariableNode "$X")
* (TypeNode "ConceptNode")
* )
* (RuleLink
* (EvaluationLink
* (PredicateNode "P")
* (VariableNode "$X")
* )
* (EvaluationLink
* (PredicateNode "P")
* (VariableNode "$X")
* )
* )
* )
* (ConceptNode "A")
* )
*/
void PutLinkUTest::test_eval_implication_1()
{
logger().info("BEGIN TEST: %s", __FUNCTION__);
Handle X = N(VARIABLE_NODE, "$X"),
A = N(CONCEPT_NODE, "A"),
CT = N(TYPE_NODE, "ConceptNode"),
P = N(PREDICATE_NODE, "P"),
P_X = L(EDGE_LINK, P, X),
P_A = L(EDGE_LINK, P, A),
body = L(QUOTE_LINK,
L(RULE_LINK,
L(UNQUOTE_LINK, P_X),
L(UNQUOTE_LINK, P_X))),
vardecl = L(TYPED_VARIABLE_LINK, X, CT),
put = L(PUT_LINK, L(LAMBDA_LINK, vardecl, body), A);
Handle putted = _asp->add_atom(HandleCast(put->execute(_asp.get())));
Handle expected = L(RULE_LINK, P_A, P_A);
printf("Executing %s\n", put->to_string().c_str());
printf("Expecting %s\n", expected->to_string().c_str());
printf("Got %s\n", putted->to_string().c_str());
TS_ASSERT_EQUALS(putted, expected);
logger().info("END TEST: %s", __FUNCTION__);
}
/**
* This test is for the case where PutLink has to evaluate the beta
* reduced pattern and this pattern contains an implication link. For
* instance
*
* (PutLink
* (LambdaLink
* (VariableList
* (TypedVariableLink
* (VariableNode "$X")
* (TypeNode "PredicateNode")
* )
* (TypedVariableLink
* (VariableNode "$Y")
* (TypeNode "PredicateNode")
* )
* )
* (AndLink
* (ImplicationLink
* (VariableNode "$X")
* (PredicateNode "is-human")
* )
* (ImplicationLink
* (VariableNode "$Y")
* (PredicateNode "is-human")
* )
* (EvaluationLink
* (PredicateNode "acquainted")
* (ListLink
* (VariableNode "$X")
* (VariableNode "$Y")
* )
* )
* )
* )
* (ListLink
* (PredicateNode "is-Self")
* (PredicateNode "is-Bob")
* )
* )
*/
void PutLinkUTest::test_eval_implication_2()
{
logger().info("BEGIN TEST: %s", __FUNCTION__);
Handle X = N(VARIABLE_NODE, "$X"),
Y = N(VARIABLE_NODE, "$Y"),
Predicate = N(TYPE_NODE, "PredicateNode"),
human = N(PREDICATE_NODE, "is-human"),
Self = N(PREDICATE_NODE, "is-Self"),
Bob = N(PREDICATE_NODE, "is-Bob"),
acquainted = N(PREDICATE_NODE, "acquainted"),
X_human = L(IMPLICATION_LINK, X, human),
Y_human = L(IMPLICATION_LINK, Y, human),
Self_human = L(IMPLICATION_LINK, Self, human),
Bob_human = L(IMPLICATION_LINK, Bob, human),
X_Y_acquainted = L(EDGE_LINK,
acquainted,
L(LIST_LINK, X, Y)),
Self_Bob_acquainted = L(EDGE_LINK,
acquainted,
L(LIST_LINK, Self, Bob)),
vardecl = L(VARIABLE_LIST,
L(TYPED_VARIABLE_LINK, X, Predicate),
L(TYPED_VARIABLE_LINK, Y, Predicate)),
body = L(UNORDERED_LINK, X_human, Y_human, X_Y_acquainted),
args = L(LIST_LINK, Self, Bob),
put = L(PUT_LINK, L(LAMBDA_LINK, vardecl, body), args);
Handle putted = _asp->add_atom(HandleCast(put->execute(_asp.get())));
Handle expected = L(UNORDERED_LINK, Self_human, Bob_human, Self_Bob_acquainted);
printf("Executing %s\n", put->to_string().c_str());
printf("Expecting %s\n", expected->to_string().c_str());
printf("Got %s\n", putted->to_string().c_str());
TS_ASSERT_EQUALS(putted, expected);
logger().info("END TEST: %s", __FUNCTION__);
}
/**
* Test that the ill quotation use doesn't crash execution
*
* (PutLink
* (LambdaLink
* (VariableNode "$X")
* (EvaluationLink
* (PredicateNode "P")
* (VariableNode "$X")
* )
* )
* (LambdaLink
* (UnquoteLink
* (VariableNode "$x")
* )
* (UnquoteLink
* (VariableNode "$g")
* )
* )
* )
*/
void PutLinkUTest::test_ill_unquote()
{
logger().info("BEGIN TEST: %s", __FUNCTION__);
Handle X = N(VARIABLE_NODE, "$X"),
P = N(PREDICATE_NODE, "P"),
x = N(VARIABLE_NODE, "$x"),
g = N(VARIABLE_NODE, "$g"),
put = L(PUT_LINK,
L(LAMBDA_LINK,
X,
L(EDGE_LINK, P, X)),
L(LAMBDA_LINK,
L(UNQUOTE_LINK, x),
L(UNQUOTE_LINK, g)));
TS_ASSERT_THROWS_ANYTHING(HandleCast(put->execute(_asp.get())));
logger().info("END TEST: %s", __FUNCTION__);
}
/**
* Test that nested PutLinks is supported, specifically that executing
*
* (Put
* (Put
* (Lambda
* (Variable "$X")
* (Variable "$X"))
* (Lambda
* (VariableList
* (Variable "$Y")
* (Variable "$Z"))
* (Inheritance
* (Variable "$Y")
* (Variable "$Z"))))
* (List
* (Concept "A")
* (Variable "$X")))
*
* outputs
*
* (Lambda
* (Variable "X")
* (Inheritance
* (Concept "A")
* (Variable "$X")))
*
*/
void PutLinkUTest::test_nested_1()
{
logger().info("BEGIN TEST: %s", __FUNCTION__);
std::string rs = _eval->eval("(load-from-path \"tests/atoms/scope/put-nested.scm\")");
logger().debug() << "rs = " << rs;
Handle nested_put = _eval->eval_h("nested-put-1"),
result = _asp->add_atom(HandleCast(nested_put->execute(_asp.get()))),
expected = _eval->eval_h("expected-1");
logger().debug() << "result = " << oc_to_string(result);
logger().debug() << "expected = " << oc_to_string(expected);
TS_ASSERT_EQUALS(result, expected);
logger().info("END TEST: %s", __FUNCTION__);
}
/**
* Test that the following
*
* (PutLink
* (PutLink
* (LambdaLink
* (VariableNode "$X")
* (VariableNode "$X"))
* (ListLink
* (ConceptNode "texts")
* (VariableNode "$W")))
* (LambdaLink
* (VariableList
* (VariableNode "$Y")
* (VariableNode "$Z"))
* (InheritanceLink
* (VariableNode "$Y")
* (VariableNode "$Z"))))
*
* outputs
*
* (Lambda
* (VariableList
* (VariableNode "$Y")
* (VariableNode "$Z"))
* (ListLink
* (ConceptNode "texts")
* (Inheritance
* (VariableNode "$Y")
* (VariableNode "$Z"))))
*
* We expect the inner put to be evaluated first, resulting in
* (ListLink (Concept "texts") (Variable "$W"))
* and then the outer put will just paste the lambda.yz where the $W goes.
* Finally, the whole expression is re-written in prenex form, so that the
* variable bindings are moved to outer-most.
*/
void PutLinkUTest::test_nested_2()
{
logger().info("BEGIN TEST: %s", __FUNCTION__);
std::string rs = _eval->eval("(load-from-path \"tests/atoms/scope/put-nested.scm\")");
logger().debug() << "rs = " << rs;
Handle nested = _eval->eval_h("nested-put-2");
Handle expected = _eval->eval_h("expected-2");
Handle result = _asp->add_atom(HandleCast(nested->execute(_asp.get())));
logger().debug() << "result = " << oc_to_string(result);
logger().debug() << "expected = " << oc_to_string(expected);
TS_ASSERT_EQUALS(result, expected);
logger().info("END TEST: %s", __FUNCTION__);
}
/**
* Test that that executing the below raises an exception
*
* (PutLink
* (PutLink
* (PutLink
* (LambdaLink
* (VariableNode "$X")
* (VariableNode "$X"))
* (ConceptNode "A"))
* (Concept "B"))
* (Concept "C"))
*
* The reason for this is that the innermost Put should evaluate
* to just (ConceptNode "A"), and so the middle one would be
* (Put (Concept "A") (Concept "B"))
* which is ill-defined, and throws.
*/
void PutLinkUTest::test_nested_3()
{
logger().info("BEGIN TEST: %s", __FUNCTION__);
std::string rs = _eval->eval("(load-from-path \"tests/atoms/scope/put-nested.scm\")");
logger().debug() << "rs = " << rs;
Handle nested_put = _eval->eval_h("nested-put-3");
TS_ASSERT_THROWS_ANYTHING(HandleCast(nested_put->execute(_asp.get())));
logger().info("END TEST: %s", __FUNCTION__);
}
/**
* Test that the following PutLinks raise an exception when executed
* This is essentially the same test as that above, and throws for the
* same reason (viz. its "texts" instead of "A", but same idea).
*
* (PutLink
* (PutLink
* (PutLink
* (LambdaLink
* (VariableNode "$X")
* (VariableNode "$X"))
* (ConceptNode "texts"))
* (ListLink
* (ConceptNode "texts")
* (VariableNode "$x-1")))
* (ConceptNode "texts"))
*/
void PutLinkUTest::test_nested_4()
{
logger().info("BEGIN TEST: %s", __FUNCTION__);
std::string rs = _eval->eval("(load-from-path \"tests/atoms/scope/put-nested.scm\")");
logger().debug() << "rs = " << rs;
Handle nested_put = _eval->eval_h("nested-put-4");
TS_ASSERT_THROWS_ANYTHING(HandleCast(nested_put->execute(_asp.get())));
logger().info("END TEST: %s", __FUNCTION__);
}
/**
* Test that the following nested sequence of PutLinks
*
* (Put
* (Put
* (Put
* (Lambda
* (Variable "$top-arg")
* (Variable "$top-arg"))
* (Lambda
* (Variable "$top-arg")
* (Variable "$top-arg")))
* (List
* (Variable "$spe-arg-0")
* (Concept "D")))
* (Lambda
* (VariableList
* (Variable "$sha-arg-0")
* (Variable "$sha-arg-1"))
* (Inheritance
* (Variable "$sha-arg-0")
* (Variable "$sha-arg-1"))))
*
* reduces to
*
* (Lambda
* (VariableList
* (Variable "$sha-arg-0")
* (Variable "$sha-arg-1"))
* (List
* (Inheritance
* (Variable "$sha-arg-0")
* (Variable "$sha-arg-1"))
* (Concept "D")))
*
* The reason for this is that the outermost Put should be of the form
* (Put
* (ListLink (Variable "$spe-arg-0") (Concept "D"))
* (Lambda stuff)
* and so the (Lambda stuff) should get pasted verbatim into where the
* (Variable "$spe-arg-0") is. Finally, its reassembled in prenex form,
* so that the variable declarations are outermost.
*/
void PutLinkUTest::test_nested_5()
{
logger().info("BEGIN TEST: %s", __FUNCTION__);
std::string rs = _eval->eval("(load-from-path \"tests/atoms/scope/put-nested.scm\")");
logger().debug() << "rs = " << rs;
Handle simple_put = _eval->eval_h("simple-put-5");
Handle result = _asp->add_atom(HandleCast(simple_put->execute(_asp.get())));
Handle expected = _eval->eval_h("expected-5");
logger().debug() << "result = " << oc_to_string(result);
logger().debug() << "expected = " << oc_to_string(expected);
TS_ASSERT_EQUALS(result, expected);
Handle nested_put = _eval->eval_h("nested-put-5");
result = _asp->add_atom(HandleCast(nested_put->execute(_asp.get())));
logger().debug() << "result = " << oc_to_string(result);
logger().debug() << "expected = " << oc_to_string(expected);
TS_ASSERT_EQUALS(result, expected);
logger().info("END TEST: %s", __FUNCTION__);
}
/**
* Make sure that composing a top abstraction with aquoted AndLink
* doesn't remove the quotes, because otherwise the AndLink is
* interpreted as being a pattern matcher logic connector. So
* specifically check that
*
* (PutLink
* (LambdaLink
* (VariableNode "$top-arg")
* (VariableNode "$top-arg"))
* (LambdaLink
* (VariableList
* (VariableNode "$sha-arg-0")
* (VariableNode "$sha-arg-1")))
* (LocalQuoteLink
* (AndLink
* (VariableNode "$sha-arg-0")
* (VariableNode "$sha-arg-1"))))
*
* upon execution outputs
*
* (LambdaLink
* (VariableList
* (VariableNode "$sha-arg-0")
* (VariableNode "$sha-arg-1"))
* (LocalQuoteLink
* (AndLink
* (VariableNode "$sha-arg-0")
* (VariableNode "$sha-arg-1"))))
*
*/
void PutLinkUTest::test_and_compose_1()
{
logger().info("BEGIN TEST: %s", __FUNCTION__);
std::string rs = _eval->eval("(load-from-path \"tests/atoms/scope/put-and.scm\")");
logger().debug() << "rs = " << rs;
Handle top = _eval->eval_h("top"),
and_sha_abs = _eval->eval_h("and-shallow-abstraction"),
put_top_and = L(PUT_LINK, top,
and_sha_abs),
result = _asp->add_atom(HandleCast(put_top_and->execute(_asp.get()))),
expected = and_sha_abs;
logger().debug() << "result = " << oc_to_string(result);
logger().debug() << "expected = " << oc_to_string(expected);
TS_ASSERT_EQUALS(result, expected);
logger().info("END TEST: %s", __FUNCTION__);
}
/**
* Make sure that composing a non top abstraction with a quoted
* AndLink does remove the quotation as it is useless. Specifically
*
* (PutLink
* (LambdaLink
* (VariableList
* (VariableNode "$sha-arg-0")
* (VariableNode "$sha-arg-1"))
* (InheritanceLink
* (VariableNode "$sha-arg-0")
* (VariableNode "$sha-arg-1")))
* (ListLink
* (VariableNode "spe-0")
* (LambdaLink
* (VariableList
* (VariableNode "$sha-arg-0")
* (VariableNode "$sha-arg-1"))
* (LocalQuoteLink
* (AndLink
* (VariableNode "$sha-arg-0")
* (VariableNode "$sha-arg-1"))))))
*
* upon execution outputs
*
* (LambdaLink
* (VariableList
* (VariableNode "spe-0")
* (VariableNode "$sha-arg-0")
* (VariableNode "$sha-arg-1"))
* (InheritanceLink
* (VariableNode "spe-0")
* (AndLink
* (VariableNode "$sha-arg-0")
* (VariableNode "$sha-arg-1"))))
*
*/
void PutLinkUTest::test_and_compose_2()
{
logger().info("BEGIN TEST: %s", __FUNCTION__);
std::string rs = _eval->eval("(load-from-path \"tests/atoms/scope/put-and.scm\")");
logger().debug() << "rs = " << rs;
Handle inh_sha_abs = _eval->eval_h("inheritance-shallow-abstraction"),
and_sha_abs = _eval->eval_h("and-shallow-abstraction"),
spe_var = N(VARIABLE_NODE, "$spe-0"),
sha_var_1 = N(VARIABLE_NODE, "$sha-arg-0"),
sha_var_2 = N(VARIABLE_NODE, "$sha-arg-1"),
put_inh_and = L(PUT_LINK, inh_sha_abs,
L(LIST_LINK, spe_var, and_sha_abs)),
result = _asp->add_atom(HandleCast(put_inh_and->execute(_asp.get()))),
expected = L(LAMBDA_LINK,
L(VARIABLE_LIST,
spe_var,
sha_var_1,
sha_var_2),
L(INHERITANCE_LINK,
spe_var,
L(AND_LINK,
sha_var_1,
sha_var_2)));
logger().debug() << "result = " << oc_to_string(result);
logger().debug() << "expected = " << oc_to_string(expected);
TS_ASSERT_EQUALS(result, expected);
logger().info("END TEST: %s", __FUNCTION__);
}
/**
* Make sure one can build quoted PutLink like
*
* Quote
* Put
* Lambda
* Inheritance
* Variable "$X"
* Variable "$Y"
* Unquote Variable "$patvar"
*/
void PutLinkUTest::test_quoted_put()
{
logger().info("BEGIN TEST: %s", __FUNCTION__);
Handle quoted_put = L(QUOTE_LINK,
L(PUT_LINK,
L(LAMBDA_LINK,
L(INHERITANCE_LINK,
N(VARIABLE_NODE, "$X"),
N(VARIABLE_NODE, "$Y"))),
L(UNQUOTE_LINK,
N(VARIABLE_NODE, "$patvar"))));
logger().debug() << "quoted_put = " << oc_to_string(quoted_put);
TS_ASSERT_DIFFERS(quoted_put, nullptr);
logger().info("END TEST: %s", __FUNCTION__);
}
/**
* The following
*
* (Put
* (Lambda (Inheritance (Variable "$X") (Variable "$Y")))
* (List (Variable "$Z") (Variable "$Z")))
*
* should output upon execution
*
* (LambdaLink
* (VariableNode "$Z")
* (InheritanceLink
* (VariableNode "$Z")
* (VariableNode "$Z")))
*/
void PutLinkUTest::test_tricky_put_1()
{
logger().info("BEGIN TEST: %s", __FUNCTION__);
std::string rs = _eval->eval("(load-from-path \"tests/atoms/scope/put-tricky.scm\")");
logger().debug() << "rs = " << rs;
Handle put = _eval->eval_h("put-1"),
result = _asp->add_atom(HandleCast(put->execute(_asp.get()))),
expected = _eval->eval_h("expected-1");
logger().debug() << "result = " << oc_to_string(result);
logger().debug() << "expected = " << oc_to_string(expected);
TS_ASSERT_EQUALS(result, expected);
logger().info("END TEST: %s", __FUNCTION__);
}
/**
* The following
*
* (Put
* (Inheritance (Variable "$X") (Variable "$Y"))
* (List (Variable "$Z") (Variable "$Z")))
*
* should output upon execution
*
* (InheritanceLink
* (VariableNode "$Z")
* (VariableNode "$Z"))
*/
void PutLinkUTest::test_tricky_put_2()
{
logger().info("BEGIN TEST: %s", __FUNCTION__);
std::string rs = _eval->eval("(load-from-path \"tests/atoms/scope/put-tricky.scm\")");
logger().debug() << "rs = " << rs;
Handle put = _eval->eval_h("put-2"),
result = _asp->add_atom(HandleCast(put->execute(_asp.get()))),
expected = _eval->eval_h("expected-2");
logger().debug() << "result = " << oc_to_string(result);
logger().debug() << "expected = " << oc_to_string(expected);
TS_ASSERT_EQUALS(result, expected);
logger().info("END TEST: %s", __FUNCTION__);
}
/**
* The following
*
* (Put
* (Lambda (Inheritance (Variable "$X") (Variable "$Y")))
* (List (Variable "$Z") (Variable "$W")))
*
* should output upon execution
*
* (LambdaLink
* (InheritanceLink
* (VariableNode "$X")
* (VariableNode "$Y")))
*/
void PutLinkUTest::test_tricky_put_3()
{
logger().info("BEGIN TEST: %s", __FUNCTION__);
std::string rs = _eval->eval("(load-from-path \"tests/atoms/scope/put-tricky.scm\")");
logger().debug() << "rs = " << rs;
Handle put = _eval->eval_h("put-3");
Handle result = _asp->add_atom(HandleCast(put->execute(_asp.get())));
Handle expected = _eval->eval_h("expected-3");
logger().debug() << "result = " << oc_to_string(result);
logger().debug() << "expected = " << oc_to_string(expected);
TS_ASSERT_EQUALS(result, expected);
expected = _eval->eval_h("expected-3-alt");
logger().debug() << "alternative expected = " << oc_to_string(expected);
TS_ASSERT_EQUALS(result, expected);
expected = _eval->eval_h("expected-3-alt-b");
logger().debug() << "alt-b expected = " << oc_to_string(expected);
TS_ASSERT_EQUALS(result, expected);
logger().info("END TEST: %s", __FUNCTION__);
}
/**
* The following
*
* (Put
* (Inheritance (Variable "$X") (Variable "$Y"))
* (List (Variable "$Z") (Variable "$W")))
*
* should output upon execution
*
* (InheritanceLink
* (VariableNode "$Z")
* (VariableNode "$W"))
*/
void PutLinkUTest::test_tricky_put_4()
{
logger().info("BEGIN TEST: %s", __FUNCTION__);
std::string rs = _eval->eval("(load-from-path \"tests/atoms/scope/put-tricky.scm\")");
logger().debug() << "rs = " << rs;
Handle put = _eval->eval_h("put-4");
Handle result = _asp->add_atom(HandleCast(put->execute(_asp.get())));
Handle expected = _eval->eval_h("expected-4");
Handle unexpected = _eval->eval_h("unexpected-4");
logger().debug() << "result = " << oc_to_string(result);
logger().debug() << "expected = " << oc_to_string(expected);
TS_ASSERT_EQUALS(result, expected);
TS_ASSERT_DIFFERS(result, unexpected);
logger().info("END TEST: %s", __FUNCTION__);
}
/**
* The following
*
* (Put
* (List
* (Variable "$spe-arg-0")
* (Concept "D"))
* (Lambda
* (VariableList
* (Variable "$sha-arg-0")
* (Variable "$sha-arg-1"))
* (Inheritance
* (Variable "$sha-arg-0")
* (Variable "$sha-arg-1"))))
*
* should output upon execution
*
* (Lambda
* (VariableList
* (Variable "$sha-arg-0")
* (Variable "$sha-arg-1"))
* (List
* (Inheritance
* (Variable "$sha-arg-0")
* (Variable "$sha-arg-1"))
* (Concept "D")))
*/
void PutLinkUTest::test_tricky_put_5()
{
logger().info("BEGIN TEST: %s", __FUNCTION__);
std::string rs = _eval->eval("(load-from-path \"tests/atoms/scope/put-tricky.scm\")");
logger().debug() << "rs = " << rs;
Handle put = _eval->eval_h("put-5"),
result = _asp->add_atom(HandleCast(put->execute(_asp.get()))),
expected = _eval->eval_h("expected-5");
logger().debug() << "result = " << oc_to_string(result);
logger().debug() << "expected = " << oc_to_string(expected);
TS_ASSERT_EQUALS(result, expected);
logger().info("END TEST: %s", __FUNCTION__);
}
/**
* Just like tricky_put_5, but with a non-lambda prenex link.
*/
// XXX FIXME this currently triggers an exception in RUleLink::execute()
// complaining of mal-formed syntax. I don't understand why execute()
// is even being called, but am too lazy to debug. Something seems off.
void PutLinkUTest::xtest_tricky_put_6()
{
logger().info("BEGIN TEST: %s", __FUNCTION__);
std::string rs = _eval->eval("(load-from-path \"tests/atoms/scope/put-tricky.scm\")");
logger().debug() << "rs = " << rs;
Handle put = _eval->eval_h("put-6"),
result = _asp->add_atom(HandleCast(put->execute(_asp.get()))),
expected = _eval->eval_h("expected-6");
logger().debug() << "result = " << oc_to_string(result);
logger().debug() << "expected = " << oc_to_string(expected);
TS_ASSERT_EQUALS(result, expected);
logger().info("END TEST: %s", __FUNCTION__);
}
/**
* Just like tricky_put_5, but with a non-prenex link.
* Unlike trick_put_5, this should NOT be rewritten into prenex form!
*/
void PutLinkUTest::test_tricky_put_7()
{
logger().info("BEGIN TEST: %s", __FUNCTION__);
std::string rs = _eval->eval("(load-from-path \"tests/atoms/scope/put-tricky.scm\")");
logger().debug() << "rs = " << rs;
Handle put = _eval->eval_h("put-7"),
result = _asp->add_atom(HandleCast(put->execute(_asp.get()))),
expected = _eval->eval_h("expected-7");
logger().debug() << "result = " << oc_to_string(result);
logger().debug() << "expected = " << oc_to_string(expected);
TS_ASSERT_EQUALS(result, expected);
logger().info("END TEST: %s", __FUNCTION__);
}
/**
* Test
*
* (PutLink
* (LambdaLink
* (VariableNode "$X")
* )
* (LambdaLink
* (VariableList
* (VariableNode "$gsn")
* (VariableNode "$arg")
* )
* (QuoteLink
* (ExecutionOutputLink
* (UnquoteLink
* (VariableNode "$gsn")
* )
* (UnquoteLink
* (VariableNode "$arg")
* )
* )
* )
* )
* )
*
* which should return the argument, without touching the quotation.
*/
void PutLinkUTest::test_quoted_exec()
{
logger().info("BEGIN TEST: %s", __FUNCTION__);
std::string rs = _eval->eval("(load-from-path \"tests/atoms/scope/put-quoted.scm\")");
logger().debug() << "rs = " << rs;
Handle put = _eval->eval_h("put-quoted-exec"),
result = _asp->add_atom(HandleCast(put->execute(_asp.get()))),
expected = _eval->eval_h("quoted-exec");
logger().debug() << "result = " << oc_to_string(result);
logger().debug() << "expected = " << oc_to_string(expected);
TS_ASSERT_EQUALS(result, expected);
logger().info("END TEST: %s", __FUNCTION__);
}
/**
* Test
*
* (PutLink
* (LambdaLink
* (VariableNode "$X")
* )
* (LambdaLink
* (VariableList
* (VariableNode "$gpn")
* (VariableNode "$arg")
* )
* (QuoteLink
* (EvaluationLink
* (UnquoteLink
* (VariableNode "$gpn")
* )
* (UnquoteLink
* (VariableNode "$arg")
* )
* )
* )
* )
* )
*
* which should return the argument, without touching the quotation.
*/
void PutLinkUTest::test_quoted_eval()
{
logger().info("BEGIN TEST: %s", __FUNCTION__);
std::string rs = _eval->eval("(load-from-path \"tests/atoms/scope/put-quoted.scm\")");
logger().debug() << "rs = " << rs;
Handle put = _eval->eval_h("put-quoted-eval"),
result = _asp->add_atom(HandleCast(put->execute(_asp.get()))),
expected = _eval->eval_h("quoted-eval");
logger().debug() << "result = " << oc_to_string(result);
logger().debug() << "expected = " << oc_to_string(expected);
TS_ASSERT_EQUALS(result, expected);
logger().info("END TEST: %s", __FUNCTION__);
}
/**
* Test
*
* (Put
* (VariableList
* (Variable "$vardecl")
* (Variable "$clause-1")
* (Variable "$clause-2"))
* (Quote
* (Lambda
* (Unquote (Variable "$vardecl"))
* (And
* (Unquote (Variable "$clause-1"))
* (Unquote (Variable "$clause-2")))))
* (List
* (VariableList (Variable "$X") (Variable "$Y"))
* (Inheritance (Concept "A") (Variable "$X"))
* (Inheritance (Concept "$X") (Variable "$Y"))))
*
* which should return
*
* (LambdaLink
* (VariableList
* (VariableNode "$X")
* (VariableNode "$Y")
* )
* (AndLink
* (InheritanceLink
* (ConceptNode "$X")
* (VariableNode "$Y")
* )
* (InheritanceLink
* (ConceptNode "A")
* (VariableNode "$X")
* )
* )
* )
*
* That is the quotation should be entirely consumed as the lambda
* link is fully constructed at the end of the substitution.
*/
void PutLinkUTest::test_quoted_lambda()
{
logger().info("BEGIN TEST: %s", __FUNCTION__);
std::string rs = _eval->eval("(load-from-path \"tests/atoms/scope/put-quoted-lambda.scm\")");
logger().debug() << "rs = " << rs;
Handle put = _eval->eval_h("put-quoted-conjuction-lambda"),
result = _asp->add_atom(HandleCast(put->execute(_asp.get()))),
expected = _eval->eval_h("put-quoted-conjuction-lambda-result");
logger().debug() << "result = " << oc_to_string(result);
logger().debug() << "expected = " << oc_to_string(expected);
TS_ASSERT_EQUALS(result, expected);
logger().info("END TEST: %s", __FUNCTION__);
}
/**
*
* Test
*
* (Inheritance (Concept "B") (Concept "Parent"))
* (Inheritance (Concept "C") (Concept "Parent"))
*
* (PutLink
* (LambdaLink
* (VariableNode "x")
* (EvaluationLink
* (PredicateNode "relation")
* (ListLink
* (VariableNode "x")
* (VariableNode "A"))))
* (MeetLink
* (Inheritance (Variable "$X") (Concept "Parent"))))
*
* which should return
*
* (SetLink
* (EvaluationLink
* (PredicateNode "relation")
* (ListLink
* (ConceptNode "B")
* (VariableNode "A")))
* (EvaluationLink
* (PredicateNode "relation")
* (ListLink
* (ConceptNode "C")
* (VariableNode "A"))))
*/
void PutLinkUTest::test_get()
{
logger().info("BEGIN TEST: %s", __FUNCTION__);
std::string rs = _eval->eval("(load-from-path \"tests/atoms/scope/put-get.scm\")");
logger().debug() << "rs = " << rs;
Handle put = _eval->eval_h("put-get"),
result = _asp->add_atom(HandleCast(put->execute(_asp.get()))),
expected = _eval->eval_h("expected-put-get");
logger().debug() << "result = " << oc_to_string(result);
logger().debug() << "expected = " << oc_to_string(expected);
TS_ASSERT_EQUALS(result, expected);
logger().info("END TEST: %s", __FUNCTION__);
}
/**
*
* Test
*
* (Inheritance (Concept "B") (Concept "Parent"))
* (Inheritance (Concept "C") (Concept "Parent"))
*
* (PutLink
* (LambdaLink
* (VariableNode "x")
* (EvaluationLink
* (PredicateNode "relation")
* (ListLink
* (VariableNode "x")
* (VariableNode "A"))))
* (MeetLink
* (Inheritance (Variable "$X") (Concept "Parent"))))
*
* which should return
*
* (SetLink
* (EvaluationLink
* (PredicateNode "relation")
* (ListLink
* (ConceptNode "B")
* (VariableNode "A")))
* (EvaluationLink
* (PredicateNode "relation")
* (ListLink
* (ConceptNode "C")
* (VariableNode "A"))))
*/
void PutLinkUTest::test_get_lambda()
{
logger().info("BEGIN TEST: %s", __FUNCTION__);
std::string rs = _eval->eval("(load-from-path \"tests/atoms/scope/put-get-lambda.scm\")");
logger().debug() << "rs = " << rs;
Handle put = _eval->eval_h("put-get-lambda"),
result = _asp->add_atom(HandleCast(put->execute(_asp.get()))),
expected = _eval->eval_h("expected-put-get-lambda");
logger().debug() << "result = " << oc_to_string(result);
logger().debug() << "expected = " << oc_to_string(expected);
TS_ASSERT_EQUALS(result, expected);
logger().info("END TEST: %s", __FUNCTION__);
}
/*
* Like above, but with multiple arguments
*/
void PutLinkUTest::test_get_multi()
{
logger().info("BEGIN TEST: %s", __FUNCTION__);
std::string rs = _eval->eval("(load-from-path \"tests/atoms/scope/put-get-multi.scm\")");
logger().debug() << "rs = " << rs;
Handle result = _eval->eval_h("(cog-execute! put-get-multi)");
Handle expected =
L(EDGE_LINK,
N(PREDICATE_NODE, "relatives"),
L(LIST_LINK,
N(CONCEPT_NODE, "Jim"),
N(CONCEPT_NODE, "Jane"),
N(CONCEPT_NODE, "mom and pop")));
logger().debug() << "result = " << oc_to_string(result);
logger().debug() << "expected = " << oc_to_string(expected);
TS_ASSERT_EQUALS(result, expected);
TS_ASSERT_THROWS_ANYTHING(
_eval->eval_h("(cog-execute! put-get-multi-empty)"));
logger().info("END TEST: %s", __FUNCTION__);
}
/*
* Like above, but with pre-existing sets
*/
void PutLinkUTest::test_multi_set()
{
logger().info("BEGIN TEST: %s", __FUNCTION__);
std::string rs = _eval->eval("(load-from-path \"tests/atoms/scope/put-multi-set.scm\")");
logger().debug() << "rs = " << rs;
Handle result = _eval->eval_h("(cog-execute! put-multi-set)");
Handle expected =
L(EDGE_LINK,
N(PREDICATE_NODE, "relatives"),
L(LIST_LINK,
N(CONCEPT_NODE, "Jim"),
N(CONCEPT_NODE, "Jane"),
N(CONCEPT_NODE, "mom and pop")));
logger().debug() << "result = " << oc_to_string(result);
logger().debug() << "expected = " << oc_to_string(expected);
TS_ASSERT_EQUALS(result, expected);
logger().info("END TEST: %s", __FUNCTION__);
}
/**
* Test quoted put link, where vardecl, body and arguments are
* unquoted variables. Make just sure that it doesn't crash or throw
* exception.
*/
void PutLinkUTest::test_full_quotation()
{
logger().info("BEGIN TEST: %s", __FUNCTION__);
Handle unquoted_vardecl = L(UNQUOTE_LINK, N(VARIABLE_NODE, "$vardecl"));
Handle unquoted_body = L(UNQUOTE_LINK, N(VARIABLE_NODE, "$body"));
Handle unquoted_args = L(UNQUOTE_LINK, N(VARIABLE_NODE, "$args"));
TS_ASSERT_THROWS_NOTHING(L(QUOTE_LINK,
L(PUT_LINK,
unquoted_vardecl,
unquoted_body,
unquoted_args)));
logger().info("END TEST: %s", __FUNCTION__);
}