knowrob  2.1.0
A Knowledge Base System for Cognition-enabled Robots
AnswerYes.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 <utility>
7 
8 #include "iomanip"
9 #include "knowrob/queries/AnswerYes.h"
10 #include "knowrob/knowrob.h"
11 #include "knowrob/Logger.h"
12 #include "knowrob/integration/python/utils.h"
13 
14 using namespace knowrob;
15 
17  : Answer(),
18  substitution_(std::make_shared<Bindings>()) {
19  setIsPositive(true);
20 }
21 
23  : Answer(),
24  substitution_(std::move(substitution)) {
25  setIsPositive(true);
26 }
27 
29  : Answer(other),
30  positiveGroundings_(other.positiveGroundings_),
31  negativeGroundings_(other.negativeGroundings_),
32  substitution_(std::make_shared<Bindings>(*other.substitution_)) {
33  setIsPositive(true);
34 }
35 
36 bool AnswerYes::isRicherThan(const AnswerYes &other) const {
37  if (isUncertain() != other.isUncertain()) {
38  // certain answer is richer than uncertain answer
39  return isUncertain() < other.isUncertain();
40  } else if (substitution_->size() != other.substitution_->size()) {
41  // answer with more substitutions is richer
42  return substitution_->size() > other.substitution_->size();
43  } else if (positiveGroundings_.size() != other.positiveGroundings_.size()) {
44  // answer with more positive groundings is richer
45  return positiveGroundings_.size() > other.positiveGroundings_.size();
46  } else if (negativeGroundings_.size() != other.negativeGroundings_.size()) {
47  // answer with more negative groundings is richer
48  return negativeGroundings_.size() > other.negativeGroundings_.size();
49  } else {
50  return false;
51  }
52 }
53 
55  return substitution_->empty();
56 }
57 
58 bool AnswerYes::addGrounding(const std::shared_ptr<Predicate> &predicate,
59  bool isNegated,
60  const GraphSelectorPtr &frame) {
61  if (!frame_->mergeWith(*frame)) {
62  KB_WARN("Failed to frame \"{}\" with \"{}\".", *frame_, *frame);
63  return false;
64  }
65  if (isNegated) {
67  } else {
69  }
70  return true;
71 }
72 
73 bool AnswerYes::mergeWith(const AnswerYes &other, bool ignoreInconsistencies) {
74  auto mergedBindings = std::make_shared<Bindings>(*substitution_);
75  if (ignoreInconsistencies) {
76  // insert all substitutions of other answer, possibly overwriting existing ones
77  *mergedBindings += *other.substitution_;
78  } else {
79  // unify substitutions
80  if (!mergedBindings->unifyWith(*other.substitution_)) {
81  // unification failed -> results cannot be combined
82  return false;
83  }
84  }
85  substitution_ = mergedBindings;
86 
87  if (!frame_->mergeWith(*other.frame_)) {
88  // merging frames failed -> results cannot be combined
89  return false;
90  }
91 
92  reasonerTerm_ = {};
93  // insert groundings of other answer
95  other.positiveGroundings_.begin(), other.positiveGroundings_.end());
97  other.negativeGroundings_.begin(), other.negativeGroundings_.end());
98 
99  return true;
100 }
101 
103  std::stringstream os;
104  if (reasonerTerm_) {
105  os << "[" << *reasonerTerm_ << "] ";
106  }
107  if (isUncertain()) {
108  os << "probably ";
109  }
110  os << "yes";
111  if (!positiveGroundings_.empty() || !negativeGroundings_.empty()) {
112  os << ", because:\n";
113  for (auto &x: positiveGroundings_) {
114  os << '\t' << *x.graphSelector() << ' ' << *x.predicate();
115  if (x.reasonerTerm() && x.reasonerTerm() != reasonerTerm_) {
116  os << ' ' << '[' << *x.reasonerTerm() << "]";
117  }
118  os << '\n';
119  }
120  for (auto &x: negativeGroundings_) {
121  os << '\t' << *x.graphSelector() << '~' << *x.predicate();
122  if (x.reasonerTerm() && x.reasonerTerm() != reasonerTerm_) {
123  os << ' ' << '[' << *x.reasonerTerm() << "]";
124  }
125  os << '\n';
126  }
127  } else {
128  os << '\n';
129  }
130  return os.str();
131 }
132 
134  std::stringstream os;
135  os << std::setprecision(4);
136  os << "the query is ";
137  if (isUncertain()) {
138  if (frame_->confidence.has_value()) {
139  os << "true with a confidence of " << std::setprecision(4) << frame_->confidence.value();
140  } else {
141  os << "probably true";
142  }
143  } else {
144  os << "true";
145  }
146  if (frame_->occasional) {
147  os << " at some time ";
148  }
149  if (frame_->begin.has_value() && frame_->end.has_value()) {
150  os << " during the time points " << frame_->begin.value() << " and " << frame_->end.value();
151  } else if (frame_->begin.has_value()) {
152  os << " since " << frame_->begin.value();
153  } else if (frame_->end.has_value()) {
154  os << " until " << frame_->end.value();
155  }
156  os << ".";
157  return os.str();
158 }
159 
160 namespace knowrob {
161  const std::shared_ptr<const AnswerYes> &GenericYes() {
162  static const auto instance = std::make_shared<const AnswerYes>();
163  return instance;
164  }
165 
166  AnswerPtr mergePositiveAnswers(const AnswerYesPtr &a, const AnswerYesPtr &b, bool ignoreInconsistencies) {
167  if (!a || a->isGenericYes()) {
168  return b;
169  } else if (!b || b->isGenericYes()) {
170  return a;
171  } else {
172  AnswerYesPtr smaller, larger;
173  if (a->isRicherThan(*b)) {
174  smaller = b;
175  larger = a;
176  } else {
177  smaller = a;
178  larger = b;
179  }
180  auto mergedAnswer = std::make_shared<AnswerYes>(*larger);
181  if (mergedAnswer->mergeWith(*smaller, ignoreInconsistencies)) {
182  return mergedAnswer;
183  } else {
184  // merging failed
185  return {};
186  }
187  }
188  }
189 } // namespace knowrob
190 
191 namespace knowrob::py {
192  template<>
194  using namespace boost::python;
195 
196  class_<AnswerYes, std::shared_ptr<AnswerYes>, bases<Answer>>
197  ("AnswerYes", init<>())
198  .def(init<BindingsPtr>())
199  .def("hasGrounding", &AnswerYes::hasGrounding)
200  .def("addGrounding", +[](AnswerYes &self, const PredicatePtr &predicate) {
201  return self.addGrounding(predicate);
202  })
203  .def("addGrounding", +[](AnswerYes &self, const PredicatePtr &predicate, bool isNegated) {
204  return self.addGrounding(predicate, isNegated);
205  })
206  .def("addGrounding", +[](AnswerYes &self, const PredicatePtr &predicate, bool isNegated, const GraphSelectorPtr &frame) {
207  return self.addGrounding(predicate, isNegated, frame);
208  })
209  .def("substitution", &AnswerYes::substitution, return_value_policy<copy_const_reference>())
210  .def("positiveGroundings", &AnswerYes::positiveGroundings, return_value_policy<copy_const_reference>())
211  .def("negativeGroundings", &AnswerYes::negativeGroundings, return_value_policy<copy_const_reference>())
212  .def("mergeWith", &AnswerYes::mergeWith)
213  .def("isRicherThan", &AnswerYes::isRicherThan)
214  .def("isGenericYes", &AnswerYes::isGenericYes);
215  // Allow implicit conversion from AnswerYes to const AnswerYes
216  register_ptr_to_python<std::shared_ptr<const AnswerYes> >();
217  implicitly_convertible<std::shared_ptr<AnswerYes>, std::shared_ptr<const AnswerYes> >();
218  }
219 }
#define KB_WARN
Definition: Logger.h:27
AtomPtr reasonerTerm_
Definition: Answer.h:119
void setIsPositive(bool val)
Definition: Answer.h:123
bool isUncertain() const
Definition: Answer.cpp:35
auto & frame() const
Definition: Answer.h:35
std::shared_ptr< GraphSelector > frame_
Definition: Answer.h:118
std::vector< FramedPredicate > positiveGroundings_
Definition: AnswerYes.h:102
auto & positiveGroundings() const
Definition: AnswerYes.h:74
bool mergeWith(const AnswerYes &other, bool ignoreInconsistencies=false)
Definition: AnswerYes.cpp:73
BindingsPtr substitution_
Definition: AnswerYes.h:104
bool isRicherThan(const AnswerYes &other) const
Definition: AnswerYes.cpp:36
auto & negativeGroundings() const
Definition: AnswerYes.h:81
std::vector< FramedPredicate > negativeGroundings_
Definition: AnswerYes.h:103
bool isGenericYes() const
Definition: AnswerYes.cpp:54
bool addGrounding(const std::shared_ptr< Predicate > &predicate, bool isNegated=false, const GraphSelectorPtr &frame=DefaultGraphSelector())
Definition: AnswerYes.cpp:58
auto & substitution() const
Definition: AnswerYes.h:50
bool hasGrounding(const Variable &var) const
Definition: AnswerYes.h:56
std::string humanReadableFormOfYes() const
Definition: AnswerYes.cpp:133
std::string stringFormOfYes() const
Definition: AnswerYes.cpp:102
PredicateRule & predicate()
Definition: formula.cpp:221
TermRule & string()
Definition: terms.cpp:63
void createType< AnswerYes >()
Definition: AnswerYes.cpp:193
std::shared_ptr< const Bindings > BindingsPtr
Definition: Bindings.h:151
const std::shared_ptr< const AnswerYes > & GenericYes()
Definition: AnswerYes.cpp:161
std::shared_ptr< Predicate > PredicatePtr
Definition: Predicate.h:77
std::shared_ptr< const GraphSelector > GraphSelectorPtr
Definition: GraphSelector.h:76
AnswerPtr mergePositiveAnswers(const AnswerYesPtr &a, const AnswerYesPtr &b, bool ignoreInconsistencies)
Definition: AnswerYes.cpp:166
std::shared_ptr< const Answer > AnswerPtr
Definition: Answer.h:129
std::shared_ptr< const AnswerYes > AnswerYesPtr
Definition: AnswerYes.h:108