aGrUM  0.20.2
a C++ library for (probabilistic) graphical models
IBayesNet_tpl.h
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 /**
23  * @file
24  * @brief Template implementation of bns/bayesNet.h classes.
25  *
26  * @author Pierre-Henri WUILLEMIN(@LIP6) and Lionel TORTI
27  */
28 
29 #include <limits>
30 #include <cmath>
31 
32 #include <agrum/BN/IBayesNet.h>
33 
34 #include <agrum/tools/multidim/aggregators/and.h>
35 #include <agrum/tools/multidim/aggregators/or.h>
36 
37 #include <agrum/tools/multidim/ICIModels/multiDimNoisyAND.h>
38 #include <agrum/tools/multidim/ICIModels/multiDimNoisyORCompound.h>
39 #include <agrum/tools/multidim/ICIModels/multiDimNoisyORNet.h>
40 
41 #include <agrum/BN/generator/simpleCPTGenerator.h>
42 #include <agrum/tools/multidim/potential.h>
43 
44 namespace gum {
45 
46  // IBayesNet
47 
48  template < typename GUM_SCALAR >
49  INLINE IBayesNet< GUM_SCALAR >::IBayesNet() : DAGmodel() {
51  }
52 
53  template < typename GUM_SCALAR >
56  this->setProperty("name", name);
57  }
58 
59  template < typename GUM_SCALAR >
61  DAGmodel(source) {
63  }
64 
65  template < typename GUM_SCALAR >
68  if (this != &source) { DAGmodel::operator=(source); }
69 
70  return *this;
71  }
72 
73  template < typename GUM_SCALAR >
76  }
77 
78  template < typename GUM_SCALAR >
79  Size IBayesNet< GUM_SCALAR >::dim() const {
80  Size dim = 0;
81 
82  for (auto node: nodes()) {
83  Size q = 1;
84 
85  for (auto parent: parents(node))
87 
88  dim += (variable(node).domainSize() - 1) * q;
89  }
90 
91  return dim;
92  }
93 
94  template < typename GUM_SCALAR >
96  Size res = 0;
97  for (auto node: nodes()) {
98  auto v = variable(node).domainSize();
99  if (v > res) { res = v; }
100  }
101  return res;
102  }
103 
104  template < typename GUM_SCALAR >
106  GUM_SCALAR res = 1.0;
107  for (auto node: nodes()) {
108  auto v = cpt(node).min();
109  if (v < res) { res = v; }
110  }
111  return res;
112  }
113 
114  template < typename GUM_SCALAR >
116  GUM_SCALAR res = 1.0;
117  for (auto node: nodes()) {
118  auto v = cpt(node).max();
119  if (v > res) { res = v; }
120  }
121  return res;
122  }
123 
124  template < typename GUM_SCALAR >
126  GUM_SCALAR res = 1.0;
127  for (auto node: nodes()) {
128  auto v = cpt(node).minNonZero();
129  if (v < res) { res = v; }
130  }
131  return res;
132  }
133 
134  template < typename GUM_SCALAR >
136  GUM_SCALAR res = 0.0;
137  for (auto node: nodes()) {
138  auto v = cpt(node).maxNonOne();
139  if (v > res) { res = v; }
140  }
141  return res;
142  }
143 
144  template < typename GUM_SCALAR >
146  Size param = 0;
147  double dSize = log10DomainSize();
148 
149  for (auto node: nodes())
150  param += cpt(node).content()->realSize();
151 
152  std::stringstream s;
153  s << "BN{nodes: " << size() << ", arcs: " << dag().sizeArcs() << ", ";
154 
155  if (dSize > 6)
156  s << "domainSize: 10^" << dSize;
157  else
158  s << "domainSize: " << std::round(std::pow(10.0, dSize));
159 
160  s << ", dim: " << param << "}";
161 
162  return s.str();
163  }
164 
165  template < typename GUM_SCALAR >
168  output << "digraph \"";
169 
170  std::string bn_name;
171 
172  try {
173  bn_name = this->property("name");
174  } catch (NotFound&) { bn_name = "no_name"; }
175 
176  output << bn_name << "\" {" << std::endl;
177  output << " graph [bgcolor=transparent,label=\"" << bn_name << "\"];"
178  << std::endl;
179  output << " node [style=filled fillcolor=\"#ffffaa\"];" << std::endl
180  << std::endl;
181 
182  for (auto node: nodes())
183  output << "\"" << variable(node).name() << "\" [comment=\"" << node << ":"
184  << variable(node).toStringWithDescription() << "\"];" << std::endl;
185 
186  output << std::endl;
187 
188  std::string tab = " ";
189 
190  for (auto node: nodes()) {
191  if (children(node).size() > 0) {
192  for (auto child: children(node)) {
193  output << tab << "\"" << variable(node).name() << "\" -> "
194  << "\"" << variable(child).name() << "\";" << std::endl;
195  }
196  } else if (parents(node).size() == 0) {
197  output << tab << "\"" << variable(node).name() << "\";" << std::endl;
198  }
199  }
200 
201  output << "}" << std::endl;
202 
203  return output.str();
204  }
205 
206  /// Compute a parameter of the joint probability for the BN (given an
207  /// instantiation
208  /// of the vars)
209  template < typename GUM_SCALAR >
210  GUM_SCALAR
212  auto value = (GUM_SCALAR)1.0;
213 
214  GUM_SCALAR tmp;
215 
216  for (auto node: nodes()) {
217  if ((tmp = cpt(node)[i]) == (GUM_SCALAR)0) { return (GUM_SCALAR)0; }
218 
219  value *= tmp;
220  }
221 
222  return value;
223  }
224 
225  /// Compute a parameter of the joint probability for the BN (given an
226  /// instantiation
227  /// of the vars)
228  template < typename GUM_SCALAR >
229  GUM_SCALAR
231  auto value = (GUM_SCALAR)0.0;
232 
233  GUM_SCALAR tmp;
234 
235  for (auto node: nodes()) {
236  if ((tmp = cpt(node)[i]) == (GUM_SCALAR)0) {
237  return (GUM_SCALAR)(-std::numeric_limits< double >::infinity());
238  }
239 
240  value += std::log2(cpt(node)[i]);
241  }
242 
243  return value;
244  }
245 
246  template < typename GUM_SCALAR >
247  bool IBayesNet< GUM_SCALAR >::operator==(const IBayesNet& from) const {
248  if (size() != from.size()) { return false; }
249 
250  if (sizeArcs() != from.sizeArcs()) { return false; }
251 
252  // alignment of variables between the 2 BNs
254 
255  for (auto node: nodes()) {
256  try {
259  } catch (NotFound&) {
260  // a name is not found in from
261  return false;
262  }
263  }
264 
265  for (auto node: nodes()) {
267 
268  if (cpt(node).nbrDim() != from.cpt(fromnode).nbrDim()) { return false; }
269 
270  if (cpt(node).domainSize() != from.cpt(fromnode).domainSize()) {
271  return false;
272  }
273 
276 
277  for (i.setFirst(); !i.end(); i.inc()) {
278  for (Idx indice = 0; indice < cpt(node).nbrDim(); ++indice) {
279  const DiscreteVariable* p = &(i.variable(indice));
280  j.chgVal(*(alignment.second(p)), i.val(*p));
281  }
282 
283  if (std::pow(cpt(node).get(i) - from.cpt(fromnode).get(j), (GUM_SCALAR)2)
284  > (GUM_SCALAR)1e-6) {
285  return false;
286  }
287  }
288  }
289 
290  return true;
291  }
292 
293  template < typename GUM_SCALAR >
294  bool IBayesNet< GUM_SCALAR >::operator!=(const IBayesNet& from) const {
295  return !this->operator==(from);
296  }
297 
298  // visit the nodes and add some of node from soids in minimal
299  template < typename GUM_SCALAR >
301  NodeId node,
302  const NodeSet& soids,
303  NodeSet& minimal,
305  NodeSet& alreadyVisitedDn) const {
306  if (alreadyVisitedUp.contains(node)) return;
308 
309  if (soids.contains(node)) {
310  minimal << node;
311  } else {
312  for (auto fath: dag_.parents(node))
314  soids,
315  minimal,
318  for (auto chil: dag_.children(node))
320  soids,
321  minimal,
324  }
325  }
326 
327  // visit the nodes and add some of node from soids in minimal
328  template < typename GUM_SCALAR >
330  NodeId node,
331  const NodeSet& soids,
332  NodeSet& minimal,
334  NodeSet& alreadyVisitedDn) const {
335  if (alreadyVisitedDn.contains(node)) return;
337 
338  if (soids.contains(node)) {
339  minimal << node;
340  for (auto fath: dag_.parents(node))
342  soids,
343  minimal,
346  } else {
347  for (auto chil: dag_.children(node))
349  soids,
350  minimal,
353  }
354  }
355 
356 
357  template < typename GUM_SCALAR >
359  const NodeSet& soids) const {
360  if (soids.contains(target)) return NodeSet({target});
361 
362  NodeSet res;
367 
368  for (auto fath: dag_.parents(target))
370  soids,
371  res,
374  for (auto chil: dag_.children(target))
376  soids,
377  res,
380  return res;
381  }
382 
383  template < typename GUM_SCALAR >
385  const NodeSet& soids) const {
386  NodeSet res;
387  for (auto node: targets) {
389  }
390  return res;
391  }
392 
393  template < typename GUM_SCALAR >
395  const IBayesNet< GUM_SCALAR >& bn) {
396  output << bn.toString();
397  return output;
398  }
399 
400 } /* namespace gum */
INLINE void emplace(Args &&... args)
Definition: set_tpl.h:669