aGrUM
0.20.2
a C++ library for (probabilistic) graphical models
multiDimWithOffset_tpl.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
/**
23
* @file
24
* @brief Headers of the MultiDimWithOffset class.
25
*
26
* @author Pierre-Henri WUILLEMIN(@LIP6) & Christophe GONZALES(@AMU)
27
*/
28
29
#
include
<
limits
>
30
31
// to ease IDE parsers...
32
#
include
<
agrum
/
tools
/
multidim
/
implementations
/
multiDimImplementation
.
h
>
33
#
include
<
agrum
/
tools
/
multidim
/
implementations
/
multiDimWithOffset
.
h
>
34
35
namespace
gum
{
36
37
// Default constructor: creates an empty null dimensional matrix
38
39
template
<
typename
GUM_SCALAR >
40
MultiDimWithOffset< GUM_SCALAR >::MultiDimWithOffset() :
41
MultiDimImplementation< GUM_SCALAR >() {
42
// for debugging purposes
43
GUM_CONSTRUCTOR(MultiDimWithOffset);
44
}
45
46
// copy constructor
47
48
template
<
typename
GUM_SCALAR
>
49
MultiDimWithOffset
<
GUM_SCALAR
>::
MultiDimWithOffset
(
50
const
MultiDimWithOffset
<
GUM_SCALAR
>&
from
) :
51
MultiDimImplementation
<
GUM_SCALAR
>(
from
),
52
gaps_
(
from
.
gaps_
) {
53
// for debugging purposes
54
GUM_CONS_CPY
(
MultiDimWithOffset
);
55
}
56
57
// destructor
58
59
template
<
typename
GUM_SCALAR
>
60
MultiDimWithOffset
<
GUM_SCALAR
>::~
MultiDimWithOffset
() {
61
// for debugging purposes
62
GUM_DESTRUCTOR
(
MultiDimWithOffset
);
63
// no need to unregister all slaves as it will be done by
64
// MultiDimImplementation
65
}
66
67
// add a new dimension, needed for updating the offsets_ & gaps_
68
69
template
<
typename
GUM_SCALAR
>
70
INLINE
void
MultiDimWithOffset
<
GUM_SCALAR
>::
add
(
const
DiscreteVariable
&
v
) {
71
Size
lg
=
this
->
domainSize
();
72
73
if
(
lg
>
std
::
numeric_limits
<
Idx
>::
max
() /
v
.
domainSize
()) {
74
GUM_ERROR
(
OutOfBounds
,
"Out of bounds !"
);
75
}
76
77
MultiDimImplementation
<
GUM_SCALAR
>::
add
(
v
);
78
gaps_
.
insert
(&
v
,
lg
);
79
}
80
81
// removes a dimension, needed for updating the offsets_ & gaps_
82
83
template
<
typename
GUM_SCALAR
>
84
INLINE
void
MultiDimWithOffset
<
GUM_SCALAR
>::
erase
(
const
DiscreteVariable
&
v
) {
85
Sequence
<
const
DiscreteVariable
* >
variables
=
this
->
variablesSequence
();
86
Idx
pos
=
variables
.
pos
(&
v
);
// throw a NotFound if necessary
87
88
if
(
variables
.
size
() == 1) {
89
gaps_
.
clear
();
90
}
else
{
91
// update the gaps_
92
Size
v_size
=
v
.
domainSize
();
93
gaps_
.
erase
(
variables
[
pos
]);
94
95
for
(
Idx
i
=
pos
+ 1;
i
<
variables
.
size
(); ++
i
) {
96
gaps_
[
variables
[
i
]] /=
v_size
;
97
}
98
}
99
100
MultiDimImplementation
<
GUM_SCALAR
>::
erase
(
v
);
101
}
102
103
// listen to change in each recorded Instantiation.
104
105
template
<
typename
GUM_SCALAR
>
106
INLINE
void
MultiDimWithOffset
<
GUM_SCALAR
>::
changeNotification
(
107
const
Instantiation
&
i
,
108
const
DiscreteVariable
*
const
var
,
109
Idx
oldval
,
110
Idx
newval
) {
111
GUM_ASSERT
(
offsets_
.
exists
(&
i
));
112
GUM_ASSERT
(
offsets_
[&
i
] <
this
->
domainSize
());
113
GUM_ASSERT
(
newval
<
var
->
domainSize
());
114
GUM_ASSERT
(
oldval
<
var
->
domainSize
());
115
116
if
(
newval
>=
oldval
) {
117
offsets_
[&
i
] +=
gaps_
[
var
] * (
newval
-
oldval
);
118
GUM_ASSERT
(
offsets_
[&
i
] <
this
->
domainSize
());
119
}
else
{
120
GUM_ASSERT
(
offsets_
[&
i
] >=
gaps_
[
var
] * (
oldval
-
newval
));
121
offsets_
[&
i
] -=
gaps_
[
var
] * (
oldval
-
newval
);
122
}
123
}
124
125
// listen to an assignment of a value in a Instantiation
126
127
template
<
typename
GUM_SCALAR
>
128
INLINE
void
MultiDimWithOffset
<
GUM_SCALAR
>::
setChangeNotification
(
129
const
Instantiation
&
i
) {
130
GUM_ASSERT
(
offsets_
.
exists
(&
i
));
131
offsets_
[&
i
] =
getOffs_
(
i
);
132
}
133
134
// listen to setFirst in each recorded Instantiation.
135
136
template
<
typename
GUM_SCALAR
>
137
INLINE
void
MultiDimWithOffset
<
GUM_SCALAR
>::
setFirstNotification
(
138
const
Instantiation
&
i
) {
139
GUM_ASSERT
(
offsets_
.
exists
(&
i
));
140
offsets_
[&
i
] = 0;
141
}
142
143
// listen to setLast in each recorded Instantiation.
144
145
template
<
typename
GUM_SCALAR
>
146
INLINE
void
MultiDimWithOffset
<
GUM_SCALAR
>::
setLastNotification
(
147
const
Instantiation
&
i
) {
148
GUM_ASSERT
(
offsets_
.
exists
(&
i
));
149
offsets_
[&
i
] =
this
->
domainSize
() - 1;
150
}
151
152
// listen to increment in each recorded Instantiation.
153
154
template
<
typename
GUM_SCALAR
>
155
INLINE
void
156
MultiDimWithOffset
<
GUM_SCALAR
>::
setIncNotification
(
const
Instantiation
&
i
) {
157
GUM_ASSERT
(
offsets_
.
exists
(&
i
));
158
GUM_ASSERT
(
offsets_
[&
i
] !=
this
->
domainSize
() - 1);
159
++
offsets_
[&
i
];
160
}
161
162
// listen to increment in each recorded Instantiation.
163
164
template
<
typename
GUM_SCALAR
>
165
INLINE
void
166
MultiDimWithOffset
<
GUM_SCALAR
>::
setDecNotification
(
const
Instantiation
&
i
) {
167
GUM_ASSERT
(
offsets_
.
exists
(&
i
));
168
GUM_ASSERT
(
offsets_
[&
i
] != 0);
169
--
offsets_
[&
i
];
170
}
171
172
// add a Instantiation as a slave
173
174
template
<
typename
GUM_SCALAR
>
175
INLINE
bool
MultiDimWithOffset
<
GUM_SCALAR
>::
registerSlave
(
Instantiation
&
i
) {
176
if
(
MultiDimImplementation
<
GUM_SCALAR
>::
registerSlave
(
i
)) {
177
GUM_ASSERT
(!
offsets_
.
exists
(&
i
));
178
offsets_
.
insert
(&
i
,
getOffs_
(
i
));
179
return
true
;
180
}
181
182
return
false
;
183
}
184
185
// remove a registered slave instantiation
186
187
template
<
typename
GUM_SCALAR
>
188
INLINE
bool
MultiDimWithOffset
<
GUM_SCALAR
>::
unregisterSlave
(
Instantiation
&
i
) {
189
MultiDimImplementation
<
GUM_SCALAR
>::
unregisterSlave
(
i
);
190
offsets_
.
erase
(&
i
);
191
return
true
;
192
}
193
194
// Compute the offset of a Instantiation
195
/** If the instantiation is not fully compatible with the MultiDimWithOffset,
196
* no exception thrown
197
* but 0 is assumed for dimensions not present in the instantiation.
198
* for instance : M<<a<<b<<c; with i=b:1|c:2|d:1 then M.getOffs_(i) give the
199
* offset of a:0|b:1|c:2.
200
*/
201
202
template
<
typename
GUM_SCALAR
>
203
INLINE
Size
204
MultiDimWithOffset
<
GUM_SCALAR
>::
getOffs_
(
const
Instantiation
&
i
)
const
{
205
Idx
off
= 0;
206
207
for
(
HashTableConstIteratorSafe
<
const
DiscreteVariable
*,
Size
>
iter
208
=
gaps_
.
beginSafe
();
209
iter
!=
gaps_
.
endSafe
();
210
++
iter
)
211
if
(
i
.
contains
(
iter
.
key
()))
212
off
+=
iter
.
val
() *
i
.
valFromPtr
(
iter
.
key
());
213
else
214
GUM_ERROR
(
InvalidArgument
,
215
iter
.
key
()->
name
() <<
" not present in the instantiation "
<<
i
);
216
217
return
off
;
218
}
219
220
// For a given indice of a value in the vector values_, this method computes
221
// the corresponding instantiation
222
/**
223
* @param result the result of this methods, we assume that the given
224
* instantiation already contains all the variables
225
* contained in the multidimarray (if V is the set of variables
226
* of this tab, V must be a subset of variables in
227
* result or the exact set)
228
* @param indice indice in the vector values_
229
*/
230
231
template
<
typename
GUM_SCALAR
>
232
INLINE
void
MultiDimWithOffset
<
GUM_SCALAR
>::
computeInstantiationValue_
(
233
Instantiation
&
result
,
234
Size
indice
)
const
{
235
for
(
Idx
i
= 0;
i
<
this
->
nbrDim
(); ++
i
) {
236
const
DiscreteVariable
&
var
=
this
->
variable
(
i
);
237
Idx
domainSize
=
var
.
domainSize
();
238
result
.
chgVal
(
var
,
indice
%
domainSize
);
239
indice
=
indice
/
domainSize
;
240
}
241
242
GUM_ASSERT
(
indice
== 0);
243
}
244
245
// string representation of internal data about i in this.
246
template
<
typename
GUM_SCALAR
>
247
INLINE
std
::
string
248
MultiDimWithOffset
<
GUM_SCALAR
>::
toString
(
const
Instantiation
*
i
)
const
{
249
if
(
i
->
isMaster
(
this
)) {
250
std
::
stringstream
s
;
251
s
<<
offsets_
[
i
];
252
std
::
string
res
;
253
s
>>
res
;
254
return
res
;
255
}
else
{
256
return
"--"
;
257
}
258
}
259
260
template
<
typename
GUM_SCALAR
>
261
INLINE
Size
262
MultiDimWithOffset
<
GUM_SCALAR
>::
toOffset
(
const
Instantiation
&
i
)
const
{
263
return
getOffs_
(
i
);
264
}
265
266
// set the Instantiation to the values corresponding to the offset (in this
267
// array)
268
template
<
typename
GUM_SCALAR
>
269
INLINE
Instantiation
&
270
MultiDimWithOffset
<
GUM_SCALAR
>::
fromOffset
(
Instantiation
&
i
,
271
Size
offset
)
const
{
272
this
->
computeInstantiationValue_
(
i
,
offset
);
273
return
i
;
274
}
275
276
}
/* namespace gum */
gum::Set::emplace
INLINE void emplace(Args &&... args)
Definition:
set_tpl.h:669