Commit 885ba85e authored by Alejandro Suarez Hernandez's avatar Alejandro Suarez Hernandez
Browse files

Factory classes (for convenience)

parent 3edec4e0
#include <iostream>
#include "types.h"
#include <iostream>
#include <set>
using namespace imagine_planner;
const char* b2s(bool b)
......@@ -7,6 +8,20 @@ const char* b2s(bool b)
return b? "true" : "false";
}
std::ostream& operator<<(std::ostream& os, const std::set<Predicate>& ctn)
{
bool first = true;
os << '{';
for (auto thing : ctn)
{
if (not first) os << ',';
os << thing;
first = false;
}
os << '}';
return os;
}
int main(int argc, char* argv[])
{
std::hash<Term> h;
......@@ -21,6 +36,7 @@ int main(int argc, char* argv[])
std::cout << "Testing < operator (lt): " << b2s(*atom_ < *atom) << std::endl;
std::cout << "Testing clone() method: " << *(atom->clone()) << std::endl;
std::cout << std::endl;
Term::Ptr term_v(new TermV{Term::Ptr(new Atom("a1")), Term::Ptr(new Atom("a2"))});
Term::Ptr term_v_(new TermV{Term::Ptr(new Atom("a2")), Term::Ptr(new Atom("a3"))});
std::cout << "Testing stream operator for TermV: " << *term_v << std::endl;
......@@ -34,5 +50,20 @@ int main(int argc, char* argv[])
std::cout << "Testing < operator (gt): " << b2s(*term_v < *atom_) << std::endl;
std::cout << "Testing < operator (lt): " << b2s(*atom_ < *term_v) << std::endl;
std::cout << "Testing clone() method: " << *(term_v->clone()) << std::endl;
// Testing PredicateFactory
PredicateFactory p;
auto p1 = p("p", "x", "y");
auto p2 = p("q", 1, 3, -0.5);
auto p3 = p("r", "x", 0.5);
std::cout << *p1 << std::endl;
std::cout << *p2 << std::endl;
std::cout << *p3 << std::endl;
// Testing Predicate ordered sets.
//std::set<Predicate> predicate_set;
//predicate_set.add(Predicate("p", {}));
}
......@@ -77,7 +77,7 @@ Variable::Variable(const std::string& name, const Term& value) : name_(name), va
void Variable::reset(const std::string& name, Term::ConstPtr value)
{
value_ = (name.empty() or name == name_)? value : value_;
if (name.empty() or name == name_) value_ = value;
}
bool Variable::operator==(const Term& other) const
......@@ -106,19 +106,34 @@ std::size_t Variable::hash() const
// Implementation of TermV's methods
#define TERMV_CONSTRUCTOR(Container, PtrType)\
TermV::TermV(const Container<Term::PtrType>& term_v)\
{\
for (auto term : term_v) term_v_.push_back(term->clone());\
#define COPY_TERMV() for (auto term : term_v) term_v_.push_back(term->clone())
TermV::TermV() {}
TermV::TermV(const TermV& term_v)
{
COPY_TERMV();
}
TERMV_CONSTRUCTOR(std::vector, Ptr)
TermV::TermV(const std::vector<Term::Ptr>& term_v)
{
COPY_TERMV();
}
TERMV_CONSTRUCTOR(std::vector, ConstPtr)
TermV::TermV(const std::vector<Term::ConstPtr>& term_v)
{
COPY_TERMV();
}
TERMV_CONSTRUCTOR(std::initializer_list, Ptr)
TermV::TermV(const std::initializer_list<Term::Ptr>& term_v)
{
COPY_TERMV();
}
TERMV_CONSTRUCTOR(std::initializer_list, ConstPtr)
TermV::TermV(const std::initializer_list<Term::ConstPtr>& term_v)
{
COPY_TERMV();
}
std::string TermV::to_str() const
{
......@@ -186,11 +201,48 @@ std::size_t TermV::hash() const
std::hash<Term> h;
for (auto term : term_v_)
{
ret += h(*term) + 0x9e3779b9 + (ret << 6) + (ret >> 2);
ret ^= h(*term) + 0x9e3779b9 + (ret << 6) + (ret >> 2);
}
return ret;
}
// Implementation of Predicate's methods
Predicate::Predicate(const std::string& name, const TermV& arguments) : name_(name), arguments_(arguments) {}
std::string Predicate::to_str() const
{
std::ostringstream oss;
oss << name_ << '(' << arguments_ << ')';
return oss.str();
}
bool Predicate::operator==(const Term& other) const
{
if (const Predicate* c_other = dynamic_cast<const Predicate*>(&other))
{
return this->name_ == c_other->name_ and this->arguments_ == c_other->arguments_;
}
return false;
}
bool Predicate::operator<(const Term& other) const
{
if (const Predicate* c_other = dynamic_cast<const Predicate*>(&other))
{
if (this->name_ < c_other->name_) return true;
if (c_other->name_ < this->name_) return false;
return this->arguments_ < c_other->arguments_;
}
return this->type() < other.type();
}
std::size_t Predicate::hash() const
{
std::hash<std::string> h;
return h(name_)^(arguments_.hash());
}
// Implementation of stream operator
std::ostream& operator<<(std::ostream& os, const Term& term)
......
#ifndef _LIBIMAGINE_PLANNER_TYPES_H_
#define _LIBIMAGINE_PLANNER_TYPES_H_
// Let's group some functions and typedefs that are common to all the Types
// defined here in a macro for convenience.
#define TYPES_COMMON(Class)\
typedef std::shared_ptr<Class> Ptr;\
typedef std::shared_ptr<const Class> ConstPtr;\
......@@ -18,6 +20,11 @@ namespace imagine_planner
/**
* @brief Generic Term class.
*
* Declares the == and < operators and the hash function so they can be used
* with both unordered and ordered sets/maps. The class is abstract.
* Functionality is given by this class descendants (Atom, Number, TermV and
* Predicate).
*/
class Term
{
......@@ -26,32 +33,116 @@ class Term
typedef std::shared_ptr<Term> Ptr;
typedef std::shared_ptr<const Term> ConstPtr;
/**
* @brief Readable representation of the term.
*
* @return Readable string.
*/
virtual std::string to_str() const =0;
/**
* @brief Substitutes/clear the value of a given variable.
*
* Should the term be atomic or ground, this method does not have any effect.
* Otherwise, all the nested variables with the given name will be
* assigned the given value (or all the variables if the name is empty). If
* the value is a null pointer, the variable(s) are cleared.
*
* @param name Name of the variable(s). If empty, all the variables are
* affected.
* @param value New value given to the variable(s). If it is null, the
* variables are cleared.
*/
virtual void reset(const std::string& name="", Term::ConstPtr value=nullptr) =0;
/**
* @brief Tells whether the term has a nested unground variable.
*
* @return true if the term is an unground variable or contains one.
*/
virtual bool is_ground() const =0;
/**
* @brief true for atomic terms (i.e. numbers and atoms).
*
* @return true if the term is atomic.
*/
virtual bool is_atomic() const =0;
/**
* @brief Equality operator. Each type of Term is responsible to implement
* one that works for its own type.
*
* @param other Another term
*
* @return true if the two terms are equal.
*/
virtual bool operator==(const Term& other) const =0;
/**
* @brief Simple inequality operator implemented as the negation of the
* result given by operator==.
*
* @param other Another term
*
* @return true if the two terms are not equal.
*/
virtual bool operator!=(const Term& other) const { return not(*this == other); }
/**
* @brief LT operator. Included in the Term interface so terms can be used
* in ordered sets and maps.
*
* @param other Another term
*
* @return true if this term is smaller than the other.
*/
virtual bool operator<(const Term& other) const =0;
/**
* @brief Hash method, specified so terms can be used in unordered sets
* and maps.
*
* @return hash integer
*/
virtual std::size_t hash() const =0;
/**
* @brief Gives the type (class) of this term, so it can be used in
* heterogeneous comparisons (e.g. comparing Atoms with Numbers).
*
* It is not necessary to implement this method manually since it is
* automatically introduced by the TYPES_COMMON macro.
*
* @return the stringified class name.
*/
virtual std::string type() const =0;
/**
* @brief Copies and returns a pointer to the copy of the current term.
*
* The attributes of the derived class are maintained. The method is
* automatically introduced by the TYPES_COMMON macro, and its definition
* makes use of the copy constructor of the derived class. Therefore,
* the copy constructor should be explicitly defined if the behavior of the
* default one is not satisfactory.
*
* @return Pointer to a copy of this term.
*/
virtual Term::Ptr clone() const =0;
/**
* @brief Virtual destructor.
*/
virtual ~Term() {}
};
/**
* @brief
* @brief This Term can be used to represent qualitative concepts like names.
*
* It essentially contains a string: the name of the atom.
*/
class Atom : public Term
{
......@@ -63,22 +154,79 @@ class Atom : public Term
TYPES_COMMON(Atom);
/**
* @brief Creates an Atom with a certain name.
*
* @param name Name (label) of the atom.
*/
Atom(const std::string& name);
/**
* @brief The representation consists simply in the Atom's name.
*
* @return Atom's name
*/
virtual std::string to_str() const override { return name_; }
/**
* @brief Has no effect since this is an atomic term.
*
* @param name N/A
* @param value N/A
*/
virtual void reset(const std::string& name="", Term::ConstPtr value=nullptr) override {}
/**
* @brief Always returns true.
*
* @return true.
*/
virtual bool is_ground() const override { return true; }
/**
* @brief Always returns true.
*
* @return true.
*/
virtual bool is_atomic() const override { return true; }
/**
* @brief A term is equal to an Atom iff it is also an Atom and has the
* same name.
*
* @param other Another Term.
*
* @return true if both terms are Atoms and have the same name.
*/
virtual bool operator==(const Term& other) const override;
/**
* @brief Tells whether this Atom is lexicographically smaller than another
* given one.
*
* If both terms are Atoms, the method uses the Atoms' names to establish
* the lexicographical order. Otherwise, it uses the Term's types.
*
* @param other Another Term.
*
* @return true if this term is lexicographically smaller.
*/
virtual bool operator<(const Term& other) const override;
/**
* @brief Standard string hash is applied to name.
*
* @return name's hash.
*/
virtual std::size_t hash() const override;
/**
* @brief Gives Atom's name.
*
* This is a class specific method (i.e. not present in Term).
*
* @return Atom's name.
*/
virtual std::string name() const { return name_; }
};
......@@ -170,14 +318,18 @@ class TermV : public Term
TYPES_COMMON(TermV);
TermV();
TermV(const TermV& term_v);
TermV(const std::vector<Term::Ptr>& term_v);
TermV(const std::vector<Term::ConstPtr>& term_v);
TermV(const std::initializer_list<Term::Ptr>& il);
TermV(const std::initializer_list<Term::ConstPtr>& il);
TermV(const std::initializer_list<Term::Ptr>& il);
virtual std::string to_str() const override;
virtual void reset(const std::string& name="", Term::ConstPtr value=nullptr) override;
......@@ -196,32 +348,125 @@ class TermV : public Term
const Term::ConstPtr at(int idx) const { return term_v_.at(idx); }
CIter cbegin() const { return term_v_.cbegin(); }
CIter begin() const { return term_v_.cbegin(); }
CIter cend() const { return term_v_.cend(); }
CIter end() const { return term_v_.cend(); }
};
//class Compound : public Term
//{
//private:
class Predicate : public Term
{
private:
//std::string name_;
//TermV arguments_;
std::string name_;
TermV arguments_;
//public:
public:
TYPES_COMMON(Predicate);
Predicate(const std::string& name, const TermV& arguments=TermV());
virtual std::string to_str() const override;
virtual void reset(const std::string& name="", Term::ConstPtr value=nullptr) override { arguments_.reset(name, value); }
virtual bool is_ground() const override { return arguments_.is_ground(); }
virtual bool is_atomic() const override { return false; }
virtual bool operator==(const Term& other) const override;
virtual bool operator<(const Term& other) const override;
virtual std::size_t hash() const override;
const std::string& name() const { return name_; }
//TYPES_COMMON(Compound);
const TermV& arguments() const { return arguments_; }
//Compound(const std::string& name, const TermV& arguments=TermV());
};
class AtomFactory
{
public:
Atom::Ptr operator()(const std::string& name) const
{
return Atom::Ptr(new Atom(name));
}
};
//virtual std::string to_str() const override;
class NumberFactory
{
public:
Number::Ptr operator()(double number) const
{
return Number::Ptr(new Number(number));
}
};
class VariableFactory
{
public:
Variable::Ptr operator()(const std::string& name) const
{
return Variable::Ptr(new Variable(name));
}
};
//class TermVFactory
//{
//public:
//};
class PredicateFactory
{
private:
std::vector<Term::Ptr> gen_term_v() const
{
return std::vector<Term::Ptr>();
}
template<typename... Args>
std::vector<Term::Ptr> gen_term_v(double number, Args... args) const
{
Number::Ptr num(new Number(number));
auto term_v = gen_term_v(args...);
term_v.insert(term_v.begin(), num);
return term_v;
}
template<typename... Args>
std::vector<Term::Ptr> gen_term_v(const std::string& atom, Args... args) const
{
Atom::Ptr at(new Atom(atom));
auto term_v = gen_term_v(args...);
term_v.insert(term_v.begin(), at);
return term_v;
}
public:
template<typename... Args>
Predicate::Ptr operator()(const std::string& name, Args... args) const
{
TermV term_v = gen_term_v(args...);
return Predicate::Ptr(new Predicate(name, term_v));
}
};
/**
* @brief Stream operator that conveniently puts a Term printable version into
* an output stream.
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment