aGrUM  0.16.0
BayesBall_tpl.h
Go to the documentation of this file.
1 
28 namespace gum {
29 
30 
31  // update a set of potentials, keeping only those d-connected with
32  // query variables
33  template < typename GUM_SCALAR, template < typename > class TABLE >
34  void
36  const NodeSet& query,
37  const NodeSet& hardEvidence,
38  const NodeSet& softEvidence,
39  Set< const TABLE< GUM_SCALAR >* >& potentials) {
40  const DAG& dag = bn.dag();
41 
42  // create the marks (top = first and bottom = second)
44  marks.resize(dag.size());
45  const std::pair< bool, bool > empty_mark(false, false);
46 
50  for (const auto pot : potentials) {
51  const Sequence< const DiscreteVariable* >& vars = pot->variablesSequence();
52  for (const auto var : vars) {
53  const NodeId id = bn.nodeId(*var);
54  if (!node2potentials.exists(id)) {
55  node2potentials.insert(id, Set< const TABLE< GUM_SCALAR >* >());
56  }
57  node2potentials[id].insert(pot);
58  }
59  }
60 
61  // indicate that we will send the ball to all the query nodes (as children):
62  // in list nodes_to_visit, the first element is the next node to send the
63  // ball to and the Boolean indicates whether we shall reach it from one of
64  // its children (true) or from one parent (false)
65  List< std::pair< NodeId, bool > > nodes_to_visit;
66  for (const auto node : query) {
67  nodes_to_visit.insert(std::pair< NodeId, bool >(node, true));
68  }
69 
70  // perform the bouncing ball until __node2potentials becomes empty (which
71  // means that we have reached all the potentials and, therefore, those
72  // are d-connected to query) or until there is no node in the graph to send
73  // the ball to
74  while (!nodes_to_visit.empty() && !node2potentials.empty()) {
75  // get the next node to visit
76  NodeId node = nodes_to_visit.front().first;
77 
78  // if the marks of the node do not exist, create them
79  if (!marks.exists(node)) marks.insert(node, empty_mark);
80 
81  // if the node belongs to the query, update __node2potentials: remove all
82  // the potentials containing the node
83  if (node2potentials.exists(node)) {
84  auto& pot_set = node2potentials[node];
85  for (const auto pot : pot_set) {
86  const auto& vars = pot->variablesSequence();
87  for (const auto var : vars) {
88  const NodeId id = bn.nodeId(*var);
89  if (id != node) {
90  node2potentials[id].erase(pot);
91  if (node2potentials[id].empty()) { node2potentials.erase(id); }
92  }
93  }
94  }
95  node2potentials.erase(node);
96 
97  // if __node2potentials is empty, no need to go on: all the potentials
98  // are d-connected to the query
99  if (node2potentials.empty()) return;
100  }
101 
102 
103  // bounce the ball toward the neighbors
104  if (nodes_to_visit.front().second) { // visit from a child
105  nodes_to_visit.popFront();
106 
107  if (hardEvidence.exists(node)) { continue; }
108 
109  if (!marks[node].first) {
110  marks[node].first = true; // top marked
111  for (const auto par : dag.parents(node)) {
112  nodes_to_visit.insert(std::pair< NodeId, bool >(par, true));
113  }
114  }
115 
116  if (!marks[node].second) {
117  marks[node].second = true; // bottom marked
118  for (const auto chi : dag.children(node)) {
119  nodes_to_visit.insert(std::pair< NodeId, bool >(chi, false));
120  }
121  }
122  } else { // visit from a parent
123  nodes_to_visit.popFront();
124 
125  const bool is_hard_evidence = hardEvidence.exists(node);
126  const bool is_evidence = is_hard_evidence || softEvidence.exists(node);
127 
128  if (is_evidence && !marks[node].first) {
129  marks[node].first = true;
130 
131  for (const auto par : dag.parents(node)) {
132  nodes_to_visit.insert(std::pair< NodeId, bool >(par, true));
133  }
134  }
135 
136  if (!is_hard_evidence && !marks[node].second) {
137  marks[node].second = true;
138 
139  for (const auto chi : dag.children(node)) {
140  nodes_to_visit.insert(std::pair< NodeId, bool >(chi, false));
141  }
142  }
143  }
144  }
145 
146 
147  // here, all the potentials that belong to __node2potentials are d-separated
148  // from the query
149  for (const auto elt : node2potentials) {
150  for (const auto pot : elt.second) {
151  potentials.erase(pot);
152  }
153  }
154  }
155 
156 
157 } /* namespace gum */
void resize(Size new_size)
Changes the number of slots in the &#39;nodes&#39; vector of the hash table.
bool empty() const noexcept
Returns a boolean indicating whether the chained list is empty.
Definition: list_tpl.h:1970
void erase(const Key &key)
Removes a given element from the hash table.
Size size() const
alias for sizeNodes
The generic class for storing (ordered) sequences of objects.
Definition: sequence.h:1022
static void relevantPotentials(const IBayesNet< GUM_SCALAR > &bn, const NodeSet &query, const NodeSet &hardEvidence, const NodeSet &softEvidence, Set< const TABLE< GUM_SCALAR > * > &potentials)
update a set of potentials, keeping only those d-connected with query variables given evidence ...
Definition: BayesBall_tpl.h:35
bool exists(const Key &key) const
Checks whether there exists an element with a given key in the hashtable.
Generic doubly linked lists.
Definition: list.h:372
Class representing the minimal interface for Bayesian Network.
Definition: IBayesNet.h:62
Copyright 2005-2019 Pierre-Henri WUILLEMIN et Christophe GONZALES (LIP6) {prenom.nom}_at_lip6.fr.
Definition: agrum.h:25
void popFront()
Removes the first element of a List, if any.
Definition: list_tpl.h:1964
The class for generic Hash Tables.
Definition: hashTable.h:679
bool exists(const Key &k) const
Indicates whether a given elements belong to the set.
Definition: set_tpl.h:607
const NodeSet & parents(const NodeId id) const
returns the set of nodes with arc ingoing to a given node
Val & insert(const Val &val)
Inserts a new element at the end of the chained list (alias of pushBack).
Definition: list_tpl.h:1619
Val & front() const
Returns a reference to first element of a list, if any.
Definition: list_tpl.h:1831
const NodeSet & children(const NodeId id) const
returns the set of nodes with arc outgoing from a given node
value_type & insert(const Key &key, const Val &val)
Adds a new element (actually a copy of this element) into the hash table.
bool empty() const noexcept
Indicates whether the hash table is empty.
virtual NodeId nodeId(const DiscreteVariable &var) const =0
Return id node from discrete var pointer.
Base class for dag.
Definition: DAG.h:102
const DAG & dag() const
Returns a constant reference to the dag of this Bayes Net.
Definition: DAGmodel_inl.h:63
Size NodeId
Type for node ids.
Definition: graphElements.h:98