aGrUM
0.20.2
a C++ library for (probabilistic) graphical models
nodeGraphPart_inl.h
Go to the documentation of this file.
1
/**
2
*
3
* Copyright 2005-2020 Pierre-Henri WUILLEMIN(@LIP6) & Christophe GONZALES(@AMU)
4
* info_at_agrum_dot_org
5
*
6
* This library is free software: you can redistribute it and/or modify
7
* it under the terms of the GNU Lesser General Public License as published by
8
* the Free Software Foundation, either version 3 of the License, or
9
* (at your option) any later version.
10
*
11
* This library is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
* GNU Lesser General Public License for more details.
15
*
16
* You should have received a copy of the GNU Lesser General Public License
17
* along with this library. If not, see <http://www.gnu.org/licenses/>.
18
*
19
*/
20
21
22
/** @file
23
* @brief Inline implementation of the base node set class for graphs
24
*
25
* @author Pierre-Henri WUILLEMIN(@LIP6) & Christophe GONZALES(@AMU)
26
*
27
*/
28
29
// to ease parsing by IDE
30
#
include
<
agrum
/
tools
/
graphs
/
parts
/
nodeGraphPart
.
h
>
31
32
namespace
gum
{
33
34
//=================NODEGRAPHPARTITERATOR============================
35
36
/// ensure that the nodeId is either end() either a valid NodeId
37
INLINE
void
NodeGraphPartIterator
::
validate_
()
noexcept
{
38
valid_
=
false
;
39
40
if
(
pos_
>
nodes_
->
bound
()) {
pos_
=
nodes_
->
bound
(); }
41
42
while
(
pos_
<
nodes_
->
bound
()) {
43
if
(!
nodes_
->
inHoles__
(
pos_
)) {
44
valid_
=
true
;
45
return
;
46
}
47
48
++
pos_
;
49
}
50
}
51
52
/// default constructor
53
INLINE
54
NodeGraphPartIterator
::
NodeGraphPartIterator
(
const
NodeGraphPart
&
nodes
)
noexcept
55
:
56
nodes_
(&
nodes
) {
57
GUM_CONSTRUCTOR
(
NodeGraphPartIterator
);
58
}
59
60
/// copy constructor
61
INLINE
62
NodeGraphPartIterator
::
NodeGraphPartIterator
(
63
const
NodeGraphPartIterator
&
it
)
noexcept
:
64
nodes_
(
it
.
nodes_
),
65
pos_
(
it
.
pos_
),
valid_
(
it
.
valid_
) {
66
GUM_CONS_CPY
(
NodeGraphPartIterator
);
67
}
68
69
/// move constructor
70
INLINE
71
NodeGraphPartIterator
::
NodeGraphPartIterator
(
NodeGraphPartIterator
&&
it
)
noexcept
72
:
73
nodes_
(
it
.
nodes_
),
74
pos_
(
it
.
pos_
),
valid_
(
it
.
valid_
) {
75
GUM_CONS_MOV
(
NodeGraphPartIterator
);
76
}
77
78
/// destructor
79
INLINE
NodeGraphPartIterator
::~
NodeGraphPartIterator
()
noexcept
{
80
GUM_DESTRUCTOR
(
NodeGraphPartIterator
);
81
}
82
83
/// copy assignment operator
84
INLINE NodeGraphPartIterator&
85
NodeGraphPartIterator
::
operator
=(
const
NodeGraphPartIterator
&
it
)
noexcept
{
86
nodes_
=
it
.
nodes_
;
87
pos_
=
it
.
pos_
;
88
valid_
=
it
.
valid_
;
89
GUM_OP_CPY
(
NodeGraphPartIterator
);
90
91
return
*
this
;
92
}
93
94
/// move assignment operator
95
INLINE
NodeGraphPartIterator
&
96
NodeGraphPartIterator
::
operator
=(
NodeGraphPartIterator
&&
it
)
noexcept
{
97
nodes_
=
it
.
nodes_
;
98
pos_
=
it
.
pos_
;
99
valid_
=
it
.
valid_
;
100
GUM_OP_MOV
(
NodeGraphPartIterator
);
101
102
return
*
this
;
103
}
104
105
/// checks whether two iterators point toward the same node
106
INLINE
107
bool
NodeGraphPartIterator
::
operator
==(
108
const
NodeGraphPartIterator
&
it
)
const
noexcept
{
109
return
((
pos_
==
it
.
pos_
) && (
valid_
==
it
.
valid_
) && (
nodes_
==
it
.
nodes_
));
110
}
111
112
/// checks whether two iterators point toward different nodes
113
INLINE
114
bool
NodeGraphPartIterator
::
operator
!=(
115
const
NodeGraphPartIterator
&
it
)
const
noexcept
{
116
return
!(
operator
==(
it
));
117
}
118
119
/// increment the iterator
120
INLINE
NodeGraphPartIterator
&
NodeGraphPartIterator
::
operator
++()
noexcept
{
121
++
pos_
;
122
validate_
();
123
return
*
this
;
124
}
125
126
/// dereferencing operator
127
INLINE
NodeId
NodeGraphPartIterator
::
operator
*()
const
{
128
if
(!
valid_
) {
129
GUM_ERROR
(
UndefinedIteratorValue
,
"This iterator is not valid !"
);
130
}
131
132
return
pos_
;
133
}
134
135
// unsafe private method
136
INLINE
void
NodeGraphPartIterator
::
setPos_
(
NodeId
id
)
noexcept
{
137
pos_
=
id
;
138
139
if
(
pos_
>=
nodes_
->
bound
()) {
140
pos_
=
nodes_
->
bound
();
141
valid_
=
false
;
142
}
else
{
143
valid_
=
nodes_
->
exists
(
pos_
);
144
}
145
}
146
147
//=================NODEGRAPHPARTITERATORSAFE============================
148
149
/// default constructor
150
INLINE
151
NodeGraphPartIteratorSafe
::
NodeGraphPartIteratorSafe
(
152
const
NodeGraphPart
&
nodes
) :
153
NodeGraphPartIterator
(
nodes
) {
154
GUM_CONNECT
(*
const_cast
<
NodeGraphPart
* >(&
nodes
),
155
onNodeDeleted
,
156
*
this
,
157
NodeGraphPartIteratorSafe
::
whenNodeDeleted
);
158
GUM_CONSTRUCTOR
(
NodeGraphPartIteratorSafe
);
159
}
160
161
/// copy constructor
162
INLINE
163
NodeGraphPartIteratorSafe
::
NodeGraphPartIteratorSafe
(
164
const
NodeGraphPartIteratorSafe
&
it
) :
165
NodeGraphPartIterator
(
it
) {
166
GUM_CONNECT
(*
const_cast
<
NodeGraphPart
* >(
nodes_
),
167
onNodeDeleted
,
168
*
this
,
169
NodeGraphPartIteratorSafe
::
whenNodeDeleted
);
170
GUM_CONS_CPY
(
NodeGraphPartIteratorSafe
);
171
}
172
173
/// move constructor
174
INLINE
175
NodeGraphPartIteratorSafe
::
NodeGraphPartIteratorSafe
(
176
NodeGraphPartIteratorSafe
&&
it
) :
177
NodeGraphPartIterator
(
std
::
move
(
it
)) {
178
GUM_CONNECT
(*
const_cast
<
NodeGraphPart
* >(
nodes_
),
179
onNodeDeleted
,
180
*
this
,
181
NodeGraphPartIteratorSafe
::
whenNodeDeleted
);
182
GUM_CONS_MOV
(
NodeGraphPartIteratorSafe
);
183
}
184
185
/// destructor
186
INLINE
NodeGraphPartIteratorSafe
::~
NodeGraphPartIteratorSafe
() {
187
GUM_DESTRUCTOR
(
NodeGraphPartIteratorSafe
);
188
}
189
190
/// copy assignment operator
191
INLINE
NodeGraphPartIteratorSafe
&
192
NodeGraphPartIteratorSafe
::
operator
=(
const
NodeGraphPartIteratorSafe
&
it
) {
193
// avoid self assignment
194
if
(&
it
!=
this
) {
195
NodeGraphPartIterator
::
operator
=(
it
);
196
Listener
::
operator
=(
it
);
197
GUM_OP_CPY
(
NodeGraphPartIteratorSafe
);
198
}
199
200
return
*
this
;
201
}
202
203
/// move assignment operator
204
INLINE
NodeGraphPartIteratorSafe
&
205
NodeGraphPartIteratorSafe
::
operator
=(
NodeGraphPartIteratorSafe
&&
it
) {
206
// avoid self assignment
207
if
(&
it
!=
this
) {
208
NodeGraphPartIterator
::
operator
=(
std
::
move
(
it
));
209
Listener
::
operator
=(
std
::
move
(
it
));
210
GUM_OP_MOV
(
NodeGraphPartIteratorSafe
);
211
}
212
213
return
*
this
;
214
}
215
216
//=================NODEGRAPHPART============================
217
218
INLINE
NodeGraphPart
&
NodeGraphPart
::
operator
=(
const
NodeGraphPart
&
p
) {
219
// avoid self assignment
220
if
(
this
!= &
p
) {
populateNodes
(
p
); }
221
222
return
*
this
;
223
}
224
225
INLINE
NodeId
NodeGraphPart
::
nextNodeId
()
const
{
226
NodeId
next
= 0;
227
228
// return the first hole if holes exist
229
if
(
holes__
&& (!
holes__
->
empty
()))
230
next
= *(
holes__
->
begin
());
231
else
// in other case
232
next
=
boundVal__
;
233
234
return
next
;
235
}
236
237
// holes__ is assumed to be not nullptr and id is assumed to be in holes__
238
INLINE
void
NodeGraphPart
::
eraseHole__
(
NodeId
id
) {
239
holes__
->
erase
(
id
);
240
241
if
(
holes__
->
empty
()) {
242
delete
holes__
;
243
holes__
=
nullptr
;
244
}
245
}
246
247
// warning: do not try to use function addNodeWithId ( const NodeId id ) within
248
// function addNodeWithId(): as both functions are virtual, this may create
249
// bugs within the graphs hierarchy (i.e., virtual functions calling
250
// recursively
251
// each other along the hierarchy) that are not easy to debug.
252
INLINE
NodeId
NodeGraphPart
::
addNode
() {
253
NodeId
newNode
;
254
255
// fill the first hole if holes exist
256
if
(
holes__
&& (!
holes__
->
empty
())) {
257
newNode
= *(
holes__
->
begin
());
258
eraseHole__
(
newNode
);
259
}
else
{
260
newNode
=
boundVal__
;
261
++
boundVal__
;
262
updateEndIteratorSafe__
();
263
}
264
265
GUM_EMIT1
(
onNodeAdded
,
newNode
);
266
267
return
newNode
;
268
}
269
270
INLINE
std
::
vector
<
NodeId
>
NodeGraphPart
::
addNodes
(
Size
N
) {
271
std
::
vector
<
NodeId
>
v
;
272
v
.
reserve
(
N
);
273
for
(
Idx
i
= 0;
i
<
N
;
i
++)
274
v
.
push_back
(
this
->
addNode
());
275
return
v
;
276
}
277
278
279
INLINE
Size
NodeGraphPart
::
sizeNodes
()
const
{
280
return
(
holes__
) ? (
boundVal__
-
holes__
->
size
()) :
boundVal__
;
281
}
282
283
INLINE
Size
NodeGraphPart
::
size
()
const
{
return
sizeNodes
(); }
284
285
INLINE
bool
NodeGraphPart
::
existsNode
(
const
NodeId
node
)
const
{
286
if
(
node
>=
boundVal__
)
return
false
;
287
288
return
(!
inHoles__
(
node
));
289
}
290
291
INLINE
bool
NodeGraphPart
::
exists
(
const
NodeId
node
)
const
{
292
return
existsNode
(
node
);
293
}
294
295
INLINE
void
NodeGraphPart
::
eraseNode
(
const
NodeId
node
) {
296
if
(!
existsNode
(
node
))
return
;
297
298
addHole__
(
node
);
299
300
GUM_EMIT1
(
onNodeDeleted
,
node
);
301
}
302
303
INLINE
bool
NodeGraphPart
::
emptyNodes
()
const
{
return
(
sizeNodes
() == 0); }
304
305
INLINE
bool
NodeGraphPart
::
empty
()
const
{
return
emptyNodes
(); }
306
307
INLINE
NodeId
NodeGraphPart
::
bound
()
const
{
return
boundVal__
; }
308
309
INLINE
void
NodeGraphPart
::
clearNodes
() {
clearNodes__
(); }
310
311
// warning: clear is an alias for clearNodes but it should never be the case
312
// that the code of clear is just a call to clearNodes: as both methods are
313
// virtual, this could induce bugs within the graphs hierarchy (i.e., virtual
314
// functions calling recursively each other along the hierarchy) that are not
315
// easy to debug. Hence, the code of clearNodes should be duplicated here.
316
INLINE
void
NodeGraphPart
::
clear
() {
clearNodes__
(); }
317
318
INLINE
NodeGraphPartIteratorSafe
NodeGraphPart
::
beginSafe
()
const
{
319
NodeGraphPartIteratorSafe
it
(*
this
);
320
it
.
validate_
();
// stop the iterator at the first not-in-holes
321
return
it
;
322
}
323
324
INLINE
void
NodeGraphPart
::
updateEndIteratorSafe__
() {
325
endIteratorSafe__
.
setPos_
(
boundVal__
);
326
}
327
328
INLINE
const
NodeGraphPartIteratorSafe
&
NodeGraphPart
::
endSafe
()
const
noexcept
{
329
return
endIteratorSafe__
;
330
}
331
332
INLINE
NodeGraphPartIterator
NodeGraphPart
::
begin
()
const
noexcept
{
333
NodeGraphPartIterator
it
(*
this
);
334
it
.
validate_
();
// stop the iterator at the first not-in-holes
335
return
it
;
336
}
337
338
INLINE
const
NodeGraphPartIterator
&
NodeGraphPart
::
end
()
const
noexcept
{
339
return
endIteratorSafe__
;
340
}
341
342
INLINE
bool
NodeGraphPart
::
operator
==(
const
NodeGraphPart
&
p
)
const
{
343
if
(
boundVal__
!=
p
.
boundVal__
)
return
false
;
344
345
if
(
holes__
)
346
if
(
p
.
holes__
)
347
return
(*
holes__
== *
p
.
holes__
);
348
else
349
return
false
;
350
else
if
(
p
.
holes__
)
351
return
false
;
352
353
return
true
;
354
}
355
356
INLINE
bool
NodeGraphPart
::
operator
!=(
const
NodeGraphPart
&
p
)
const
{
357
return
!
operator
==(
p
);
358
}
359
360
INLINE
NodeSet
NodeGraphPart
::
asNodeSet
()
const
{
361
NodeSet
son
(
sizeNodes
());
362
363
if
(!
empty
()) {
364
for
(
NodeId
n
= 0;
n
<
boundVal__
; ++
n
) {
365
if
(!
inHoles__
(
n
))
son
.
insert
(
n
);
366
}
367
}
368
369
return
son
;
370
}
371
372
INLINE
const
NodeGraphPart
&
NodeGraphPart
::
nodes
()
const
{
373
return
*(
static_cast
<
const
NodeGraphPart
* >(
this
));
374
}
375
376
INLINE
bool
NodeGraphPart
::
inHoles__
(
NodeId
id
)
const
{
377
return
holes__
&&
holes__
->
contains
(
id
);
378
}
379
380
/// @return the size of holes__
381
INLINE
Size
NodeGraphPart
::
sizeHoles__
()
const
{
382
return
holes__
?
holes__
->
size
() : (
Size
)0;
383
}
384
385
}
/* namespace gum */
gum::Set::emplace
INLINE void emplace(Args &&... args)
Definition:
set_tpl.h:669