aGrUM  0.20.2
a C++ library for (probabilistic) graphical models
essentialGraph.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 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 {
38  }
39 
41  dagmodel__(&m), mg__(mg) {}
45  }
47  if (&g != this) {
50  }
51  return *this;
52  }
53 
54  EssentialGraph::~EssentialGraph() = default;
55 
57  mg__.clear();
58  if (dagmodel__ == nullptr) return;
59 
60  for (const auto& node: dagmodel__->nodes()) {
62  }
63  for (const auto& arc: dagmodel__->arcs()) {
64  mg__.addArc(arc.tail(), arc.head());
65  }
66 
67  std::vector< Arc > v;
68  do {
69  v.clear();
70  for (const auto x: dagmodel__->topologicalOrder())
71  for (const auto y: mg__.children(x))
73 
74  for (const auto& arc: v) {
75  mg__.eraseArc(arc);
76  mg__.addEdge(arc.tail(), arc.head());
77  }
78  } while (!v.empty());
79  }
80 
82  // testing a->b from
83  // A Characterization of Markov Equivalence Classes for Acyclic Digraphs (2001)
84  // Steen A. Andersson, David Madigan, and Michael D. Perlman*
85 
86  // condition (a)
87  for (const auto& c: mg__.parents(a)) {
88  if (!mg__.existsArc(c, b)) {
89  // GUM_TRACE(a << "->" << b << " with "<<c<<" : (a)")
90  return true;
91  }
92  }
93 
94 
95  for (const auto& c: mg__.parents(b)) {
96  if (c == a) { continue; }
97  // condition (c)
98  if (mg__.existsArc(a, c)) {
99  // GUM_TRACE(a << "->" << b << " with "<<c<<" : (c)")
100  return true;
101  }
102 
103  // condition (b) knowing that a can not be a parent of c (condition below)
104  if (!mg__.existsEdge(a, c) && !mg__.existsArc(c, a)) {
105  // GUM_TRACE(a << "->" << b << " with "<<c<<" : (b)")
106  return true;
107  }
108  }
109 
110  // condition (d)
111  bool oneFound = false;
112  for (const auto& c: mg__.parents(b)) {
113  if (c == a) { continue; }
114  // condition (d)
115  if (mg__.existsEdge(c, a)) {
116  if (oneFound) { // this is the second found
117  // GUM_TRACE(a << "->" << b << " : (d)")
118  return true;
119  }
120  oneFound = true;
121  }
122  }
123 
124  return false;
125  }
126 
132  output << "digraph \""
133  << "no_name\" {" << std::endl;
134  nodeStream << "node [shape = ellipse];" << std::endl;
135  std::string tab = " ";
136  if (dagmodel__ != nullptr) {
137  for (const auto node: mg__.nodes()) {
138  nodeStream << tab << node << "[label=\""
139  << dagmodel__->variable(node).name() << "\"];";
140 
141  for (const auto nei: mg__.neighbours(node))
142  if (!treatedNodes.exists(nei))
143  edgeStream << tab << node << " -> " << nei << " [dir=none];"
144  << std::endl;
145 
146  for (const auto chi: mg__.children(node))
147  edgeStream << tab << node << " -> " << chi << " [color=red];"
148  << std::endl;
149 
151  }
152  }
153  output << nodeStream.str() << std::endl
154  << edgeStream.str() << std::endl
155  << "}" << std::endl;
156 
157  return output.str();
158  }
159 
161  UndiGraph skel;
162  for (const auto& n: nodes())
164  for (const auto& edge: edges())
166  for (const auto& arc: arcs())
167  skel.addEdge(arc.tail(), arc.head());
168  return skel;
169  }
170 } // namespace gum
INLINE void emplace(Args &&... args)
Definition: set_tpl.h:669