/*
* tests/query/BiggerPatternUTest.cxxtest
*
* Copyright (C) 2009,2011 Linas Vepstas <linasvepstas@gmail.com>
* 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/atomspace/AtomSpace.h>
#include <opencog/util/Logger.h>
#include "imply.h"
#include "test-types.h"
using namespace opencog;
class BiggerPatternUTest : public CxxTest::TestSuite
{
private:
AtomSpacePtr as;
Handle clauses, implicand;
Handle hbenode, hvar0, hvar1, hvar2, hvar2_france;
Handle hword0, hprep, hphrase;
public:
BiggerPatternUTest(void)
{
logger().set_level(Logger::DEBUG);
logger().set_print_to_stdout_flag(true);
#include "test-types.cc"
}
~BiggerPatternUTest()
{
// 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 do_tst_prep(void);
void test_prep_rw(void);
void test_prep_overlay(void);
};
#define an as->add_node
#define al as->add_link
#define getarity(hand) hand->get_arity()
#define getlink(hand,pos) hand->getOutgoingAtom(pos)
#define prtnode(str,hand) \
printf("%s %s\n", str, hand->get_name().c_str());
/*
* This function sets up both the implication link, and the
* input data, for a typical, real-world preposition deduction.
*
* The supplied data is:
* _subj (<<be>>, <<capital>>)
* _obj (<<be>>, <<Berlin>>)
* of (<<capital>>, <<Germany>>)
* of (<<capital>>, <<France>>)
* Note that, for this test case, we've made Berlin the capital of both
* Germany and France. This sounds crazy, but that's what we want this
* test case to do.
*
* The actual rule encoded below is
*
* # IF _subj($cop,$var0) ; subject is now $var0
* ^ _obj($cop,$var1) ; object is $var1
* ^ %LemmaLink($cop,be) ; copula verb must be 'be'
* ^ $prep($var0,$var2) ; preposition
* ^ %LemmaLink($var0,$word0) ; word of word instance.
* ^ $phrase($word0, $prep) ; convert to phrase
* THEN ^3_$phrase($var2, $var1)
*
* Note that there is an implicit LemmaLink created for 'be'.
*/
void BiggerPatternUTest::tearDown(void)
{
}
void BiggerPatternUTest::setUp(void)
{
as = createAtomSpace();
// Create an implication link that will be tested.
clauses =
al(AND_LINK,
// _subj(be,$var0)
al(EVALUATION_LINK,
an(DEFINED_LINGUISTIC_RELATIONSHIP_NODE, "_subj"),
al(LIST_LINK,
an(VARIABLE_NODE, "$benode"),
an(VARIABLE_NODE, "$var0")
)
),
// _obj(be,$var1)
al(EVALUATION_LINK,
an(DEFINED_LINGUISTIC_RELATIONSHIP_NODE, "_obj"),
al(LIST_LINK,
an(VARIABLE_NODE, "$benode"),
an(VARIABLE_NODE, "$var1")
)
),
al(LEMMA_LINK,
an(VARIABLE_NODE, "$benode"),
an(WORD_NODE, "be")
),
// $prep($var0,$var2)
al(EVALUATION_LINK,
an(VARIABLE_NODE, "$prep"),
al(LIST_LINK,
an(VARIABLE_NODE, "$var0"),
an(VARIABLE_NODE, "$var2")
)
),
al(LEMMA_LINK,
an(VARIABLE_NODE, "$var0"),
an(VARIABLE_NODE, "$word0")
),
// $phrase($word0, $prep)
al(EVALUATION_LINK,
an(VARIABLE_NODE, "$phrase"),
al(LIST_LINK,
an(VARIABLE_NODE, "$word0"),
an(VARIABLE_NODE, "$prep")
)
)
);
implicand =
al(LIST_LINK,
an(VARIABLE_NODE, "$benode"),
an(VARIABLE_NODE, "$var0"),
an(VARIABLE_NODE, "$word0"),
an(VARIABLE_NODE, "$var1"),
an(VARIABLE_NODE, "$var2"),
an(VARIABLE_NODE, "$prep"),
an(VARIABLE_NODE, "$phrase")
);
// Create data on which the above pattern should match
al(LEMMA_LINK,
an(WORD_INSTANCE_NODE, "capital@14601ec7-4b6a-4739-b2d6-0213d43be682"),
hword0 = an(WORD_NODE, "capital")
);
al(LEMMA_LINK,
hbenode = an(WORD_INSTANCE_NODE, "is@a085b454-0d49-414c-b1d1-98d8c5e2cffb"),
an(WORD_NODE, "be")
);
// of (<<capital>>, <<Germany>>)
al(EVALUATION_LINK,
hprep = an(DEFINED_LINGUISTIC_RELATIONSHIP_NODE, "of"),
al(LIST_LINK,
an(WORD_INSTANCE_NODE, "capital@14601ec7-4b6a-4739-b2d6-0213d43be682"),
hvar2 = an(WORD_INSTANCE_NODE, "Germany@372c7cd3-a9c9-44bb-bc7b-5bb356dda358")
)
);
// of (<<capital>>, <<France>>)
al(EVALUATION_LINK,
hprep = an(DEFINED_LINGUISTIC_RELATIONSHIP_NODE, "of"),
al(LIST_LINK,
an(WORD_INSTANCE_NODE, "capital@14601ec7-4b6a-4739-b2d6-0213d43be682"),
hvar2_france = an(WORD_INSTANCE_NODE, "France@11223344-a9c9-44bb-bc7b-5bb356dda358")
)
);
// ; _subj (<<be>>, <<capital>>)
al(EVALUATION_LINK,
an(DEFINED_LINGUISTIC_RELATIONSHIP_NODE, "_subj"),
al(LIST_LINK,
an(WORD_INSTANCE_NODE, "is@a085b454-0d49-414c-b1d1-98d8c5e2cffb"),
hvar0 = an(WORD_INSTANCE_NODE, "capital@14601ec7-4b6a-4739-b2d6-0213d43be682")
)
);
// _obj (<<be>>, <<Berlin>>)
al(EVALUATION_LINK,
an(DEFINED_LINGUISTIC_RELATIONSHIP_NODE, "_obj"),
al(LIST_LINK,
an(WORD_INSTANCE_NODE, "is@a085b454-0d49-414c-b1d1-98d8c5e2cffb"),
hvar1 = an(WORD_INSTANCE_NODE, "Berlin@614f9e08-42c7-451f-8dea-0e73d5018029")
)
);
// prep map
al(EVALUATION_LINK,
hphrase = an(DEFINED_LINGUISTIC_RELATIONSHIP_NODE, "capital_of"),
al(LIST_LINK,
an(WORD_NODE, "capital"),
an(DEFINED_LINGUISTIC_RELATIONSHIP_NODE, "of")
)
);
}
/*
* Preposition reasoning test.
*
* Expect to get the following result, given the above data:
*
* ListLink
* $benode = WordInstanceNode "is@a085b454-0d49-414c-b1d1-98d8c5e2cffb"
* $var0 = WordInstanceNode "capital@14601ec7-4b6a-4739-b2d6-0213d43be682"
* $word0 = WordNode "capital"
* $var1 = WordInstanceNode "Berlin@614f9e08-42c7-451f-8dea-0e73d5018029"
* $var2 = WordInstanceNode "Germany@372c7cd3-a9c9-44bb-bc7b-5bb356dda358"
* $prep = DefinedLinguisticRelationshipNode "of"
* $phrase = DefinedLinguisticRelationshipNode "capital_of"
*/
void BiggerPatternUTest::do_tst_prep(void)
{
logger().debug("BEGIN TEST: %s", __FUNCTION__);
// Result should be a ListLink
Handle imlist = imply(as.get(), clauses, implicand);
// Expect two answers: Berlin is the capital of Germany,
// and of France. (just for this test case :-)
int arity = getarity(imlist);
TSM_ASSERT_EQUALS("incorrect arity", arity, 2);
// 0 has France, 1 has Germany
Handle result_france = getlink(imlist, 0);
Handle result = getlink(imlist, 1);
// Actually, changes to atomspace internals can cause this
// to flip-flop. In fact, either order is valid. So just make
// this a run-time flip-flop, not a compile-time one.
// (For a fixed atomspace & pattern matcher, these won't change).
if (hvar2_france != getlink(result_france, 4))
{
result_france = getlink(imlist,1 );
result = getlink(imlist, 0);
}
Handle vbenode = getlink(result, 0);
Handle vvar0 = getlink(result, 1);
Handle vword0 = getlink(result, 2);
Handle vvar1 = getlink(result, 3);
Handle vvar2 = getlink(result, 4);
Handle vprep = getlink(result, 5);
Handle vphrase = getlink(result, 6);
#if 0
prtnode("hbenode is", hbenode);
prtnode("vbenode is", vbenode);
prtnode("hvar0 is", hvar0);
prtnode("vvar0 is", vvar0);
prtnode("hword0 is", hword0);
prtnode("vword0 is", vword0);
prtnode("hvar1 is", hvar1);
prtnode("vvar1 is", vvar1);
prtnode("hvar2 is", hvar2);
prtnode("vvar2 is", vvar2);
prtnode("hprep is", hprep);
prtnode("vprep is", vprep);
prtnode("hphrase is", hphrase);
prtnode("vphrase is", vphrase);
#endif
TSM_ASSERT_EQUALS("incorrect benode", hbenode, vbenode);
TSM_ASSERT_EQUALS("incorrect var0", hvar0, vvar0);
TSM_ASSERT_EQUALS("incorrect word0", hword0, vword0);
TSM_ASSERT_EQUALS("incorrect var1", hvar1, vvar1);
TSM_ASSERT_EQUALS("incorrect var2 - Germany", hvar2, vvar2);
TSM_ASSERT_EQUALS("incorrect prep", hprep, vprep);
TSM_ASSERT_EQUALS("incorrect phrase", hphrase, vphrase);
Handle france_benode = getlink(result_france, 0);
Handle france_var0 = getlink(result_france, 1);
Handle france_word0 = getlink(result_france, 2);
Handle france_var1 = getlink(result_france, 3);
Handle france_var2 = getlink(result_france, 4);
Handle france_prep = getlink(result_france, 5);
Handle france_phrase = getlink(result_france, 6);
TSM_ASSERT_EQUALS("incorrect benode", hbenode, france_benode);
TSM_ASSERT_EQUALS("incorrect var0", hvar0, france_var0);
TSM_ASSERT_EQUALS("incorrect word0", hword0, france_word0);
TSM_ASSERT_EQUALS("incorrect var1", hvar1, france_var1);
TSM_ASSERT_EQUALS("incorrect var2 - France", hvar2_france, france_var2);
TSM_ASSERT_EQUALS("incorrect prep", hprep, france_prep);
TSM_ASSERT_EQUALS("incorrect phrase", hphrase, france_phrase);
logger().debug("END TEST: %s", __FUNCTION__);
}
void BiggerPatternUTest::test_prep_rw(void)
{
do_tst_prep();
}
void BiggerPatternUTest::test_prep_overlay(void)
{
// Mark base-space as readonly; create a read-write overlay.
as->set_read_only();
AtomSpacePtr save = as;
as = createAtomSpace(as);
do_tst_prep();
as = save;
as->set_read_write();
}