aGrUM  0.16.0
dSeparation.cpp
Go to the documentation of this file.
1 
31 #include <agrum/core/list.h>
32 
33 #ifdef GUM_NO_INLINE
35 #endif // GUM_NO_INLINE
36 
37 namespace gum {
38 
39  // Fill 'requisite' with the requisite nodes in dag given a query and
40  // evidence.
42  const NodeSet& query,
43  const NodeSet& hardEvidence,
44  const NodeSet& softEvidence,
45  NodeSet& requisite) {
46  // for the moment, no node is requisite
47  requisite.clear();
48 
49  // mark the set of ancestors of the evidence
50  NodeSet ev_ancestors(dag.size());
51  {
52  List< NodeId > anc_to_visit;
53  for (const auto node : hardEvidence)
54  anc_to_visit.insert(node);
55  for (const auto node : softEvidence)
56  anc_to_visit.insert(node);
57  while (!anc_to_visit.empty()) {
58  const NodeId node = anc_to_visit.front();
59  anc_to_visit.popFront();
60 
61  if (!ev_ancestors.exists(node)) {
62  ev_ancestors.insert(node);
63  for (const auto par : dag.parents(node)) {
64  anc_to_visit.insert(par);
65  }
66  }
67  }
68  }
69 
70  // create the marks indicating that we have visited a node
71  NodeSet visited_from_child(dag.size());
72  NodeSet visited_from_parent(dag.size());
73 
74  // indicate that we will send the ball to all the query nodes (as children):
75  // in list nodes_to_visit, the first element is the next node to send the
76  // ball to and the Boolean indicates whether we shall reach it from one of
77  // its children (true) or from one parent (false)
78  List< std::pair< NodeId, bool > > nodes_to_visit;
79  for (const auto node : query) {
80  nodes_to_visit.insert(std::pair< NodeId, bool >(node, true));
81  }
82 
83  // perform the bouncing ball until there is no node in the graph to send
84  // the ball to
85  while (!nodes_to_visit.empty()) {
86  // get the next node to visit
87  const NodeId node = nodes_to_visit.front().first;
88  const bool direction = nodes_to_visit.front().second;
89  nodes_to_visit.popFront();
90 
91  // check if the node has not already been visited in the same direction
92  bool already_visited;
93  if (direction) {
94  already_visited = visited_from_child.exists(node);
95  if (!already_visited) { visited_from_child.insert(node); }
96  } else {
97  already_visited = visited_from_parent.exists(node);
98  if (!already_visited) { visited_from_parent.insert(node); }
99  }
100 
101  // if this is the first time we meet the node, then visit it
102  if (!already_visited) {
103  // mark the node as reachable if this is not a hard evidence
104  const bool is_hard_evidence = hardEvidence.exists(node);
105  if (!is_hard_evidence) { requisite.insert(node); }
106 
107  // bounce the ball toward the neighbors
108  if (direction && !is_hard_evidence) { // visit from a child
109  // visit the parents
110  for (const auto par : dag.parents(node)) {
111  nodes_to_visit.insert(std::pair< NodeId, bool >(par, true));
112  }
113 
114  // visit the children
115  for (const auto chi : dag.children(node)) {
116  nodes_to_visit.insert(std::pair< NodeId, bool >(chi, false));
117  }
118  } else { // visit from a parent
119  if (!hardEvidence.exists(node)) {
120  // visit the children
121  for (const auto chi : dag.children(node)) {
122  nodes_to_visit.insert(std::pair< NodeId, bool >(chi, false));
123  }
124  }
125  if (ev_ancestors.exists(node)) {
126  // visit the parents
127  for (const auto par : dag.parents(node)) {
128  nodes_to_visit.insert(std::pair< NodeId, bool >(par, true));
129  }
130  }
131  }
132  }
133  }
134  }
135 
136 } /* namespace gum */
bool empty() const noexcept
Returns a boolean indicating whether the chained list is empty.
Definition: list_tpl.h:1970
Copyright 2005-2019 Pierre-Henri WUILLEMIN et Christophe GONZALES (LIP6) {prenom.nom}_at_lip6.fr.
Size size() const
alias for sizeNodes
Copyright 2005-2019 Pierre-Henri WUILLEMIN et Christophe GONZALES (LIP6) {prenom.nom}_at_lip6.fr.
Generic doubly linked lists.
Definition: list.h:372
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
bool exists(const Key &k) const
Indicates whether a given elements belong to the set.
Definition: set_tpl.h:607
Copyright 2005-2019 Pierre-Henri WUILLEMIN et Christophe GONZALES (LIP6) {prenom.nom}_at_lip6.fr.
const NodeSet & parents(const NodeId id) const
returns the set of nodes with arc ingoing to a given node
void requisiteNodes(const DAG &dag, const NodeSet &query, const NodeSet &hardEvidence, const NodeSet &softEvidence, NodeSet &requisite)
Fill the &#39;requisite&#39; nodeset with the requisite nodes in dag given a query and evidence.
Definition: dSeparation.cpp:41
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
void clear()
Removes all the elements, if any, from the set.
Definition: set_tpl.h:375
Base class for dag.
Definition: DAG.h:102
Size NodeId
Type for node ids.
Definition: graphElements.h:98
void insert(const Key &k)
Inserts a new element into the set.
Definition: set_tpl.h:613