aGrUM  0.20.3
a C++ library for (probabilistic) graphical models
mixedGraph.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 Base classes for undirected graphs
24  *
25  * @author Pierre-Henri WUILLEMIN(@LIP6) & Christophe GONZALES(@AMU)
26  *
27  */
28 #include <agrum/tools/graphs/mixedGraph.h>
29 
30 #ifdef GUM_NO_INLINE
31 # include <agrum/tools/graphs/mixedGraph_inl.h>
32 #endif // GUM_NOINLINE
33 
34 namespace gum {
35 
39  bool arcs_resize_policy,
41  bool edges_resize_policy) :
42  // Note that we need to initialize the NodeGraphPart by ourselves
43  // because
44  // it is a virtual inherited class (see C++ FAQ Lite #25.12 for details)
47  DiGraph(arcs_size, arcs_resize_policy) { // for debugging purposes
49  }
50 
53  }
54 
57  }
58 
60  NodeGraphPart(g), UndiGraph(g), DiGraph(g) { // for debugging purposes
62  }
63 
64  MixedGraph::~MixedGraph() { // for debugging purposes
66  }
67 
70  s += " , ";
71  s += ArcGraphPart::toString();
72  s += " , ";
73  s += EdgeGraphPart::toString();
74  return s;
75  }
76 
78  std::vector< NodeId > v;
79  // not recursive version => use a FIFO for simulating the recursion
82 
83  // mark[node] = successor if visited, else mark[node] does not exist
85  mark.insert(n2, n2);
86 
88  while (!node_fifo.empty()) {
91 
92  // check the neighbours
93  for (const auto new_one: neighbours(current)) {
94  if (mark.exists(new_one)) // if the node has already been visited
95  continue; // do not check it again
96 
98 
99  if (new_one == n1) {
100  for (current = n1; current != n2; current = mark[current])
102  v.push_back(n2);
103  return v;
104  }
105 
107  }
108 
109  // check the parents
110  for (const auto new_one: parents(current)) {
111  if (mark.exists(new_one)) // if this node is already marked, do not
112  continue; // check it again
113 
115 
116  if (new_one == n1) {
117  for (current = n1; current != n2; current = mark[current])
119  v.push_back(n2);
120  return v;
121  }
122 
124  }
125  }
126 
127  return v;
128  }
129 
131  std::vector< NodeId > v;
132  // not recursive version => use a FIFO for simulating the recursion
133  List< NodeId > node_fifo;
135 
136  // mark[node] = successor if visited, else mark[node] does not exist
138  mark.insert(n2, n2);
139 
140  NodeId current;
141 
142  while (!node_fifo.empty()) {
143  current = node_fifo.front();
145 
146  // check the neighbours
147  for (const auto new_one: neighbours(current)) {
148  if (mark.exists(new_one)) // if the node has already been visited
149  continue; // do not check it again
150 
152 
153  if (new_one == n1) {
154  for (current = n1; current != n2; current = mark[current])
156  v.push_back(n2);
157  return v;
158  }
159 
161  }
162 
163  // check the parents
164  for (const auto new_one: parents(current)) {
165  if (mark.exists(new_one)) // the node has already been visited
166  continue;
167 
169  if (new_one == n1) {
170  for (current = n1; current != n2; current = mark[current])
172  v.push_back(n2);
173  return v;
174  }
176  }
177 
178  // check the children
179  for (const auto new_one: children(current)) {
180  if (mark.exists(new_one)) // the node has already been visited
181  continue;
182 
184 
185  if (new_one == n1) {
186  for (current = n1; current != n2; current = mark[current])
188  v.push_back(n2);
189  return v;
190  }
191 
193  }
194  }
195 
196  return v;
197  }
198 
204  output << "digraph \""
205  << "no_name\" {" << std::endl;
206  nodeStream << "node [shape = ellipse];" << std::endl;
207  std::string tab = " ";
208 
209  for (const auto node: nodes()) {
210  nodeStream << tab << node << ";";
211 
212  for (const auto nei: neighbours(node))
213  if (!treatedNodes.exists(nei))
214  edgeStream << tab << node << " -> " << nei << " [dir=none];" << std::endl;
215 
216  for (const auto chi: children(node))
217  edgeStream << tab << node << " -> " << chi << ";" << std::endl;
218 
220  }
221 
222  output << nodeStream.str() << std::endl << edgeStream.str() << std::endl << "}" << std::endl;
223 
224  return output.str();
225  }
226 
228  return neighbours(id) + parents(id) + children(id);
229  }
230 
231  /// for friendly displaying the content of directed graphs
233  stream << g.toString();
234  return stream;
235  }
236 
237 
238 } /* namespace gum */
INLINE void emplace(Args &&... args)
Definition: set_tpl.h:643
std::ostream & operator<<(std::ostream &aStream, const Instantiation &i)
Print information of the instantiation in the stream.