aGrUM  0.20.2
a C++ library for (probabilistic) graphical models
IMarkovNet_tpl.h
Go to the documentation of this file.
1 /**
2  *
3  * Copyright 2005-2020 Pierre-Henri WUILLEMIN(@LIP6) et Christophe GONZALES(@AMU)
4  * (@AMU) 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 
31 #include <agrum/MN/IMarkovNet.h>
32 #include <agrum/tools/multidim/potential.h>
33 
34 #define EF get
35 namespace gum {
36 
37  // IMarkovNet
38 
39  template < typename GUM_SCALAR >
40  INLINE IMarkovNet< GUM_SCALAR >::IMarkovNet() : UGmodel() {
42  }
43 
44  template < typename GUM_SCALAR >
47  this->setProperty("name", name);
48  }
49 
50  template < typename GUM_SCALAR >
52  UGmodel(source) {
54  }
55 
56  template < typename GUM_SCALAR >
59  if (this != &source) { UGmodel::operator=(source); }
60 
61  return *this;
62  }
63 
64  template < typename GUM_SCALAR >
67  }
68 
69  template < typename GUM_SCALAR >
71  Size res = 0;
72  for (auto f: factors()) {
73  res += f.second->domainSize();
74  }
75  return res;
76  }
77 
78  template < typename GUM_SCALAR >
80  Size res = 0;
81  for (auto node: nodes()) {
82  auto v = variable(node).domainSize();
83  if (v > res) { res = v; }
84  }
85  return res;
86  }
87 
88  template < typename GUM_SCALAR >
90  GUM_SCALAR res = 1.0;
91  for (auto elt: factors()) {
92  auto v = elt.second->min();
93  if (v < res) { res = v; }
94  }
95  return res;
96  }
97 
98  template < typename GUM_SCALAR >
100  GUM_SCALAR res = 1.0;
101  for (auto elt: factors()) {
102  auto v = elt.second->max();
103  if (v > res) { res = v; }
104  }
105  return res;
106  }
107 
108  template < typename GUM_SCALAR >
110  GUM_SCALAR res = 1.0;
111  for (auto elt: factors()) {
112  auto v = elt.second->minNonZero();
113  if (v < res) { res = v; }
114  }
115  return res;
116  }
117 
118  template < typename GUM_SCALAR >
120  GUM_SCALAR res = 0.0;
121  for (auto elt: factors()) {
122  auto v = elt.second->maxNonOne();
123  if (v > res) { res = v; }
124  }
125  return res;
126  }
127 
128  template < typename GUM_SCALAR >
130  Size param = 0;
131  double dSize = log10DomainSize();
132 
133  for (auto factor: factors())
135 
136  std::stringstream s;
137  s << "MN{nodes: " << size() << ", edges: " << graph().sizeEdges() << ", ";
138 
139  if (dSize > 6)
140  s << "domainSize: 10^" << dSize;
141  else
142  s << "domainSize: " << std::round(std::pow(10.0, dSize));
143 
144  s << ", dim: " << param << "}";
145 
146  return s.str();
147  }
148 
149  template < typename GUM_SCALAR >
152  output << "graph \"";
153 
154  std::string mn_name;
155 
156  try {
157  mn_name = this->property("name");
158  } catch (NotFound&) { mn_name = "no_name"; }
159 
160  output << mn_name << "\" {" << std::endl;
161  output << " graph [bgcolor=transparent,label=\"" << mn_name << "\"];"
162  << std::endl;
163  output << " node [style=filled fillcolor=\"#ffffaa\"];" << std::endl
164  << std::endl;
165 
166  for (auto node: nodes())
167  output << " \"" << variable(node).name() << "\" [comment=\"" << node << ":"
168  << variable(node).toStringWithDescription() << "\"];" << std::endl;
169 
170  output << std::endl;
171 
172  std::string tab = " ";
173 
174  for (auto node: nodes()) {
175  if (neighbours(node).size() > 0) {
176  for (auto nei: neighbours(node)) {
177  if (variable(node).name() < variable(nei).name()) {
178  output << tab << "\"" << variable(node).name() << "\" -- "
179  << "\"" << variable(nei).name() << "\";" << std::endl;
180  }
181  }
182  } else {
183  output << tab << "\"" << variable(node).name() << "\";" << std::endl;
184  }
185  }
186 
187  output << "}" << std::endl;
188 
189  return output.str();
190  }
191 
192 
193  template < typename GUM_SCALAR >
196  std::string mn_name;
197  try {
198  mn_name = this->property("name");
199  } catch (NotFound&) { mn_name = "no_name"; }
200 
201  output << "graph FG_" << mn_name << " {" << std::endl;
202  output << " layout=neato;" << std::endl;
203  output << " graph [bgcolor=transparent,label=\"factor graph for " << mn_name
204  << "\"];" << std::endl;
205 
206  // the variables
207  output << " node [shape=rectangle,margin=0.04,width=0,height=0, "
208  "style=filled,color=\"coral\"];"
209  << std::endl;
210  for (auto nod: nodes()) {
211  output << "\"" << variable(nod).name() << "\";" << std::endl;
212  }
213  output << std::endl;
214 
215  // the factor
216  output << "node[shape = point,width = 0.1,height = 0.1,style = filled,color = "
217  "\"burlywood\"];"
218  << std::endl;
219  for (const auto& kv: factors()) {
220  output << " \"f";
221  for (NodeId nod: kv.first) {
222  output << "#" << variable(nod).name();
223  }
224  output << "\";" << std::endl;
225  }
226 
227  // the link variable--factors
228  output << " edge[len = 0.7];" << std::endl;
229  for (const auto& kv: factors()) {
230  std::string clicname = "\"f";
231  for (NodeId nod: kv.first) {
232  clicname += "#";
233  clicname += variable(nod).name();
234  }
235  clicname += "\"";
236 
237  for (NodeId nod: kv.first)
238  output << " " << clicname << " -- \"" << variable(nod).name() << "\";"
239  << std::endl;
240  }
241  output << "}" << std::endl;
242 
243  return output.str();
244  }
245 
246  template < typename GUM_SCALAR >
247  bool IMarkovNet< GUM_SCALAR >::operator==(const IMarkovNet& from) const {
248  if (size() != from.size()) { return false; }
249 
250  if (sizeEdges() != from.sizeEdges()) { 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 (const auto& elt: factors()) {
266  const auto& key = elt.first;
267  const auto& factor = *elt.second;
268 
270  for (const auto n: key)
272 
273  if (!from.factors().exists(fromkey)) { return false; }
274 
275  const auto& fromfactor = from.factor(fromkey);
276 
279  for (i.setFirst(); !i.end(); i.inc()) {
280  for (Idx indice = 0; indice < factor.nbrDim(); ++indice) {
281  const DiscreteVariable* p = &(i.variable(indice));
282  j.chgVal(*(alignment.second(p)), i.val(*p));
283  }
284 
285  if (std::pow(factor.get(i) - fromfactor.get(j), (GUM_SCALAR)2)
286  > (GUM_SCALAR)1e-6) {
287  return false;
288  }
289  }
290  }
291  return true;
292  }
293 
294  template < typename GUM_SCALAR >
295  INLINE bool IMarkovNet< GUM_SCALAR >::operator!=(const IMarkovNet& from) const {
296  return !this->operator==(from);
297  }
298 
299  template < typename GUM_SCALAR >
301  const IMarkovNet< GUM_SCALAR >& bn) {
302  output << bn.toString();
303  return output;
304  }
305 
306  template < typename GUM_SCALAR >
308  const std::string& name) const {
309  try {
311  } catch (NotFound) {
312  GUM_ERROR(NotFound, "No factor containing the variable <" << name << ">");
313  }
314  }
315 
316  // visit the nodes and add some of node from soids in minimal
317  template < typename GUM_SCALAR >
319  NodeId node,
320  const NodeSet& soids,
321  NodeSet& minimal,
322  NodeSet& alreadyVisited) const {
323  if (alreadyVisited.contains(node)) return;
324  alreadyVisited << node;
325 
326  if (soids.contains(node)) {
327  minimal << node;
328  } else {
329  for (auto neig: graph_.neighbours(node))
331  }
332  }
333 
334 
335  template < typename GUM_SCALAR >
337  const NodeSet& soids) const {
338  if (soids.contains(target)) return NodeSet({target});
339 
340  NodeSet res;
343 
344  for (auto neig: graph_.neighbours(target))
346  return res;
347  }
348 
349  template < typename GUM_SCALAR >
351  const NodeSet& soids) const {
352  NodeSet res;
353  for (auto node: targets) {
355  }
356  return res;
357  }
358 } /* namespace gum */
INLINE void emplace(Args &&... args)
Definition: set_tpl.h:669