33 #endif // GUM_NOINLINE 35 #ifndef DOXYGEN_SHOULD_SKIP_THIS 53 bool nodes_resize_policy,
55 bool edges_resize_policy) :
56 NodeGraphPart(nodes_size, nodes_resize_policy),
57 UndiGraph(nodes_size, nodes_resize_policy, edges_size, edges_resize_policy) {
59 GUM_CONSTRUCTOR(CliqueGraph);
67 __cliques(from.__cliques), __separators(from.__separators) {
69 GUM_CONS_CPY(CliqueGraph);
76 GUM_DESTRUCTOR(CliqueGraph);
82 const NodeId node2)
const {
85 std::vector< NodeId > path =
86 undirectedPath(container(node1), container(node2));
90 while ((path.size() >= 2) && (clique(path[path.size() - 2]).contains(node2)))
93 while ((path.size() >= 2) && (clique(path[1]).contains(node1)))
94 path.erase(path.begin());
105 NodeSet& clique = __cliques[clique_id];
108 if (clique.contains(node_id)) {
110 "the clique set already contains the node " << node_id);
113 clique.insert(node_id);
116 for (
const auto nei : neighbours(clique_id))
117 if (__cliques[nei].contains(node_id))
118 __separators[Edge(nei, clique_id)].insert(node_id);
125 NodeSet& clique = __cliques[clique_id];
128 if (clique.contains(node_id)) {
129 clique.
erase(node_id);
132 for (
const auto nei : neighbours(clique_id)) {
133 Edge edge(nei, clique_id);
135 if (__separators[edge].contains(node_id))
136 __separators[edge].erase(node_id);
146 CliqueGraph::__RunningIntersect& infos_DFS)
const {
149 const NodeSet& nodes_clique = __cliques[clique];
151 for (
const auto node : nodes_clique)
152 if (infos_DFS.nodes_other_components.contains(node))
return false;
156 for (
const auto node : nodes_clique)
157 if (!infos_DFS.nodes_DFS_forbidden.contains(node))
158 infos_DFS.cliques_DFS_chain[clique].
erase(node);
162 if (infos_DFS.visited_cliques.contains(clique))
return true;
165 for (
const auto node : nodes_clique)
166 if (!infos_DFS.nodes_DFS_seen.contains(node))
167 infos_DFS.nodes_DFS_seen.insert(node);
170 infos_DFS.visited_cliques.insert(clique);
175 for (
const auto otherID : neighbours(clique))
176 if (otherID != from) {
179 const Edge edge(otherID, clique);
180 const NodeSet& from_separ = __separators[edge];
182 for (
const auto node : nodes_clique) {
183 if (!from_separ.contains(node))
184 infos_DFS.nodes_DFS_forbidden.
insert(node);
188 if (!__runningIntersectionDFS(otherID, clique, infos_DFS))
return false;
191 for (
const auto node : nodes_clique)
192 infos_DFS.nodes_DFS_forbidden.erase(node);
197 for (
const auto node : nodes_clique) {
198 if (!infos_DFS.nodes_DFS_forbidden.contains(node))
199 infos_DFS.cliques_DFS_chain[clique].erase(node);
208 if (neighbours(clique).size() <= 1)
209 for (
const auto node : nodes_clique)
210 if (!infos_DFS.nodes_DFS_forbidden.contains(node))
211 infos_DFS.nodes_DFS_forbidden.insert(node);
221 __RunningIntersect infos_DFS;
222 infos_DFS.cliques_DFS_chain = __cliques;
225 for (
const auto DFSnode : nodes())
226 if (!infos_DFS.visited_cliques.contains(DFSnode)) {
228 infos_DFS.nodes_DFS_forbidden.clear();
231 infos_DFS.nodes_DFS_seen.clear();
235 if (!__runningIntersectionDFS(DFSnode, DFSnode, infos_DFS))
return false;
240 for (
const auto node : infos_DFS.nodes_DFS_seen)
241 if (!infos_DFS.nodes_other_components.contains(node))
242 infos_DFS.nodes_other_components.insert(node);
247 for (
const auto& elt : infos_DFS.cliques_DFS_chain)
248 if (!elt.second.empty())
return false;
257 if (UndiGraph::operator!=(from))
return false;
260 for (
const auto& elt : __cliques)
261 if (elt.second != from.__cliques[elt.first])
return false;
267 std::stringstream stream;
268 stream <<
"list of nodes:" << std::endl;
270 for (
const auto node : nodes()) {
271 stream <<
" -- node: " << node << std::endl <<
" clique:";
273 for (
const auto cliq : clique(node))
274 stream <<
" " << cliq;
279 stream <<
"\n\nlist of edges:\n";
281 for (
const auto edge : edges())
282 stream << edge <<
" ";
287 const std::string expandCliqueContent(
const NodeSet& clique) {
288 std::stringstream stream;
291 for (
auto node : clique) {
292 if (!first) { stream <<
"-"; }
300 const std::string expandClique(
const NodeId n,
const NodeSet& clique) {
301 std::stringstream stream;
302 stream <<
'(' << n <<
") " << expandCliqueContent(clique);
305 const std::string expandSeparator(
const NodeId n1,
309 std::stringstream stream;
310 stream << expandClique(n1, clique1) <<
"^" << expandClique(n2, clique2);
315 std::stringstream stream;
316 stream <<
"graph {" << std::endl;
319 for (
auto node : nodes()) {
320 std::string nom =
'"' + expandClique(node, clique(node)) +
'"';
321 stream <<
" " << nom <<
" [label=\"" << expandCliqueContent(clique(node))
322 <<
"\",fillcolor =\"burlywood\",style=\"filled\"];" << std::endl;
328 for (
auto edge : edges()) {
330 << expandSeparator(edge.first(),
331 clique(edge.first()),
333 clique(edge.second()))
334 <<
"\" [label=\"" << expandCliqueContent(separator(edge)) <<
"\"" 335 <<
",shape=box,fillcolor=\"palegreen\",style=\"filled\",fontsize=8," 343 for (
auto edge : edges())
344 stream <<
" \"" << expandClique(edge.first(), clique(edge.first()))
346 << expandSeparator(edge.first(),
347 clique(edge.first()),
349 clique(edge.second()))
350 <<
"\"--\"" << expandClique(edge.second(), clique(edge.second()))
351 <<
"\";" << std::endl;
353 stream <<
"}" << std::endl;
360 std::ostream&
operator<<(std::ostream& stream,
const CliqueGraph& graph) {
361 stream << graph.toString();
bool operator==(const CliqueGraph &from) const
checks whether two clique graphs are equal
Set< NodeId > NodeSet
Some typdefs and define for shortcuts ...
virtual const std::string toDot() const
friendly displays the content of the CliqueGraph in DOT format
void erase(const Key &k)
Erases an element from the set.
Copyright 2005-2019 Pierre-Henri WUILLEMIN et Christophe GONZALES (LIP6) {prenom.nom}_at_lip6.fr.
bool __runningIntersectionDFS(const NodeId clique, const NodeId from, __RunningIntersect &infos_DFS) const
function used for the computation of the running intersection property
virtual ~CliqueGraph()
destructor
std::ostream & operator<<(std::ostream &output, const BayesNet< GUM_SCALAR > &bn)
Prints map's DAG in output using the Graphviz-dot format.
virtual void addToClique(const NodeId clique_id, const NodeId node_id)
changes the set of nodes included into a given clique and returns the new set
virtual const std::string toString() const
friendly displays the content of the CliqueGraph
std::vector< NodeId > containerPath(const NodeId node1, const NodeId node2) const
returns a path from a clique containing node1 to a clique containing node2
CliqueGraph(Size nodes_size=HashTableConst::default_size, bool nodes_resize_policy=true, Size edges_size=HashTableConst::default_size, bool edges_resize_policy=true)
basic constructor: creates an empty clique graph
std::size_t Size
In aGrUM, hashed values are unsigned long int.
virtual void eraseFromClique(const NodeId clique_id, const NodeId node_id)
remove a node from a clique
Copyright 2005-2019 Pierre-Henri WUILLEMIN et Christophe GONZALES (LIP6) {prenom.nom}_at_lip6.fr.
Size NodeId
Type for node ids.
void insert(const Key &k)
Inserts a new element into the set.
bool hasRunningIntersection() const
indicates whether the running intersection property holds
#define GUM_ERROR(type, msg)
Copyright 2005-2019 Pierre-Henri WUILLEMIN et Christophe GONZALES (LIP6) {prenom.nom}_at_lip6.fr.