aGrUM
0.20.2
a C++ library for (probabilistic) graphical models
O3InterfaceFactory_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 Implementation for the O3InterfaceFactory class.
25
*
26
* @author Christophe GONZALES(@AMU) and Pierre-Henri WUILLEMIN(@LIP6)
27
* @author Lionel TORTI
28
*/
29
30
#
include
<
agrum
/
PRM
/
o3prm
/
O3InterfaceFactory
.
h
>
31
32
namespace
gum
{
33
namespace
prm
{
34
namespace
o3prm
{
35
36
template
<
typename
GUM_SCALAR >
37
INLINE O3InterfaceFactory<
GUM_SCALAR
>::
O3InterfaceFactory
(
38
PRM
<
GUM_SCALAR
>&
prm
,
39
O3PRM
&
o3_prm
,
40
O3NameSolver
<
GUM_SCALAR
>&
solver
,
41
ErrorsContainer
&
errors
) :
42
prm__
(&
prm
),
43
o3_prm__
(&
o3_prm
),
solver__
(&
solver
),
errors__
(&
errors
) {
44
GUM_CONSTRUCTOR
(
O3InterfaceFactory
);
45
}
46
47
template
<
typename
GUM_SCALAR
>
48
INLINE
O3InterfaceFactory
<
GUM_SCALAR
>::
O3InterfaceFactory
(
49
const
O3InterfaceFactory
<
GUM_SCALAR
>&
src
) :
50
prm__
(
src
.
prm__
),
51
o3_prm__
(
src
.
o3_prm__
),
solver__
(
src
.
solver__
),
errors__
(
src
.
errors__
) {
52
GUM_CONS_CPY
(
O3InterfaceFactory
);
53
}
54
55
template
<
typename
GUM_SCALAR
>
56
INLINE
O3InterfaceFactory
<
GUM_SCALAR
>::
O3InterfaceFactory
(
57
O3InterfaceFactory
<
GUM_SCALAR
>&&
src
) :
58
prm__
(
std
::
move
(
src
.
prm__
)),
59
o3_prm__
(
std
::
move
(
src
.
o3_prm__
)),
solver__
(
std
::
move
(
src
.
solver__
)),
60
errors__
(
std
::
move
(
src
.
errors__
)) {
61
GUM_CONS_MOV
(
O3InterfaceFactory
);
62
}
63
64
template
<
typename
GUM_SCALAR
>
65
INLINE
O3InterfaceFactory
<
GUM_SCALAR
>::~
O3InterfaceFactory
() {
66
GUM_DESTRUCTOR
(
O3InterfaceFactory
);
67
}
68
69
template
<
typename
GUM_SCALAR
>
70
INLINE
O3InterfaceFactory
<
GUM_SCALAR
>&
71
O3InterfaceFactory
<
GUM_SCALAR
>::
operator
=(
72
const
O3InterfaceFactory
<
GUM_SCALAR
>&
src
) {
73
if
(
this
== &
src
) {
return
*
this
; }
74
prm__
=
src
.
prm__
;
75
o3_prm__
=
src
.
o3_prm__
;
76
solver__
=
src
.
solver__
;
77
errors__
=
src
.
errors__
;
78
return
*
this
;
79
}
80
81
template
<
typename
GUM_SCALAR
>
82
INLINE
O3InterfaceFactory
<
GUM_SCALAR
>&
83
O3InterfaceFactory
<
GUM_SCALAR
>::
operator
=(
84
O3InterfaceFactory
<
GUM_SCALAR
>&&
src
) {
85
if
(
this
== &
src
) {
return
*
this
; }
86
prm__
=
std
::
move
(
src
.
prm__
);
87
o3_prm__
=
std
::
move
(
src
.
o3_prm__
);
88
solver__
=
std
::
move
(
src
.
solver__
);
89
errors__
=
std
::
move
(
src
.
errors__
);
90
return
*
this
;
91
}
92
93
template
<
typename
GUM_SCALAR
>
94
INLINE
void
O3InterfaceFactory
<
GUM_SCALAR
>::
buildInterfaces
() {
95
PRMFactory
<
GUM_SCALAR
>
factory
(
prm__
);
96
if
(
checkO3Interfaces__
()) {
97
setO3InterfaceCreationOrder__
();
98
99
for
(
auto
i
:
o3Interface__
) {
100
if
(
solver__
->
resolveInterface
(
i
->
superLabel
())) {
101
factory
.
startInterface
(
i
->
name
().
label
(),
102
i
->
superLabel
().
label
(),
103
true
);
104
factory
.
endInterface
();
105
}
106
}
107
}
108
}
109
110
template
<
typename
GUM_SCALAR
>
111
INLINE
bool
O3InterfaceFactory
<
GUM_SCALAR
>::
checkO3Interfaces__
() {
112
return
addInterface2Dag__
() &&
addArcs2Dag__
();
113
}
114
115
template
<
typename
GUM_SCALAR
>
116
INLINE
bool
O3InterfaceFactory
<
GUM_SCALAR
>::
addInterface2Dag__
() {
117
// Adding nodes to the type inheritance graph
118
for
(
auto
&
i
:
o3_prm__
->
interfaces
()) {
119
auto
id
=
dag__
.
addNode
();
120
try
{
121
nameMap__
.
insert
(
i
->
name
().
label
(),
id
);
122
interfaceMap__
.
insert
(
i
->
name
().
label
(),
i
.
get
());
123
nodeMap__
.
insert
(
id
,
i
.
get
());
124
125
}
catch
(
DuplicateElement
&) {
126
// Raised if duplicate type names
127
O3PRM_INTERFACE_DUPLICATE
(
i
->
name
(), *
errors__
);
128
return
false
;
129
}
130
}
131
return
true
;
132
}
133
134
template
<
typename
GUM_SCALAR
>
135
INLINE
bool
O3InterfaceFactory
<
GUM_SCALAR
>::
addArcs2Dag__
() {
136
// Adding arcs to the graph inheritance graph
137
for
(
auto
&
i
:
o3_prm__
->
interfaces
()) {
138
if
(
i
->
superLabel
().
label
() !=
""
) {
139
if
(!
solver__
->
resolveInterface
(
i
->
superLabel
())) {
return
false
; }
140
141
auto
head
=
nameMap__
[
i
->
superLabel
().
label
()];
142
auto
tail
=
nameMap__
[
i
->
name
().
label
()];
143
144
try
{
145
dag__
.
addArc
(
tail
,
head
);
146
147
}
catch
(
InvalidDirectedCycle
&) {
148
// Cyclic inheritance
149
O3PRM_INTERFACE_CYCLIC_INHERITANCE
(
i
->
name
(),
150
i
->
superLabel
(),
151
*
errors__
);
152
return
false
;
153
}
154
}
155
}
156
return
true
;
157
}
158
159
template
<
typename
GUM_SCALAR
>
160
INLINE
void
161
O3InterfaceFactory
<
GUM_SCALAR
>::
setO3InterfaceCreationOrder__
() {
162
auto
topo_order
=
dag__
.
topologicalOrder
();
163
for
(
auto
id
=
topo_order
.
rbegin
();
id
!=
topo_order
.
rend
(); --
id
) {
164
o3Interface__
.
push_back
(
nodeMap__
[*
id
]);
165
}
166
}
167
168
template
<
typename
GUM_SCALAR
>
169
INLINE
void
O3InterfaceFactory
<
GUM_SCALAR
>::
buildElements
() {
170
PRMFactory
<
GUM_SCALAR
>
factory
(
prm__
);
171
172
for
(
auto
i
:
o3Interface__
) {
173
prm__
->
getInterface
(
i
->
name
().
label
()).
inheritInterface
();
174
175
factory
.
continueInterface
(
i
->
name
().
label
());
176
177
for
(
auto
&
elt
:
i
->
elements
()) {
178
if
(
checkInterfaceElement__
(*
i
,
elt
)) {
179
try
{
180
if
(
prm__
->
isType
(
elt
.
type
().
label
())) {
181
factory
.
addAttribute
(
elt
.
type
().
label
(),
elt
.
name
().
label
());
182
}
else
{
183
factory
.
addReferenceSlot
(
elt
.
type
().
label
(),
184
elt
.
name
().
label
(),
185
elt
.
isArray
());
186
}
187
188
}
catch
(
OperationNotAllowed
&) {
189
// Duplicate or Wrong overload
190
O3PRM_INTERFACE_DUPLICATE_ELEMENT
(
elt
, *
errors__
);
191
}
192
}
193
}
194
factory
.
endInterface
();
195
}
196
}
197
198
template
<
typename
GUM_SCALAR
>
199
INLINE
bool
O3InterfaceFactory
<
GUM_SCALAR
>::
checkInterfaceElement__
(
200
O3Interface
&
i
,
201
O3InterfaceElement
&
elt
) {
202
if
(!
solver__
->
resolveClassElement
(
elt
.
type
())) {
return
false
; }
203
204
if
(
prm__
->
isType
(
elt
.
type
().
label
()) &&
elt
.
isArray
()) {
205
O3PRM_INTERFACE_ILLEGAL_ARRAY
(
elt
.
name
(), *
errors__
);
206
return
false
;
207
}
208
209
const
auto
&
real_i
=
prm__
->
getInterface
(
i
.
name
().
label
());
210
211
if
(
real_i
.
exists
(
elt
.
name
().
label
())) {
212
if
(!
checkOverloadLegality__
(
i
,
elt
)) {
return
false
; }
213
}
214
215
if
(!
checkCyclicReference__
(
i
,
elt
)) {
return
false
; }
216
217
return
true
;
218
}
219
220
template
<
typename
GUM_SCALAR
>
221
INLINE
bool
O3InterfaceFactory
<
GUM_SCALAR
>::
checkOverloadLegality__
(
222
O3Interface
&
i
,
223
O3InterfaceElement
&
elt
) {
224
const
auto
&
real_i
=
prm__
->
getInterface
(
i
.
name
().
label
());
225
const
auto
&
real_elt
=
real_i
.
get
(
elt
.
name
().
label
());
226
227
if
(
PRMClassElement
<
GUM_SCALAR
>::
isAttribute
(
real_elt
)) {
228
return
checkAttributeOverloadLegality__
(
i
,
elt
);
229
}
230
231
if
(
PRMClassElement
<
GUM_SCALAR
>::
isReferenceSlot
(
real_elt
)) {
232
return
checkReferenceOverloadLegality__
(
i
,
elt
);
233
}
234
235
return
false
;
236
}
237
238
template
<
typename
GUM_SCALAR
>
239
INLINE
bool
240
O3InterfaceFactory
<
GUM_SCALAR
>::
checkAttributeOverloadLegality__
(
241
O3Interface
&
i
,
242
O3InterfaceElement
&
elt
) {
243
const
auto
&
real_i
=
prm__
->
getInterface
(
i
.
name
().
label
());
244
const
auto
&
real_elt
=
real_i
.
get
(
elt
.
name
().
label
());
245
246
const
auto
&
sub_type
=
prm__
->
type
(
elt
.
type
().
label
());
247
const
auto
&
super_type
=
real_elt
.
type
();
248
249
if
(!
sub_type
.
isSubTypeOf
(
super_type
)) {
250
O3PRM_INTERFACE_ILLEGAL_OVERLOAD
(
elt
, *
errors__
);
251
return
false
;
252
}
253
254
if
(
sub_type
.
name
() ==
super_type
.
name
()) {
255
O3PRM_INTERFACE_DUPLICATE_ELEMENT
(
elt
, *
errors__
);
256
return
false
;
257
}
258
259
return
true
;
260
}
261
262
template
<
typename
GUM_SCALAR
>
263
INLINE
bool
264
O3InterfaceFactory
<
GUM_SCALAR
>::
checkReferenceOverloadLegality__
(
265
O3Interface
&
i
,
266
O3InterfaceElement
&
elt
) {
267
const
auto
&
real_i
=
prm__
->
getInterface
(
i
.
name
().
label
());
268
const
auto
&
real_elt
269
=
static_cast
<
const
PRMReferenceSlot
<
GUM_SCALAR
>& >(
270
real_i
.
get
(
elt
.
name
().
label
()));
271
272
auto
sub_type
= (
const
PRMClassElementContainer
<
GUM_SCALAR
>*)
nullptr
;
273
274
if
(
prm__
->
isClass
(
elt
.
type
().
label
())) {
275
sub_type
= &(
prm__
->
getClass
(
elt
.
type
().
label
()));
276
}
else
{
277
sub_type
= &(
prm__
->
getInterface
(
elt
.
type
().
label
()));
278
}
279
280
auto
super_type
= &(
real_elt
.
slotType
());
281
282
if
(!
sub_type
->
isSubTypeOf
(*
super_type
)) {
283
O3PRM_INTERFACE_ILLEGAL_OVERLOAD
(
elt
, *
errors__
);
284
return
false
;
285
}
286
287
if
(
sub_type
->
name
() ==
super_type
->
name
()) {
288
O3PRM_INTERFACE_DUPLICATE_ELEMENT
(
elt
, *
errors__
);
289
return
false
;
290
}
291
292
return
true
;
293
}
294
295
template
<
typename
GUM_SCALAR
>
296
INLINE
bool
O3InterfaceFactory
<
GUM_SCALAR
>::
checkCyclicReference__
(
297
O3Interface
&
i
,
298
O3InterfaceElement
&
elt
) {
299
if
(
prm__
->
isInterface
(
elt
.
type
().
label
())
300
||
prm__
->
isClass
(
elt
.
type
().
label
())) {
301
auto
ref_type
= (
const
PRMClassElementContainer
<
GUM_SCALAR
>*)
nullptr
;
302
303
if
(
prm__
->
isInterface
(
elt
.
type
().
label
())) {
304
ref_type
= &(
prm__
->
getInterface
(
elt
.
type
().
label
()));
305
}
else
{
306
ref_type
= &(
prm__
->
getClass
(
elt
.
type
().
label
()));
307
}
308
309
const
auto
&
real_i
=
prm__
->
getInterface
(
i
.
name
().
label
());
310
311
if
(&
real_i
==
ref_type
) {
312
O3PRM_INTERFACE_SELF_REFERENCE
(
i
,
elt
, *
errors__
);
313
return
false
;
314
}
315
316
if
(
ref_type
->
isSubTypeOf
(
real_i
)) {
317
O3PRM_INTERFACE_ILLEGAL_SUB_REFERENCE
(
i
,
elt
, *
errors__
);
318
return
false
;
319
}
320
}
321
322
return
true
;
323
}
324
325
}
// namespace o3prm
326
}
// namespace prm
327
}
// namespace gum
gum::Set::emplace
INLINE void emplace(Args &&... args)
Definition:
set_tpl.h:669
gum::prm::o3prm
Definition:
O3prm.cpp:34
gum::prm::ParamScopeData::ParamScopeData
ParamScopeData(const std::string &s, const PRMReferenceSlot< GUM_SCALAR > &ref, Idx d)
Definition:
PRMClass_tpl.h:1101