OverviewFilesCommitsIssuesDocsReleasesPeers

opencog-atomspace / tests / query / UnorderedUTest.cxxtest

716 lines · cxxtest ref:
/*
 * tests/query/UnorderedUTest.cxxtest
 *
 * Copyright (C) 2009, 2011, 2014 Linas Vepstas <linasvepstas@gmail.com>
 * All Rights Reserved
 * SPDX-License-Identifier: AGPL-3.0-or-later
 */

#include <opencog/guile/SchemeEval.h>
#include <opencog/util/Logger.h>
#include "test-types.h"

using namespace opencog;

class UnorderedUTest :  public CxxTest::TestSuite
{
	private:
		AtomSpacePtr as;
		SchemeEval* eval;
		Handle pair;
		Handle disorder;
		Handle disordered;
		Handle disor_more;
		Handle exhaust;
		Handle exhaust2;
		Handle exhaust3;
		Handle exhaust4;
		Handle exhaust5;
		Handle exhaust_eq_12;
		Handle exhaust_eq_6;

	public:

		UnorderedUTest(void)
		{
			logger().set_level(Logger::DEBUG);
			// logger().set_level(Logger::FINE);
			logger().set_print_to_stdout_flag(true);
			logger().set_timestamp_flag(false);
			logger().set_sync_flag(true);
#include "test-types.cc"
		}

		~UnorderedUTest()
		{
			logger().info("Completed running UnorderedUTest");

			// erase the log file if no assertions failed
			if (!CxxTest::TestTracker::tracker().suiteFailed())
				std::remove(logger().get_filename().c_str());
			else
			{
				logger().info("UnorderedUTest failed!");
				logger().flush();
			}
		}

		void setUp(void);

		void tearDown(void) { }

		void test_un1(void);
		void test_un2(void);
		void test_jswiergo(void);
		void test_big_jswiergo(void);
		void test_exhaust(void);
		void test_embed(void);
		void test_cube(void);
		void test_quote(void);
		void test_odometer(void);
		void test_odo_below(void);
		void test_odo_distinct(void);
		void test_odo_indistinct(void);
		void test_odo_layer(void);
		void test_odo_couple(void);
		void test_odo_equ_pred(void);
		void test_odo_equal(void);
		void test_odo_couplayer(void);
};

/*
 * This function sets up an implication link, and some data.
 */
#define an as->add_node
#define al as->add_link
void UnorderedUTest::setUp(void)
{
	as = createAtomSpace();
	eval = SchemeEval::get_scheme_evaluator(as);
	eval->eval("(add-to-load-path \"" PROJECT_SOURCE_DIR "\")");

	eval->eval("(load-from-path \"tests/query/test_types.scm\")");
	eval->eval("(load-from-path \"tests/query/unordered.scm\")");
	eval->eval("(load-from-path \"tests/query/unordered-more.scm\")");
	eval->eval("(load-from-path \"tests/query/unordered-exhaust.scm\")");

	// Create an implication link that will be tested.
	pair = eval->apply("pair", Handle::UNDEFINED);
	disorder = eval->apply("blink", Handle::UNDEFINED);
	disordered = eval->apply("blinker", Handle::UNDEFINED);
	disor_more = eval->apply("blank", Handle::UNDEFINED);
	exhaust = eval->apply("exhaust", Handle::UNDEFINED);
	exhaust2 = eval->apply("exhaust-2", Handle::UNDEFINED);
	exhaust3 = eval->apply("exhaust-3", Handle::UNDEFINED);
	exhaust4 = eval->apply("exhaust-4", Handle::UNDEFINED);
	exhaust5 = eval->apply("exhaust-5", Handle::UNDEFINED);
	exhaust_eq_12 = eval->apply("exhaust-eq-12", Handle::UNDEFINED);
	exhaust_eq_6 = eval->apply("exhaust-eq-6", Handle::UNDEFINED);
}

/*
 * Test of pattern matching on unordered links. This turns out to be
 * rather stressful on the pattern matcher, as it requires a bit of a
 * combinatoric explosion of the search space, under certain circumstances.
 * The trick is, of course, not to search too much, and not to search too
 * little.
 */
#define getarity(hand) hand->get_arity()

// ================================================================
void UnorderedUTest::test_un1(void)
{
	logger().debug("BEGIN TEST: %s", __FUNCTION__);

	// Make sure the scheme file actually loaded!
	TSM_ASSERT("Failed to load test data", Handle::UNDEFINED != pair);
	TSM_ASSERT("Failed to load test data", Handle::UNDEFINED != disorder);
	TSM_ASSERT("Failed to load test data", Handle::UNDEFINED != disordered);

	// Result should be a ListLink w/ two solutions
	Handle result = HandleCast(pair->execute(as.get()));

	logger().debug("pair result is %s\n", result->to_string().c_str());
	TSM_ASSERT_EQUALS("wrong number of solutions found", 2, getarity(result));

	// Result should be a ListLink w/ one solution. Well, actually, two
	// solutions.  One should bind the NumberNode, Goournded schema node,
	// the other should bind to VariableNodes appearing elsewhere in the
	// atomspace.  We could avoid this by using TypedVariableLinks, but this
	// potentially confused the test case even more ... so we don't
	result = HandleCast(disorder->execute(as.get()));
	logger().debug() << "Disorder Result is this:\n" << result->to_string();

	logger().debug("first result is %s\n", result->to_string().c_str());
	TSM_ASSERT_EQUALS("wrong number of solutions found", 2, getarity(result));

	// Result should be a ListLink w/ one solution. Well, actually, two as above.
	result = HandleCast(disordered->execute(as.get()));
	logger().debug() << "DisorderED Result is this:\n" << result->to_string();

	logger().debug("next result is %s\n", result->to_string().c_str());
	TSM_ASSERT_EQUALS("wrong number of solutions found", 2, getarity(result));

	logger().debug("END TEST: %s", __FUNCTION__);
}

// ================================================================
void UnorderedUTest::test_un2(void)
{
	logger().debug("BEGIN TEST: %s", __FUNCTION__);

	// Make sure the scheme file actually loaded!
	TSM_ASSERT("Failed to load test data", Handle::UNDEFINED != disor_more);

	// Result should be a ListLink w/ one solution
	Handle result = HandleCast(disor_more->execute(as.get()));

	logger().debug("second result is %s\n", result->to_string().c_str());
	TSM_ASSERT_EQUALS("wrong number of solutions found", 1, getarity(result));

	logger().debug("END TEST: %s", __FUNCTION__);
}

// ================================================================

void UnorderedUTest::test_jswiergo(void)
{
	logger().debug("BEGIN TEST: %s", __FUNCTION__);

	eval->eval("(load-from-path \"tests/query/unordered-jswiergo.scm\")");

	Handle result, expected;

	// --------------------
	result = eval->eval_h("(cog-execute! (CollectionOf tree-query1))");
	expected = eval->eval_h("expect-q1");

	logger().debug("jsw first result is %s\n", result->to_string().c_str());
	TSM_ASSERT_EQUALS("Incorrect result", result, expected);

	// --------------------
	result = eval->eval_h("(cog-execute! (CollectionOf tree-query2))");
	expected = eval->eval_h("expect-q2");

	logger().debug("jsw second result is %s\n", result->to_string().c_str());
	TSM_ASSERT_EQUALS("Incorrect result", result, expected);

	logger().debug("END TEST: %s", __FUNCTION__);
}

// ================================================================

// More complicated variant of above.
void UnorderedUTest::test_big_jswiergo(void)
{
	logger().debug("BEGIN TEST: %s", __FUNCTION__);

	eval->eval("(load-from-path \"tests/query/unordered-jswiergo.scm\")");

	Handle result, expected;

	// --------------------
	result = eval->eval_h("(cog-execute! (CollectionOf big-tree-q1))");
	expected = eval->eval_h("big-expect1");

	logger().debug("jsw big first result is %s\n", result->to_string().c_str());
	TSM_ASSERT_EQUALS("wrong number of solutions found", 6, getarity(result));
	TSM_ASSERT_EQUALS("Incorrect result", result, expected);

	// --------------------
	result = eval->eval_h("(cog-execute! (CollectionOf big-tree-q2))");
	expected = eval->eval_h("big-expect2");

	logger().debug("jsw big second result is %s\n", result->to_string().c_str());
	TSM_ASSERT_EQUALS("wrong number of solutions found", 6, getarity(result));
	TSM_ASSERT_EQUALS("Incorrect result", result, expected);

	logger().debug("END TEST: %s", __FUNCTION__);
}

// ================================================================
void UnorderedUTest::test_exhaust(void)
{
	logger().debug("BEGIN TEST: %s", __FUNCTION__);

	// Make sure the scheme file actually loaded!
	TSM_ASSERT("Failed to load test data", Handle::UNDEFINED != exhaust);
	TSM_ASSERT("Failed to load test data", Handle::UNDEFINED != exhaust2);
	TSM_ASSERT("Failed to load test data", Handle::UNDEFINED != exhaust3);
	TSM_ASSERT("Failed to load test data", Handle::UNDEFINED != exhaust4);
	TSM_ASSERT("Failed to load test data", Handle::UNDEFINED != exhaust5);
	TSM_ASSERT("Failed to load test data", Handle::UNDEFINED != exhaust_eq_12);
	TSM_ASSERT("Failed to load test data", Handle::UNDEFINED != exhaust_eq_6);

	// --------------------
	// Result should be a ListLink w/ 60 solutions.
	Handle result = HandleCast(exhaust->execute(as.get()));

	// logger().debug("exhaustive result is %s\n", result->to_string().c_str());
	TSM_ASSERT_EQUALS("wrong number of solutions found", 60, getarity(result));

	// --------------------
	// Result should be a ListLink w/ 72 solutions
	result = HandleCast(exhaust2->execute(as.get()));

	// logger().debug("exhaust-2 result is %s\n", result->to_string().c_str());
	TSM_ASSERT_EQUALS("wrong number of solutions found", 72, getarity(result));

	// --------------------
	// Result should be a ListLink w/ 12 solutions
	result = HandleCast(exhaust3->execute(as.get()));

	logger().debug("exhaust-3 result is %s\n", result->to_string().c_str());
	TSM_ASSERT_EQUALS("wrong number of solutions found", 12, getarity(result));

	// --------------------
	// Result should be a ListLink w/ 6 solutions
	result = HandleCast(exhaust4->execute(as.get()));

	logger().debug("exhaust-4 result is %s\n", result->to_string().c_str());
	TSM_ASSERT_EQUALS("wrong number of solutions found", 6, getarity(result));

	// --------------------
	// Result should be a ListLink w/ 6 solutions
	result = HandleCast(exhaust5->execute(as.get()));

	logger().debug("exhaust-5 result is %s\n", result->to_string().c_str());
	TSM_ASSERT_EQUALS("wrong number of solutions found", 6, getarity(result));

	// --------------------
	// Result should be a ListLink w/ 12 solutions
	result = HandleCast(exhaust_eq_12->execute(as.get()));

	logger().debug("exhaust-eq-12 result is %s\n", result->to_string().c_str());
	TSM_ASSERT_EQUALS("wrong number of solutions found", 12, getarity(result));

	// --------------------
	// Result should be a ListLink w/ 6 solutions
	result = HandleCast(exhaust_eq_6->execute(as.get()));

	logger().debug("exhaust-eq-6 result is %s\n", result->to_string().c_str());
	TSM_ASSERT_EQUALS("wrong number of solutions found", 6, getarity(result));

	logger().debug("END TEST: %s", __FUNCTION__);
}

// ================================================================
void UnorderedUTest::test_embed(void)
{
	logger().debug("BEGIN TEST: %s", __FUNCTION__);

	eval->eval("(load-from-path \"tests/query/unordered-embed.scm\")");
	Handle expected = eval->eval_h("expect-embedded-set");

	// Make sure the scheme file actually loaded!
	TSM_ASSERT("Failed to load test data", expected);

	// Result should be a SetLink w/ two solutions
	Handle result = eval->eval_h("(cog-execute! (CollectionOf embedded-set))");

	logger().debug("embedded result is %s\n", result->to_string().c_str());
	if (2 != getarity(result))
		logger().info("Error: unexpected number of solutions\n");
	TSM_ASSERT_EQUALS("wrong number of solutions found", 2, getarity(result));
	TSM_ASSERT_EQUALS("Incorrect result", result, expected);

	logger().debug("END TEST: %s", __FUNCTION__);
}

// ================================================================
void UnorderedUTest::test_cube(void)
{
	logger().debug("BEGIN TEST: %s", __FUNCTION__);

	eval->eval("(load-from-path \"tests/query/unordered-embed.scm\")");
	Handle expected = eval->eval_h("expect-two-x-two");

	// Make sure the scheme file actually loaded!
	TSM_ASSERT("Failed to load test data", expected);

	// Result should be a SetLink w/ four solutions
	Handle result = eval->eval_h("(cog-execute! (CollectionOf two-x-two))");

	logger().debug("square result is %s\n", result->to_string().c_str());
	TSM_ASSERT_EQUALS("wrong number of solutions found", 4, getarity(result));
	TSM_ASSERT_EQUALS("Incorrect result", result, expected);

	// --------------------------------------------
	// Again, but cubed.
	expected = eval->eval_h("expect-cube");

	// Make sure the scheme file actually loaded!
	TSM_ASSERT("Failed to load test data", expected);

	// Result should be a SetLink w/ eight solutions
	result = eval->eval_h("(cog-execute! (CollectionOf cube))");

	logger().debug("cube result is %s\n", result->to_string().c_str());
	TSM_ASSERT_EQUALS("wrong number of solutions found", 8, getarity(result));
	TSM_ASSERT_EQUALS("Incorrect result", result, expected);

	// --------------------------------------------
	// Again, but four-dimensional.

	// Result should be a SetLink w/ sixteen solutions
	result = eval->eval_h("(cog-execute! (CollectionOf tesseract))");

	// logger().debug("tesseract result is %s\n", result->to_string().c_str());
	TSM_ASSERT_EQUALS("wrong number of solutions found", 16, getarity(result));

	logger().debug("END TEST: %s", __FUNCTION__);
}

// ================================================================
// Infinite loop triggered by screwy handling of quoting during
// grounding.  See #2357 and #2360 for details.
void UnorderedUTest::test_quote(void)
{
	logger().debug("BEGIN TEST: %s", __FUNCTION__);

	eval->eval("(load-from-path \"tests/query/unordered-quote.scm\")");

	// Result should be a SetLink w/ one solution
	Handle result = eval->eval_h("(cog-execute! (CollectionOf query))");

	logger().debug("embedded result is %s\n", result->to_string().c_str());
	TSM_ASSERT_EQUALS("wrong number of solutions found", 1, getarity(result));

	logger().debug("END TEST: %s", __FUNCTION__);
}

// ================================================================

void UnorderedUTest::test_odometer(void)
{
	logger().debug("BEGIN TEST: %s", __FUNCTION__);

	eval->eval("(load-from-path \"tests/query/unordered-odometer.scm\")");

	// Result should be a SetLink w/ 3!=six solutions
	Handle result = eval->eval_h("(cog-execute! (CollectionOf odo-dim-one))");

	logger().debug("D=1 odo arity is %d\n", getarity(result));
	TSM_ASSERT_EQUALS("wrong number of solutions found", 6, getarity(result));

	// --------------------------------------------
	// Again, but squared
	// Result should be a SetLink w/ 6*6=36 solutions
	result = eval->eval_h("(cog-execute! (CollectionOf odo-dim-two))");

	logger().debug("D=2 odo arity is %d\n", getarity(result));
	TSM_ASSERT_EQUALS("wrong number of solutions found", 36, getarity(result));

	// --------------------------------------------
	// Result should be a SetLink w/ 6*6*6=216 solutions
	result = eval->eval_h("(cog-execute! (CollectionOf odo-dim-three))");

	logger().debug("D=3 odo arity is %d\n", getarity(result));
	TSM_ASSERT_EQUALS("wrong number of solutions found", 216, getarity(result));

	// --------------------------------------------
	// Result should be a SetLink w/ 6*6*6*6=1296 solutions
	result = eval->eval_h("(cog-execute! (CollectionOf odo-dim-four))");

	logger().debug("D=4 odo arity is %d\n", getarity(result));
	TSM_ASSERT_EQUALS("wrong number of solutions found", 1296, getarity(result));

	logger().debug("END TEST: %s", __FUNCTION__);
}

// ================================================================

void UnorderedUTest::test_odo_below(void)
{
	logger().debug("BEGIN TEST: %s", __FUNCTION__);

	eval->eval("(load-from-path \"tests/query/unordered-odo-below.scm\")");

	// Result should be a SetLink w/ 3!=six solutions
	Handle result = eval->eval_h("(cog-execute! (CollectionOf below-dim-one))");

	logger().debug("D=1 below arity is %d\n", getarity(result));
	TSM_ASSERT_EQUALS("wrong number of solutions found", 6, getarity(result));

	// --------------------------------------------
	// Again, but squared
	// Result should be a SetLink w/ 6*6=36 solutions
	result = eval->eval_h("(cog-execute! (CollectionOf below-dim-two))");

	logger().debug("D=2 below arity is %d\n", getarity(result));
	TSM_ASSERT_EQUALS("wrong number of solutions found", 36, getarity(result));

	// --------------------------------------------
	// Result should be a SetLink w/ 6*6*6=216 solutions
	result = eval->eval_h("(cog-execute! (CollectionOf below-dim-three))");

	logger().debug("D=3 below arity is %d\n", getarity(result));
	TSM_ASSERT_EQUALS("wrong number of solutions found", 216, getarity(result));

	// --------------------------------------------
	// Result should be a SetLink w/ 6*6*6*6=1296 solutions
	result = eval->eval_h("(cog-execute! (CollectionOf below-dim-four))");

	logger().debug("D=4 below arity is %d\n", getarity(result));
	TSM_ASSERT_EQUALS("wrong number of solutions found", 1296, getarity(result));

	logger().debug("END TEST: %s", __FUNCTION__);
}

// ================================================================

void UnorderedUTest::test_odo_distinct(void)
{
	logger().debug("BEGIN TEST: %s", __FUNCTION__);

	eval->eval("(load-from-path \"tests/query/unordered-odo-distinct.scm\")");

	// Result should be a SetLink w/ 3!=six solutions
	Handle result = eval->eval_h("(cog-execute! (CollectionOf distinct-dim-one))");

	logger().debug("D=1 distinct arity is %d\n", getarity(result));
	TSM_ASSERT_EQUALS("wrong number of solutions found", 6, getarity(result));

	// --------------------------------------------
	// Again, but squared
	// Result should be a SetLink w/ 6*6=36 solutions
	result = eval->eval_h("(cog-execute! (CollectionOf distinct-dim-two))");

	logger().debug("D=2 distinct arity is %d\n", getarity(result));
	TSM_ASSERT_EQUALS("wrong number of solutions found", 36, getarity(result));

	// --------------------------------------------
	// Result should be a SetLink w/ 6*6*6=216 solutions
	result = eval->eval_h("(cog-execute! (CollectionOf distinct-dim-three))");

	logger().debug("D=3 distinct arity is %d\n", getarity(result));
	TSM_ASSERT_EQUALS("wrong number of solutions found", 216, getarity(result));

	// --------------------------------------------
	// Result should be a SetLink w/ 6*6*6*6=1296 solutions
	result = eval->eval_h("(cog-execute! (CollectionOf distinct-dim-four))");

	logger().debug("D=4 distinct arity is %d\n", getarity(result));
	TSM_ASSERT_EQUALS("wrong number of solutions found", 1296, getarity(result));

	logger().debug("END TEST: %s", __FUNCTION__);
}

// ================================================================

void UnorderedUTest::test_odo_indistinct(void)
{
	logger().debug("BEGIN TEST: %s", __FUNCTION__);

	eval->eval("(load-from-path \"tests/query/unordered-odo-indistinct.scm\")");

	// Result should be a SetLink w/ 3!=six solutions
	Handle result = eval->eval_h("(cog-execute! (CollectionOf indistinct-dim-one))");

	logger().debug("D=1 indistinct arity is %d\n", getarity(result));
	TSM_ASSERT_EQUALS("wrong number of solutions found", 6, getarity(result));

	// --------------------------------------------
	// Again, but squared
	// Result should be a SetLink w/ 2*6*6=72 solutions
	result = eval->eval_h("(cog-execute! (CollectionOf indistinct-dim-two))");

	logger().debug("D=2 indistinct arity is %d\n", getarity(result));
	TSM_ASSERT_EQUALS("wrong number of solutions found", 72, getarity(result));

	// --------------------------------------------
	// Result should be a SetLink w/ 6*6*6*6=1296 solutions
	result = eval->eval_h("(cog-execute! (CollectionOf indistinct-dim-three))");

	logger().debug("D=3 indistinct arity is %d\n", getarity(result));
	TSM_ASSERT_EQUALS("wrong number of solutions found", 1296, getarity(result));

	// --------------------------------------------
	// Result should be a SetLink w/ 6*6*6*6 *4! = 31104 solutions
	result = eval->eval_h("(cog-execute! (CollectionOf indistinct-dim-four))");

	logger().debug("D=4 indistinct arity is %d\n", getarity(result));
	TSM_ASSERT_EQUALS("wrong number of solutions found", 31104, getarity(result));

	logger().debug("END TEST: %s", __FUNCTION__);
}

// ================================================================

// Stacked odometers.
// Currently fails
void UnorderedUTest::test_odo_layer(void)
{
	logger().debug("BEGIN TEST: %s", __FUNCTION__);

	eval->eval("(load-from-path \"tests/query/unordered-odo-layer.scm\")");

	// --------------------------------------------
	// Result should be a SetLink w/ 3!=6 solutions
	Handle result = eval->eval_h("(cog-execute! (CollectionOf layer-dim-one))");

	logger().debug("D=1 layer arity is %d\n", getarity(result));
	TSM_ASSERT_EQUALS("wrong number of solutions found", 6, getarity(result));

	// --------------------------------------------
	// Result should be a SetLink w/ 2!*(3!* 3!) = 72 solutions
	result = eval->eval_h("(cog-execute! (CollectionOf layer-dim-two))");

	logger().debug("D=2 layer arity is %d\n", getarity(result));
	TSM_ASSERT_EQUALS("wrong number of solutions found", 72, getarity(result));

	// --------------------------------------------
	// Result should be a SetLink w/ 3!*(3!* 3! *3!) = 1296 solutions
	result = eval->eval_h("(cog-execute! (CollectionOf layer-dim-three))");

	logger().debug("D=3 layer arity is %d\n", getarity(result));
	TSM_ASSERT_EQUALS("wrong number of solutions found", 1296, getarity(result));

	// --------------------------------------------
	// Result should be a SetLink w/ 4!*(3! * 3!* 3! *3!) = 31104 solutions
	result = eval->eval_h("(cog-execute! (CollectionOf layer-dim-four))");

	logger().debug("D=4 odo arity is %d\n", getarity(result));
	TSM_ASSERT_EQUALS("wrong number of solutions found", 31104, getarity(result));

	logger().debug("END TEST: %s", __FUNCTION__);
}

// ================================================================

// Coupled odometers. Currently failing.
void UnorderedUTest::test_odo_couple(void)
{
	logger().debug("BEGIN TEST: %s", __FUNCTION__);

	eval->eval("(load-from-path \"tests/query/unordered-odo-couple.scm\")");
	Handle result;

	// --------------------------------------------
	// Result should be a SetLink w/ 2*2=4 solutions
	result = eval->eval_h("(cog-execute! (CollectionOf couple-dim-two))");

	logger().debug("D=2 couple arity is %d\n", getarity(result));
	TSM_ASSERT_EQUALS("wrong number of solutions found", 4, getarity(result));

	// --------------------------------------------
	// Result should be a SetLink w/ 2*1*2=4 solutions
	result = eval->eval_h("(cog-execute! (CollectionOf couple-dim-three))");

	logger().debug("D=3 couple arity is %d\n", getarity(result));
	TSM_ASSERT_EQUALS("wrong number of solutions found", 4, getarity(result));

	// --------------------------------------------
	// Result should be a SetLink w/ 2*1*1*2=4 solutions
	result = eval->eval_h("(cog-execute! (CollectionOf couple-dim-four))");

	logger().debug("D=4 couple arity is %d\n", getarity(result));
	TSM_ASSERT_EQUALS("wrong number of solutions found", 4, getarity(result));

	logger().debug("END TEST: %s", __FUNCTION__);
}

// ================================================================

// Coupled odometers. Currently failing.
void UnorderedUTest::test_odo_equ_pred(void)
{
	logger().debug("BEGIN TEST: %s", __FUNCTION__);

	eval->eval("(load-from-path \"tests/query/unordered-odo-equpr.scm\")");
	Handle result;

	// --------------------------------------------
	// Result should be a SetLink w/ 2*2=4 solutions
	result = eval->eval_h("(cog-execute! (CollectionOf epr-dim-two))");

	logger().debug("D=2 epr arity is %d\n", getarity(result));
	TSM_ASSERT_EQUALS("wrong number of solutions found", 4, getarity(result));

	// --------------------------------------------
	// Result should be a SetLink w/ 2*1*2=4 solutions
	result = eval->eval_h("(cog-execute! (CollectionOf epr-dim-three))");

	logger().debug("D=3 epr arity is %d\n", getarity(result));
	TSM_ASSERT_EQUALS("wrong number of solutions found", 4, getarity(result));

	// --------------------------------------------
	// Result should be a SetLink w/ 2*1*1*2=4 solutions
	result = eval->eval_h("(cog-execute! (CollectionOf epr-dim-four))");

	logger().debug("D=4 epr arity is %d\n", getarity(result));
	TSM_ASSERT_EQUALS("wrong number of solutions found", 4, getarity(result));

	logger().debug("END TEST: %s", __FUNCTION__);
}

// ================================================================

// Coupled odometers. Currently failing.
void UnorderedUTest::test_odo_equal(void)
{
	logger().debug("BEGIN TEST: %s", __FUNCTION__);

	eval->eval("(load-from-path \"tests/query/unordered-odo-equal.scm\")");
	Handle result;

	// --------------------------------------------
	// Result should be a SetLink w/ 2*2=4 solutions
	result = eval->eval_h("(cog-execute! (CollectionOf equ-dim-two))");

	logger().debug("D=2 equ arity is %d\n", getarity(result));
	TSM_ASSERT_EQUALS("wrong number of solutions found", 4, getarity(result));

	// --------------------------------------------
	// Result should be a SetLink w/ 2*1*2=4 solutions
	result = eval->eval_h("(cog-execute! (CollectionOf equ-dim-three))");

	logger().debug("D=3 equ arity is %d\n", getarity(result));
	TSM_ASSERT_EQUALS("wrong number of solutions found", 4, getarity(result));

	// --------------------------------------------
	// Result should be a SetLink w/ 2*1*1*2=4 solutions
	result = eval->eval_h("(cog-execute! (CollectionOf equ-dim-four))");

	logger().debug("D=4 equ arity is %d\n", getarity(result));
	TSM_ASSERT_EQUALS("wrong number of solutions found", 4, getarity(result));

	logger().debug("END TEST: %s", __FUNCTION__);
}

// ================================================================

// Coupled odometers. Currently failing.
void UnorderedUTest::test_odo_couplayer(void)
{
	logger().debug("BEGIN TEST: %s", __FUNCTION__);

	eval->eval("(load-from-path \"tests/query/unordered-odo-couplayer.scm\")");
	Handle result;

	// --------------------------------------------
	// Result should be a SetLink w/ 2*(2*2)=8 solutions
	result = eval->eval_h("(cog-execute! (CollectionOf play-dim-two))");

	logger().debug("D=2 play arity is %d\n", getarity(result));
	TSM_ASSERT_EQUALS("wrong number of solutions found", 8, getarity(result));

	// --------------------------------------------
	// Result should be a SetLink w/ 2*(2*1*2)=8 solutions
	result = eval->eval_h("(cog-execute! (CollectionOf play-dim-three))");

	logger().debug("D=3 play arity is %d\n", getarity(result));
	TSM_ASSERT_EQUALS("wrong number of solutions found", 8, getarity(result));

	// --------------------------------------------
	// Result should be a SetLink w/ 2*(2*1*1*2)=8 solutions
	result = eval->eval_h("(cog-execute! (CollectionOf play-dim-four))");

	logger().debug("D=4 play arity is %d\n", getarity(result));
	TSM_ASSERT_EQUALS("wrong number of solutions found", 8, getarity(result));

	logger().debug("END TEST: %s", __FUNCTION__);
}

// ================================================================