aGrUM
0.20.3
a C++ library for (probabilistic) graphical models
O3InterfaceFactory_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 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
38
O3InterfaceFactory<
GUM_SCALAR
>::
O3InterfaceFactory
(
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
=(
const
O3InterfaceFactory
<
GUM_SCALAR
>&
src
) {
72
if
(
this
== &
src
) {
return
*
this
; }
73
_prm_
=
src
.
_prm_
;
74
_o3_prm_
=
src
.
_o3_prm_
;
75
_solver_
=
src
.
_solver_
;
76
_errors_
=
src
.
_errors_
;
77
return
*
this
;
78
}
79
80
template
<
typename
GUM_SCALAR
>
81
INLINE
O3InterfaceFactory
<
GUM_SCALAR
>&
82
O3InterfaceFactory
<
GUM_SCALAR
>::
operator
=(
O3InterfaceFactory
<
GUM_SCALAR
>&&
src
) {
83
if
(
this
== &
src
) {
return
*
this
; }
84
_prm_
=
std
::
move
(
src
.
_prm_
);
85
_o3_prm_
=
std
::
move
(
src
.
_o3_prm_
);
86
_solver_
=
std
::
move
(
src
.
_solver_
);
87
_errors_
=
std
::
move
(
src
.
_errors_
);
88
return
*
this
;
89
}
90
91
template
<
typename
GUM_SCALAR
>
92
INLINE
void
O3InterfaceFactory
<
GUM_SCALAR
>::
buildInterfaces
() {
93
PRMFactory
<
GUM_SCALAR
>
factory
(
_prm_
);
94
if
(
_checkO3Interfaces_
()) {
95
_setO3InterfaceCreationOrder_
();
96
97
for
(
auto
i
:
_o3Interface_
) {
98
if
(
_solver_
->
resolveInterface
(
i
->
superLabel
())) {
99
factory
.
startInterface
(
i
->
name
().
label
(),
i
->
superLabel
().
label
(),
true
);
100
factory
.
endInterface
();
101
}
102
}
103
}
104
}
105
106
template
<
typename
GUM_SCALAR
>
107
INLINE
bool
O3InterfaceFactory
<
GUM_SCALAR
>::
_checkO3Interfaces_
() {
108
return
_addInterface2Dag_
() &&
_addArcs2Dag_
();
109
}
110
111
template
<
typename
GUM_SCALAR
>
112
INLINE
bool
O3InterfaceFactory
<
GUM_SCALAR
>::
_addInterface2Dag_
() {
113
// Adding nodes to the type inheritance graph
114
for
(
auto
&
i
:
_o3_prm_
->
interfaces
()) {
115
auto
id
=
_dag_
.
addNode
();
116
try
{
117
_nameMap_
.
insert
(
i
->
name
().
label
(),
id
);
118
_interfaceMap_
.
insert
(
i
->
name
().
label
(),
i
.
get
());
119
_nodeMap_
.
insert
(
id
,
i
.
get
());
120
121
}
catch
(
DuplicateElement
&) {
122
// Raised if duplicate type names
123
O3PRM_INTERFACE_DUPLICATE
(
i
->
name
(), *
_errors_
);
124
return
false
;
125
}
126
}
127
return
true
;
128
}
129
130
template
<
typename
GUM_SCALAR
>
131
INLINE
bool
O3InterfaceFactory
<
GUM_SCALAR
>::
_addArcs2Dag_
() {
132
// Adding arcs to the graph inheritance graph
133
for
(
auto
&
i
:
_o3_prm_
->
interfaces
()) {
134
if
(
i
->
superLabel
().
label
() !=
""
) {
135
if
(!
_solver_
->
resolveInterface
(
i
->
superLabel
())) {
return
false
; }
136
137
auto
head
=
_nameMap_
[
i
->
superLabel
().
label
()];
138
auto
tail
=
_nameMap_
[
i
->
name
().
label
()];
139
140
try
{
141
_dag_
.
addArc
(
tail
,
head
);
142
143
}
catch
(
InvalidDirectedCycle
&) {
144
// Cyclic inheritance
145
O3PRM_INTERFACE_CYCLIC_INHERITANCE
(
i
->
name
(),
i
->
superLabel
(), *
_errors_
);
146
return
false
;
147
}
148
}
149
}
150
return
true
;
151
}
152
153
template
<
typename
GUM_SCALAR
>
154
INLINE
void
O3InterfaceFactory
<
GUM_SCALAR
>::
_setO3InterfaceCreationOrder_
() {
155
auto
topo_order
=
_dag_
.
topologicalOrder
();
156
for
(
auto
id
=
topo_order
.
rbegin
();
id
!=
topo_order
.
rend
(); --
id
) {
157
_o3Interface_
.
push_back
(
_nodeMap_
[*
id
]);
158
}
159
}
160
161
template
<
typename
GUM_SCALAR
>
162
INLINE
void
O3InterfaceFactory
<
GUM_SCALAR
>::
buildElements
() {
163
PRMFactory
<
GUM_SCALAR
>
factory
(
_prm_
);
164
165
for
(
auto
i
:
_o3Interface_
) {
166
_prm_
->
getInterface
(
i
->
name
().
label
()).
inheritInterface
();
167
168
factory
.
continueInterface
(
i
->
name
().
label
());
169
170
for
(
auto
&
elt
:
i
->
elements
()) {
171
if
(
_checkInterfaceElement_
(*
i
,
elt
)) {
172
try
{
173
if
(
_prm_
->
isType
(
elt
.
type
().
label
())) {
174
factory
.
addAttribute
(
elt
.
type
().
label
(),
elt
.
name
().
label
());
175
}
else
{
176
factory
.
addReferenceSlot
(
elt
.
type
().
label
(),
elt
.
name
().
label
(),
elt
.
isArray
());
177
}
178
179
}
catch
(
OperationNotAllowed
&) {
180
// Duplicate or Wrong overload
181
O3PRM_INTERFACE_DUPLICATE_ELEMENT
(
elt
, *
_errors_
);
182
}
183
}
184
}
185
factory
.
endInterface
();
186
}
187
}
188
189
template
<
typename
GUM_SCALAR
>
190
INLINE
bool
191
O3InterfaceFactory
<
GUM_SCALAR
>::
_checkInterfaceElement_
(
O3Interface
&
i
,
192
O3InterfaceElement
&
elt
) {
193
if
(!
_solver_
->
resolveClassElement
(
elt
.
type
())) {
return
false
; }
194
195
if
(
_prm_
->
isType
(
elt
.
type
().
label
()) &&
elt
.
isArray
()) {
196
O3PRM_INTERFACE_ILLEGAL_ARRAY
(
elt
.
name
(), *
_errors_
);
197
return
false
;
198
}
199
200
const
auto
&
real_i
=
_prm_
->
getInterface
(
i
.
name
().
label
());
201
202
if
(
real_i
.
exists
(
elt
.
name
().
label
())) {
203
if
(!
_checkOverloadLegality_
(
i
,
elt
)) {
return
false
; }
204
}
205
206
if
(!
_checkCyclicReference_
(
i
,
elt
)) {
return
false
; }
207
208
return
true
;
209
}
210
211
template
<
typename
GUM_SCALAR
>
212
INLINE
bool
213
O3InterfaceFactory
<
GUM_SCALAR
>::
_checkOverloadLegality_
(
O3Interface
&
i
,
214
O3InterfaceElement
&
elt
) {
215
const
auto
&
real_i
=
_prm_
->
getInterface
(
i
.
name
().
label
());
216
const
auto
&
real_elt
=
real_i
.
get
(
elt
.
name
().
label
());
217
218
if
(
PRMClassElement
<
GUM_SCALAR
>::
isAttribute
(
real_elt
)) {
219
return
_checkAttributeOverloadLegality_
(
i
,
elt
);
220
}
221
222
if
(
PRMClassElement
<
GUM_SCALAR
>::
isReferenceSlot
(
real_elt
)) {
223
return
_checkReferenceOverloadLegality_
(
i
,
elt
);
224
}
225
226
return
false
;
227
}
228
229
template
<
typename
GUM_SCALAR
>
230
INLINE
bool
O3InterfaceFactory
<
GUM_SCALAR
>::
_checkAttributeOverloadLegality_
(
231
O3Interface
&
i
,
232
O3InterfaceElement
&
elt
) {
233
const
auto
&
real_i
=
_prm_
->
getInterface
(
i
.
name
().
label
());
234
const
auto
&
real_elt
=
real_i
.
get
(
elt
.
name
().
label
());
235
236
const
auto
&
sub_type
=
_prm_
->
type
(
elt
.
type
().
label
());
237
const
auto
&
super_type
=
real_elt
.
type
();
238
239
if
(!
sub_type
.
isSubTypeOf
(
super_type
)) {
240
O3PRM_INTERFACE_ILLEGAL_OVERLOAD
(
elt
, *
_errors_
);
241
return
false
;
242
}
243
244
if
(
sub_type
.
name
() ==
super_type
.
name
()) {
245
O3PRM_INTERFACE_DUPLICATE_ELEMENT
(
elt
, *
_errors_
);
246
return
false
;
247
}
248
249
return
true
;
250
}
251
252
template
<
typename
GUM_SCALAR
>
253
INLINE
bool
O3InterfaceFactory
<
GUM_SCALAR
>::
_checkReferenceOverloadLegality_
(
254
O3Interface
&
i
,
255
O3InterfaceElement
&
elt
) {
256
const
auto
&
real_i
=
_prm_
->
getInterface
(
i
.
name
().
label
());
257
const
auto
&
real_elt
258
=
static_cast
<
const
PRMReferenceSlot
<
GUM_SCALAR
>& >(
real_i
.
get
(
elt
.
name
().
label
()));
259
260
auto
sub_type
= (
const
PRMClassElementContainer
<
GUM_SCALAR
>*)
nullptr
;
261
262
if
(
_prm_
->
isClass
(
elt
.
type
().
label
())) {
263
sub_type
= &(
_prm_
->
getClass
(
elt
.
type
().
label
()));
264
}
else
{
265
sub_type
= &(
_prm_
->
getInterface
(
elt
.
type
().
label
()));
266
}
267
268
auto
super_type
= &(
real_elt
.
slotType
());
269
270
if
(!
sub_type
->
isSubTypeOf
(*
super_type
)) {
271
O3PRM_INTERFACE_ILLEGAL_OVERLOAD
(
elt
, *
_errors_
);
272
return
false
;
273
}
274
275
if
(
sub_type
->
name
() ==
super_type
->
name
()) {
276
O3PRM_INTERFACE_DUPLICATE_ELEMENT
(
elt
, *
_errors_
);
277
return
false
;
278
}
279
280
return
true
;
281
}
282
283
template
<
typename
GUM_SCALAR
>
284
INLINE
bool
285
O3InterfaceFactory
<
GUM_SCALAR
>::
_checkCyclicReference_
(
O3Interface
&
i
,
286
O3InterfaceElement
&
elt
) {
287
if
(
_prm_
->
isInterface
(
elt
.
type
().
label
()) ||
_prm_
->
isClass
(
elt
.
type
().
label
())) {
288
auto
ref_type
= (
const
PRMClassElementContainer
<
GUM_SCALAR
>*)
nullptr
;
289
290
if
(
_prm_
->
isInterface
(
elt
.
type
().
label
())) {
291
ref_type
= &(
_prm_
->
getInterface
(
elt
.
type
().
label
()));
292
}
else
{
293
ref_type
= &(
_prm_
->
getClass
(
elt
.
type
().
label
()));
294
}
295
296
const
auto
&
real_i
=
_prm_
->
getInterface
(
i
.
name
().
label
());
297
298
if
(&
real_i
==
ref_type
) {
299
O3PRM_INTERFACE_SELF_REFERENCE
(
i
,
elt
, *
_errors_
);
300
return
false
;
301
}
302
303
if
(
ref_type
->
isSubTypeOf
(
real_i
)) {
304
O3PRM_INTERFACE_ILLEGAL_SUB_REFERENCE
(
i
,
elt
, *
_errors_
);
305
return
false
;
306
}
307
}
308
309
return
true
;
310
}
311
312
}
// namespace o3prm
313
}
// namespace prm
314
}
// namespace gum
gum::Set::emplace
INLINE void emplace(Args &&... args)
Definition:
set_tpl.h:643
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:1032