/*
* tests/atoms/BetaReduceUTest.cxxtest
*
* Copyright (C) 2016 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 <opencog/atoms/base/Atom.h>
#include <opencog/atomspace/AtomSpace.h>
#include <opencog/atoms/scope/ScopeLink.h>
using namespace opencog;
// Test the BetaReduce.
//
class BetaReduceUTest : public CxxTest::TestSuite
{
private:
AtomSpace _as;
public:
BetaReduceUTest()
{
logger().set_print_to_stdout_flag(true);
}
void setUp() {}
void tearDown() {}
void test_unquote();
void test_alpha_hiding();
};
#define N _as.add_node
#define L _as.add_link
// Test beta reduction involving quasi-quotes.
void BetaReduceUTest::test_unquote()
{
logger().info("BEGIN TEST: %s", __FUNCTION__);
// Create ScopeLink.
Handle body =
L(SET_LINK,
N(VARIABLE_NODE, "$X"),
L(QUOTE_LINK, N(VARIABLE_NODE, "$X")),
L(QUOTE_LINK,
L(SET_LINK,
N(VARIABLE_NODE, "$X"),
L(UNQUOTE_LINK, N(VARIABLE_NODE, "$X")))));
Handle hscox =
L(SCOPE_LINK, N(VARIABLE_NODE, "$X"), body);
ScopeLinkPtr scox(ScopeLinkCast(hscox));
TS_ASSERT(scox != nullptr);
// Create a value to plug in;
Handle smothers_brothers = N(CONCEPT_NODE, "hippy chick");
HandleSeq vals;
vals.push_back(smothers_brothers);
// Perform beta reduction
const Variables& vars = scox->get_variables();
Handle redox = vars.substitute(body, vals);
TS_ASSERT(nullptr != redox);
redox = _as.add_atom(redox);
printf("reduced set=%s\n", redox->to_string().c_str());
// This is the answer we expect to get:
Handle oxy =
L(SET_LINK,
smothers_brothers,
L(QUOTE_LINK, N(VARIABLE_NODE, "$X")),
L(QUOTE_LINK,
L(SET_LINK,
N(VARIABLE_NODE, "$X"),
L(UNQUOTE_LINK, smothers_brothers))));
printf("expected set=%s\n", oxy->to_string().c_str());
// the reduced and the expected sets should be identical.
TS_ASSERT(redox == oxy);
logger().info("END TEST: %s", __FUNCTION__);
}
// Test beta reduction involving colliding variable names.
void BetaReduceUTest::test_alpha_hiding()
{
logger().info("BEGIN TEST: %s", __FUNCTION__);
// Create ScopeLink with one variable.
Handle xbody =
L(SET_LINK,
N(VARIABLE_NODE, "$X"),
L(QUOTE_LINK, N(VARIABLE_NODE, "$X")),
L(QUOTE_LINK,
L(SET_LINK,
N(VARIABLE_NODE, "$X"),
L(UNQUOTE_LINK, N(VARIABLE_NODE, "$X")))));
Handle hscox =
L(SCOPE_LINK, N(VARIABLE_NODE, "$X"), xbody);
// A scope link with two variables, and $X is clobbered/hidden
// aka alpha-conversion-conflicted by the inner ScopeLink.
Handle xybody =
L(SET_LINK,
N(VARIABLE_NODE, "$X"),
N(VARIABLE_NODE, "$Y"),
L(QUOTE_LINK, N(VARIABLE_NODE, "$X")),
L(QUOTE_LINK, N(VARIABLE_NODE, "$Y")),
hscox);
Handle hscoxy =
L(SCOPE_LINK,
L(VARIABLE_LIST,
N(VARIABLE_NODE, "$X"),
N(VARIABLE_NODE, "$Y")),
xybody);
ScopeLinkPtr scoxy(ScopeLinkCast(hscoxy));
TS_ASSERT(scoxy != nullptr);
// Create values to plug in;
Handle chick = N(CONCEPT_NODE, "hippy chick");
Handle dude = N(CONCEPT_NODE, "smelly dude");
HandleSeq vals;
vals.push_back(chick);
vals.push_back(dude);
// Perform beta reduction
const Variables& vars = scoxy->get_variables();
Handle redox = vars.substitute(xybody, vals);
redox = _as.add_atom(redox);
TS_ASSERT(nullptr != redox);
printf("reduced set=%s\n", redox->to_string().c_str());
// What we expect to get.
Handle xypect =
L(SET_LINK, chick, dude,
L(QUOTE_LINK, N(VARIABLE_NODE, "$X")),
L(QUOTE_LINK, N(VARIABLE_NODE, "$Y")),
hscox);
printf("expected set=%s\n", xypect->to_string().c_str());
// the reduced and the expected sets should be identical.
TS_ASSERT(redox == xypect);
logger().info("END TEST: %s", __FUNCTION__);
}