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