aGrUM 3.1.1
a C++ library for (probabilistic) graphical models
interfaceGraph_tpl.h
Go to the documentation of this file.
1/****************************************************************************
2 * This file is part of the aGrUM/pyAgrum library. *
3 * *
4 * Copyright (c) 2005-2026 by *
5 * - Pierre-Henri WUILLEMIN(_at_LIP6) *
6 * - Christophe GONZALES(_at_AMU) *
7 * *
8 * The aGrUM/pyAgrum library is free software; you can redistribute it *
9 * and/or modify it under the terms of either : *
10 * *
11 * - the GNU Lesser General Public License as published by *
12 * the Free Software Foundation, either version 3 of the License, *
13 * or (at your option) any later version, *
14 * - the MIT license (MIT), *
15 * - or both in dual license, as here. *
16 * *
17 * (see https://agrum.gitlab.io/articles/dual-licenses-lgplv3mit.html) *
18 * *
19 * This aGrUM/pyAgrum library is distributed in the hope that it will be *
20 * useful, but WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
21 * INCLUDING BUT NOT LIMITED TO THE WARRANTIES MERCHANTABILITY or FITNESS *
22 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE *
23 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *
24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
25 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
26 * OTHER DEALINGS IN THE SOFTWARE. *
27 * *
28 * See LICENCES for more details. *
29 * *
30 * SPDX-FileCopyrightText: Copyright 2005-2026 *
31 * - Pierre-Henri WUILLEMIN(_at_LIP6) *
32 * - Christophe GONZALES(_at_AMU) *
33 * SPDX-License-Identifier: LGPL-3.0-or-later OR MIT *
34 * *
35 * Contact : info_at_agrum_dot_org *
36 * homepage : http://agrum.gitlab.io *
37 * gitlab : https://gitlab.com/agrumery/agrum *
38 * *
39 ****************************************************************************/
40
41#pragma once
42
49
50#include <agrum/PRM/gspan/interfaceGraph.h> // to ease IDE parser
51
52namespace gum {
53 namespace prm {
54 namespace gspan {
55
56 // NodeData
57
58 template < GUM_Numeric GUM_SCALAR >
60 GUM_CONSTRUCTOR(NodeData);
61 }
62
63 template < GUM_Numeric GUM_SCALAR >
65 GUM_CONS_CPY(NodeData);
66 }
67
68 template < GUM_Numeric GUM_SCALAR >
70 GUM_DESTRUCTOR(NodeData);
71 }
72
73 template < GUM_Numeric GUM_SCALAR >
75 return (n == from.n) && (l == from.l);
76 }
77
78 template < GUM_Numeric GUM_SCALAR >
80 return (n != from.n) && (l != from.l);
81 }
82
83 // EdgeData<GUM_SCALAR>
84
85 template < GUM_Numeric GUM_SCALAR >
87 GUM_CONSTRUCTOR(EdgeData);
88 }
89
90 template < GUM_Numeric GUM_SCALAR >
92 u(from.u), v(from.v), l(from.l) {
93 GUM_CONS_CPY(EdgeData);
94 }
95
96 template < GUM_Numeric GUM_SCALAR >
98 GUM_DESTRUCTOR(EdgeData);
99 }
100
101 template < GUM_Numeric GUM_SCALAR >
103 return (u == from.u) && (l_u == from.l_u) && (v == from.v) && (l_v == from.l_v)
104 && (l == from.l);
105 }
106
107 template < GUM_Numeric GUM_SCALAR >
109 return (u != from.u) && (l_u != from.l_u) && (v != from.v) && (l_v != from.l_v)
110 && (l != from.l);
111 }
112
113 // InterfaceGraph
114
115 template < GUM_Numeric GUM_SCALAR >
117 _sys_(&sys), _labels_(new Bijection< Idx, LabelData* >()), _counter_(0),
118 _erase_flag_(true) {
119 GUM_CONSTRUCTOR(InterfaceGraph);
121
122 // We need to add each instance in _graph_
123 for (auto iter = sys.begin(); iter != sys.end(); ++iter) {
125 node->n = iter.val();
126 _label_(node, label_map);
127 _graph_.addNodeWithId(iter.key());
128 _idMap_.insert(node->n, iter.key());
129 _nodes_.insert(iter.key(), node);
130 }
131
132 NodeData< GUM_SCALAR >* u = nullptr;
133 NodeData< GUM_SCALAR >* v = nullptr;
134
135 for (const auto& elt: _nodes_) {
136 NodeData< GUM_SCALAR >* data = elt.second;
137
138 for (const auto chain: data->n->type().slotChains()) {
139 for (const auto inst: data->n->getInstances(chain->id())) {
140 u = (_nodes_[_idMap_[inst]]->l < data->l) ? _nodes_[_idMap_[inst]] : data;
141 v = (u != data) ? data : _nodes_[_idMap_[inst]];
142
143 if (!_graph_.existsEdge(_idMap_[u->n], _idMap_[v->n])) {
145 edge->u = u->n;
146 edge->l_u = u->l;
147 edge->v = v->n;
148 edge->l_v = v->l;
149 _label_(edge, label_map);
150 _graph_.addEdge(_idMap_[u->n], _idMap_[v->n]);
151 _edges_.insert(Edge(_idMap_[u->n], _idMap_[v->n]), edge);
152 }
153 }
154 }
155 }
156 }
157
158 template < GUM_Numeric GUM_SCALAR >
160 _sys_(source._sys_), _graph_(source._graph_), _nodes_(source._nodes_),
161 _idMap_(source._idMap_), _edges_(source._edges_),
162 _labels_(new Bijection< Idx, LabelData* >(*(source._labels_))),
163 _nodeMap_(source._nodeMap_), _edgeMap_(source._edgeMap_), _counter_(source._counter_),
164 _erase_flag_(false) {
165 GUM_CONS_CPY(InterfaceGraph);
166 }
167
168 template < GUM_Numeric GUM_SCALAR >
170 GUM_DESTRUCTOR(InterfaceGraph);
171
172 if (_erase_flag_) {
173 for (const auto& elt: _nodes_)
174 delete elt.second;
175
176 for (const auto& elt: _edges_)
177 delete elt.second;
178
179 for (const auto& elt: _nodeMap_) {
180 delete elt.first;
181 delete elt.second;
182 }
183
184 for (const auto& elt: _edgeMap_) {
185 delete elt.first;
186 delete elt.second;
187 }
188 }
189
190 delete _labels_;
191 }
192
193 template < GUM_Numeric GUM_SCALAR >
198
199 template < GUM_Numeric GUM_SCALAR >
202 Size size = Size(1);
203 std::string sBuff = node->n->type().name();
204
205 // First we search for multiple inputs
206 for (const auto chain: node->n->type().slotChains()) {
207 if (chain->isMultiple()) {
208 sBuff += std::format("-{}{}", node->n->getInstances(chain->id()).size(), chain->name());
209 size *= node->n->getInstances(chain->id()).size()
210 * chain->lastElt().type().variable().domainSize();
211 } else {
212 size *= chain->lastElt().type().variable().domainSize();
213 }
214 }
215
216 // Second we search for active outputs
217 for (const auto nn: node->n->type().containerDag().nodes()) {
218 if (node->n->type().isOutputNode(node->n->type().get(nn))) {
219 if (node->n->hasRefAttr(nn) && node->n->exists(nn)) {
220 sBuff
221 += std::format("-{}{}", node->n->getRefAttr(nn).size(), node->n->get(nn).name());
222 size *= node->n->get(nn).type().variable().domainSize();
223 }
224 }
225 }
226
227 // Label is ready
228 auto p_lm = label_map.tryGet(sBuff);
229 if (!p_lm) {
230 LabelData* label = new LabelData();
231 label_map.insert(sBuff, label);
232 label->id = ++_counter_;
233 label->tree_width = size;
234 label->l = sBuff;
235 _labels_->insert(label->id, label);
236 _nodeMap_.insert(label, new Set< NodeData< GUM_SCALAR >* >());
237 p_lm = label_map.tryGet(sBuff);
238 }
239
240 node->l = *p_lm;
241 _nodeMap_[node->l]->insert(node);
242 }
243
244 template < GUM_Numeric GUM_SCALAR >
247 Size size = Size(1);
248 std::string sBuff = std::format("{}-{}", edge->u->type().name(), edge->v->type().name());
249
250 // First looking for edge->u output nodes in v
251 for (const auto chain: edge->u->type().slotChains()) {
252 if (edge->u->getInstances(chain->id()).exists(edge->v)) {
253 sBuff += std::format("-{}.{}", edge->v->type().name(), chain->lastElt().name());
254 size *= chain->lastElt().type().variable().domainSize();
255 }
256 }
257
258 // Second looking for edge->v output nodes in u
259 for (const auto chain: edge->v->type().slotChains())
260 if (edge->v->getInstances(chain->id()).exists(edge->u)) {
261 sBuff += std::format("-{}.{}", edge->u->type().name(), chain->lastElt().name());
262 size *= chain->lastElt().type().variable().domainSize();
263 }
264
265 // Label is ready
266 auto p_elm = label_map.tryGet(sBuff);
267 if (!p_elm) {
268 LabelData* label = new LabelData();
269 label_map.insert(sBuff, label);
270 label->id = ++_counter_;
271 label->l = sBuff;
272 label->tree_width = size;
273 _labels_->insert(label->id, label);
274 _edgeMap_.insert(label, new Set< EdgeData< GUM_SCALAR >* >());
275 p_elm = label_map.tryGet(sBuff);
276 }
277
278 edge->l = *p_elm;
279 _edgeMap_[edge->l]->insert(edge);
280 }
281
282 template < GUM_Numeric GUM_SCALAR >
286
287 template < GUM_Numeric GUM_SCALAR >
291
292 template < GUM_Numeric GUM_SCALAR >
296
297 template < GUM_Numeric GUM_SCALAR >
301
302 template < GUM_Numeric GUM_SCALAR >
304 if (auto p = _nodeMap_.tryGet(const_cast< LabelData* >(l))) return (*p)->size();
305 return _edgeMap_[const_cast< LabelData* >(l)]->size();
306 }
307
308 template < GUM_Numeric GUM_SCALAR >
310 return *(_nodeMap_[const_cast< LabelData* >(l)]);
311 }
312
313 template < GUM_Numeric GUM_SCALAR >
316 return *(_nodeMap_[const_cast< LabelData* >(l)]);
317 }
318
319 template < GUM_Numeric GUM_SCALAR >
321 return *(_edgeMap_[const_cast< LabelData* >(l)]);
322 }
323
324 template < GUM_Numeric GUM_SCALAR >
327 return *(_edgeMap_[const_cast< LabelData* >(l)]);
328 }
329
330 template < GUM_Numeric GUM_SCALAR >
332 return _labels_->second(id);
333 }
334
335 template < GUM_Numeric GUM_SCALAR >
339
340 template < GUM_Numeric GUM_SCALAR >
344
345 template < GUM_Numeric GUM_SCALAR >
350
351 template < GUM_Numeric GUM_SCALAR >
354 return node(id(i));
355 }
356
357 template < GUM_Numeric GUM_SCALAR >
361
362 template < GUM_Numeric GUM_SCALAR >
366
367 template < GUM_Numeric GUM_SCALAR >
369 if (auto p = _edges_.tryGet(Edge(u, v))) return *(*p);
370 return *(_edges_[Edge(v, u)]);
371 }
372
373 template < GUM_Numeric GUM_SCALAR >
375 if (auto p = _edges_.tryGet(Edge(u, v))) return *(*p);
376 return *(_edges_[Edge(v, u)]);
377 }
378
379 template < GUM_Numeric GUM_SCALAR >
380 std::ostream& operator<<(std::ostream& out, const NodeData< GUM_SCALAR >& data) {
381 out << data.n->name() << "(" << data.l->l << ")";
382 return out;
383 }
384
385 template < GUM_Numeric GUM_SCALAR >
386 std::ostream& operator<<(std::ostream& out, const EdgeData< GUM_SCALAR >& data) {
387 out << data.u->name() << " -> " << data.v->name() << "(" << data.l->l << ")";
388 return out;
389 }
390
391 } /* namespace gspan */
392 } /* namespace prm */
393} /* namespace gum */
Set of pairs of elements with fast search for both elements.
Definition bijection.h:1640
The base class for all undirected edges.
Exception : fatal (unknown ?) error.
The class for generic Hash Tables.
Definition hashTable.h:640
value_type & insert(const Key &key, const Val &val)
Adds a new element (actually a copy of this element) into the hash table.
optional_ref< Val > tryGet(const Key &key)
Returns a pointer to the value associated with a given key, or nullptr if the key does not exist.
Representation of a set.
Definition set.h:129
Base class for undirected graphs.
Definition undiGraph.h:130
An PRMInstance is a Bayesian network fragment defined by a Class and used in a PRMSystem.
Definition PRMInstance.h:79
A PRMSystem is a container of PRMInstance and describe a relational skeleton.
Definition PRMSystem.h:72
const iterator & end()
Returns an iterator at the end of the set of PRMInstance in this PRMSystem.
iterator begin()
Returns an iterator over the instances in this system.
Inner class to handle data about edges in graph.
bool operator!=(const EdgeData< GUM_SCALAR > &from) const
Difference operator.
bool operator==(const EdgeData< GUM_SCALAR > &from) const
Equality operator.
PRMInstance< GUM_SCALAR > * v
The other instance represented by thus edge.
PRMInstance< GUM_SCALAR > * u
One of the two instance represented by this edge.
LabelData * l_u
The label data of u.
LabelData * l
The labal data of this edge.
LabelData * l_v
The label data of v.
This class represent the interface graph of a given gum::prm::PRMSystem<GUM_SCALAR>.
Set< NodeData< GUM_SCALAR > * > & nodes(const LabelData *l)
Returns the set of nodes labelled by l.
const PRMSystem< GUM_SCALAR > * _sys_
The gum::prm::PRMSystem<GUM_SCALAR> represented by this interface graph.
NodeProperty< NodeData< GUM_SCALAR > * > _nodes_
Data associated with a node in graph.
UndiGraph & internalGraph()
Returns the graph of this interface graph.
Size size(const LabelData *l) const
Returns the number of node or edges labelled by l.
UndiGraph _graph_
The interface graph.
InterfaceGraph & operator=(const InterfaceGraph &source)
Copy operator.
Idx _counter_
A counter used of assigning ids to labels.
InterfaceGraph(const PRMSystem< GUM_SCALAR > &sys)
Default constructor.
NodeData< GUM_SCALAR > & node(const PRMInstance< GUM_SCALAR > *i)
Returns data about a node.
HashTable< LabelData *, Set< NodeData< GUM_SCALAR > * > * > _nodeMap_
Mapping between a LabelData and the set of NodeData<GUM_SCALAR> with that label.
LabelData * label(Idx id)
Returns a label given its id.
EdgeProperty< EdgeData< GUM_SCALAR > * > _edges_
Data associated with edges in graph.
EdgeData< GUM_SCALAR > & edge(NodeId u, NodeId v)
Returns data about an edge.
bool _erase_flag_
For shallow copies.
HashTable< LabelData *, Set< EdgeData< GUM_SCALAR > * > * > _edgeMap_
Mapping between a LabelData and the set of EdgeData<GUM_SCALAR> with that label.
void _label_(NodeData< GUM_SCALAR > *node, HashTable< std::string, LabelData * > &label_map)
Compute the label of node and add it to labels if it does not exists yet. Update node with the correc...
NodeId id(const PRMInstance< GUM_SCALAR > &i) const
Returns the id of i in this interface graph.
Bijection< Idx, LabelData * > * _labels_
Bijection between labels and their ids.
Set< EdgeData< GUM_SCALAR > * > & edges(const LabelData *l)
Returns the set of nodes labelled by l.
Bijection< Idx, LabelData * > & labels()
Returns the bijection between LabelData and their string representation.
HashTable< PRMInstance< GUM_SCALAR > *, NodeId > _idMap_
Mapping between PRMInstance<GUM_SCALAR> dans their id in graph.
Inner class to handle data about nodes in graph.
bool operator==(const NodeData< GUM_SCALAR > &from) const
Equality operator.
PRMInstance< GUM_SCALAR > * n
The instance represented by this node.
bool operator!=(const NodeData< GUM_SCALAR > &from) const
Difference operator.
LabelData * l
The label of this node.
#define GUM_ERROR(type, msg)
Definition exceptions.h:76
std::size_t Size
In aGrUM, hashed values are unsigned long int.
Definition types.h:74
Size Idx
Type for indexes.
Definition types.h:79
Size NodeId
Type for node ids.
Headers of InterfaceGraph.
std::ostream & operator<<(std::ostream &out, const DFSCode &code)
Print code in out.
Definition DFSCode.cpp:59
namespace for all probabilistic relational models entities
Definition agrum.h:68
gum is the global namespace for all aGrUM entities
Definition agrum.h:46
Inner class to handle data about labels in this interface graph.
std::string l
The string version of this label.