30 #endif // GUM_NOINLINE 32 #ifndef DOXYGEN_SHOULD_SKIP_THIS 50 bool nodes_resize_policy,
52 bool edges_resize_policy) :
53 NodeGraphPart(nodes_size, nodes_resize_policy),
54 UndiGraph(nodes_size, nodes_resize_policy, edges_size, edges_resize_policy) {
56 GUM_CONSTRUCTOR(CliqueGraph);
64 __cliques(from.__cliques), __separators(from.__separators) {
66 GUM_CONS_CPY(CliqueGraph);
73 GUM_DESTRUCTOR(CliqueGraph);
79 const NodeId node2)
const {
82 std::vector< NodeId > path =
83 undirectedPath(container(node1), container(node2));
87 while ((path.size() >= 2) && (clique(path[path.size() - 2]).contains(node2)))
90 while ((path.size() >= 2) && (clique(path[1]).contains(node1)))
91 path.erase(path.begin());
102 NodeSet& clique = __cliques[clique_id];
105 if (clique.contains(node_id)) {
107 "the clique set already contains the node " << node_id);
110 clique.insert(node_id);
113 for (
const auto nei : neighbours(clique_id))
114 if (__cliques[nei].contains(node_id))
115 __separators[Edge(nei, clique_id)].insert(node_id);
122 NodeSet& clique = __cliques[clique_id];
125 if (clique.contains(node_id)) {
126 clique.
erase(node_id);
129 for (
const auto nei : neighbours(clique_id)) {
130 Edge edge(nei, clique_id);
132 if (__separators[edge].contains(node_id))
133 __separators[edge].erase(node_id);
143 CliqueGraph::__RunningIntersect& infos_DFS)
const {
146 const NodeSet& nodes_clique = __cliques[clique];
148 for (
const auto node : nodes_clique)
149 if (infos_DFS.nodes_other_components.contains(node))
return false;
153 for (
const auto node : nodes_clique)
154 if (!infos_DFS.nodes_DFS_forbidden.contains(node))
155 infos_DFS.cliques_DFS_chain[clique].
erase(node);
159 if (infos_DFS.visited_cliques.contains(clique))
return true;
162 for (
const auto node : nodes_clique)
163 if (!infos_DFS.nodes_DFS_seen.contains(node))
164 infos_DFS.nodes_DFS_seen.insert(node);
167 infos_DFS.visited_cliques.insert(clique);
172 for (
const auto otherID : neighbours(clique))
173 if (otherID != from) {
176 const Edge edge(otherID, clique);
177 const NodeSet& from_separ = __separators[edge];
179 for (
const auto node : nodes_clique) {
180 if (!from_separ.contains(node))
181 infos_DFS.nodes_DFS_forbidden.
insert(node);
185 if (!__runningIntersectionDFS(otherID, clique, infos_DFS))
return false;
188 for (
const auto node : nodes_clique)
189 infos_DFS.nodes_DFS_forbidden.erase(node);
194 for (
const auto node : nodes_clique) {
195 if (!infos_DFS.nodes_DFS_forbidden.contains(node))
196 infos_DFS.cliques_DFS_chain[clique].erase(node);
205 if (neighbours(clique).size() <= 1)
206 for (
const auto node : nodes_clique)
207 if (!infos_DFS.nodes_DFS_forbidden.contains(node))
208 infos_DFS.nodes_DFS_forbidden.insert(node);
218 __RunningIntersect infos_DFS;
219 infos_DFS.cliques_DFS_chain = __cliques;
222 for (
const auto DFSnode : nodes())
223 if (!infos_DFS.visited_cliques.contains(DFSnode)) {
225 infos_DFS.nodes_DFS_forbidden.clear();
228 infos_DFS.nodes_DFS_seen.clear();
232 if (!__runningIntersectionDFS(DFSnode, DFSnode, infos_DFS))
return false;
237 for (
const auto node : infos_DFS.nodes_DFS_seen)
238 if (!infos_DFS.nodes_other_components.contains(node))
239 infos_DFS.nodes_other_components.insert(node);
244 for (
const auto& elt : infos_DFS.cliques_DFS_chain)
245 if (!elt.second.empty())
return false;
254 if (UndiGraph::operator!=(from))
return false;
257 for (
const auto& elt : __cliques)
258 if (elt.second != from.__cliques[elt.first])
return false;
264 std::stringstream stream;
265 stream <<
"list of nodes:" << std::endl;
267 for (
const auto node : nodes()) {
268 stream <<
" -- node: " << node << std::endl <<
" clique:";
270 for (
const auto cliq : clique(node))
271 stream <<
" " << cliq;
276 stream <<
"\n\nlist of edges:\n";
278 for (
const auto edge : edges())
279 stream << edge <<
" ";
284 const std::string expandCliqueContent(
const NodeSet& clique) {
285 std::stringstream stream;
288 for (
auto node : clique) {
289 if (!first) { stream <<
"-"; }
297 const std::string expandClique(
const NodeId n,
const NodeSet& clique) {
298 std::stringstream stream;
299 stream <<
'(' << n <<
") " << expandCliqueContent(clique);
302 const std::string expandSeparator(
const NodeId n1,
306 std::stringstream stream;
307 stream << expandClique(n1, clique1) <<
"^" << expandClique(n2, clique2);
312 std::stringstream stream;
313 stream <<
"graph {" << std::endl;
316 for (
auto node : nodes()) {
317 std::string nom =
'"' + expandClique(node, clique(node)) +
'"';
318 stream <<
" " << nom <<
" [label=\"" << expandCliqueContent(clique(node))
319 <<
"\",fillcolor =\"burlywood\",style=\"filled\"];" << std::endl;
325 for (
auto edge : edges()) {
327 << expandSeparator(edge.first(),
328 clique(edge.first()),
330 clique(edge.second()))
331 <<
"\" [label=\"" << expandCliqueContent(separator(edge)) <<
"\"" 332 <<
",shape=box,fillcolor=\"palegreen\",style=\"filled\",fontsize=8," 340 for (
auto edge : edges())
341 stream <<
" \"" << expandClique(edge.first(), clique(edge.first()))
343 << expandSeparator(edge.first(),
344 clique(edge.first()),
346 clique(edge.second()))
347 <<
"\"--\"" << expandClique(edge.second(), clique(edge.second()))
348 <<
"\";" << std::endl;
350 stream <<
"}" << std::endl;
357 std::ostream&
operator<<(std::ostream& stream,
const CliqueGraph& graph) {
358 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.
gum is the global namespace for all aGrUM entities
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
Basic class for all graphs of cliques (join trees, etc)
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)
inline source of basic clique graphs