/*
* tests/atomspace/AtomSpaceUTest.cxxtest
*
* Copyright (C) 2002-2007 Novamente LLC
* Copyright (C) 2008-2010 OpenCog Foundation
* All Rights Reserved
*
* Written by Welter Silva <welter@vettalabs.com>
* Ricardo Bittencourt <ricbit@700km.com.br>
*
* 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 <algorithm>
#include <math.h>
#include <string.h>
#include <opencog/atoms/atom_types/types.h>
#include <opencog/atomspace/AtomSpace.h>
#include <opencog/atoms/base/Handle.h>
#include <opencog/atoms/base/Node.h>
#include <opencog/atoms/base/Link.h>
#include <opencog/atoms/value/FloatValue.h>
#include <opencog/util/Logger.h>
#include <opencog/util/platform.h>
#include <opencog/util/oc_assert.h>
#include <cxxtest/TestSuite.h>
using namespace opencog;
using namespace std;
#define FLOAT_ACCEPTABLE_ERROR 0.000001
#define NUM_NODES 6
#define NUM_FORCEUSER_LINKS 4
#define NUM_HUMAN_LINKS 4
#define NUM_VHS 4
#define NUM_VH_NODES 3
Handle addRealAtom(AtomSpace& as, Handle atom,
ValuePtr tvn = ValuePtr())
{
ValuePtr newTV = tvn ? tvn: FloatValueCast(atom->getValue(truth_key()));
// Check if the given Atom reference is of an atom
// that was not inserted yet. If so, adds the atom. Otherwise, just sets
// result to the correct/valid handle.
Handle result;
NodePtr node(NodeCast(atom));
if (node) {
result = as.xget_handle(node->get_type(), node->get_name());
if (result == Handle::UNDEFINED) {
result = as.add_node(node->get_type(),
std::move(std::string(node->get_name())));
result->setValue(truth_key(), newTV);
return result;
}
} else {
LinkPtr link(LinkCast(atom));
result = as.xget_handle(link->get_type(), link->getOutgoingSet());
if (result == Handle::UNDEFINED) {
result = as.add_link(link->get_type(),
std::move(HandleSeq(link->getOutgoingSet())));
result->setValue(truth_key(), newTV);
return result;
}
}
result->setValue(truth_key(), newTV);
return result;
}
HandleSeq createSimpleGraph(AtomSpace* atomSpace, const char* baseName)
{
char buf[256];
memset(buf, 0, 256);
int baseNameLength = strlen(baseName);
strcpy(buf, baseName);
ValuePtr tv1 = createFloatValue(std::vector<double>({0.001, 0.00001}));
ValuePtr tv2 = createFloatValue(std::vector<double>({0.001, 0.00001}));
ValuePtr tv3 = createFloatValue(std::vector<double>({0.5, 0.99}));
buf[baseNameLength] = '1';
Handle h1 = atomSpace->add_node(CONCEPT_NODE, buf);
h1->setValue(truth_key(), tv1);
buf[baseNameLength] = '2';
Handle h2 = atomSpace->add_node(CONCEPT_NODE, buf);
h2->setValue(truth_key(), tv2);
buf[baseNameLength] = '3';
Handle h3 = atomSpace->add_node(CONCEPT_NODE, buf);
h3->setValue(truth_key(), tv3);
HandleSeq outgoing1;
outgoing1.push_back(h2);
outgoing1.push_back(h3);
Handle l1 = atomSpace->add_link(LIST_LINK, std::move(outgoing1));
l1->setValue(truth_key(), tv1);
HandleSeq outgoing2;
outgoing2.push_back(h1);
outgoing2.push_back(l1);
Handle l2 = atomSpace->add_link(EVALUATION_LINK, std::move(outgoing2));
l2->setValue(truth_key(), tv2);
HandleSeq testAtoms;
testAtoms.push_back(h1);
testAtoms.push_back(h2);
testAtoms.push_back(h3);
testAtoms.push_back(l1);
testAtoms.push_back(l2);
return testAtoms;
}
class HandlePredicate {
public:
inline bool operator()(const Handle& h) const { return this->test(h); }
virtual bool test(const Handle&) const = 0;
};
class AtomComparator {
public:
inline bool operator()(const Handle& a, const Handle& b) const
{ return this->test(a,b); }
virtual bool test(const Handle&, const Handle&) const = 0;
};
/**
* Filter handles from a sequence according to the given criterion.
*
* @param begin iterator for the sequence
* @param end iterator for the sequence
* @param struct or function embodying the criterion
* @return The handles in the sequence that match the criterion.
* @deprecated do not use in new code!
*/
template<typename InputIterator>
HandleSeq filter(InputIterator begin, InputIterator end, HandlePredicate& compare)
{
HandleSeq result;
std::copy_if(begin, end, back_inserter(result),
[&](Handle h)->bool { return compare(h); } );
return result;
}
/**
* Gets a set of handles that matches with the given type
* (subclasses optionally) and a given criterion.
*
* @param result An output iterator.
* @param type The desired type.
* @param subclass Whether type subclasses should be considered.
* @param compare A criterion for including atoms. It must be something
* that returns a bool when called.
*
* @return The set of atoms of a given type (subclasses optionally).
*
* @note The matched entries are appended to a container whose
* OutputIterator is passed as the first argument. Example of call to this
* method, which would return all entries in AtomSpace beyond 500 LTI:
* @code
* std::list<Handle> ret;
* atomSpace.getHandleSet(back_inserter(ret), ATOM, true, LTIAboveThreshold(500));
* @endcode
*/
template <typename OutputIterator> OutputIterator
getHandleSetFiltered(AtomSpace* as, OutputIterator result,
Type type,
bool subclass,
HandlePredicate& compare)
{
HandleSeq hs;
as->get_handles_by_type(hs, type, subclass);
return std::copy_if(hs.begin(), hs.end(), result,
[&](Handle h)->bool { return compare(h); } );
}
// Wrapper for comparing atoms from a HandleSeq
template <typename Compare>
struct compareAtom
{
Compare* c;
compareAtom(Compare* _c) : c(_c) {}
bool operator()(Handle h1, Handle h2) {
return (*c)(h1, h2);
}
};
/**
* Gets a set of handles that matches with the given type
* (subclasses optionally), sorted according to the given comparison
* structure.
*
* @param result An output iterator.
* @param type The desired type.
* @param subclass Whether type subclasses should be considered.
* @param compare The comparison struct to use in the sort.
*
* @return The set of atoms of a given type (subclasses optionally).
*
* @note The matched entries are appended to a container whose
* OutputIterator is passed as the first argument.
*/
template <typename OutputIterator, typename Compare> OutputIterator
getSortedHandleSet(AtomSpace* as,
OutputIterator result,
Type type,
bool subclass,
Compare compare)
{
// get the handle set as a vector and sort it.
HandleSeq hs;
as->get_handles_by_type(hs, type, subclass);
std::sort(hs.begin(), hs.end(), compareAtom<AtomComparator>(compare));
return std::copy(hs.begin(), hs.end(), result);
}
template <typename OutputIterator> OutputIterator
get_handles_by_name(AtomSpace* as,
OutputIterator result,
const std::string& name,
Type type = NODE,
bool subclass = true)
{
if (name.c_str()[0] == 0) {
HandleSeq hset;
as->get_handles_by_type(hset, type, subclass);
return std::copy(hset.begin(), hset.end(), result);
}
if (false == subclass) {
Handle h(as->xget_handle(type, name));
if (h) *(result++) = h;
return result;
}
nameserver().foreachRecursive(
[&](Type t)->void {
// Avoid illegal gets.
if (nameserver().isA(t, NUMBER_NODE)) return;
if (nameserver().isA(t, TYPE_NODE)) return;
Handle h(as->xget_handle(t, name));
if (h) *(result++) = h; }, type);
return result;
}
class AtomSpaceUTest : public CxxTest::TestSuite
{
private:
AtomSpacePtr asp;
AtomSpace* atomSpace;
public:
AtomSpaceUTest() {
logger().set_level(Logger::DEBUG);
// logger().set_sync_flag(true);
logger().set_print_to_stdout_flag(true);
}
void setUp() {
asp = createAtomSpace();
atomSpace = asp.get();
}
void tearDown() {
}
struct mean : public HandlePredicate {
virtual bool test(const Handle& h) const {
return FloatValueCast(h->getValue(truth_key()))->value()[0] > 0.8;
}
};
struct everything : public HandlePredicate {
virtual bool test(const Handle& h) const {
return true;
}
};
void testMiscellaneous()
{
logger().info("Begin testMiscellaneous()");
const char* nodeNames[NUM_NODES] = {
"Vader",
"Luke",
"Chewbacca",
"R2D2",
"Force",
"Human"
};
Handle h[NUM_NODES];
for (int i = 0; i < NUM_NODES; i++) {
h[i] = atomSpace->add_node(CONCEPT_NODE, nodeNames[i]);
h[i]->setValue(truth_key(), createFloatValue(std::vector<double>({0.001, 0.99})));
}
logger().debug("Nodes created");
float ForceUser[NUM_FORCEUSER_LINKS] = {0.99, 0.99, 0.0, 0.5};
Handle FU[NUM_FORCEUSER_LINKS];
for (int i = 0; i < NUM_FORCEUSER_LINKS; i++) {
HandleSeq temp(2);
temp[0] = h[i];
temp[1] = h[4];
FU[i] = atomSpace->add_link(SUBSET_LINK, std::move(temp));
FU[i]->setValue(truth_key(), createFloatValue(std::vector<double>({ForceUser[i], 0.99})));
}
logger().debug("ForceUser links created");
float Human[4] = {0.99, 0.99, 0.5, 0.0f};
HandleSeq out[4];
Handle H[4];
for (int i = 0; i < 4; i++) {
out[i].push_back(h[i]);
out[i].push_back(h[5]);
H[i] = atomSpace->add_link(INHERITANCE_LINK,
std::move(HandleSeq(out[i])));
H[i]->setValue(truth_key(), createFloatValue(std::vector<double>({Human[i], 0.99})));
}
logger().debug("Human links created");
// Check TVS
for (int i = 0; i < NUM_NODES; i++) {
FloatValuePtr tv = FloatValueCast(h[i]->getValue(truth_key()));
logger().debug("h: tv mean = %f, atomSpace->getMean(h[i]) = %f",
tv->value()[0], FloatValueCast(h[i]->getValue(truth_key()))->value()[0]);
TS_ASSERT(fabs(tv->value()[0] - 0.001) < FLOAT_ACCEPTABLE_ERROR);
logger().debug("h: confidence = %f, diff = %f, error = %f", tv->value()[1], fabs(tv->value()[1] - 0.99), FLOAT_ACCEPTABLE_ERROR);
TS_ASSERT(fabs(tv->value()[1] - 0.99) < FLOAT_ACCEPTABLE_ERROR);
if (i < NUM_FORCEUSER_LINKS) {
FloatValuePtr tv = FloatValueCast(FU[i]->getValue(truth_key()));
logger().debug("h: tv mean = %f, atomSpace->getMean(h[i]) = %f",
tv->value()[0], FloatValueCast(h[i]->getValue(truth_key()))->value()[0]);
logger().debug("FU: tv mean = %f, atomSpace->getMean(FU[i]) = %f\n",
tv->value()[0], FloatValueCast(FU[i]->getValue(truth_key()))->value()[0]);
TS_ASSERT(fabs(tv->value()[0] - ForceUser[i]) < FLOAT_ACCEPTABLE_ERROR);
logger().debug("FU: confidence = %f, diff = %f, error = %f", tv->value()[1], fabs(tv->value()[1] - 0.99), FLOAT_ACCEPTABLE_ERROR);
TS_ASSERT(fabs(tv->value()[1] - 0.99) < FLOAT_ACCEPTABLE_ERROR);
}
if (i < NUM_HUMAN_LINKS) {
FloatValuePtr tv = FloatValueCast(H[i]->getValue(truth_key()));
logger().debug("h: tv mean = %f, atomSpace->getMean(h[i]) = %f",
tv->value()[0], FloatValueCast(h[i]->getValue(truth_key()))->value()[0]);
TS_ASSERT(fabs(tv->value()[0] - Human[i]) < FLOAT_ACCEPTABLE_ERROR);
logger().debug("H: confidence = %f, diff = %f, error = %f", tv->value()[1], fabs(tv->value()[1] - 0.99), FLOAT_ACCEPTABLE_ERROR);
TS_ASSERT(fabs(tv->value()[1] - 0.99) < FLOAT_ACCEPTABLE_ERROR);
}
}
logger().debug("TVS checked");
TS_ASSERT(atomSpace->get_num_atoms_of_type(NODE, true) == NUM_NODES);
TS_ASSERT(atomSpace->get_num_atoms_of_type(LINK, true) == 8);
// Test filters
for (int vhIdx = 0; vhIdx < NUM_VHS; vhIdx++) {
mean m;
HandleSeq high_mean;
getHandleSetFiltered(atomSpace, back_inserter(high_mean), ATOM, true, m);
logger().debug("Filter %d checked", vhIdx);
//std::cout << "high mean size " << high_mean.size() << std::endl;
//for (int jj = 0; jj < high_mean.size(); jj++) {
// std::cout << atomSpace->atomAsString(high_mean[jj],false) << std::endl;
//}
HandleSeq nodes;
atomSpace->get_handles_by_type(nodes, NODE, true);
logger().debug("Get nodes by type %d checked", vhIdx);
HandleSeq links;
atomSpace->get_handles_by_type(links, LINK, true);
logger().debug("Get links by type %d checked", vhIdx);
HandleSeq all;
everything e;
getHandleSetFiltered(atomSpace, back_inserter(all), ATOM, true, e);
TS_ASSERT(high_mean.size() == 4);
TS_ASSERT(nodes.size() == NUM_NODES);
TS_ASSERT(links.size() == 8);
TS_ASSERT(all.size() == 14);
if (vhIdx == 0) {
TS_ASSERT(find(high_mean.begin(), high_mean.end(), FU[0]) != high_mean.end());
TS_ASSERT(find(high_mean.begin(), high_mean.end(), H[0]) != high_mean.end());
}
if (vhIdx == 0 || vhIdx == 1) {
TS_ASSERT(find(high_mean.begin(), high_mean.end(), FU[1]) != high_mean.end());
TS_ASSERT(find(high_mean.begin(), high_mean.end(), H[1]) != high_mean.end());
}
for (int i = 0; i < NUM_FORCEUSER_LINKS; i++) {
if (vhIdx == 0 || (i % 4 == vhIdx)) {
TS_ASSERT (find(links.begin(), links.end(), FU[i]) != links.end());
TS_ASSERT (find(all.begin(), all.end(), FU[i]) != all.end());
}
}
logger().debug("Forceuser %d checked", vhIdx);
for (int i = 0; i < NUM_HUMAN_LINKS; i++) {
if (vhIdx == 0 || (i % 4 == vhIdx)) {
TS_ASSERT (find(links.begin(), links.end(), H[i]) != links.end());
TS_ASSERT (find(all.begin(), all.end(), H[i]) != all.end());
}
}
logger().debug("Human %d checked", vhIdx);
for (int i = 0; i < NUM_NODES; i++) {
if (vhIdx == 0 || (i % 4 == vhIdx)) {
TS_ASSERT (find(all.begin(), all.end(), h[i]) != all.end());
TS_ASSERT (find(nodes.begin(), nodes.end(), h[i]) != nodes.end());
}
}
logger().debug("Rest of them %d checked", vhIdx);
}
// Test getHandleSet
// OutputIterator getHandleSet(OutputIterator, Type, const string& name, bool acceptSubTypes=true) const;
logger().debug("Start subset test");
for (int vhIdx = 0; vhIdx < NUM_VHS; vhIdx++) {
for (int i = 0; i < NUM_NODES; i++) {
HandleSeq nodes;
logger().debug("start get handle by name %d %d", vhIdx, i);
get_handles_by_name(atomSpace, back_inserter(nodes), nodeNames[i], NODE, true);
TS_ASSERT_EQUALS(nodes.size(), 1);
for (int j = 0; j < NUM_NODES; j++) {
if (i == j) {
TS_ASSERT(find(nodes.begin(), nodes.end(), h[j]) != nodes.end());
} else {
TS_ASSERT(find(nodes.begin(), nodes.end(), h[j]) == nodes.end());
}
}
}
logger().debug("Subset %d checked", vhIdx);
HandleSeq links;
get_handles_by_name(atomSpace, back_inserter(links), "", LINK, true);
logger().debug("1) links.size() = %d Expected = %d", (int) links.size(), 8);
TS_ASSERT(links.size() == 8);
links.clear();
get_handles_by_name(atomSpace, back_inserter(links), "", LINK, false);
logger().debug("2) links.size() = %d", links.size());
TS_ASSERT(links.size() == 0);
HandleSeq allInhLinks;
get_handles_by_name(atomSpace, back_inserter(allInhLinks), "", INHERITANCE_LINK, true);
logger().debug("4) allInhLinks.size() = %d (vhIdx: %d)", allInhLinks.size(), vhIdx);
//for (unsigned int x = 0; x < allInhLinks.size(); ++x) {
// logger().info("allInhLinks[x]: %s\n", allInhLinks[x]->to_string().c_str());
//}
// TS_ASSERT(allInhLinks.size() == 8);
HandleSeq justInhLinks;
get_handles_by_name(atomSpace, back_inserter(justInhLinks), "", INHERITANCE_LINK, false);
logger().debug("5) justInhLinks.size() = %d (vhIdx: %d)", justInhLinks.size(), vhIdx);
TS_ASSERT(justInhLinks.size() == 4);
HandleSeq partOfLinks;
get_handles_by_name(atomSpace, back_inserter(partOfLinks), "", SUBSET_LINK, true);
logger().debug("6) partOfLinks.size() = %d", partOfLinks.size());
TS_ASSERT(partOfLinks.size() == 4);
partOfLinks.clear();
get_handles_by_name(atomSpace, back_inserter(partOfLinks), "", SUBSET_LINK, false);
logger().debug("7) partOfLinks.size() = %d", partOfLinks.size());
TS_ASSERT(partOfLinks.size() == 4);
}
logger().info("\nEnd testMiscellaneous()");
}
/**
* Method tested:
*
* Add a new node to the Atom Table
* @param t Type of the node
* @param name Name of the node
*
* virtual Handle add_node(Type t,const string& name)=0;
*
*/
void testAddNode()
{
logger().info("Begin testAddNode()");
ValuePtr tv1 = createFloatValue(std::vector<double>({0.001, 0.00001}));
ValuePtr tv2 = createFloatValue(std::vector<double>({0.001, 0.00001}));
ValuePtr tv3 = createFloatValue(std::vector<double>({0.5, 0.99}));
Handle h1 = atomSpace->add_node(PREDICATE_NODE, "barkingAt");
h1->setValue(truth_key(), tv1);
Handle h2 = atomSpace->add_node(CONCEPT_NODE, "dog1");
h2->setValue(truth_key(), tv2);
Handle h3 = atomSpace->add_node(CONCEPT_NODE, "tree");
h3->setValue(truth_key(), tv3);
tv1 = createFloatValue(std::vector<double>({0.002, 0.00002}));
tv2 = createFloatValue(std::vector<double>({0.1, 0.0}));
tv3 = createFloatValue(std::vector<double>({0.6, 0.90}));
h1->setValue(truth_key(), tv1);
h2->setValue(truth_key(), tv2);
h3->setValue(truth_key(), tv3);
Handle h1_ = atomSpace->add_node(PREDICATE_NODE, "barkingAt");
Handle h2_ = atomSpace->add_node(CONCEPT_NODE, "dog1");
Handle h3_ = atomSpace->add_node(CONCEPT_NODE, "tree");
TS_ASSERT(h1 == h1_);
FloatValuePtr h1tv = FloatValueCast(h1->getValue(truth_key()));
logger().debug("h1tv = %s", h1tv->to_string().c_str());
logger().debug("tv1 = %s", tv1->to_string().c_str());
FloatValuePtr fv1 = FloatValueCast(tv1);
TS_ASSERT(fabs(h1tv->value()[0] - fv1->value()[0]) < FLOAT_ACCEPTABLE_ERROR);
TS_ASSERT(fabs(h1tv->value()[1] - fv1->value()[1]) < FLOAT_ACCEPTABLE_ERROR);
TS_ASSERT(h2 == h2_);
FloatValuePtr h2tv = FloatValueCast(h2->getValue(truth_key()));
FloatValuePtr fv2 = FloatValueCast(tv2);
TS_ASSERT(fabs(h2tv->value()[0] - fv2->value()[0]) < FLOAT_ACCEPTABLE_ERROR);
TS_ASSERT(fabs(h2tv->value()[1] - fv2->value()[1]) < FLOAT_ACCEPTABLE_ERROR);
TS_ASSERT(h3 == h3_);
FloatValuePtr h3tv = FloatValueCast(h3->getValue(truth_key()));
FloatValuePtr fv3 = FloatValueCast(tv3);
TS_ASSERT(fabs(h3tv->value()[0] - fv3->value()[0]) < FLOAT_ACCEPTABLE_ERROR);
TS_ASSERT(fabs(h3tv->value()[1] - fv3->value()[1]) < FLOAT_ACCEPTABLE_ERROR);
// test adding a node with no truth value
Handle h4 = atomSpace->add_node(CONCEPT_NODE, "wood");
TS_ASSERT(h4 != Handle::UNDEFINED);
logger().info("End testAddNode()");
}
/**
* Method tested:
*
* Add a new link to the Atom Table
* @param t Type of the link
* @param outgoing HandleSeq containing the outgoing set of the link
*
* virtual Handle add_link(Type t,const HandleSeq& outgoing)=0;
*/
void testAddLink()
{
logger().info("Begin testAddLink()");
Handle h1 = atomSpace->add_node(PREDICATE_NODE, "barkingAt");
h1->setValue(truth_key(), createFloatValue(std::vector<double>({0.001, 0.00001})));
Handle h2 = atomSpace->add_node(CONCEPT_NODE, "dog1");
h2->setValue(truth_key(), createFloatValue(std::vector<double>({0.001, 0.00001})));
Handle h3 = atomSpace->add_node(CONCEPT_NODE, "tree");
h3->setValue(truth_key(), createFloatValue(std::vector<double>({0.5, 0.99})));
ValuePtr tv1 = createFloatValue(std::vector<double>({0.001, 0.00001}));
ValuePtr tv2 = createFloatValue(std::vector<double>({0.001, 0.00001}));
HandleSeq outgoing1;
outgoing1.push_back(h2);
outgoing1.push_back(h3);
Handle l1 = atomSpace->add_link(LIST_LINK,
std::move(HandleSeq(outgoing1)));
l1->setValue(truth_key(), tv1);
HandleSeq outgoing2;
outgoing2.push_back(h1);
outgoing2.push_back(l1);
Handle l2 = atomSpace->add_link(EVALUATION_LINK,
std::move(HandleSeq(outgoing2)));
l2->setValue(truth_key(), tv2);
tv1 = createFloatValue(std::vector<double>({0.002, 0.00002}));
l1->setValue(truth_key(), tv1);
Handle l1_ = atomSpace->add_link(LIST_LINK,
std::move(HandleSeq(outgoing1)));
tv2 = createFloatValue(std::vector<double>({0.1, 0.0}));
l2->setValue(truth_key(), tv2);
Handle l2_ = atomSpace->add_link(EVALUATION_LINK,
std::move(HandleSeq(outgoing2)));
TS_ASSERT(l1 == l1_);
FloatValuePtr l1tv = FloatValueCast(l1->getValue(truth_key()));
logger().debug("l1tv = %s", l1tv->to_string().c_str());
logger().debug("tv1 = %s", tv1->to_string().c_str());
FloatValuePtr fv1 = FloatValueCast(tv1);
TS_ASSERT(fabs(l1tv->value()[0] - fv1->value()[0]) < FLOAT_ACCEPTABLE_ERROR);
TS_ASSERT(fabs(l1tv->value()[1] - fv1->value()[1]) < FLOAT_ACCEPTABLE_ERROR);
TS_ASSERT(l2 == l2_);
FloatValuePtr l2tv = FloatValueCast(l2->getValue(truth_key()));
FloatValuePtr fv2 = FloatValueCast(tv2);
TS_ASSERT(fabs(l2tv->value()[0] - fv2->value()[0]) < FLOAT_ACCEPTABLE_ERROR);
TS_ASSERT(fabs(l2tv->value()[1] - fv2->value()[1]) < FLOAT_ACCEPTABLE_ERROR);
logger().info("End testAddLink()");
}
/**
* Values should get copied over, when a new version of the same atom is added.
*/
void testTVUpdate()
{
logger().info("Begin testTVUpdate");
Handle h1 = createNode(CONCEPT_NODE, "dog1");
h1->setValue(truth_key(), createFloatValue(std::vector<double>({0.001, 0.00001})));
Handle ash1 = atomSpace->add_atom(h1);
ValuePtr tv1 = createFloatValue(std::vector<double>({0.001, 0.00001}));
FloatValuePtr htv = FloatValueCast(ash1->getValue(truth_key()));
logger().debug("ash1 = %s", ash1->to_string().c_str());
logger().debug("htv = %s", htv->to_string().c_str());
logger().debug("tv1 = %s", tv1->to_string().c_str());
FloatValuePtr fv1 = FloatValueCast(tv1);
TS_ASSERT(fabs(htv->value()[0] - fv1->value()[0]) < FLOAT_ACCEPTABLE_ERROR);
TS_ASSERT(fabs(htv->value()[1] - fv1->value()[1]) < FLOAT_ACCEPTABLE_ERROR);
Handle h2 = createNode(CONCEPT_NODE, "dog1");
h2->setValue(truth_key(), createFloatValue(std::vector<double>({0.02, 0.002})));
Handle ash2 = atomSpace->add_atom(h2);
ValuePtr tv2 = createFloatValue(std::vector<double>({0.02, 0.002}));
logger().debug("ash2 = %s", ash2->to_string().c_str());
TS_ASSERT(ash1 == ash2);
htv = FloatValueCast(ash1->getValue(truth_key()));
logger().debug("htv = %s", htv->to_string().c_str());
logger().debug("tv2 = %s", tv2->to_string().c_str());
FloatValuePtr fv2 = FloatValueCast(tv2);
TS_ASSERT(fabs(htv->value()[0] - fv2->value()[0]) < FLOAT_ACCEPTABLE_ERROR);
TS_ASSERT(fabs(htv->value()[1] - fv2->value()[1]) < FLOAT_ACCEPTABLE_ERROR);
Handle h3 = createNode(CONCEPT_NODE, "dog1");
h3->setValue(truth_key(), createFloatValue(std::vector<double>({0.3, 0.03})));
Handle ash3 = atomSpace->add_atom(h3);
ValuePtr tv3 = createFloatValue(std::vector<double>({0.3, 0.03}));
logger().debug("ash3 = %s", ash3->to_string().c_str());
TS_ASSERT(ash1 == ash3);
htv = FloatValueCast(ash1->getValue(truth_key()));
logger().debug("htv = %s", htv->to_string().c_str());
logger().debug("tv3 = %s", tv3->to_string().c_str());
FloatValuePtr fv3 = FloatValueCast(tv3);
TS_ASSERT(fabs(htv->value()[0] - fv3->value()[0]) < FLOAT_ACCEPTABLE_ERROR);
TS_ASSERT(fabs(htv->value()[1] - fv3->value()[1]) < FLOAT_ACCEPTABLE_ERROR);
logger().info("End testTVUpdate");
}
void testGetHandle_bugfix1()
{
HandleSeq emptyOutgoing;
Handle result = atomSpace->xget_handle(LIST_LINK, emptyOutgoing);
TS_ASSERT(result == Handle::UNDEFINED);
atomSpace->add_link(LIST_LINK,
std::move(HandleSeq(emptyOutgoing)));
result = atomSpace->xget_handle(LIST_LINK, emptyOutgoing);
TS_ASSERT(result != Handle::UNDEFINED);
}
void testGetHandleSetByName()
{
Handle h1 = atomSpace->add_node(PREDICATE_NODE, "dog1");
h1->setValue(truth_key(), createFloatValue(std::vector<double>({0.001, 0.00001})));
Handle h2 = atomSpace->add_node(CONCEPT_NODE, "dog1");
h2->setValue(truth_key(), createFloatValue(std::vector<double>({0.001, 0.00001})));
Handle h3 = atomSpace->add_node(NODE, "dog1");
h3->setValue(truth_key(), createFloatValue(std::vector<double>({0.5, 0.99})));
HandleSeq namedAtoms;
atomSpace->get_handles_by_type(namedAtoms, NODE, true);
TS_ASSERT_EQUALS(namedAtoms.size(), 3);
}
};