aGrUM  0.14.1
IBayesNet_tpl.h
Go to the documentation of this file.
1 /***************************************************************************
2  * Copyright (C) 2005 by Pierre-Henri WUILLEMIN et Christophe GONZALES *
3  * {prenom.nom}_at_lip6.fr *
4  * *
5  * This program is free software; you can redistribute it and/or modify *
6  * it under the terms of the GNU General Public License as published by *
7  * the Free Software Foundation; either version 2 of the License, or *
8  * (at your option) any later version. *
9  * *
10  * This program is distributed in the hope that it will be useful, *
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13  * GNU General Public License for more details. *
14  * *
15  * You should have received a copy of the GNU General Public License *
16  * along with this program; if not, write to the *
17  * Free Software Foundation, Inc., *
18  * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19  ***************************************************************************/
27 #include <limits>
28 
29 #include <agrum/BN/IBayesNet.h>
30 
33 
37 
40 
41 namespace gum {
42 
43  // IBayesNet
44 
45  template < typename GUM_SCALAR >
47  GUM_CONSTRUCTOR(IBayesNet);
48  }
49 
50  template < typename GUM_SCALAR >
51  INLINE IBayesNet< GUM_SCALAR >::IBayesNet(std::string name) : DAGmodel() {
52  GUM_CONSTRUCTOR(IBayesNet);
53  this->setProperty("name", name);
54  }
55 
56  template < typename GUM_SCALAR >
58  DAGmodel(source) {
59  GUM_CONS_CPY(IBayesNet);
60  }
61 
62  template < typename GUM_SCALAR >
65  if (this != &source) { DAGmodel::operator=(source); }
66 
67  return *this;
68  }
69 
70  template < typename GUM_SCALAR >
72  GUM_DESTRUCTOR(IBayesNet);
73  }
74 
75  template < typename GUM_SCALAR >
77  Size dim = 0;
78 
79  for (auto node : nodes()) {
80  Size q = 1;
81 
82  for (auto parent : parents(node))
83  q *= variable(parent).domainSize();
84 
85  dim += (variable(node).domainSize() - 1) * q;
86  }
87 
88  return dim;
89  }
90 
91  template < typename GUM_SCALAR >
93  Size res = 0;
94  for (auto node : nodes()) {
95  auto v = variable(node).domainSize();
96  if (v > res) { res = v; }
97  }
98  return res;
99  }
100 
101  template < typename GUM_SCALAR >
103  GUM_SCALAR res = 1.0;
104  for (auto node : nodes()) {
105  auto v = cpt(node).min();
106  if (v < res) { res = v; }
107  }
108  return res;
109  }
110 
111  template < typename GUM_SCALAR >
113  GUM_SCALAR res = 1.0;
114  for (auto node : nodes()) {
115  auto v = cpt(node).max();
116  if (v > res) { res = v; }
117  }
118  return res;
119  }
120 
121  template < typename GUM_SCALAR >
123  GUM_SCALAR res = 1.0;
124  for (auto node : nodes()) {
125  auto v = cpt(node).minNonZero();
126  if (v < res) { res = v; }
127  }
128  return res;
129  }
130 
131  template < typename GUM_SCALAR >
133  GUM_SCALAR res = 0.0;
134  for (auto node : nodes()) {
135  auto v = cpt(node).maxNonOne();
136  if (v > res) { res = v; }
137  }
138  return res;
139  }
140 
141  template < typename GUM_SCALAR >
142  INLINE std::string IBayesNet< GUM_SCALAR >::toString() const {
143  Size param = 0;
144  double dSize = log10DomainSize();
145 
146  for (auto node : nodes())
147  param += cpt(node).content()->realSize();
148 
149  double compressionRatio = log10(1.0 * param) - dSize;
150 
151  std::stringstream s;
152  s << "BN{nodes: " << size() << ", arcs: " << dag().sizeArcs() << ", ";
153 
154  if (dSize > 6)
155  s << "domainSize: 10^" << dSize;
156  else
157  s << "domainSize: " << std::round(std::pow(10.0, dSize));
158 
159  s << ", parameters: " << param << ", compression ratio: ";
160 
161  if (compressionRatio > -3)
162  s << trunc(100.0 - std::pow(10.0, compressionRatio + 2.0));
163  else
164  s << "100-10^" << compressionRatio + 2.0;
165 
166  s << "% }";
167 
168  return s.str();
169  }
170 
171  template < typename GUM_SCALAR >
172  std::string IBayesNet< GUM_SCALAR >::toDot() const {
173  std::stringstream output;
174  output << "digraph \"";
175 
176  std::string bn_name;
177 
178  try {
179  bn_name = this->property("name");
180  } catch (NotFound&) { bn_name = "no_name"; }
181 
182  output << bn_name << "\" {" << std::endl;
183  output << " graph [bgcolor=transparent,label=\"" << bn_name << "\"];"
184  << std::endl;
185  output << " node [style=filled fillcolor=\"#ffffaa\"];" << std::endl
186  << std::endl;
187 
188  for (auto node : nodes())
189  output << "\"" << variable(node).name() << "\" [comment=\"" << node << ":"
190  << variable(node).toStringWithDescription() << "\"];" << std::endl;
191 
192  output << std::endl;
193 
194  std::string tab = " ";
195 
196  for (auto node : nodes()) {
197  if (children(node).size() > 0) {
198  for (auto child : children(node)) {
199  output << tab << "\"" << variable(node).name() << "\" -> "
200  << "\"" << variable(child).name() << "\";" << std::endl;
201  }
202  } else if (parents(node).size() == 0) {
203  output << tab << "\"" << variable(node).name() << "\";" << std::endl;
204  }
205  }
206 
207  output << "}" << std::endl;
208 
209  return output.str();
210  }
211 
215  template < typename GUM_SCALAR >
216  GUM_SCALAR
218  auto value = (GUM_SCALAR)1.0;
219 
220  GUM_SCALAR tmp;
221 
222  for (auto node : nodes()) {
223  if ((tmp = cpt(node)[i]) == (GUM_SCALAR)0) { return (GUM_SCALAR)0; }
224 
225  value *= tmp;
226  }
227 
228  return value;
229  }
230 
234  template < typename GUM_SCALAR >
235  GUM_SCALAR
237  auto value = (GUM_SCALAR)0.0;
238 
239  GUM_SCALAR tmp;
240 
241  for (auto node : nodes()) {
242  if ((tmp = cpt(node)[i]) == (GUM_SCALAR)0) {
243  return (GUM_SCALAR)(-std::numeric_limits< double >::infinity());
244  }
245 
246  value += log2(cpt(node)[i]);
247  }
248 
249  return value;
250  }
251 
252  template < typename GUM_SCALAR >
254  if (size() != from.size()) { return false; }
255 
256  if (sizeArcs() != from.sizeArcs()) { return false; }
257 
258  // alignment of variables between the 2 BNs
260 
261  for (auto node : nodes()) {
262  try {
263  alignment.insert(&variable(node),
264  &from.variableFromName(variable(node).name()));
265  } catch (NotFound&) {
266  // a name is not found in from
267  return false;
268  }
269  }
270 
271  for (auto node : nodes()) {
272  NodeId fromnode = from.idFromName(variable(node).name());
273 
274  if (cpt(node).nbrDim() != from.cpt(fromnode).nbrDim()) { return false; }
275 
276  if (cpt(node).domainSize() != from.cpt(fromnode).domainSize()) {
277  return false;
278  }
279 
280  Instantiation i(cpt(node));
281  Instantiation j(from.cpt(fromnode));
282 
283  for (i.setFirst(); !i.end(); i.inc()) {
284  for (Idx indice = 0; indice < cpt(node).nbrDim(); ++indice) {
285  const DiscreteVariable* p = &(i.variable(indice));
286  j.chgVal(*(alignment.second(p)), i.val(*p));
287  }
288 
289  if (std::pow(cpt(node).get(i) - from.cpt(fromnode).get(j), (GUM_SCALAR)2)
290  > (GUM_SCALAR)1e-6) {
291  return false;
292  }
293  }
294  }
295 
296  return true;
297  }
298 
299  template < typename GUM_SCALAR >
301  return !this->operator==(from);
302  }
303 
304  // visit the nodes and add some of node from soids in minimal
305  template < typename GUM_SCALAR >
307  NodeId node,
308  const NodeSet& soids,
309  NodeSet& minimal,
310  NodeSet& alreadyVisitedUp,
311  NodeSet& alreadyVisitedDn) const {
312  if (alreadyVisitedUp.contains(node)) return;
313  alreadyVisitedUp << node;
314 
315  if (soids.contains(node)) {
316  minimal << node;
317  } else {
318  for (auto fath : _dag.parents(node))
319  __minimalCondSetVisitUp(
320  fath, soids, minimal, alreadyVisitedUp, alreadyVisitedDn);
321  for (auto chil : _dag.children(node))
322  __minimalCondSetVisitDn(
323  chil, soids, minimal, alreadyVisitedUp, alreadyVisitedDn);
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,
333  NodeSet& alreadyVisitedUp,
334  NodeSet& alreadyVisitedDn) const {
335  if (alreadyVisitedDn.contains(node)) return;
336  alreadyVisitedDn << node;
337 
338  if (soids.contains(node)) {
339  minimal << node;
340  for (auto fath : _dag.parents(node))
341  __minimalCondSetVisitUp(
342  fath, soids, minimal, alreadyVisitedUp, alreadyVisitedDn);
343  } else {
344  for (auto chil : _dag.children(node))
345  __minimalCondSetVisitDn(
346  chil, soids, minimal, alreadyVisitedUp, alreadyVisitedDn);
347  }
348  }
349 
350 
351  template < typename GUM_SCALAR >
353  const NodeSet& soids) const {
354  if (soids.contains(target)) return NodeSet({target});
355 
356  NodeSet res;
357  NodeSet alreadyVisitedUp;
358  NodeSet alreadyVisitedDn;
359  alreadyVisitedDn << target;
360  alreadyVisitedUp << target;
361 
362  for (auto fath : _dag.parents(target))
363  __minimalCondSetVisitUp(
364  fath, soids, res, alreadyVisitedUp, alreadyVisitedDn);
365  for (auto chil : _dag.children(target))
366  __minimalCondSetVisitDn(
367  chil, soids, res, alreadyVisitedUp, alreadyVisitedDn);
368  return res;
369  }
370 
371  template < typename GUM_SCALAR >
373  const NodeSet& soids) const {
374  NodeSet res;
375  for (auto node : targets) {
376  res += minimalCondSet(node, soids);
377  }
378  return res;
379  }
380 
381  template < typename GUM_SCALAR >
382  INLINE std::ostream& operator<<(std::ostream& output,
383  const IBayesNet< GUM_SCALAR >& bn) {
384  output << bn.toString();
385  return output;
386  }
387 
388 } /* namespace gum */
bool contains(const Key &k) const
Indicates whether a given elements belong to the set.
Definition: set_tpl.h:578
void insert(const T1 &first, const T2 &second)
Inserts a new association in the gum::Bijection.
const T2 & second(const T1 &first) const
Returns the second value of a pair given its first value.
Abstract class for generating Conditional Probability Tables.
Virtual base class for PGMs using a DAG.
Definition: DAGmodel.h:45
class for NoisyOR-net implementation as multiDim
Set< NodeId > NodeSet
Some typdefs and define for shortcuts ...
Size sizeArcs() const
Returns the number of arcs in this Directed Graphical Model.
Definition: DAGmodel_inl.h:99
virtual const Potential< GUM_SCALAR > & cpt(NodeId varId) const =0
Returns the CPT of a variable.
Class representing Bayesian networks.
class for multiDimNoisyORCompound
Base class for discrete random variable.
Class representing the minimal interface for Bayesian Network.
Definition: IBayesNet.h:59
gum is the global namespace for all aGrUM entities
Definition: agrum.h:25
virtual NodeId idFromName(const std::string &name) const =0
Getter by name.
Idx val(Idx i) const
Returns the current value of the variable at position i.
Size size() const
Returns the number of variables in this Directed Graphical Model.
Definition: DAGmodel_inl.h:93
Header of the Potential class.
or aggregator
void inc()
Operator increment.
virtual const DiscreteVariable & variableFromName(const std::string &name) const =0
Getter by name.
bool operator==(const TiXmlString &a, const TiXmlString &b)
Definition: tinystr.h:243
Set of pairs of elements with fast search for both elements.
Definition: bijection.h:1803
Class for assigning/browsing values to tuples of discrete variables.
Definition: instantiation.h:80
std::string toString() const
INLINE std::ostream & operator<<(std::ostream &output, const IBayesNet< GUM_SCALAR > &bn)
Prints map&#39;s DAG in output using the Graphviz-dot format.
count aggregator
class for NoisyAND-net implementation as multiDim
bool operator!=(const TiXmlString &a, const TiXmlString &b)
Definition: tinystr.h:251
void setFirst()
Assign the first values to the tuple of the Instantiation.
IBayesNet()
Default constructor.
Definition: IBayesNet_tpl.h:46
Size Idx
Type for indexes.
Definition: types.h:50
std::size_t Size
In aGrUM, hashed values are unsigned long int.
Definition: types.h:45
const DiscreteVariable & variable(Idx i) const final
Returns the variable at position i in the tuple.
Size NodeId
Type for node ids.
Definition: graphElements.h:97
bool end() const
Returns true if the Instantiation reached the end.