aGrUM  0.20.3
a C++ library for (probabilistic) graphical models
MarkovBlanket.cpp
Go to the documentation of this file.
1 /**
2  *
3  * Copyright (c) 2005-2021 by Pierre-Henri WUILLEMIN(@LIP6) & Christophe GONZALES(@AMU)
4  * info_at_agrum_dot_org
5  *
6  * This library is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU Lesser General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public License
17  * along with this library. If not, see <http://www.gnu.org/licenses/>.
18  *
19  */
20 
21 
22 /** @file
23  * @brief Source implementation of the class building the Markov Blanket from a
24  * DAGmodel and a node (id or name)
25  *
26  * @author Pierre-Henri WUILLEMIN(@LIP6) & Christophe GONZALES(@AMU)
27  *
28  */
29 #include <agrum/BN/algorithms/MarkovBlanket.h>
30 
31 #ifdef GUM_NO_INLINE
32 # include <agrum/BN/algorithms/MarkovBlanket_inl.h>
33 #endif // GUM_NOINLINE
34 
35 namespace gum {
37  if (level < 1) GUM_ERROR(InvalidArgument, "Argument level(=" << level << ") must be >0.")
38 
39  NodeSet done;
42 
43  while (level > 1) {
44  level--;
45  auto todo = _mb_.nodes().asNodeSet() - done;
46  bool anythingnew = false;
47  for (NodeId n: todo) {
48  done.insert(n);
49  if (_buildMarkovBlanket_(n)) anythingnew = true;
50  }
51  if (!anythingnew) break;
52  }
53 
54  // we add now some arcs that are between the nodes in _mb_ but are not part of
55  // the last ones.
56  // For instance, an arc between a parent and a parent of children
57  for (const auto node: _mb_.nodes()) {
58  for (const auto child: _model_.children(node)) {
62  }
63  }
64  }
65  }
66 
69 
71 
73  bool change = false;
74  if (!_model_.nodes().exists(node))
75  GUM_ERROR(InvalidArgument, "Node " << node << " does not exist.")
76 
77  if (!_mb_.nodes().exists(node)) {
79  change = true;
80  }
81 
82  for (const auto& parent: _model_.parents(node)) {
83  if (!_mb_.nodes().exists(parent)) {
85  change = true;
86  }
88  }
89 
90  for (const auto& child: _model_.children(node)) {
91  if (!_mb_.nodes().exists(child)) {
93  change = true;
94  }
96  for (const auto& opar: _model_.parents(child)) {
97  if (opar != node) {
98  if (!_mb_.nodes().exists(opar)) {
100  change = true;
101  }
102  _mb_.addArc(opar, child);
103  }
104  }
105  }
106 
107  return change;
108  }
109 
111  if (size() != other.size()) return false;
112 
113  if (sizeArcs() != other.sizeArcs()) return false;
114 
115  for (const auto& nid: nodes()) {
116  try {
118  } catch (NotFound) { return false; }
119  }
120 
121  for (const auto& arc: arcs()) {
124  return false;
125  }
126 
127  return true;
128  }
129 
135  output << "digraph \""
136  << "no_name\" {" << std::endl;
137  nodeStream << "node [shape = ellipse];" << std::endl;
138  std::string tab = " ";
139 
140  for (const auto node: _mb_.nodes()) {
141  nodeStream << tab << node << "[label=\"" << _model_.variable(node).name() << "\"";
142  if (node == _node_) { nodeStream << ", color=red"; }
143  nodeStream << "];" << std::endl;
144 
145  for (const auto chi: _mb_.children(node)) {
146  arcStream << tab << node << " -> " << chi;
147  if (_specialArcs_.exists(Arc(node, chi))) { arcStream << " [color=grey]"; }
148  arcStream << ";" << std::endl;
149  }
150  }
151 
152  output << nodeStream.str() << std::endl << arcStream.str() << std::endl << "}" << std::endl;
153 
154  return output.str();
155  }
156 } // namespace gum
INLINE void emplace(Args &&... args)
Definition: set_tpl.h:643