aGrUM  0.20.2
a C++ library for (probabilistic) graphical models
MarkovBlanket.cpp
Go to the documentation of this file.
1 /**
2  *
3  * Copyright 2005-2020 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  model__(m), node__(id) {
38  if (level < 1)
39  GUM_ERROR(InvalidArgument, "Argument level(=" << level << ") must be >0.")
40 
41  NodeSet done;
44 
45  while (level > 1) {
46  level--;
47  auto todo = mb__.nodes().asNodeSet() - done;
48  bool anythingnew = false;
49  for (NodeId n: todo) {
50  done.insert(n);
51  if (buildMarkovBlanket__(n)) anythingnew = true;
52  }
53  if (!anythingnew) break;
54  }
55 
56  // we add now some arcs that are between the nodes in mb__ but are not part of
57  // the last ones.
58  // For instance, an arc between a parent and a parent of children
59  for (const auto node: mb__.nodes()) {
60  for (const auto child: model__.children(node)) {
64  }
65  }
66  }
67  }
68 
70  const std::string& name,
71  int level) :
73 
75 
77  bool change = false;
78  if (!model__.nodes().exists(node))
79  GUM_ERROR(InvalidArgument, "Node " << node << " does not exist.");
80 
81  if (!mb__.nodes().exists(node)) {
83  change = true;
84  }
85 
86  for (const auto& parent: model__.parents(node)) {
87  if (!mb__.nodes().exists(parent)) {
89  change = true;
90  }
92  }
93 
94  for (const auto& child: model__.children(node)) {
95  if (!mb__.nodes().exists(child)) {
97  change = true;
98  }
100  for (const auto& opar: model__.parents(child)) {
101  if (opar != node) {
102  if (!mb__.nodes().exists(opar)) {
104  change = true;
105  }
106  mb__.addArc(opar, child);
107  }
108  }
109  }
110 
111  return change;
112  }
113 
115  if (size() != other.size()) return false;
116 
117  if (sizeArcs() != other.sizeArcs()) return false;
118 
119  for (const auto& nid: nodes()) {
120  try {
122  } catch (NotFound) { return false; }
123  }
124 
125  for (const auto& arc: arcs()) {
126  if (!other.arcs().exists(
129  return false;
130  }
131 
132  return true;
133  }
134 
140  output << "digraph \""
141  << "no_name\" {" << std::endl;
142  nodeStream << "node [shape = ellipse];" << std::endl;
143  std::string tab = " ";
144 
145  for (const auto node: mb__.nodes()) {
146  nodeStream << tab << node << "[label=\"" << model__.variable(node).name()
147  << "\"";
148  if (node == node__) { nodeStream << ", color=red"; }
149  nodeStream << "];" << std::endl;
150 
151  for (const auto chi: mb__.children(node)) {
152  arcStream << tab << node << " -> " << chi;
153  if (specialArcs__.exists(Arc(node, chi))) { arcStream << " [color=grey]"; }
154  arcStream << ";" << std::endl;
155  }
156  }
157 
158  output << nodeStream.str() << std::endl
159  << arcStream.str() << std::endl
160  << "}" << std::endl;
161 
162  return output.str();
163  }
164 } // namespace gum
INLINE void emplace(Args &&... args)
Definition: set_tpl.h:669