From 6b7c77f3a28d9a44afacb76e3db58a5ff5f59f4d Mon Sep 17 00:00:00 2001
From: Kelly Rauchenberger <fefferburbia@gmail.com>
Date: Sat, 26 Mar 2016 09:40:13 -0400
Subject: Added full hierarchy search for meronymy

---
 lib/noun_query.cpp | 302 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
 lib/noun_query.h   |  12 +++
 2 files changed, 313 insertions(+), 1 deletion(-)

diff --git a/lib/noun_query.cpp b/lib/noun_query.cpp
index cb11577..2c3f57c 100644
--- a/lib/noun_query.cpp
+++ b/lib/noun_query.cpp
@@ -121,6 +121,14 @@ namespace verbly {
     return *this;
   }
   
+  noun_query& noun_query::full_part_meronym_of(filter<noun> _f)
+  {
+    _f.clean();
+    _full_part_meronym_of = _f;
+    
+    return *this;
+  }
+  
   noun_query& noun_query::is_part_holonym()
   {
     _is_part_holonym = true;
@@ -136,6 +144,14 @@ namespace verbly {
     return *this;
   }
   
+  noun_query& noun_query::full_part_holonym_of(filter<noun> _f)
+  {
+    _f.clean();
+    _full_part_holonym_of = _f;
+    
+    return *this;
+  }
+  
   noun_query& noun_query::is_substance_meronym()
   {
     _is_substance_meronym = true;
@@ -151,6 +167,14 @@ namespace verbly {
     return *this;
   }
   
+  noun_query& noun_query::full_substance_meronym_of(filter<noun> _f)
+  {
+    _f.clean();
+    _full_substance_meronym_of = _f;
+    
+    return *this;
+  }
+  
   noun_query& noun_query::is_substance_holonym()
   {
     _is_substance_holonym = true;
@@ -166,6 +190,14 @@ namespace verbly {
     return *this;
   }
   
+  noun_query& noun_query::full_substance_holonym_of(filter<noun> _f)
+  {
+    _f.clean();
+    _full_substance_holonym_of = _f;
+    
+    return *this;
+  }
+  
   noun_query& noun_query::is_member_meronym()
   {
     _is_member_meronym = true;
@@ -181,6 +213,14 @@ namespace verbly {
     return *this;
   }
   
+  noun_query& noun_query::full_member_meronym_of(filter<noun> _f)
+  {
+    _f.clean();
+    _full_member_meronym_of = _f;
+    
+    return *this;
+  }
+  
   noun_query& noun_query::is_member_holonym()
   {
     _is_member_holonym = true;
@@ -196,6 +236,14 @@ namespace verbly {
     return *this;
   }
   
+  noun_query& noun_query::full_member_holonym_of(filter<noun> _f)
+  {
+    _f.clean();
+    _full_member_holonym_of = _f;
+    
+    return *this;
+  }
+  
   noun_query& noun_query::is_proper()
   {
     _is_proper = true;
@@ -336,7 +384,7 @@ namespace verbly {
   {
     std::stringstream construct;
     
-    if (!_full_hypernym_of.empty() || !_full_hyponym_of.empty())
+    if (!_full_hypernym_of.empty() || !_full_hyponym_of.empty() || !_full_part_meronym_of.empty() || !_full_part_holonym_of.empty() || !_full_substance_meronym_of.empty() || !_full_substance_holonym_of.empty() || !_full_member_meronym_of.empty() || !_full_member_holonym_of.empty())
     {
       construct << "WITH RECURSIVE ";
       
@@ -352,6 +400,36 @@ namespace verbly {
         ctes.push_back("hyponym_tree_" + std::to_string(hypernym._id) + " AS (SELECT hyponym_id FROM hypernymy WHERE hypernym_id = " + std::to_string(hypernym._id) + " UNION SELECT h.hyponym_id FROM hyponym_tree_" + std::to_string(hypernym._id) + " AS t INNER JOIN hypernymy AS h ON t.hyponym_id = h.hypernym_id)");
       }
       
+      for (auto holonym : _full_part_meronym_of.uniq_flatten())
+      {
+        ctes.push_back("part_meronym_tree_" + std::to_string(holonym._id) + " AS (SELECT meronym_id FROM part_meronymy WHERE holonym_id = " + std::to_string(holonym._id) + " UNION SELECT h.meronym_id FROM part_meronym_tree_" + std::to_string(holonym._id) + " AS t INNER JOIN part_meronymy AS h ON t.meronym_id = h.holonym_id)");
+      }
+      
+      for (auto meronym : _full_part_holonym_of.uniq_flatten())
+      {
+        ctes.push_back("part_holonym_tree_" + std::to_string(meronym._id) + " AS (SELECT holonym_id FROM part_meronymy WHERE meronym_id = " + std::to_string(meronym._id) + " UNION SELECT h.holonym_id FROM part_holonym_tree_" + std::to_string(meronym._id) + " AS t INNER JOIN part_meronymy AS h ON t.holonym_id = h.meronym_id)");
+      }
+      
+      for (auto holonym : _full_substance_meronym_of.uniq_flatten())
+      {
+        ctes.push_back("substance_meronym_tree_" + std::to_string(holonym._id) + " AS (SELECT meronym_id FROM substance_meronymy WHERE holonym_id = " + std::to_string(holonym._id) + " UNION SELECT h.meronym_id FROM substance_meronym_tree_" + std::to_string(holonym._id) + " AS t INNER JOIN substance_meronymy AS h ON t.meronym_id = h.holonym_id)");
+      }
+      
+      for (auto meronym : _full_substance_holonym_of.uniq_flatten())
+      {
+        ctes.push_back("substance_holonym_tree_" + std::to_string(meronym._id) + " AS (SELECT holonym_id FROM substance_meronymy WHERE meronym_id = " + std::to_string(meronym._id) + " UNION SELECT h.holonym_id FROM substance_holonym_tree_" + std::to_string(meronym._id) + " AS t INNER JOIN substance_meronymy AS h ON t.holonym_id = h.meronym_id)");
+      }
+      
+      for (auto holonym : _full_member_meronym_of.uniq_flatten())
+      {
+        ctes.push_back("member_meronym_tree_" + std::to_string(holonym._id) + " AS (SELECT meronym_id FROM member_meronymy WHERE holonym_id = " + std::to_string(holonym._id) + " UNION SELECT h.meronym_id FROM member_meronym_tree_" + std::to_string(holonym._id) + " AS t INNER JOIN member_meronymy AS h ON t.meronym_id = h.holonym_id)");
+      }
+      
+      for (auto meronym : _full_member_holonym_of.uniq_flatten())
+      {
+        ctes.push_back("member_holonym_tree_" + std::to_string(meronym._id) + " AS (SELECT holonym_id FROM member_meronymy WHERE meronym_id = " + std::to_string(meronym._id) + " UNION SELECT h.holonym_id FROM member_holonym_tree_" + std::to_string(meronym._id) + " AS t INNER JOIN member_meronymy AS h ON t.holonym_id = h.meronym_id)");
+      }
+      
       construct << verbly::implode(std::begin(ctes), std::end(ctes), ", ");
       construct << " ";
     }
@@ -619,6 +697,43 @@ namespace verbly {
       conditions.push_back(cond.str());
     }
     
+    if (!_full_part_meronym_of.empty())
+    {
+      std::function<std::string (filter<noun>, bool)> recur = [&] (filter<noun> f, bool notlogic) -> std::string {
+        switch (f.get_type())
+        {
+          case filter<noun>::type::singleton:
+          {
+            if (notlogic == f.get_notlogic())
+            {
+              return "noun_id IN (SELECT meronym_id FROM part_meronym_tree_" + std::to_string(f.get_elem()._id) + ")";
+            } else {
+              return "noun_id NOT IN (SELECT meronym_id FROM part_meronym_tree_" + std::to_string(f.get_elem()._id) + ")";
+            }
+          }
+          
+          case filter<noun>::type::group:
+          {
+            bool truelogic = notlogic != f.get_notlogic();
+            
+            std::list<std::string> clauses;
+            std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter<noun> f2) {
+              return recur(f2, truelogic);
+            });
+            
+            if (truelogic == f.get_orlogic())
+            {
+              return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")";
+            } else {
+              return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")";
+            }
+          }
+        }
+      };
+      
+      conditions.push_back(recur(_full_part_meronym_of, false));
+    }
+    
     if (_is_part_holonym)
     {
       conditions.push_back("noun_id IN (SELECT holonym_id FROM part_meronymy)");
@@ -673,6 +788,43 @@ namespace verbly {
       conditions.push_back(cond.str());
     }
     
+    if (!_full_part_holonym_of.empty())
+    {
+      std::function<std::string (filter<noun>, bool)> recur = [&] (filter<noun> f, bool notlogic) -> std::string {
+        switch (f.get_type())
+        {
+          case filter<noun>::type::singleton:
+          {
+            if (notlogic == f.get_notlogic())
+            {
+              return "noun_id IN (SELECT holonym_id FROM part_holonym_tree_" + std::to_string(f.get_elem()._id) + ")";
+            } else {
+              return "noun_id NOT IN (SELECT holonym_id FROM part_holonym_tree_" + std::to_string(f.get_elem()._id) + ")";
+            }
+          }
+          
+          case filter<noun>::type::group:
+          {
+            bool truelogic = notlogic != f.get_notlogic();
+            
+            std::list<std::string> clauses;
+            std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter<noun> f2) {
+              return recur(f2, truelogic);
+            });
+            
+            if (truelogic == f.get_orlogic())
+            {
+              return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")";
+            } else {
+              return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")";
+            }
+          }
+        }
+      };
+      
+      conditions.push_back(recur(_full_part_holonym_of, false));
+    }
+    
     if (_is_substance_meronym)
     {
       conditions.push_back("noun_id IN (SELECT meronym_id FROM substance_meronymy)");
@@ -727,6 +879,43 @@ namespace verbly {
       conditions.push_back(cond.str());
     }
     
+    if (!_full_substance_meronym_of.empty())
+    {
+      std::function<std::string (filter<noun>, bool)> recur = [&] (filter<noun> f, bool notlogic) -> std::string {
+        switch (f.get_type())
+        {
+          case filter<noun>::type::singleton:
+          {
+            if (notlogic == f.get_notlogic())
+            {
+              return "noun_id IN (SELECT meronym_id FROM substance_meronym_tree_" + std::to_string(f.get_elem()._id) + ")";
+            } else {
+              return "noun_id NOT IN (SELECT meronym_id FROM substance_meronym_tree_" + std::to_string(f.get_elem()._id) + ")";
+            }
+          }
+          
+          case filter<noun>::type::group:
+          {
+            bool truelogic = notlogic != f.get_notlogic();
+            
+            std::list<std::string> clauses;
+            std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter<noun> f2) {
+              return recur(f2, truelogic);
+            });
+            
+            if (truelogic == f.get_orlogic())
+            {
+              return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")";
+            } else {
+              return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")";
+            }
+          }
+        }
+      };
+      
+      conditions.push_back(recur(_full_substance_meronym_of, false));
+    }
+    
     if (_is_substance_holonym)
     {
       conditions.push_back("noun_id IN (SELECT holonym_id FROM substance_meronymy)");
@@ -781,6 +970,43 @@ namespace verbly {
       conditions.push_back(cond.str());
     }
     
+    if (!_full_substance_holonym_of.empty())
+    {
+      std::function<std::string (filter<noun>, bool)> recur = [&] (filter<noun> f, bool notlogic) -> std::string {
+        switch (f.get_type())
+        {
+          case filter<noun>::type::singleton:
+          {
+            if (notlogic == f.get_notlogic())
+            {
+              return "noun_id IN (SELECT holonym_id FROM substance_holonym_tree_" + std::to_string(f.get_elem()._id) + ")";
+            } else {
+              return "noun_id NOT IN (SELECT holonym_id FROM substance_holonym_tree_" + std::to_string(f.get_elem()._id) + ")";
+            }
+          }
+          
+          case filter<noun>::type::group:
+          {
+            bool truelogic = notlogic != f.get_notlogic();
+            
+            std::list<std::string> clauses;
+            std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter<noun> f2) {
+              return recur(f2, truelogic);
+            });
+            
+            if (truelogic == f.get_orlogic())
+            {
+              return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")";
+            } else {
+              return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")";
+            }
+          }
+        }
+      };
+      
+      conditions.push_back(recur(_full_substance_holonym_of, false));
+    }
+    
     if (_is_member_meronym)
     {
       conditions.push_back("noun_id IN (SELECT meronym_id FROM member_meronymy)");
@@ -835,6 +1061,43 @@ namespace verbly {
       conditions.push_back(cond.str());
     }
     
+    if (!_full_member_meronym_of.empty())
+    {
+      std::function<std::string (filter<noun>, bool)> recur = [&] (filter<noun> f, bool notlogic) -> std::string {
+        switch (f.get_type())
+        {
+          case filter<noun>::type::singleton:
+          {
+            if (notlogic == f.get_notlogic())
+            {
+              return "noun_id IN (SELECT meronym_id FROM member_meronym_tree_" + std::to_string(f.get_elem()._id) + ")";
+            } else {
+              return "noun_id NOT IN (SELECT meronym_id FROM member_meronym_tree_" + std::to_string(f.get_elem()._id) + ")";
+            }
+          }
+          
+          case filter<noun>::type::group:
+          {
+            bool truelogic = notlogic != f.get_notlogic();
+            
+            std::list<std::string> clauses;
+            std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter<noun> f2) {
+              return recur(f2, truelogic);
+            });
+            
+            if (truelogic == f.get_orlogic())
+            {
+              return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")";
+            } else {
+              return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")";
+            }
+          }
+        }
+      };
+      
+      conditions.push_back(recur(_full_member_meronym_of, false));
+    }
+    
     if (_is_member_holonym)
     {
       conditions.push_back("noun_id IN (SELECT holonym_id FROM member_meronym)");
@@ -889,6 +1152,43 @@ namespace verbly {
       conditions.push_back(cond.str());
     }
     
+    if (!_full_member_holonym_of.empty())
+    {
+      std::function<std::string (filter<noun>, bool)> recur = [&] (filter<noun> f, bool notlogic) -> std::string {
+        switch (f.get_type())
+        {
+          case filter<noun>::type::singleton:
+          {
+            if (notlogic == f.get_notlogic())
+            {
+              return "noun_id IN (SELECT holonym_id FROM member_holonym_tree_" + std::to_string(f.get_elem()._id) + ")";
+            } else {
+              return "noun_id NOT IN (SELECT holonym_id FROM member_holonym_tree_" + std::to_string(f.get_elem()._id) + ")";
+            }
+          }
+          
+          case filter<noun>::type::group:
+          {
+            bool truelogic = notlogic != f.get_notlogic();
+            
+            std::list<std::string> clauses;
+            std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter<noun> f2) {
+              return recur(f2, truelogic);
+            });
+            
+            if (truelogic == f.get_orlogic())
+            {
+              return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")";
+            } else {
+              return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")";
+            }
+          }
+        }
+      };
+      
+      conditions.push_back(recur(_full_member_holonym_of, false));
+    }
+    
     if (_is_proper)
     {
       conditions.push_back("proper = 1");
diff --git a/lib/noun_query.h b/lib/noun_query.h
index 0c41a68..e95e0c0 100644
--- a/lib/noun_query.h
+++ b/lib/noun_query.h
@@ -25,21 +25,27 @@ namespace verbly {
       
       noun_query& is_part_meronym();
       noun_query& part_meronym_of(filter<noun> _f);
+      noun_query& full_part_meronym_of(filter<noun> _f);
       
       noun_query& is_part_holonym();
       noun_query& part_holonym_of(filter<noun> _f);
+      noun_query& full_part_holonym_of(filter<noun> _f);
       
       noun_query& is_substance_meronym();
       noun_query& substance_meronym_of(filter<noun> _f);
+      noun_query& full_substance_meronym_of(filter<noun> _f);
       
       noun_query& is_substance_holonym();
       noun_query& substance_holonym_of(filter<noun> _f);
+      noun_query& full_substance_holonym_of(filter<noun> _f);
       
       noun_query& is_member_meronym();
       noun_query& member_meronym_of(filter<noun> _f);
+      noun_query& full_member_meronym_of(filter<noun> _f);
       
       noun_query& is_member_holonym();
       noun_query& member_holonym_of(filter<noun> _f);
+      noun_query& full_member_holonym_of(filter<noun> _f);
       
       noun_query& is_proper();
       noun_query& is_not_proper();
@@ -89,21 +95,27 @@ namespace verbly {
       
       bool _is_part_meronym = false;
       filter<noun> _part_meronym_of;
+      filter<noun> _full_part_meronym_of;
       
       bool _is_substance_meronym = false;
       filter<noun> _substance_meronym_of;
+      filter<noun> _full_substance_meronym_of;
       
       bool _is_member_meronym = false;
       filter<noun> _member_meronym_of;
+      filter<noun> _full_member_meronym_of;
       
       bool _is_part_holonym = false;
       filter<noun> _part_holonym_of;
+      filter<noun> _full_part_holonym_of;
       
       bool _is_substance_holonym = false;
       filter<noun> _substance_holonym_of;
+      filter<noun> _full_substance_holonym_of;
       
       bool _is_member_holonym = false;
       filter<noun> _member_holonym_of;
+      filter<noun> _full_member_holonym_of;
       
       bool _is_proper = false;
       bool _is_not_proper = false;
-- 
cgit 1.4.1