aGrUM  0.20.3
a C++ library for (probabilistic) graphical models
essentialGraph.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 essential Graph from a
24  * DAGmodel
25  *
26  * @author Pierre-Henri WUILLEMIN(@LIP6) & Christophe GONZALES(@AMU)
27  *
28  */
29 #include <agrum/BN/algorithms/essentialGraph.h>
30 
31 #ifdef GUM_NO_INLINE
32 # include <agrum/BN/algorithms/essentialGraph_inl.h>
33 #endif // GUM_NOINLINE
34 
35 namespace gum {
37 
39  _dagmodel_(&m), _mg_(mg) {}
43  }
45  if (&g != this) {
48  }
49  return *this;
50  }
51 
52  EssentialGraph::~EssentialGraph() = default;
53 
55  _mg_.clear();
56  if (_dagmodel_ == nullptr) return;
57 
58  for (const auto& node: _dagmodel_->nodes()) {
60  }
61  for (const auto& arc: _dagmodel_->arcs()) {
62  _mg_.addArc(arc.tail(), arc.head());
63  }
64 
65  std::vector< Arc > v;
66  do {
67  v.clear();
68  for (const auto x: _dagmodel_->topologicalOrder())
69  for (const auto y: _mg_.children(x))
71 
72  for (const auto& arc: v) {
73  _mg_.eraseArc(arc);
74  _mg_.addEdge(arc.tail(), arc.head());
75  }
76  } while (!v.empty());
77  }
78 
80  // testing a->b from
81  // A Characterization of Markov Equivalence Classes for Acyclic Digraphs (2001)
82  // Steen A. Andersson, David Madigan, and Michael D. Perlman*
83 
84  // condition (a)
85  for (const auto& c: _mg_.parents(a)) {
86  if (!_mg_.existsArc(c, b)) { return true; }
87  }
88 
89 
90  for (const auto& c: _mg_.parents(b)) {
91  if (c == a) { continue; }
92  // condition (c)
93  if (_mg_.existsArc(a, c)) { return true; }
94 
95  // condition (b) knowing that a can not be a parent of c (condition below)
96  if (!_mg_.existsEdge(a, c) && !_mg_.existsArc(c, a)) { return true; }
97  }
98 
99  // condition (d)
100  bool oneFound = false;
101  for (const auto& c: _mg_.parents(b)) {
102  if (c == a) { continue; }
103  // condition (d)
104  if (_mg_.existsEdge(c, a)) {
105  if (oneFound) { // this is the second found
106  return true;
107  }
108  oneFound = true;
109  }
110  }
111 
112  return false;
113  }
114 
120  output << "digraph \""
121  << "no_name\" {" << std::endl;
122  nodeStream << "node [shape = ellipse];" << std::endl;
123  std::string tab = " ";
124  if (_dagmodel_ != nullptr) {
125  for (const auto node: _mg_.nodes()) {
126  nodeStream << tab << node << "[label=\"" << _dagmodel_->variable(node).name() << "\"];";
127 
128  for (const auto nei: _mg_.neighbours(node))
129  if (!treatedNodes.exists(nei))
130  edgeStream << tab << node << " -> " << nei << " [dir=none];" << std::endl;
131 
132  for (const auto chi: _mg_.children(node))
133  edgeStream << tab << node << " -> " << chi << " [color=red];" << std::endl;
134 
136  }
137  }
138  output << nodeStream.str() << std::endl << edgeStream.str() << std::endl << "}" << std::endl;
139 
140  return output.str();
141  }
142 
144  UndiGraph skel;
145  for (const auto& n: nodes())
147  for (const auto& edge: edges())
149  for (const auto& arc: arcs())
150  skel.addEdge(arc.tail(), arc.head());
151  return skel;
152  }
153 } // namespace gum
INLINE void emplace(Args &&... args)
Definition: set_tpl.h:643