diff --git a/src/examples/types_test.cpp b/src/examples/types_test.cpp
index 5d959877b1992a988dfc5b244aef97f6f8ba04d7..f2d8c65c0d7100d2e1317c9de806cf37e21997c2 100644
--- a/src/examples/types_test.cpp
+++ b/src/examples/types_test.cpp
@@ -214,6 +214,7 @@ BOOST_AUTO_TEST_CASE(substitution_test)
   Predicate p5("q", "Z");
   Predicate p6("r");
   Substitution sigma({{"X", TermWrapper("a")}, {"Y", TermWrapper("b")}});
+  Substitution sigma_({{"W", TermWrapper("c")}});
   INFO("p1 = " << p1);
   INFO("p2 = " << p2);
   INFO("p3 = " << p3);
@@ -233,5 +234,13 @@ BOOST_AUTO_TEST_CASE(substitution_test)
   BOOST_CHECK_EQUAL(p4_.to_str(), "q(b)");
   BOOST_CHECK_EQUAL(p5_.to_str(), "q(Z)");
   BOOST_CHECK_EQUAL(p6_.to_str(), "r()");
+  Substitution sigma_x = sigma + sigma_;
+  BOOST_CHECK_EQUAL(sigma_x.to_str(), "{\n  W -> c,\n  X -> a,\n  Y -> b\n}");
+}
+
+BOOST_AUTO_TEST_CASE(planstate_test)
+{
+  PlanState state({Predicate("p", "x", "y"), Predicate("q", "y"), Predicate("r")});
+  INFO(state);
 }
 
diff --git a/src/types.cpp b/src/types.cpp
index 664a0fd8153135441c8f74b95fb13153a4e72107..7ed05af7be6d5121b96beff437ccbef93c372a54 100644
--- a/src/types.cpp
+++ b/src/types.cpp
@@ -231,6 +231,36 @@ void Substitution::remove(const std::string& varname)
   sigma_.erase(varname);
 }
 
+void Substitution::operator+=(const Substitution& other)
+{
+  for (auto entry : other)
+  {
+    sigma_.insert(entry);
+  }
+}
+
+void Substitution::operator-=(const Substitution& other)
+{
+  for (auto entry : other)
+  {
+    sigma_.erase(entry.first);
+  }
+}
+
+Substitution Substitution::operator+(const Substitution& other) const
+{
+  Substitution ret(*this);
+  ret += other;
+  return ret;
+}
+
+Substitution Substitution::operator-(const Substitution& other) const
+{
+  Substitution ret;
+  ret -= other;
+  return ret;
+}
+
 Predicate Substitution::operator()(const Predicate& predicate) const
 {
   TermV arguments;
@@ -248,22 +278,44 @@ Predicate Substitution::operator()(const Predicate& predicate) const
 
 PlanState::PlanState() {}
 
-PlanState::PlanState(std::initializer_list<Predicate> il) : predicates_(il) {}
-
-// Implementation of StateQuery
+PlanState::PlanState(const std::set<Predicate>& predicates) :
+  predicates_(predicates) {}
 
+std::string PlanState::to_str() const
+{
+  std::ostringstream oss;
+  bool first = true;
+  oss << '{';
+  for (const Predicate& pred : predicates_)
+  {
+    if (not first) oss << ',';
+    oss << pred;
+    first = false;
+  }
+  oss << '}';
+  return oss.str();
+}
 
-//StateQuery::StateQuery(const PlanState& state, const TermV& parameters,
-    //const std::string& query) :
-  //state_(state), parameters_(parameters), values_(parameters),
-//{
+std::size_t PlanState::hash() const
+{
+  std::size_t acc = 0;
+  for (const Predicate& pred : predicates_)
+  {
+    acc += pred.hash();
+  }
+  return acc;
+}
 
-//}
 
-//bool StateQuery::next_solution()
-//{
-  //return false;
-//}
+bool PlanState::subset_of(const PlanState& other) const
+{
+  if (predicates_.size() > other.predicates_.size()) return false;
+  for (const Predicate& pred : predicates_)
+  {
+    if (not other.has(pred)) return false;
+  }
+  return true;
+}
 
 // Implementation of stream operator
 
diff --git a/src/types.h b/src/types.h
index e3925f2e8eafd601bd4deb7e53081102fbeed302..ce5a13a79911a0e8f47543bbe34dd555a80e0075 100644
--- a/src/types.h
+++ b/src/types.h
@@ -261,6 +261,14 @@ class Substitution : public Stringifiable
 
     void remove(const std::string& varname);
 
+    void operator+=(const Substitution& other);
+
+    void operator-=(const Substitution& other);
+
+    Substitution operator+(const Substitution& other) const;
+
+    Substitution operator-(const Substitution& other) const;
+
     Predicate operator()(const Predicate& predicate) const;
 
     int size() const { return sigma_.size(); }
@@ -271,49 +279,54 @@ class Substitution : public Stringifiable
 
 };
 
-class PlanState
+class PlanState : public Stringifiable,
+                  public Hashable
 {
   private:
-    typedef std::set<Predicate> Container;
-
-    Container predicates_;
+    std::set<Predicate> predicates_;
 
   public:
-    typedef Container::const_iterator CIter;
+    typedef std::set<Predicate>::const_iterator CIter;
 
     PlanState();
 
-    PlanState(std::initializer_list<Predicate> il);
-
-    template <typename InputIterator>
-    PlanState(InputIterator begin, InputIterator end) :
-      predicates_(begin, end) {}
-
-    CIter begin() const { return predicates_.begin(); }
+    PlanState(const std::set<Predicate>& predicates);
 
-    CIter end() const { return predicates_.end(); }
+    virtual std::string to_str() const override;
 
-};
+    virtual std::size_t hash() const override;
 
+    bool operator==(const PlanState& other) const
+    {
+      return predicates_ == other.predicates_;
+    }
 
-//class Operator
-//{
-  //private:
+    bool subset_of(const PlanState& other) const;
 
-    //TermV parameters_, values_;
-    //std::string name_, pre_, post_;
+    bool has(const Predicate& predicate) const
+    {
+      return (bool)predicates_.count(predicate);
+    }
 
-  //public:
+    void put(const Predicate& predicate)
+    {
+      predicates_.insert(predicate);
+    }
 
-    //Operator(TermV parameters_, const std::string& pre,
-        //const std::string& post);
+    void remove(const Predicate& predicate)
+    {
+      predicates_.erase(predicate);
+    }
 
-    //bool is_ground() const;
+    template <typename InputIterator>
+    PlanState(InputIterator begin, InputIterator end) :
+      predicates_(begin, end) {}
 
-    //int arity() const { return parameters_.size(); }
+    CIter begin() const { return predicates_.begin(); }
 
-//};
+    CIter end() const { return predicates_.end(); }
 
+};
 
 /** 
  * @brief Stream operator that conveniently puts a Stringifiable object into