Commit d1c3a3a5 authored by Alejandro Suarez Hernandez's avatar Alejandro Suarez Hernandez
Browse files

(Term) Factories are fully implemented. Added Stringifiable class.

parent 885ba85e
#include "types.h"
#include <iostream>
#include <set>
#include <unordered_set>
using namespace imagine_planner;
#define CONTAINER_TO_STREAM(ctn, os)\
bool first = true;\
os << '{';\
for (auto thing : ctn)\
{\
if (not first) os << ',';\
os << thing;\
first = false;\
}\
os << '}';\
return os;
AtomFactory A;
NumberFactory N;
VariableFactory V;
TermVFactory L;
PredicateFactory P;
const char* b2s(bool b)
{
return b? "true" : "false";
......@@ -10,16 +29,12 @@ const char* b2s(bool b)
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;
CONTAINER_TO_STREAM(ctn, os);
}
std::ostream& operator<<(std::ostream& os, const std::unordered_set<Predicate, std::hash<Term>>& ctn)
{
CONTAINER_TO_STREAM(ctn, os);
}
int main(int argc, char* argv[])
......@@ -53,17 +68,24 @@ int main(int argc, char* argv[])
// 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;
std::cout << std::endl;
auto p1 = P("p", A("x"), A("y")); std::cout << p1->hash() << std::endl;
auto p2 = P("p", A("x"), A("y")); std::cout << p2->hash() << std::endl;
auto p3 = P("p", A("x"), V("Y")); std::cout << p3->hash() << std::endl;
auto p4 = P("p", A("y"), A("x")); std::cout << p4->hash() << std::endl;
auto p5 = P("p", A("z")); std::cout << p5->hash() << std::endl;
auto p6 = P("p", N(1), N(3)); std::cout << p6->hash() << std::endl;
auto p7 = P("r", A("x"), N(0.5)); std::cout << p7->hash() << std::endl;
auto p8 = P("r", A("x"), N(0.5+5E-10)); std::cout << p8->hash() << std::endl;
auto p9 = P("r", A("x"), N(0.5+2E-9)); std::cout << p9->hash() << std::endl;
auto p10 = P("emptyhand");
std::cout << b2s(p1->arguments() == p2->arguments()) << std::endl;
std::set<Predicate> predicate_set{*p1, *p2, *p3, *p4, *p5, *p6, *p7, *p8, *p9, *p10};
std::unordered_set<Predicate, std::hash<Term>> predicate_uset{*p1, *p2, *p3, *p4, *p5, *p6, *p7, *p8, *p9, *p10};
std::cout << predicate_set << std::endl;
std::cout << predicate_uset << std::endl;
// Testing Predicate ordered sets.
//std::set<Predicate> predicate_set;
//predicate_set.add(Predicate("p", {}));
}
......@@ -60,25 +60,19 @@ bool Number::operator<(const Term& other) const
std::size_t Number::hash() const
{
std::hash<int> h;
return is_int()? h(int(number_)) : 0; // Return 0 for non-integer values to
// avoid problems in maps and sets
// Return 0 for non-integer values to avoid problems in maps and sets
// (non-integer quantities would be assigned to the same bucket).
return is_int()? h(std::round(number_)) : 0;
}
bool Number::is_int() const
{
return std::fabs(number_ - int(number_)) < EPSILON_;
return std::fabs(number_ - std::round(number_)) < EPSILON_;
}
// Implementation of Variable's methods
Variable::Variable(const std::string& name) : name_(name), value_(nullptr) {}
Variable::Variable(const std::string& name, const Term& value) : name_(name), value_(value.clone()) {}
void Variable::reset(const std::string& name, Term::ConstPtr value)
{
if (name.empty() or name == name_) value_ = value;
}
Variable::Variable(const std::string& name) : name_(name) {}
bool Variable::operator==(const Term& other) const
{
......@@ -120,21 +114,11 @@ TermV::TermV(const std::vector<Term::Ptr>& term_v)
COPY_TERMV();
}
TermV::TermV(const std::vector<Term::ConstPtr>& term_v)
{
COPY_TERMV();
}
TermV::TermV(const std::initializer_list<Term::Ptr>& term_v)
{
COPY_TERMV();
}
TermV::TermV(const std::initializer_list<Term::ConstPtr>& term_v)
{
COPY_TERMV();
}
std::string TermV::to_str() const
{
std::ostringstream oss;
......@@ -148,14 +132,6 @@ std::string TermV::to_str() const
return oss.str();
}
void TermV::reset(const std::string& name, Term::ConstPtr value)
{
for (auto term : term_v_)
{
term->reset(name, value);
}
}
bool TermV::is_ground() const
{
for (auto term : term_v_)
......@@ -165,6 +141,12 @@ bool TermV::is_ground() const
return true;
}
TermV& TermV::operator=(const TermV& term_v)
{
COPY_TERMV();
return *this;
}
bool TermV::operator==(const Term& other) const
{
if (const TermV* c_other = dynamic_cast<const TermV*>(&other))
......@@ -172,7 +154,7 @@ bool TermV::operator==(const Term& other) const
if (this->size() != c_other->size()) return false;
for (int idx = 0; idx < this->size(); ++idx)
{
if (this->at(idx) != c_other->at(idx)) return false;
if (*(this->at(idx)) != *(c_other->at(idx))) return false;
}
return true;
}
......@@ -208,7 +190,8 @@ std::size_t TermV::hash() const
// Implementation of Predicate's methods
Predicate::Predicate(const std::string& name, const TermV& arguments) : name_(name), arguments_(arguments) {}
Predicate::Predicate(const std::string& name, const TermV& arguments) :
name_(name), arguments_(arguments) {}
std::string Predicate::to_str() const
{
......@@ -221,7 +204,8 @@ 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 this->name_ == c_other->name_ and
this->arguments_ == c_other->arguments_;
}
return false;
}
......@@ -243,11 +227,31 @@ std::size_t Predicate::hash() const
return h(name_)^(arguments_.hash());
}
// Implementation of Substitution's methods
Substitution::Substitution(std::initializer_list<Entry> il) : map_(il) {}
Term::Ptr Substitution::get(const std::string& key) const
{
auto it = map_.find(key);
return it == map_.end()? nullptr : it->second;
}
void Substitution::put(const std::string& key, Term::Ptr term)
{
map_[key] = term;
}
void Substitution::remove(const std::string& key)
{
map_.erase(key);
}
// Implementation of stream operator
std::ostream& operator<<(std::ostream& os, const Term& term)
std::ostream& operator<<(std::ostream& os, const Stringifiable& strable)
{
os << term.to_str();
os << strable.to_str();
return os;
}
......@@ -256,7 +260,8 @@ std::ostream& operator<<(std::ostream& os, const Term& term)
namespace std
{
std::size_t hash<imagine_planner::Term>::operator()(const imagine_planner::Term& term) const
std::size_t hash<imagine_planner::Term>::operator()(
const imagine_planner::Term& term) const
{
return term.hash();
}
......
......@@ -4,58 +4,57 @@
// 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;\
typedef std::shared_ptr<const Class> Ptr;\
virtual std::string type() const override { return #Class; }\
virtual Term::Ptr clone() const override { return Term::Ptr(new Class(*this)); }\
virtual Term::Ptr clone() const override\
{\
return Term::Ptr(new Class(*this));\
}\
#include <functional>
#include <memory>
#include <ostream>
#include <string>
#include <vector>
#include <unordered_map>
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).
* @brief Abstract class (interface-like) that simply declares the to_str
* method (to be implemented by specific types).
*/
class Term
class Stringifiable
{
public:
typedef std::shared_ptr<Term> Ptr;
typedef std::shared_ptr<const Term> ConstPtr;
/**
* @brief Readable representation of the term.
* @brief Readable representation of the object.
*
* @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;
virtual ~Stringifiable() {}
};
/**
* @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 : public Stringifiable
{
public:
/** Terms are immutable, so only pointers to const types are considered. */
typedef std::shared_ptr<const Term> Ptr;
/**
* @brief Tells whether the term has a nested unground variable.
*
......@@ -88,7 +87,10 @@ class Term
*
* @return true if the two terms are not equal.
*/
virtual bool operator!=(const Term& other) const { return not(*this == other); }
virtual bool operator!=(const Term& other) const
{
return not(*this == other);
}
/**
* @brief LT operator. Included in the Term interface so terms can be used
......@@ -168,14 +170,6 @@ class Atom : public Term
*/
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.
*
......@@ -246,9 +240,10 @@ class Number : public Term
Number(double number);
virtual std::string to_str() const override { return std::to_string(number_); }
virtual void reset(const std::string& name="", Term::ConstPtr value=nullptr) override {}
virtual std::string to_str() const override
{
return std::to_string(number_);
}
virtual bool is_ground() const override { return true; }
......@@ -276,21 +271,15 @@ class Variable : public Term
std::string name_;
Term::ConstPtr value_;
public:
TYPES_COMMON(Variable);
Variable(const std::string& name);
Variable(const std::string& name, const Term& value);
virtual std::string to_str() const override { return value_? value_->to_str() : name_; }
virtual void reset(const std::string& name="", Term::ConstPtr value=nullptr) override;
virtual std::string to_str() const override { return name_; }
virtual bool is_ground() const override { return bool(value_); }
virtual bool is_ground() const override { return false; }
virtual bool is_atomic() const override { return false; }
......@@ -302,8 +291,6 @@ class Variable : public Term
const std::string& name() const { return name_; }
Term::ConstPtr value() const { return value_; }
};
class TermV : public Term
......@@ -324,20 +311,16 @@ class TermV : public Term
TermV(const std::vector<Term::Ptr>& term_v);
TermV(const std::vector<Term::ConstPtr>& term_v);
TermV(const std::initializer_list<Term::ConstPtr>& il);
TermV(const std::initializer_list<Term::Ptr>& il);
TermV(const std::initializer_list<Term::Ptr>& term_v);
virtual std::string to_str() const override;
virtual void reset(const std::string& name="", Term::ConstPtr value=nullptr) override;
virtual bool is_ground() const override;
virtual bool is_atomic() const override { return false; }
TermV& operator=(const TermV& term_v);
virtual bool operator==(const Term& other) const override;
virtual bool operator<(const Term& other) const override;
......@@ -346,7 +329,7 @@ class TermV : public Term
int size() const { return term_v_.size(); }
const Term::ConstPtr at(int idx) const { return term_v_.at(idx); }
const Term::Ptr at(int idx) const { return term_v_.at(idx); }
CIter begin() const { return term_v_.cbegin(); }
......@@ -370,8 +353,6 @@ class Predicate : public Term
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; }
......@@ -422,15 +403,7 @@ class VariableFactory
};
//class TermVFactory
//{
//public:
//};
class PredicateFactory
class TermVFactory
{
private:
......@@ -440,43 +413,79 @@ class PredicateFactory
}
template<typename... Args>
std::vector<Term::Ptr> gen_term_v(double number, Args... args) const
std::vector<Term::Ptr> gen_term_v(Term::Ptr term, Args... args) const
{
Number::Ptr num(new Number(number));
auto term_v = gen_term_v(args...);
term_v.insert(term_v.begin(), num);
term_v.insert(term_v.begin(), term);
return term_v;
}
public:
template<typename... Args>
std::vector<Term::Ptr> gen_term_v(const std::string& atom, Args... args) const
TermV::Ptr operator()(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;
return TermV::Ptr(new TermV(gen_term_v(args...)));
}
};
class PredicateFactory
{
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));
TermVFactory L;
return Predicate::Ptr(new Predicate(name, *L(args...)));
}
};
class Substitution : public Stringifiable
{
private:
typedef std::unordered_map<std::string, Term::Ptr> Map;
Map map_;
public:
typedef std::pair<const std::string, Term::Ptr> Entry;
Substitution(std::initializer_list<Entry> il);
Term::Ptr get(const std::string& key) const;
void put(const std::string& key, Term::Ptr term);
void remove(const std::string& key);
Predicate::Ptr operator()(Predicate::Ptr input) const;
TermV::Ptr operator()(TermV::Ptr input) const;
int size() const { return map_.size(); }
Map::const_iterator begin() const { return map_.cbegin(); }
Map::const_iterator end() const { return map_.cbegin(); }
};
/**
* @brief Stream operator that conveniently puts a Term printable version into
* @brief Stream operator that conveniently puts a Stringifiable object into
* an output stream.
*
* @param os Output stream
* @param term Term to be written into the stream
* @param strable object to be written into the stream
*
* @return os after the insertion
*/
std::ostream& operator<<(std::ostream& os, const Term& term);
std::ostream& operator<<(std::ostream& os, const Stringifiable& strable);
} /* end imagine_planner namespace */
......
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