27 #include <agrum/tools/graphs/cliqueGraph.h> 31 # include <agrum/tools/graphs/cliqueGraph_inl.h> 34 #ifndef DOXYGEN_SHOULD_SKIP_THIS 46 CliqueGraph::CliqueGraph(Size nodes_size,
47 bool nodes_resize_policy,
49 bool edges_resize_policy) :
50 NodeGraphPart(nodes_size, nodes_resize_policy),
51 UndiGraph(nodes_size, nodes_resize_policy, edges_size, edges_resize_policy) {
53 GUM_CONSTRUCTOR(CliqueGraph);
58 CliqueGraph::CliqueGraph(
const CliqueGraph& from) :
61 cliques__(from.cliques__), separators__(from.separators__) {
63 GUM_CONS_CPY(CliqueGraph);
68 CliqueGraph::~CliqueGraph() {
70 GUM_DESTRUCTOR(CliqueGraph);
75 std::vector< NodeId > CliqueGraph::containerPath(
const NodeId node1,
76 const NodeId node2)
const {
79 std::vector< NodeId > path
80 = undirectedPath(container(node1), container(node2));
84 while ((path.size() >= 2) && (clique(path[path.size() - 2]).contains(node2)))
87 while ((path.size() >= 2) && (clique(path[1]).contains(node1)))
88 path.erase(path.begin());
97 void CliqueGraph::addToClique(
const NodeId clique_id,
const NodeId node_id) {
99 NodeSet& clique = cliques__[clique_id];
102 if (clique.contains(node_id)) {
103 GUM_ERROR(DuplicateElement,
104 "the clique set already contains the node " << node_id);
107 clique.insert(node_id);
110 for (
const auto nei: neighbours(clique_id))
111 if (cliques__[nei].contains(node_id))
112 separators__[Edge(nei, clique_id)].insert(node_id);
117 void CliqueGraph::eraseFromClique(
const NodeId clique_id,
const NodeId node_id) {
119 NodeSet& clique = cliques__[clique_id];
122 if (clique.contains(node_id)) {
123 clique.erase(node_id);
126 for (
const auto nei: neighbours(clique_id)) {
127 Edge edge(nei, clique_id);
129 if (separators__[edge].contains(node_id))
130 separators__[edge].erase(node_id);
137 bool CliqueGraph::runningIntersectionDFS__(
140 CliqueGraph::RunningIntersect__& infos_DFS)
const {
143 const NodeSet& nodes_clique = cliques__[clique];
145 for (
const auto node: nodes_clique)
146 if (infos_DFS.nodes_other_components.contains(node))
return false;
150 for (
const auto node: nodes_clique)
151 if (!infos_DFS.nodes_DFS_forbidden.contains(node))
152 infos_DFS.cliques_DFS_chain[clique].erase(node);
156 if (infos_DFS.visited_cliques.contains(clique))
return true;
159 for (
const auto node: nodes_clique)
160 if (!infos_DFS.nodes_DFS_seen.contains(node))
161 infos_DFS.nodes_DFS_seen.insert(node);
164 infos_DFS.visited_cliques.insert(clique);
169 for (
const auto otherID: neighbours(clique))
170 if (otherID != from) {
173 const Edge edge(otherID, clique);
174 const NodeSet& from_separ = separators__[edge];
176 for (
const auto node: nodes_clique) {
177 if (!from_separ.contains(node))
178 infos_DFS.nodes_DFS_forbidden.insert(node);
182 if (!runningIntersectionDFS__(otherID, clique, infos_DFS))
return false;
185 for (
const auto node: nodes_clique)
186 infos_DFS.nodes_DFS_forbidden.erase(node);
191 for (
const auto node: nodes_clique) {
192 if (!infos_DFS.nodes_DFS_forbidden.contains(node))
193 infos_DFS.cliques_DFS_chain[clique].erase(node);
202 if (neighbours(clique).size() <= 1)
203 for (
const auto node: nodes_clique)
204 if (!infos_DFS.nodes_DFS_forbidden.contains(node))
205 infos_DFS.nodes_DFS_forbidden.insert(node);
213 bool CliqueGraph::hasRunningIntersection()
const {
215 RunningIntersect__ infos_DFS;
216 infos_DFS.cliques_DFS_chain = cliques__;
219 for (
const auto DFSnode: nodes())
220 if (!infos_DFS.visited_cliques.contains(DFSnode)) {
222 infos_DFS.nodes_DFS_forbidden.clear();
225 infos_DFS.nodes_DFS_seen.clear();
229 if (!runningIntersectionDFS__(DFSnode, DFSnode, infos_DFS))
return false;
234 for (
const auto node: infos_DFS.nodes_DFS_seen)
235 if (!infos_DFS.nodes_other_components.contains(node))
236 infos_DFS.nodes_other_components.insert(node);
241 for (
const auto& elt: infos_DFS.cliques_DFS_chain)
242 if (!elt.second.empty())
return false;
249 bool CliqueGraph::operator==(
const CliqueGraph& from)
const {
251 if (UndiGraph::operator!=(from))
return false;
254 for (
const auto& elt: cliques__)
255 if (elt.second != from.cliques__[elt.first])
return false;
260 std::string CliqueGraph::toString()
const {
261 std::stringstream stream;
262 stream <<
"list of nodes:" << std::endl;
264 for (
const auto node: nodes()) {
265 stream <<
" -- node: " << node << std::endl <<
" clique:";
267 for (
const auto cliq: clique(node))
268 stream <<
" " << cliq;
273 stream <<
"\n\nlist of edges:\n";
275 for (
const auto& edge: edges())
276 stream << edge <<
" ";
281 const std::string expandCliqueContent(
const NodeSet& clique) {
282 std::stringstream stream;
285 for (
auto node: clique) {
286 if (!first) { stream <<
"-"; }
294 const std::string expandClique(
const NodeId n,
const NodeSet& clique) {
295 std::stringstream stream;
296 stream <<
'(' << n <<
") " << expandCliqueContent(clique);
299 const std::string expandSeparator(
const NodeId n1,
300 const NodeSet& clique1,
302 const NodeSet& clique2) {
303 std::stringstream stream;
304 stream << expandClique(n1, clique1) <<
"^" << expandClique(n2, clique2);
308 std::string CliqueGraph::toDot()
const {
309 std::stringstream stream;
310 stream <<
"graph {" << std::endl;
311 stream <<
" node [style=\"filled\", fontcolor=\"black\"];" << std::endl;
314 for (
auto node: nodes()) {
315 std::string nom =
'"' + expandClique(node, clique(node)) +
'"';
316 stream <<
" " << nom <<
" [label=\"" << expandCliqueContent(clique(node))
317 <<
"\",fillcolor =\"burlywood\"];" << std::endl;
323 for (
const auto& edge: edges()) {
325 << expandSeparator(edge.first(),
326 clique(edge.first()),
328 clique(edge.second()))
329 <<
"\" [label=\"" << expandCliqueContent(separator(edge)) <<
"\"" 330 <<
",shape=box,fillcolor=\"palegreen\",fontsize=8," 338 for (
const auto& edge: edges())
339 stream <<
" \"" << expandClique(edge.first(), clique(edge.first()))
341 << expandSeparator(edge.first(),
342 clique(edge.first()),
344 clique(edge.second()))
345 <<
"\"--\"" << expandClique(edge.second(), clique(edge.second()))
346 <<
"\";" << std::endl;
348 stream <<
"}" << std::endl;
355 std::ostream& operator<<(std::ostream& stream,
const CliqueGraph& graph) {
356 stream << graph.toString();