aGrUM 2.3.2
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-2025 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-2025 *
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#pragma once
41
48
49namespace gum {
50 namespace prm {
51 namespace gspan {
52
53 // NodeData
54
55 template < typename GUM_SCALAR >
57 GUM_CONSTRUCTOR(NodeData);
58 }
59
60 template < typename GUM_SCALAR >
62 n(from.n), l(from.l) {
63 GUM_CONS_CPY(NodeData);
64 }
65
66 template < typename GUM_SCALAR >
68 GUM_DESTRUCTOR(NodeData);
69 }
70
71 template < typename GUM_SCALAR >
73 return (n == from.n) && (l == from.l);
74 }
75
76 template < typename GUM_SCALAR >
78 return (n != from.n) && (l != from.l);
79 }
80
81 // EdgeData<GUM_SCALAR>
82
83 template < typename GUM_SCALAR >
84 INLINE EdgeData< GUM_SCALAR >::EdgeData() : u(0), v(0), l(0) {
85 GUM_CONSTRUCTOR(EdgeData);
86 }
87
88 template < typename GUM_SCALAR >
90 u(from.u), v(from.v), l(from.l) {
91 GUM_CONS_CPY(EdgeData);
92 }
93
94 template < typename GUM_SCALAR >
96 GUM_DESTRUCTOR(EdgeData);
97 }
98
99 template < typename GUM_SCALAR >
101 return (u == from.u) && (l_u == from.l_u) && (v == from.v) && (l_v == from.l_v)
102 && (l == from.l);
103 }
104
105 template < typename GUM_SCALAR >
107 return (u != from.u) && (l_u != from.l_u) && (v != from.v) && (l_v != from.l_v)
108 && (l != from.l);
109 }
110
111 // InterfaceGraph
112
113 template < typename GUM_SCALAR >
115 _sys_(&sys), _labels_(new Bijection< Idx, LabelData* >()), _counter_(0),
116 _erase_flag_(true) {
117 GUM_CONSTRUCTOR(InterfaceGraph);
119
120 // We need to add each instance in _graph_
121 for (auto iter = sys.begin(); iter != sys.end(); ++iter) {
123 node->n = iter.val();
124 _label_(node, label_map);
125 _graph_.addNodeWithId(iter.key());
126 _idMap_.insert(node->n, iter.key());
127 _nodes_.insert(iter.key(), node);
128 }
129
130 NodeData< GUM_SCALAR >* u = nullptr;
131 NodeData< GUM_SCALAR >* v = nullptr;
132
133 for (const auto& elt: _nodes_) {
134 NodeData< GUM_SCALAR >* data = elt.second;
135
136 for (const auto chain: data->n->type().slotChains()) {
137 for (const auto inst: data->n->getInstances(chain->id())) {
138 u = (_nodes_[_idMap_[inst]]->l < data->l) ? _nodes_[_idMap_[inst]] : data;
139 v = (u != data) ? data : _nodes_[_idMap_[inst]];
140
141 if (!_graph_.existsEdge(_idMap_[u->n], _idMap_[v->n])) {
143 edge->u = u->n;
144 edge->l_u = u->l;
145 edge->v = v->n;
146 edge->l_v = v->l;
147 _label_(edge, label_map);
148 _graph_.addEdge(_idMap_[u->n], _idMap_[v->n]);
149 _edges_.insert(Edge(_idMap_[u->n], _idMap_[v->n]), edge);
150 }
151 }
152 }
153 }
154 }
155
156 template < typename GUM_SCALAR >
158 _sys_(source._sys_), _graph_(source._graph_), _nodes_(source._nodes_),
159 _idMap_(source._idMap_), _edges_(source._edges_),
160 _labels_(new Bijection< Idx, LabelData* >(*(source._labels_))),
161 _nodeMap_(source._nodeMap_), _edgeMap_(source._edgeMap_), _counter_(source._counter_),
162 _erase_flag_(false) {
163 GUM_CONS_CPY(InterfaceGraph);
164 }
165
166 template < typename GUM_SCALAR >
168 GUM_DESTRUCTOR(InterfaceGraph);
169
170 if (_erase_flag_) {
171 for (const auto& elt: _nodes_)
172 delete elt.second;
173
174 for (const auto& elt: _edges_)
175 delete elt.second;
176
177 for (const auto& elt: _nodeMap_) {
178 delete elt.first;
179 delete elt.second;
180 }
181
182 for (const auto& elt: _edgeMap_) {
183 delete elt.first;
184 delete elt.second;
185 }
186 }
187
188 delete _labels_;
189 }
190
191 template < typename GUM_SCALAR >
196
197 template < typename GUM_SCALAR >
200 Size size = Size(1);
201 std::stringstream sBuff;
202 sBuff << node->n->type().name();
203
204 // First we search for multiple inputs
205 for (const auto chain: node->n->type().slotChains()) {
206 if (chain->isMultiple()) {
207 sBuff << "-" << node->n->getInstances(chain->id()).size();
208 sBuff << 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 try {
220 sBuff << "-" << node->n->getRefAttr(nn).size() << node->n->get(nn).name();
221 size *= node->n->get(nn).type().variable().domainSize();
222 } catch (NotFound const&) {
223 // (nn) is an inactive output node
224 }
225 }
226 }
227
228 // Label is ready
229 if (!label_map.exists(sBuff.str())) {
230 LabelData* label = new LabelData();
231 label_map.insert(sBuff.str(), label);
232 label->id = ++_counter_;
233 label->tree_width = size;
234 label->l = sBuff.str();
235 _labels_->insert(label->id, label);
236 _nodeMap_.insert(label, new Set< NodeData< GUM_SCALAR >* >());
237 }
238
239 node->l = label_map[sBuff.str()];
240 _nodeMap_[node->l]->insert(node);
241 }
242
243 template < typename GUM_SCALAR >
246 Size size = Size(1);
247 std::stringstream sBuff;
248 sBuff << 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 << "-" << 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 << "-" << edge->u->type().name() << "." << chain->lastElt().name();
262 size *= chain->lastElt().type().variable().domainSize();
263 }
264
265 // Label is ready
266 if (!label_map.exists(sBuff.str())) {
267 LabelData* label = new LabelData();
268 label_map.insert(sBuff.str(), label);
269 label->id = ++_counter_;
270 label->l = sBuff.str();
271 label->tree_width = size;
272 _labels_->insert(label->id, label);
273 _edgeMap_.insert(label, new Set< EdgeData< GUM_SCALAR >* >());
274 }
275
276 edge->l = label_map[sBuff.str()];
277 _edgeMap_[edge->l]->insert(edge);
278 }
279
280 template < typename GUM_SCALAR >
284
285 template < typename GUM_SCALAR >
287 return _graph_;
288 }
289
290 template < typename GUM_SCALAR >
294
295 template < typename GUM_SCALAR >
299
300 template < typename GUM_SCALAR >
302 try {
303 return _nodeMap_[const_cast< LabelData* >(l)]->size();
304 } catch (NotFound const&) { return _edgeMap_[const_cast< LabelData* >(l)]->size(); }
305 }
306
307 template < typename GUM_SCALAR >
310 return *(_nodeMap_[const_cast< LabelData* >(l)]);
311 }
312
313 template < typename GUM_SCALAR >
314 INLINE const Set< NodeData< GUM_SCALAR >* >&
316 return *(_nodeMap_[const_cast< LabelData* >(l)]);
317 }
318
319 template < typename GUM_SCALAR >
322 return *(_edgeMap_[const_cast< LabelData* >(l)]);
323 }
324
325 template < typename GUM_SCALAR >
326 INLINE const Set< EdgeData< GUM_SCALAR >* >&
328 return *(_edgeMap_[const_cast< LabelData* >(l)]);
329 }
330
331 template < typename GUM_SCALAR >
333 return _labels_->second(id);
334 }
335
336 template < typename GUM_SCALAR >
338 return _idMap_[const_cast< PRMInstance< GUM_SCALAR >* >(&i)];
339 }
340
341 template < typename GUM_SCALAR >
343 return _idMap_[const_cast< PRMInstance< GUM_SCALAR >* >(i)];
344 }
345
346 template < typename GUM_SCALAR >
351
352 template < typename GUM_SCALAR >
353 INLINE const NodeData< GUM_SCALAR >&
355 return node(id(i));
356 }
357
358 template < typename GUM_SCALAR >
362
363 template < typename GUM_SCALAR >
365 return *(_nodes_[id]);
366 }
367
368 template < typename GUM_SCALAR >
370 try {
371 return *(_edges_[Edge(u, v)]);
372 } catch (NotFound const&) { return *(_edges_[Edge(v, u)]); }
373 }
374
375 template < typename GUM_SCALAR >
377 NodeId v) const {
378 try {
379 return *(_edges_[Edge(u, v)]);
380 } catch (NotFound const&) { return *(_edges_[Edge(v, u)]); }
381 }
382
383 template < typename GUM_SCALAR >
384 INLINE std::ostream& operator<<(std::ostream& out, const NodeData< GUM_SCALAR >& data) {
385 out << data.n->name() << "(" << data.l->l << ")";
386 return out;
387 }
388
389 template < typename GUM_SCALAR >
390 INLINE std::ostream& operator<<(std::ostream& out, const EdgeData< GUM_SCALAR >& data) {
391 out << data.u->name() << " -> " << data.v->name() << "(" << data.l->l << ")";
392 return out;
393 }
394
395 } /* namespace gspan */
396 } /* namespace prm */
397} /* namespace gum */
Set of pairs of elements with fast search for both elements.
Definition bijection.h:1594
The base class for all undirected edges.
Exception : fatal (unknown ?) error.
The class for generic Hash Tables.
Definition hashTable.h:637
bool exists(const Key &key) const
Checks whether there exists an element with a given key in the hashtable.
value_type & insert(const Key &key, const Val &val)
Adds a new element (actually a copy of this element) into the hash table.
Exception : the element we looked for cannot be found.
Representation of a set.
Definition set.h:131
Base class for undirected graphs.
Definition undiGraph.h:128
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:70
iterator begin()
Returns an iterator over the instances in this system.
const iterator & end()
Returns a iterator at the end of the set of PRMInstance in this PRMSystem.
Inner class to handle data about edges in graph.
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.
bool operator!=(const EdgeData< GUM_SCALAR > &from) const
Difference operator.
LabelData * l_v
The label data of v.
This class represent the interface graph of a given gum::prm::PRMSystem<GUM_SCALAR>.
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.
Size size(const LabelData *l) const
Returns the number of node or edges labelled by l.
Bijection< Idx, LabelData * > & labels()
Returns the bijection between LabelData and their string representation.
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.
NodeId id(const PRMInstance< GUM_SCALAR > &i) const
Returns the id of i in this interface graph.
HashTable< LabelData *, Set< NodeData< GUM_SCALAR > * > * > _nodeMap_
Mapping between a LabelData and the set of NodeData<GUM_SCALAR> with that label.
EdgeData< GUM_SCALAR > & edge(NodeId u, NodeId v)
Returns data about an edge.
Set< NodeData< GUM_SCALAR > * > & nodes(const LabelData *l)
Returns the set of nodes labelled by l.
EdgeProperty< EdgeData< GUM_SCALAR > * > _edges_
Data associated with edges in graph.
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...
UndiGraph & graph()
Returns the graph of this interface graph.
NodeData< GUM_SCALAR > & node(const PRMInstance< GUM_SCALAR > *i)
Returns data about a node.
LabelData * label(Idx id)
Returns a label given its id.
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.
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.
PRMInstance< GUM_SCALAR > * n
The instance represented by this node.
bool operator==(const NodeData< GUM_SCALAR > &from) const
Equality operator.
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:72
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.
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.