knowrob  2.1.0
A Knowledge Base System for Cognition-enabled Robots
ConjunctiveBroadcaster.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 <knowrob/queries/ConjunctiveBroadcaster.h>
8 #include "knowrob/queries/TokenQueue.h"
9 #include "knowrob/queries/AnswerYes.h"
10 #include "knowrob/queries/Answer.h"
11 #include "knowrob/terms/Numeric.h"
12 
13 using namespace knowrob;
14 
15 ConjunctiveBroadcaster::ConjunctiveBroadcaster(bool ignoreInconsistentAnswers)
16  : TokenBroadcaster(),
17  ignoreInconsistentAnswers_(ignoreInconsistentAnswers),
18  hasSolution_(false) {}
19 
20 void ConjunctiveBroadcaster::push(Channel &channel, const TokenPtr &tok) {
21  if (tok->tokenType() == TokenType::ANSWER_TOKEN) {
22  auto answer = std::static_pointer_cast<const Answer>(tok);
23  if (answer->isPositive()) {
24  const uint32_t channelID = channel.id();
25  // need to lock the whole push as genCombinations uses an iterator over the buffer.
26  std::lock_guard<std::mutex> lock(buffer_mutex_);
27 
28  // add to the buffer for later combinations
29  // replace other answer with same hash if present
30  buffer_[channelID][answer->hashOfAnswer()] = answer;
31 
32  // generate combinations with other channels if each channel
33  // buffer has some content.
34  if (buffer_.size() == channels_.size()) {
35  if (channels_.size() == 1) {
36  // not needed to generate combinations
38  } else {
39  // generate all combinations and push combined messages
40  genCombinations(channelID, buffer_.begin(), answer);
41  }
42  }
43  } else if (answer->isNegative()) {
44  // do not combine negative answers like the positive ones above.
45  // only push "no" when receiving EOF while no positive answer has been produced.
46  negativeAnswers_.emplace_back(std::static_pointer_cast<const AnswerNo>(answer));
47  }
48  } else {
49  if (tok->indicatesEndOfEvaluation()) {
51  if (numClosedChannels_ == channels_.size() && !hasSolution_) {
52  if (negativeAnswers_.size() == 1) {
54  } else {
55  auto no = std::make_shared<AnswerNo>();
56  for (auto &x: negativeAnswers_) {
57  no->mergeWith(*x);
58  }
60  }
61  } else {
62  // do not pass on the EOF token until all channels have finished
63  return;
64  }
65  }
66  // pass through non-answer messages
67  TokenStream::push(channel, tok);
68  }
69 }
70 
71 void ConjunctiveBroadcaster::genCombinations( //NOLINT(misc-no-recursion)
72  uint32_t pushedChannelID, AnswerMap::iterator it, AnswerPtr &combinedResult) {
73  if (it == buffer_.end()) {
74  // end reached, push combination
75  TokenBroadcaster::push(combinedResult);
76  hasSolution_ = true;
77  } else if (it->first == pushedChannelID) {
78  // pass through channel from which the new message was pushed
79  auto it1 = it;
80  ++it1;
81  genCombinations(pushedChannelID, it1, combinedResult);
82  } else if (it->second.size() == 1) {
83  // only a single message buffered from this channel
84  auto it1 = it;
85  ++it1;
86  auto merged = mergeAnswers(combinedResult,
87  it->second.begin()->second, ignoreInconsistentAnswers_);
88  if (merged) {
89  genCombinations(pushedChannelID, it1, merged);
90  }
91  } else {
92  // generate a combination for each buffered message
93  // note: the number of possible combinations grows exponentially with number of messages in channels
94  auto it1 = it;
95  ++it1;
96  for (auto &msg: it->second) {
97  auto merged = mergeAnswers(
98  combinedResult, msg.second, ignoreInconsistentAnswers_);
99  if (merged) {
100  genCombinations(pushedChannelID, it1, merged);
101  }
102  }
103  }
104 }
ConjunctiveBroadcaster(bool ignoreInconsistentAnswers=true)
std::vector< AnswerNoPtr > negativeAnswers_
void genCombinations(uint32_t pushedChannelID, AnswerMap::iterator it, AnswerPtr &combinedResult)
void push(Channel &channel, const TokenPtr &tok) override
void push(const TokenPtr &tok) override
virtual void push(Channel &channel, const TokenPtr &tok)
Definition: TokenStream.cpp:48
std::list< std::shared_ptr< Channel > > channels_
Definition: TokenStream.h:118
std::shared_ptr< const Token > TokenPtr
Definition: Token.h:74
AnswerPtr mergeAnswers(const AnswerPtr &a, const AnswerPtr &b, bool ignoreInconsistencies)
Definition: Answer.cpp:112
std::shared_ptr< const Answer > AnswerPtr
Definition: Answer.h:129