knowrob  2.1.0
A Knowledge Base System for Cognition-enabled Robots
QueryTree.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of KnowRob, please consult
3  * https://github.com/knowrob/knowrob for license details.
4  */
5 
6 #include <gtest/gtest.h>
7 #include <utility>
8 #include "knowrob/Logger.h"
9 #include "knowrob/queries/QueryTree.h"
10 #include "knowrob/formulas/Top.h"
11 
12 using namespace knowrob;
13 using namespace knowrob::modals;
14 
16  : rootNode_(new Node(nullptr, query, false)) {
17  openNodes_.push(rootNode_);
18  while (!openNodes_.empty()) {
20  }
21 }
22 
24  std::list<Node *> fifo;
25  fifo.push_back(rootNode_);
26  while (!fifo.empty()) {
27  Node *next = fifo.front();
28  fifo.pop_front();
29  for (auto *x: next->successors) {
30  fifo.push_back(x);
31  }
32  delete next;
33  }
34  rootNode_ = nullptr;
35 }
36 
37 QueryTree::Node::Node(Node *parent, FormulaPtr formula, bool isNegated)
38  : parent(parent),
39  formula(std::move(formula)),
40  isNegated(isNegated),
41  isOpen(true) {
42 }
43 
45  switch (formula->type()) {
46  case FormulaType::MODAL:
49  return 1;
51  return isNegated ? 0 : 1;
54  return isNegated ? 1 : 0;
55  }
56  return 0;
57 }
58 
59 bool QueryTree::NodeComparator::operator()(const Node *a, const Node *b) const {
60  int priority_a = a->priority();
61  int priority_b = b->priority();
62  if (priority_a != priority_b) {
63  return priority_a < priority_b;
64  } else {
65  return a < b;
66  }
67 }
68 
69 std::list<QueryTree::Node *> QueryTree::getLeafs(Node *n) {
70  std::list<Node *> out;
71  std::list<Node *> fifo;
72  fifo.push_back(n);
73  while (!fifo.empty()) {
74  Node *next = fifo.front();
75  fifo.pop_front();
76  if (next->successors.empty()) {
77  out.push_back(next);
78  } else {
79  for (auto *x: next->successors) {
80  fifo.push_back(x);
81  }
82  }
83  }
84  return out;
85 }
86 
87 QueryTree::Node *QueryTree::createNode(Node *parent, const FormulaPtr &phi, bool isNegated) {
88  Node *newNode = new Node(parent, phi, isNegated);
89  parent->successors.push_back(newNode);
90  openNodes_.push(newNode);
91  return newNode;
92 }
93 
95  Node *parent = leaf;
96  do {
97  if (parent->isOpen) return false;
98  parent = parent->parent;
99  } while (parent);
100  return true;
101 }
102 
103 void QueryTree::constructPath(Node *leaf, Path &path) {
104  Node *parent = leaf;
105  do {
106  if (parent->formula->type() == FormulaType::PREDICATE ||
107  parent->formula->type() == FormulaType::MODAL) {
108  if (parent->isNegated) {
109  path.nodes_.push_back(std::make_shared<Negation>(parent->formula));
110  } else {
111  path.nodes_.push_back(parent->formula);
112  }
113  }
114  parent = parent->parent;
115  } while (parent);
116 }
117 
119  auto next = openNodes_.top();
120  next->isOpen = false;
121  openNodes_.pop();
122 
123  switch (next->formula->type()) {
125  case FormulaType::MODAL:
126  for (Node *leaf: getLeafs(next)) {
127  if (hasCompletePath(leaf)) {
128  paths_.emplace_back();
129  auto &path = paths_.back();
130  constructPath(leaf, path);
131  }
132  }
133  break;
134 
136  auto *formula = (Conjunction *) next->formula.get();
137  if (next->isNegated) {
138  for (Node *leaf: getLeafs(next)) {
139  for (auto &phi: formula->formulae()) {
140  createNode(leaf, phi, true);
141  }
142  }
143  } else {
144  for (Node *leaf: getLeafs(next)) {
145  Node *parent = leaf;
146  for (auto &phi: formula->formulae()) {
147  parent = createNode(parent, phi, false);
148  }
149  }
150  }
151  break;
152  }
153 
155  auto *formula = (Disjunction *) next->formula.get();
156  if (next->isNegated) {
157  for (Node *leaf: getLeafs(next)) {
158  Node *parent = leaf;
159  for (auto &phi: formula->formulae()) {
160  parent = createNode(parent, phi, true);
161  }
162  }
163  } else {
164  for (Node *leaf: getLeafs(next)) {
165  for (auto &phi: formula->formulae()) {
166  createNode(leaf, phi, false);
167  }
168  }
169  }
170  break;
171  }
172 
174  auto *formula = (Implication *) next->formula.get();
175  if (next->isNegated) {
176  for (Node *leaf: getLeafs(next)) {
177  Node *parent = leaf;
178  parent = createNode(parent, formula->antecedent(), false);
179  createNode(parent, formula->consequent(), true);
180  }
181  } else {
182  for (Node *leaf: getLeafs(next)) {
183  createNode(leaf, formula->antecedent(), true);
184  createNode(leaf, formula->consequent(), false);
185  }
186  }
187  break;
188  }
189 
190  case FormulaType::NEGATION: {
191  auto *formula = (Negation *) next->formula.get();
192  for (Node *leaf: getLeafs(next)) {
193  createNode(leaf, formula->negatedFormula(), !next->isNegated);
194  }
195  break;
196  }
197  }
198 }
199 
200 std::shared_ptr<Formula> QueryTree::Path::toFormula() const {
201  if (nodes_.empty()) {
202  return Top::get();
203  } else if (nodes_.size() == 1) {
204  return nodes_.front();
205  } else {
206  return std::make_shared<Conjunction>(nodes_);
207  }
208 }
Node(Node *parent, FormulaPtr formula, bool isNegated)
Definition: QueryTree.cpp:37
const FormulaPtr formula
Definition: QueryTree.h:60
std::list< Node * > successors
Definition: QueryTree.h:63
std::vector< FormulaPtr > nodes_
Definition: QueryTree.h:98
std::shared_ptr< Formula > toFormula() const
Definition: QueryTree.cpp:200
std::priority_queue< Node *, std::vector< Node * >, NodeComparator > openNodes_
Definition: QueryTree.h:113
Node * createNode(Node *parent, const FormulaPtr &phi, bool isNegated)
Definition: QueryTree.cpp:87
std::list< Path > paths_
Definition: QueryTree.h:105
static bool hasCompletePath(Node *leaf)
Definition: QueryTree.cpp:94
static void constructPath(Node *leaf, Path &path)
Definition: QueryTree.cpp:103
static std::list< QueryTree::Node * > getLeafs(Node *n)
Definition: QueryTree.cpp:69
QueryTree(const FormulaPtr &query)
Definition: QueryTree.cpp:15
static const std::shared_ptr< Top > & get()
Definition: Top.cpp:11
FormulaRule & formula()
Definition: formula.cpp:283
std::shared_ptr< Formula > FormulaPtr
Definition: Formula.h:99
bool operator()(const Node *a, const Node *b) const
Definition: QueryTree.cpp:59