/*
* tests/atoms/scope/VariablesUTest.cxxtest
*
* Copyright (C) 2016 OpenCog Foundation
* All Rights Reserved
* Author: Nil Geisweiller
*
* 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/atoms/scope/Variables.h>
#include <opencog/atoms/scope/VariableList.h>
#include <opencog/atomspace/AtomSpace.h>
#include <cxxtest/TestSuite.h>
using namespace opencog;
#define al _as.add_link
#define an _as.add_node
class VariablesUTest : public CxxTest::TestSuite
{
private:
Handle A, B, N, DPN, W, X, Y, Z, G1, G2, NT, PNT, CNT, NTI, DPTCI, LLT, LTI;
AtomSpace _as;
public:
VariablesUTest()
{
logger().set_level(Logger::DEBUG);
logger().set_timestamp_flag(false);
logger().set_print_to_stdout_flag(true);
A = an(CONCEPT_NODE, "A");
B = an(CONCEPT_NODE, "B");
N = an(NODE, "N");
DPN = an(DEFINED_PREDICATE_NODE, "DPN");
X = an(VARIABLE_NODE, "$X");
Y = an(VARIABLE_NODE, "$Y");
Z = an(VARIABLE_NODE, "$Z");
W = an(VARIABLE_NODE, "$W");
G1 = an(GLOB_NODE, "$G1");
G2 = an(GLOB_NODE, "$G2");
NT = an(TYPE_NODE, "Node");
PNT = an(TYPE_NODE, "PredicateNode");
CNT = an(TYPE_NODE, "ConceptNode");
NTI = an(TYPE_INH_NODE, "Node");
DPTCI = an(TYPE_CO_INH_NODE, "DefinedPredicateNode");
LLT = an(TYPE_NODE, "ListLink");
LTI = an(TYPE_INH_NODE, "Link");
}
void test_extend_intersect_1();
void test_extend_intersect_2();
void test_extend_intersect_3();
void test_extend_intersect_4();
void test_extend_intersect_5();
void test_extend_intersect_6();
void test_find_variables_ordered_1();
void test_find_variables_ordered_2();
void test_find_variables_ordered_3();
void test_find_variables_ordered_4();
void test_find_variables_unordered_1();
void test_find_variables_unordered_2();
void test_find_variables_unordered_3();
void test_find_variables_unordered_4();
void test_find_variables_unordered_5();
void test_find_variables_mixed_1();
void test_find_variables_mixed_2();
void test_find_variables_mixed_3();
void test_find_variables_mixed_4();
void test_find_variables_mixed_5();
void test_find_variables_mixed_6();
void test_find_variables_mixed_7();
void test_find_variables_mixed_8();
void test_find_variables_mixed_9();
void test_find_variables_mixed_10();
void test_find_variables_mixed_11();
void test_find_variables_alt_as();
void test_is_type_1();
void test_is_type_2();
void test_is_type_3();
void test_is_type_4();
void test_is_type_5();
void test_is_type_6();
void test_substitute_nocheck_scope();
};
void VariablesUTest::test_extend_intersect_1()
{
logger().info("BEGIN TEST: %s", __FUNCTION__);
Handle
vardecl1 = X,
vardecl2 = al(VARIABLE_LIST,
al(TYPED_VARIABLE_LINK, X, PNT),
al(TYPED_VARIABLE_LINK, Y, CNT)),
expect = al(VARIABLE_LIST,
al(TYPED_VARIABLE_LINK, X, PNT),
al(TYPED_VARIABLE_LINK, Y, CNT));
Variables v1(vardecl1), v2(vardecl2);
v1.extend_intersect(v2);
Handle result = _as.add_atom(v1.get_vardecl());
logger().debug() << "expect = " << oc_to_string(expect);
logger().debug() << "result = " << oc_to_string(result);
TS_ASSERT_EQUALS(result, expect);
logger().info("END TEST: %s", __FUNCTION__);
}
void VariablesUTest::test_extend_intersect_2()
{
logger().info("BEGIN TEST: %s", __FUNCTION__);
Handle
vardecl1 = al(VARIABLE_LIST,
al(TYPED_VARIABLE_LINK, X, NT),
al(TYPED_VARIABLE_LINK, Y, CNT)),
vardecl2 = al(VARIABLE_LIST,
al(TYPED_VARIABLE_LINK, X, PNT),
al(TYPED_VARIABLE_LINK, Y, al(TYPE_CHOICE, PNT, CNT))),
expect = al(VARIABLE_LIST,
al(TYPED_VARIABLE_LINK, X, al(TYPE_CHOICE)),
al(TYPED_VARIABLE_LINK, Y, CNT));
Variables v1(vardecl1), v2(vardecl2);
v1.extend_intersect(v2);
Handle result = _as.add_atom(v1.get_vardecl());
logger().debug() << "expect = " << oc_to_string(expect);
logger().debug() << "result = " << oc_to_string(result);
TS_ASSERT_EQUALS(result, expect);
logger().info("END TEST: %s", __FUNCTION__);
}
void VariablesUTest::test_extend_intersect_3()
{
logger().info("BEGIN TEST: %s", __FUNCTION__);
Handle
vardecl1 = al(VARIABLE_LIST,
al(TYPED_VARIABLE_LINK, X, PNT),
al(TYPED_VARIABLE_LINK, Y, CNT)),
vardecl2 = al(VARIABLE_LIST,
al(TYPED_VARIABLE_LINK, X, NTI),
al(TYPED_VARIABLE_LINK, Y, al(TYPE_CHOICE, PNT, CNT))),
expect = al(VARIABLE_LIST,
al(TYPED_VARIABLE_LINK, X, PNT),
al(TYPED_VARIABLE_LINK, Y, CNT));
Variables v1(vardecl1), v2(vardecl2);
v1.extend_intersect(v2);
Handle result = _as.add_atom(v1.get_vardecl());
logger().debug() << "expect = " << oc_to_string(expect);
logger().debug() << "result = " << oc_to_string(result);
TS_ASSERT_EQUALS(result, expect);
logger().info("END TEST: %s", __FUNCTION__);
}
void VariablesUTest::test_extend_intersect_4()
{
logger().info("BEGIN TEST: %s", __FUNCTION__);
Handle
vardecl1 = al(VARIABLE_LIST,
al(TYPED_VARIABLE_LINK, X, al(TYPE_CHOICE, LLT, NTI)),
al(TYPED_VARIABLE_LINK, Y, NT)),
vardecl2 = al(VARIABLE_LIST,
al(TYPED_VARIABLE_LINK, X, al(TYPE_CHOICE, LTI, CNT)),
al(TYPED_VARIABLE_LINK, Y, DPTCI)),
expect = al(VARIABLE_LIST,
al(TYPED_VARIABLE_LINK, X, al(TYPE_CHOICE, CNT, LLT)),
al(TYPED_VARIABLE_LINK, Y, NT));
Variables v1(vardecl1), v2(vardecl2);
v1.extend_intersect(v2);
Handle result = _as.add_atom(v1.get_vardecl());
logger().debug() << "expect = " << oc_to_string(expect);
logger().debug() << "result = " << oc_to_string(result);
TS_ASSERT_EQUALS(result, expect);
logger().info("END TEST: %s", __FUNCTION__);
}
void VariablesUTest::test_extend_intersect_5()
{
logger().info("BEGIN TEST: %s", __FUNCTION__);
Handle vardecl1 = al(VARIABLE_LIST,
al(TYPED_VARIABLE_LINK, G1,
al(TYPE_INTERSECTION_LINK,
al(INTERVAL_LINK,
an(NUMBER_NODE, "0"),
an(NUMBER_NODE, "2")),
NTI)),
al(TYPED_VARIABLE_LINK, G2,
al(TYPE_INTERSECTION_LINK,
al(INTERVAL_LINK,
an(NUMBER_NODE, "0"),
an(NUMBER_NODE, "2")),
PNT))),
vardecl2 = al(VARIABLE_LIST,
al(TYPED_VARIABLE_LINK, G1,
al(TYPE_INTERSECTION_LINK,
al(INTERVAL_LINK,
an(NUMBER_NODE, "1"),
an(NUMBER_NODE, "-1")),
PNT)),
al(TYPED_VARIABLE_LINK, G2,
al(TYPE_INTERSECTION_LINK,
al(INTERVAL_LINK,
an(NUMBER_NODE, "1"),
an(NUMBER_NODE, "3")),
PNT))),
expect = al(VARIABLE_LIST,
al(TYPED_VARIABLE_LINK, G1,
al(TYPE_INTERSECTION_LINK,
al(INTERVAL_LINK,
an(NUMBER_NODE, "1"),
an(NUMBER_NODE, "2")),
PNT)),
al(TYPED_VARIABLE_LINK, G2,
al(TYPE_INTERSECTION_LINK,
al(INTERVAL_LINK,
an(NUMBER_NODE, "1"),
an(NUMBER_NODE, "2")),
PNT)));
Variables v1(vardecl1), v2(vardecl2);
v1.extend_intersect(v2);
Handle result = _as.add_atom(v1.get_vardecl());
logger().debug() << "expect = " << oc_to_string(expect);
logger().debug() << "result = " << oc_to_string(result);
TS_ASSERT_EQUALS(result, expect);
logger().info("END TEST: %s", __FUNCTION__);
}
void VariablesUTest::test_extend_intersect_6()
{
logger().info("BEGIN TEST: %s", __FUNCTION__);
Handle vardecl1 = al(VARIABLE_LIST,
al(TYPED_VARIABLE_LINK, X, NTI),
al(TYPED_VARIABLE_LINK, G2, PNT)),
vardecl2 = al(VARIABLE_LIST,
al(TYPED_VARIABLE_LINK, X, PNT),
al(TYPED_VARIABLE_LINK, G2, PNT)),
expect = al(VARIABLE_LIST,
al(TYPED_VARIABLE_LINK, X, PNT),
al(TYPED_VARIABLE_LINK, G2, PNT));
Variables v1(vardecl1), v2(vardecl2);
v1.extend_intersect(v2);
Handle result = _as.add_atom(v1.get_vardecl());
logger().debug() << "expect = " << oc_to_string(expect);
logger().debug() << "result = " << oc_to_string(result);
TS_ASSERT_EQUALS(result, expect);
logger().info("END TEST: %s", __FUNCTION__);
}
void VariablesUTest::test_find_variables_ordered_1()
{
logger().info("BEGIN TEST: %s", __FUNCTION__);
// Inferred vardecl should be in infix order since all links are
// ordered, that is [X, Y].
Handle body = al(INHERITANCE_LINK, X, Y);
Variables vars;
vars.find_variables(body);
HandleSeq varseq = vars.varseq;
HandleSeq expect{X, Y};
logger().debug() << "varseq = " << oc_to_string(varseq);
logger().debug() << "expect = " << oc_to_string(expect);
TS_ASSERT_EQUALS(varseq, expect);
logger().info("END TEST: %s", __FUNCTION__);
}
void VariablesUTest::test_find_variables_ordered_2()
{
logger().info("BEGIN TEST: %s", __FUNCTION__);
// Inferred vardecl should be in infix order since all links are
// ordered, that is [X, Y, Z, W].
Handle body = al(LIST_LINK,
al(INHERITANCE_LINK, X, Y),
al(INHERITANCE_LINK, Z, W));
Variables vars;
vars.find_variables(body);
HandleSeq varseq = vars.varseq;
HandleSeq expect{X, Y, Z, W};
logger().debug() << "varseq = " << oc_to_string(varseq);
logger().debug() << "expect = " << oc_to_string(expect);
TS_ASSERT_EQUALS(varseq, expect);
logger().info("END TEST: %s", __FUNCTION__);
}
void VariablesUTest::test_find_variables_ordered_3()
{
logger().info("BEGIN TEST: %s", __FUNCTION__);
// Inferred vardecl should be in infix order since all links are
// ordered, that is [X, Y], as it eliminate redundant variables.
Handle body = al(LIST_LINK,
al(INHERITANCE_LINK, X, Y),
al(INHERITANCE_LINK, Y, X));
Variables vars;
vars.find_variables(body);
HandleSeq varseq = vars.varseq;
HandleSeq expect{X, Y};
logger().debug() << "varseq = " << oc_to_string(varseq);
logger().debug() << "expect = " << oc_to_string(expect);
TS_ASSERT_EQUALS(varseq, expect);
logger().info("END TEST: %s", __FUNCTION__);
}
void VariablesUTest::test_find_variables_ordered_4()
{
logger().info("BEGIN TEST: %s", __FUNCTION__);
// Simple ordered body with quoted and scoped variables (thus that
// should be ignored). Result should be [X, Y] as the first
// occurrence of Y is quoted, and other variables like Z and W are
// scoped.
Handle body = al(LIST_LINK,
al(QUOTE_LINK, Y),
al(INHERITANCE_LINK, X, Y),
al(SCOPE_LINK, al(INHERITANCE_LINK, Z, W)));
Variables vars;
vars.find_variables(body);
HandleSeq varseq = vars.varseq;
HandleSeq expect{X, Y};
logger().debug() << "varseq = " << oc_to_string(varseq);
logger().debug() << "expect = " << oc_to_string(expect);
TS_ASSERT_EQUALS(varseq, expect);
logger().info("END TEST: %s", __FUNCTION__);
}
void VariablesUTest::test_find_variables_unordered_1()
{
logger().info("BEGIN TEST: %s", __FUNCTION__);
// Inferred vardecl may not follow any particular order since the
// body structure imposes no asymmetry.
Handle body = al(AND_LINK, X, Y);
Variables vars;
vars.find_variables(body);
HandleSet result = vars.varset;
HandleSet expect{X, Y};
logger().debug() << "result = " << oc_to_string(result);
logger().debug() << "expect = " << oc_to_string(expect);
TS_ASSERT_EQUALS(result, expect);
logger().info("END TEST: %s", __FUNCTION__);
}
void VariablesUTest::test_find_variables_unordered_2()
{
logger().info("BEGIN TEST: %s", __FUNCTION__);
// Inferred vardecl can be one of the possibilities
//
// 1. sorted({X, Y}) + sorted({Z, W})
// 2. sorted({Z, W}) + sorted({X, Y})
//
// X, Y and Z, W can be interleaved because it is would not be
// semantically equivalent.
Handle body = al(AND_LINK,
al(OR_LINK, X, Y),
al(OR_LINK, Z, W));
Variables vars;
vars.find_variables(body);
HandleSeq varseq = vars.varseq;
HandleSet XY{X, Y}, ZW{Z, W};
HandleSeq expect1;
expect1.insert(expect1.end(), XY.begin(), XY.end());
expect1.insert(expect1.end(), ZW.begin(), ZW.end());
HandleSeq expect2;
expect2.insert(expect2.end(), ZW.begin(), ZW.end());
expect2.insert(expect2.end(), XY.begin(), XY.end());
logger().debug() << "varseq = " << oc_to_string(varseq);
logger().debug() << "expect1 = " << oc_to_string(expect1);
logger().debug() << "expect2 = " << oc_to_string(expect2);
TS_ASSERT(varseq == expect1 or varseq == expect2);
logger().info("END TEST: %s", __FUNCTION__);
}
void VariablesUTest::test_find_variables_unordered_3()
{
logger().info("BEGIN TEST: %s", __FUNCTION__);
// Inferred vardecl should have Z come last because it occurs more
// often than X and Y.
Handle body = al(SEQUENTIAL_AND_LINK,
al(OR_LINK, X, Y),
al(OR_LINK, Z, Z));
Variables vars;
vars.find_variables(body);
HandleSeq varseq = vars.varseq;
HandleSet XY = HandleSet{X, Y};
HandleSeq expect;
expect.insert(expect.end(), XY.begin(), XY.end());
expect.push_back(Z);
logger().debug() << "varseq = " << oc_to_string(varseq);
logger().debug() << "expect = " << oc_to_string(expect);
TS_ASSERT_EQUALS(varseq, expect);
logger().info("END TEST: %s", __FUNCTION__);
}
void VariablesUTest::test_find_variables_unordered_4()
{
logger().info("BEGIN TEST: %s", __FUNCTION__);
// Inferred vardecl should be sorted({X, Y}) + sorted({Z, W})
// because AndLink type is less than OrLink type.
Handle body = al(AND_LINK,
al(AND_LINK, X, Y),
al(OR_LINK, Z, W));
Variables vars;
vars.find_variables(body);
HandleSeq varseq = vars.varseq;
HandleSet XY = HandleSet{X, Y};
HandleSet ZW = HandleSet{Z, W};
HandleSeq expect;
expect.insert(expect.end(), XY.begin(), XY.end());
expect.insert(expect.end(), ZW.begin(), ZW.end());
logger().debug() << "varseq = " << oc_to_string(varseq);
logger().debug() << "expect = " << oc_to_string(expect);
TS_ASSERT_EQUALS(varseq, expect);
logger().info("END TEST: %s", __FUNCTION__);
}
void VariablesUTest::test_find_variables_unordered_5()
{
logger().info("BEGIN TEST: %s", __FUNCTION__);
// Inferred vardecl of body1 should be the reverse of inferred
// vardecl of body2.
Handle body1 = al(OR_LINK,
al(AND_LINK, X, A),
al(AND_LINK, Y, B));
Handle body2 = al(OR_LINK,
al(AND_LINK, Y, A),
al(AND_LINK, X, B));
Variables vars1;
Variables vars2;
vars1.find_variables(body1);
vars2.find_variables(body2);
HandleSeq varseq1 = vars1.varseq;
HandleSeq varseq2 = vars2.varseq;
logger().debug() << "varseq1 = " << oc_to_string(varseq1);
logger().debug() << "varseq2 = " << oc_to_string(varseq2);
// Reverse varseq2 to test it if it equal to varseq1
std::reverse(varseq2.begin(), varseq2.end());
TS_ASSERT_EQUALS(varseq1, varseq2);
logger().info("END TEST: %s", __FUNCTION__);
}
void VariablesUTest::test_find_variables_mixed_1()
{
logger().info("BEGIN TEST: %s", __FUNCTION__);
// Inferred vardecl may not follow any particular order since the
// body structure imposes no asymmetry.
Handle body = al(AND_LINK,
al(INHERITANCE_LINK, X, Y),
al(INHERITANCE_LINK, Y, X));
Variables vars;
vars.find_variables(body);
HandleSet result = vars.varset;
HandleSet expect{X, Y};
logger().debug() << "result = " << oc_to_string(result);
logger().debug() << "expect = " << oc_to_string(expect);
// Just make sure the vardecl has X and Y, regardless of the order
TS_ASSERT_EQUALS(result, expect);
logger().info("END TEST: %s", __FUNCTION__);
}
void VariablesUTest::test_find_variables_mixed_2()
{
logger().info("BEGIN TEST: %s", __FUNCTION__);
// Inferred vardecl should place X before Y because the
// ExtensionalSimilarityLink type is ordered before
// IntensionalSimilarityLink type.
Handle body = al(AND_LINK,
al(SUBSET_LINK, X, Y),
al(INHERITANCE_LINK, Y, X));
Variables vars;
vars.find_variables(body);
HandleSeq varseq = vars.varseq;
HandleSeq expect{X, Y};
logger().debug() << "varseq = " << oc_to_string(varseq);
logger().debug() << "expect = " << oc_to_string(expect);
TS_ASSERT_EQUALS(varseq, expect);
logger().info("END TEST: %s", __FUNCTION__);
}
void VariablesUTest::test_find_variables_mixed_3()
{
logger().info("BEGIN TEST: %s", __FUNCTION__);
// Make sure the variable declarations of body1 and body2 are
// the reverses of each other, that is if one is [X, Y], then
// the other is [Y, X].
Handle body1 = al(INHERITANCE_LINK, al(LIST_LINK, X, Y), Y);
Handle body2 = al(INHERITANCE_LINK, al(LIST_LINK, Y, X), X);
Variables vars1;
Variables vars2;
vars1.find_variables(body1);
vars2.find_variables(body2);
HandleSeq varseq1 = vars1.varseq;
HandleSeq varseq2 = vars2.varseq;
logger().debug() << "varseq1 = " << oc_to_string(varseq1);
logger().debug() << "varseq2 = " << oc_to_string(varseq2);
// Reverse varseq2 to test it if it equal to varseq1
std::reverse(varseq2.begin(), varseq2.end());
TS_ASSERT_EQUALS(varseq1, varseq2);
logger().info("END TEST: %s", __FUNCTION__);
}
void VariablesUTest::test_find_variables_mixed_4()
{
logger().info("BEGIN TEST: %s", __FUNCTION__);
// Inferred vardecl can be any combination where {X, Y} and {Z, W}
// do not interleave.
Handle body = al(AND_LINK,
al(INHERITANCE_LINK, X, Y),
al(INHERITANCE_LINK, Y, X),
al(INHERITANCE_LINK, Z, W),
al(INHERITANCE_LINK, W, Z));
Variables vars;
vars.find_variables(body);
HandleSeq result = vars.varseq;
HandleSeq expect1{X, Y, Z, W};
HandleSeq expect2{Y, X, Z, W};
HandleSeq expect3{X, Y, W, Z};
HandleSeq expect4{Y, X, W, Z};
HandleSeq expect5{Z, W, X, Y};
HandleSeq expect6{Z, W, Y, X};
HandleSeq expect7{W, Z, X, Y};
HandleSeq expect8{W, Z, Y, X};
logger().debug() << "result = " << oc_to_string(result);
logger().debug() << "expect1 = " << oc_to_string(expect1);
logger().debug() << "expect2 = " << oc_to_string(expect2);
logger().debug() << "expect3 = " << oc_to_string(expect3);
logger().debug() << "expect4 = " << oc_to_string(expect4);
logger().debug() << "expect5 = " << oc_to_string(expect5);
logger().debug() << "expect6 = " << oc_to_string(expect6);
logger().debug() << "expect7 = " << oc_to_string(expect7);
logger().debug() << "expect8 = " << oc_to_string(expect8);
TS_ASSERT(result == expect1 or
result == expect2 or
result == expect3 or
result == expect4 or
result == expect5 or
result == expect6 or
result == expect7 or
result == expect8);
logger().info("END TEST: %s", __FUNCTION__);
}
void VariablesUTest::test_find_variables_mixed_5()
{
logger().info("BEGIN TEST: %s", __FUNCTION__);
// Like test_find_variables_mixed_1 but incorporates non variable
// nodes to cover some, otherwise non covered, code.
Handle body = al(AND_LINK,
al(INHERITANCE_LINK, X, Y),
al(INHERITANCE_LINK, Y, X),
al(INHERITANCE_LINK, A, B));
Variables vars;
vars.find_variables(body);
HandleSet result = vars.varset;
HandleSet expect{X, Y};
logger().debug() << "result = " << oc_to_string(result);
logger().debug() << "expect = " << oc_to_string(expect);
// Just make sure the vardecl has X and Y, regardless of the order
TS_ASSERT_EQUALS(result, expect);
logger().info("END TEST: %s", __FUNCTION__);
}
void VariablesUTest::test_find_variables_mixed_6()
{
logger().info("BEGIN TEST: %s", __FUNCTION__);
// Make sure the variable declarations of body1 and body2 are
// the reverses of each other, that is if one is [X, Y], then
// the other is [Y, X].
Handle body1 = al(LIST_LINK,
al(SET_LINK, X, Y),
al(LIST_LINK, X, Y));
Handle body2 = al(LIST_LINK,
al(SET_LINK, Y, X),
al(LIST_LINK, Y, X));
Variables vars1;
Variables vars2;
vars1.find_variables(body1);
vars2.find_variables(body2);
HandleSeq varseq1 = vars1.varseq;
HandleSeq varseq2 = vars2.varseq;
logger().debug() << "varseq1 = " << oc_to_string(varseq1);
logger().debug() << "varseq2 = " << oc_to_string(varseq2);
// Reverse varseq2 to test it if it equal to varseq1
std::reverse(varseq2.begin(), varseq2.end());
TS_ASSERT_EQUALS(varseq1, varseq2);
logger().info("END TEST: %s", __FUNCTION__);
}
void VariablesUTest::test_find_variables_mixed_7()
{
logger().info("BEGIN TEST: %s", __FUNCTION__);
// Make sure the variable declarations of body1 and body2 are
// the reverses of each other, that is if one is [X, Y], then
// the other is [Y, X].
Handle body1 = al(SET_LINK,
al(SET_LINK, X, Y),
al(LIST_LINK, X, Y));
Handle body2 = al(SET_LINK,
al(SET_LINK, Y, X),
al(LIST_LINK, Y, X));
Variables vars1;
Variables vars2;
vars1.find_variables(body1);
vars2.find_variables(body2);
HandleSeq varseq1 = vars1.varseq;
HandleSeq varseq2 = vars2.varseq;
logger().debug() << "varseq1 = " << oc_to_string(varseq1);
logger().debug() << "varseq2 = " << oc_to_string(varseq2);
// Reverse varseq2 to test it if it equal to varseq1
std::reverse(varseq2.begin(), varseq2.end());
TS_ASSERT_EQUALS(varseq1, varseq2);
logger().info("END TEST: %s", __FUNCTION__);
}
void VariablesUTest::test_find_variables_mixed_8()
{
logger().info("BEGIN TEST: %s", __FUNCTION__);
// The order should be XYZ, because Z appears after X in the
// ordered link XZY, which makes XYZ before ordered before ZYX in
// the SetLink.
Handle XYZ = al(LIST_LINK, X, Y, Z);
Handle ZYX = al(LIST_LINK, Z, Y, X);
Handle XZY = al(LIST_LINK, X, Z, Y);
Handle body = al(LIST_LINK, al(SET_LINK, XYZ, ZYX), XZY);
Variables vars;
vars.find_variables(body);
HandleSeq result = vars.varseq;
HandleSeq expect{X, Y, Z};
logger().debug() << "result = " << oc_to_string(result);
logger().debug() << "expect = " << oc_to_string(expect);
TS_ASSERT_EQUALS(result, expect);
logger().info("END TEST: %s", __FUNCTION__);
}
void VariablesUTest::test_find_variables_mixed_9()
{
logger().info("BEGIN TEST: %s", __FUNCTION__);
// The vardecl order of body1 should be the reverse of the vardecl
// order of body2.
Handle body1 = al(LIST_LINK,
al(SET_LINK, X, Y),
al(SET_LINK, X, al(LIST_LINK, Y)));
Handle body2 = al(LIST_LINK,
al(SET_LINK, Y, X),
al(SET_LINK, Y, al(LIST_LINK, X)));
Variables vars1;
Variables vars2;
vars1.find_variables(body1);
vars2.find_variables(body2);
HandleSeq varseq1 = vars1.varseq;
HandleSeq varseq2 = vars2.varseq;
logger().debug() << "varseq1 = " << oc_to_string(varseq1);
logger().debug() << "varseq2 = " << oc_to_string(varseq2);
// Reverse varseq2 to test it if it equal to varseq1
std::reverse(varseq2.begin(), varseq2.end());
TS_ASSERT_EQUALS(varseq1, varseq2);
logger().info("END TEST: %s", __FUNCTION__);
}
void VariablesUTest::test_find_variables_mixed_10()
{
logger().info("BEGIN TEST: %s", __FUNCTION__);
// The vardecl should be empty because no variable are free.
Handle body = al(LAMBDA_LINK,
al(VARIABLE_LIST, X, Y),
al(LOCAL_QUOTE_LINK,
al(AND_LINK, X, Y)));
Variables vars;
vars.find_variables(body);
HandleSeq varseq = vars.varseq;
logger().debug() << "varseq = " << oc_to_string(varseq);
TS_ASSERT_EQUALS(varseq, HandleSeq());
logger().info("END TEST: %s", __FUNCTION__);
}
void VariablesUTest::test_find_variables_mixed_11()
{
logger().info("BEGIN TEST: %s", __FUNCTION__);
// Inferred vardecl of body1 should be the reverse of vardecl of
// body2 because swapping names makes them equivalent.
Handle body1 = al(PRESENT_LINK,
al(INHERITANCE_LINK, X, A),
al(INHERITANCE_LINK, Y, B));
Handle body2 = al(PRESENT_LINK,
al(INHERITANCE_LINK, Y, A),
al(INHERITANCE_LINK, X, B));
Variables vars1;
Variables vars2;
vars1.find_variables(body1);
vars2.find_variables(body2);
HandleSeq varseq1 = vars1.varseq;
HandleSeq varseq2 = vars2.varseq;
logger().debug() << "varseq1 = " << oc_to_string(varseq1);
logger().debug() << "varseq2 = " << oc_to_string(varseq2);
// Reverse varseq2 to test it if it equal to varseq1
std::reverse(varseq2.begin(), varseq2.end());
TS_ASSERT_EQUALS(varseq1, varseq2);
logger().info("END TEST: %s", __FUNCTION__);
}
void VariablesUTest::test_find_variables_alt_as()
{
logger().info("BEGIN TEST: %s", __FUNCTION__);
// Make sure that variables coming from another atomspace are
// treated equally. That is body should have variables X, Y, Z,
// without duplicates.
AtomSpace _alt_as;
Handle altX = _alt_as.add_node(VARIABLE_NODE, "$X");
Handle body = al(LIST_LINK,
al(INHERITANCE_LINK, X, Y),
al(INHERITANCE_LINK, Z, altX));
Variables vars;
vars.find_variables(body);
HandleSeq varseq = vars.varseq;
HandleSeq expect{X, Y, Z};
logger().debug() << "varseq = " << oc_to_string(varseq);
logger().debug() << "expect = " << oc_to_string(expect);
TS_ASSERT_EQUALS(varseq, expect);
logger().info("END TEST: %s", __FUNCTION__);
}
void VariablesUTest::test_is_type_1()
{
logger().info("BEGIN TEST: %s", __FUNCTION__);
Handle vardecl = al(VARIABLE_LIST,
al(TYPED_VARIABLE_LINK, X, PNT),
al(TYPED_VARIABLE_LINK, Y, CNT));
Variables v1(vardecl);
bool is_x = v1.is_type(X, A);
bool is_y = v1.is_type(Y, A);
TS_ASSERT(not is_x);
TS_ASSERT(is_y);
logger().info("END TEST: %s", __FUNCTION__);
}
void VariablesUTest::test_is_type_2()
{
logger().info("BEGIN TEST: %s", __FUNCTION__);
Handle vardecl = al(VARIABLE_LIST,
al(TYPED_VARIABLE_LINK, G1,
al(TYPE_INTERSECTION_LINK,
al(INTERVAL_LINK,
an(NUMBER_NODE, "0"),
an(NUMBER_NODE, "1")),
CNT)),
al(TYPED_VARIABLE_LINK, G2,
al(TYPE_INTERSECTION_LINK,
al(INTERVAL_LINK,
an(NUMBER_NODE, "0"),
an(NUMBER_NODE, "2")),
CNT)));
Variables v1(vardecl);
bool is_x = v1.is_type(G1, al(LIST_LINK, A, B));
bool is_y = v1.is_type(G2, al(LIST_LINK, A, B));
TS_ASSERT(not is_x);
TS_ASSERT(is_y);
logger().info("END TEST: %s", __FUNCTION__);
}
void VariablesUTest::test_is_type_3()
{
logger().info("BEGIN TEST: %s", __FUNCTION__);
Handle vardecl = al(VARIABLE_LIST,
al(TYPED_VARIABLE_LINK, G1, CNT),
al(TYPED_VARIABLE_LINK, G2,
al(TYPE_INTERSECTION_LINK,
al(INTERVAL_LINK,
an(NUMBER_NODE, "0"),
an(NUMBER_NODE, "2")),
PNT)));
Variables v1(vardecl);
bool is_x = v1.is_type(G1, al(LIST_LINK, A, B));
bool is_y = v1.is_type(G2, al(LIST_LINK, A, B));
TS_ASSERT(is_x);
TS_ASSERT(not is_y);
logger().info("END TEST: %s", __FUNCTION__);
}
void VariablesUTest::test_is_type_4()
{
logger().info("BEGIN TEST: %s", __FUNCTION__);
Handle vardecl = al(VARIABLE_LIST,
al(TYPED_VARIABLE_LINK, G1,
al(TYPE_INTERSECTION_LINK,
al(INTERVAL_LINK,
an(NUMBER_NODE, "1"),
an(NUMBER_NODE, "1")),
CNT)),
al(TYPED_VARIABLE_LINK, G2,
al(TYPE_INTERSECTION_LINK,
al(INTERVAL_LINK,
an(NUMBER_NODE, "1"),
an(NUMBER_NODE, "1")),
CNT)));
Variables v1(vardecl);
bool is_x = v1.is_type(G1, al(LIST_LINK, A));
bool is_y = v1.is_type(G2, A);
TS_ASSERT(is_x);
TS_ASSERT(is_y);
logger().info("END TEST: %s", __FUNCTION__);
}
void VariablesUTest::test_is_type_5()
{
logger().info("BEGIN TEST: %s", __FUNCTION__);
Handle vardecl = al(VARIABLE_LIST,
al(TYPED_VARIABLE_LINK, X, NTI),
al(TYPED_VARIABLE_LINK, Y, DPTCI));
Variables v1(vardecl);
bool is_x_n = v1.is_type(X, N);
bool is_x_cn = v1.is_type(X, A);
bool is_y_dpn = v1.is_type(Y, DPN);
bool is_y_n = v1.is_type(Y, N);
TS_ASSERT( is_x_n);
TS_ASSERT( is_x_cn);
TS_ASSERT(is_y_dpn);
TS_ASSERT(is_y_n);
logger().info("END TEST: %s", __FUNCTION__);
}
void VariablesUTest::test_is_type_6()
{
logger().info("BEGIN TEST: %s", __FUNCTION__);
Handle vardecl = al(VARIABLE_LIST,
al(TYPED_VARIABLE_LINK, G1,
al(TYPE_INTERSECTION_LINK,
al(INTERVAL_LINK,
an(NUMBER_NODE, "1"),
an(NUMBER_NODE, "1")),
NTI)),
al(TYPED_VARIABLE_LINK, G2,
al(TYPE_INTERSECTION_LINK,
al(INTERVAL_LINK,
an(NUMBER_NODE, "1"),
an(NUMBER_NODE, "1")),
DPTCI)));
Variables v1(vardecl);
bool is_g1_n = v1.is_type(G1, al(LIST_LINK, N));
bool is_g1_cn = v1.is_type(G1, al(LIST_LINK, A));
bool is_g2_dpn = v1.is_type(G2, al(LIST_LINK, DPN));
bool is_g2_n = v1.is_type(G2, al(LIST_LINK, N));
TS_ASSERT(is_g1_n);
TS_ASSERT(is_g1_cn);
TS_ASSERT(is_g2_dpn);
TS_ASSERT(is_g2_n);
logger().info("END TEST: %s", __FUNCTION__);
}
void VariablesUTest::test_substitute_nocheck_scope()
{
logger().info("BEGIN TEST: %s", __FUNCTION__);
// Body with only one variable declared X, thus Y can be
// substituted but not X.
Handle body = al(SATISFACTION_LINK,
X,
al(PRESENT_LINK, al(INHERITANCE_LINK, X, Y)));
// Replace Y by X, thus X in the satisfaction link above should be
// renamed to avoid name collision.
HandleMap var2val{{Y, X}};
Handle result = Variables(Y).substitute_nocheck(body, var2val);
Handle expect = al(SATISFACTION_LINK,
Z,
al(PRESENT_LINK, al(INHERITANCE_LINK, Z, X)));
logger().debug() << "expect = " << oc_to_string(expect);
logger().debug() << "result = " << oc_to_string(result);
TS_ASSERT(content_eq(result, expect));
logger().info("END TEST: %s", __FUNCTION__);
}