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() && !hasSolution_) {
50  if (negativeAnswers_.size() == 1) {
52  } else {
53  auto no = std::make_shared<AnswerNo>();
54  for (auto &x: negativeAnswers_) {
55  no->mergeWith(*x);
56  }
58  }
59  }
60  // pass through non-answer messages
61  TokenStream::push(channel, tok);
62  }
63 }
64 
65 void ConjunctiveBroadcaster::genCombinations( //NOLINT(misc-no-recursion)
66  uint32_t pushedChannelID, AnswerMap::iterator it, AnswerPtr &combinedResult) {
67  if (it == buffer_.end()) {
68  // end reached, push combination
69  TokenBroadcaster::push(combinedResult);
70  hasSolution_ = true;
71  } else if (it->first == pushedChannelID) {
72  // pass through channel from which the new message was pushed
73  auto it1 = it;
74  ++it1;
75  genCombinations(pushedChannelID, it1, combinedResult);
76  } else if (it->second.size() == 1) {
77  // only a single message buffered from this channel
78  auto it1 = it;
79  ++it1;
80  auto merged = mergeAnswers(combinedResult,
81  it->second.begin()->second, ignoreInconsistentAnswers_);
82  if (merged) {
83  genCombinations(pushedChannelID, it1, merged);
84  }
85  } else {
86  // generate a combination for each buffered message
87  // note: the number of possible combinations grows exponentially with number of messages in channels
88  auto it1 = it;
89  ++it1;
90  for (auto &msg: it->second) {
91  auto merged = mergeAnswers(
92  combinedResult, msg.second, ignoreInconsistentAnswers_);
93  if (merged) {
94  genCombinations(pushedChannelID, it1, merged);
95  }
96  }
97  }
98 }
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