aGrUM 2.3.2
a C++ library for (probabilistic) graphical models
O3InterfaceFactory_tpl.h
Go to the documentation of this file.
1/****************************************************************************
2 * This file is part of the aGrUM/pyAgrum library. *
3 * *
4 * Copyright (c) 2005-2025 by *
5 * - Pierre-Henri WUILLEMIN(_at_LIP6) *
6 * - Christophe GONZALES(_at_AMU) *
7 * *
8 * The aGrUM/pyAgrum library is free software; you can redistribute it *
9 * and/or modify it under the terms of either : *
10 * *
11 * - the GNU Lesser General Public License as published by *
12 * the Free Software Foundation, either version 3 of the License, *
13 * or (at your option) any later version, *
14 * - the MIT license (MIT), *
15 * - or both in dual license, as here. *
16 * *
17 * (see https://agrum.gitlab.io/articles/dual-licenses-lgplv3mit.html) *
18 * *
19 * This aGrUM/pyAgrum library is distributed in the hope that it will be *
20 * useful, but WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
21 * INCLUDING BUT NOT LIMITED TO THE WARRANTIES MERCHANTABILITY or FITNESS *
22 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE *
23 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *
24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
25 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
26 * OTHER DEALINGS IN THE SOFTWARE. *
27 * *
28 * See LICENCES for more details. *
29 * *
30 * SPDX-FileCopyrightText: Copyright 2005-2025 *
31 * - Pierre-Henri WUILLEMIN(_at_LIP6) *
32 * - Christophe GONZALES(_at_AMU) *
33 * SPDX-License-Identifier: LGPL-3.0-or-later OR MIT *
34 * *
35 * Contact : info_at_agrum_dot_org *
36 * homepage : http://agrum.gitlab.io *
37 * gitlab : https://gitlab.com/agrumery/agrum *
38 * *
39 ****************************************************************************/
40#pragma once
41
42
50
52
53namespace gum {
54 namespace prm {
55 namespace o3prm {
56
57 template < typename GUM_SCALAR >
58 INLINE
60 O3PRM& o3_prm,
62 ErrorsContainer& errors) :
63 _prm_(&prm), _o3_prm_(&o3_prm), _solver_(&solver), _errors_(&errors) {
64 GUM_CONSTRUCTOR(O3InterfaceFactory);
65 }
66
67 template < typename GUM_SCALAR >
73
74 template < typename GUM_SCALAR >
77 _prm_(std::move(src._prm_)), _o3_prm_(std::move(src._o3_prm_)),
78 _solver_(std::move(src._solver_)), _errors_(std::move(src._errors_)) {
79 GUM_CONS_MOV(O3InterfaceFactory);
80 }
81
82 template < typename GUM_SCALAR >
86
87 template < typename GUM_SCALAR >
90 if (this == &src) { return *this; }
91 _prm_ = src._prm_;
92 _o3_prm_ = src._o3_prm_;
93 _solver_ = src._solver_;
94 _errors_ = src._errors_;
95 return *this;
96 }
97
98 template < typename GUM_SCALAR >
101 if (this == &src) { return *this; }
102 _prm_ = std::move(src._prm_);
103 _o3_prm_ = std::move(src._o3_prm_);
104 _solver_ = std::move(src._solver_);
105 _errors_ = std::move(src._errors_);
106 return *this;
107 }
108
109 template < typename GUM_SCALAR >
112 if (_checkO3Interfaces_()) {
114
115 for (auto i: _o3Interface_) {
116 if (_solver_->resolveInterface(i->superLabel())) {
117 factory.startInterface(i->name().label(), i->superLabel().label(), true);
118 factory.endInterface();
119 }
120 }
121 }
122 }
123
124 template < typename GUM_SCALAR >
128
129 template < typename GUM_SCALAR >
131 // Adding nodes to the type inheritance graph
132 for (auto& i: _o3_prm_->interfaces()) {
133 auto id = _dag_.addNode();
134 try {
135 _nameMap_.insert(i->name().label(), id);
136 _interfaceMap_.insert(i->name().label(), i.get());
137 _nodeMap_.insert(id, i.get());
138
139 } catch (DuplicateElement const&) {
140 // Raised if duplicate type names
141 O3PRM_INTERFACE_DUPLICATE(i->name(), *_errors_);
142 return false;
143 }
144 }
145 return true;
146 }
147
148 template < typename GUM_SCALAR >
150 // Adding arcs to the graph inheritance graph
151 for (auto& i: _o3_prm_->interfaces()) {
152 if (i->superLabel().label() != "") {
153 if (!_solver_->resolveInterface(i->superLabel())) { return false; }
154
155 auto head = _nameMap_[i->superLabel().label()];
156 auto tail = _nameMap_[i->name().label()];
157
158 try {
159 _dag_.addArc(tail, head);
160
161 } catch (InvalidDirectedCycle const&) {
162 // Cyclic inheritance
163 O3PRM_INTERFACE_CYCLIC_INHERITANCE(i->name(), i->superLabel(), *_errors_);
164 return false;
165 }
166 }
167 }
168 return true;
169 }
170
171 template < typename GUM_SCALAR >
173 auto topo_order = _dag_.topologicalOrder();
174 for (auto id = topo_order.rbegin(); id != topo_order.rend(); --id) {
175 _o3Interface_.push_back(_nodeMap_[*id]);
176 }
177 }
178
179 template < typename GUM_SCALAR >
182
183 for (auto i: _o3Interface_) {
184 _prm_->getInterface(i->name().label()).inheritInterface();
185
186 factory.continueInterface(i->name().label());
187
188 for (auto& elt: i->elements()) {
189 if (_checkInterfaceElement_(*i, elt)) {
190 try {
191 if (_prm_->isType(elt.type().label())) {
192 factory.addAttribute(elt.type().label(), elt.name().label());
193 } else {
194 factory.addReferenceSlot(elt.type().label(), elt.name().label(), elt.isArray());
195 }
196
197 } catch (OperationNotAllowed const&) {
198 // Duplicate or Wrong overload
199 O3PRM_INTERFACE_DUPLICATE_ELEMENT(elt, *_errors_);
200 }
201 }
202 }
203 factory.endInterface();
204 }
205 }
206
207 template < typename GUM_SCALAR >
208 INLINE bool
210 O3InterfaceElement& elt) {
211 if (!_solver_->resolveClassElement(elt.type())) { return false; }
212
213 if (_prm_->isType(elt.type().label()) && elt.isArray()) {
214 O3PRM_INTERFACE_ILLEGAL_ARRAY(elt.name(), *_errors_);
215 return false;
216 }
217
218 const auto& real_i = _prm_->getInterface(i.name().label());
219
220 if (real_i.exists(elt.name().label())) {
221 if (!_checkOverloadLegality_(i, elt)) { return false; }
222 }
223
224 if (!_checkCyclicReference_(i, elt)) { return false; }
225
226 return true;
227 }
228
229 template < typename GUM_SCALAR >
230 INLINE bool
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
238 }
239
242 }
243
244 return false;
245 }
246
247 template < typename GUM_SCALAR >
249 O3Interface& i,
250 O3InterfaceElement& elt) {
251 const auto& real_i = _prm_->getInterface(i.name().label());
252 const auto& real_elt = real_i.get(elt.name().label());
253
254 const auto& sub_type = _prm_->type(elt.type().label());
255 const auto& super_type = real_elt.type();
256
257 if (!sub_type.isSubTypeOf(super_type)) {
258 O3PRM_INTERFACE_ILLEGAL_OVERLOAD(elt, *_errors_);
259 return false;
260 }
261
262 if (sub_type.name() == super_type.name()) {
263 O3PRM_INTERFACE_DUPLICATE_ELEMENT(elt, *_errors_);
264 return false;
265 }
266
267 return true;
268 }
269
270 template < typename GUM_SCALAR >
272 O3Interface& i,
273 O3InterfaceElement& elt) {
274 const auto& real_i = _prm_->getInterface(i.name().label());
275 const auto& real_elt
276 = static_cast< const PRMReferenceSlot< GUM_SCALAR >& >(real_i.get(elt.name().label()));
277
278 auto sub_type = (const PRMClassElementContainer< GUM_SCALAR >*)nullptr;
279
280 if (_prm_->isClass(elt.type().label())) {
281 sub_type = &(_prm_->getClass(elt.type().label()));
282 } else {
283 sub_type = &(_prm_->getInterface(elt.type().label()));
284 }
285
286 auto super_type = &(real_elt.slotType());
287
288 if (!sub_type->isSubTypeOf(*super_type)) {
289 O3PRM_INTERFACE_ILLEGAL_OVERLOAD(elt, *_errors_);
290 return false;
291 }
292
293 if (sub_type->name() == super_type->name()) {
294 O3PRM_INTERFACE_DUPLICATE_ELEMENT(elt, *_errors_);
295 return false;
296 }
297
298 return true;
299 }
300
301 template < typename GUM_SCALAR >
302 INLINE bool
304 O3InterfaceElement& elt) {
305 if (_prm_->isInterface(elt.type().label()) || _prm_->isClass(elt.type().label())) {
306 auto ref_type = (const PRMClassElementContainer< GUM_SCALAR >*)nullptr;
307
308 if (_prm_->isInterface(elt.type().label())) {
309 ref_type = &(_prm_->getInterface(elt.type().label()));
310 } else {
311 ref_type = &(_prm_->getClass(elt.type().label()));
312 }
313
314 const auto& real_i = _prm_->getInterface(i.name().label());
315
316 if (&real_i == ref_type) {
317 O3PRM_INTERFACE_SELF_REFERENCE(i, elt, *_errors_);
318 return false;
319 }
320
321 if (ref_type->isSubTypeOf(real_i)) {
322 O3PRM_INTERFACE_ILLEGAL_SUB_REFERENCE(i, elt, *_errors_);
323 return false;
324 }
325 }
326
327 return true;
328 }
329
330 } // namespace o3prm
331 } // namespace prm
332} // namespace gum
Headers for the O3InterfaceFactory class.
Exception : a similar element already exists.
This class is used contain and manipulate gum::ParseError.
Exception : existence of a directed cycle in a graph.
Exception : operation not allowed.
<agrum/PRM/classElementContainer.h>
static INLINE bool isReferenceSlot(const PRMClassElement< GUM_SCALAR > &elt)
Returns true if obj_ptr is of type PRMReferenceSlot.
static INLINE bool isAttribute(const PRMClassElement< GUM_SCALAR > &elt)
Returns true if obj_ptr is of type PRMAttribute.
Factory which builds a PRM<GUM_SCALAR>.
Definition PRMFactory.h:88
virtual void addReferenceSlot(const std::string &type, const std::string &name, bool isArray) override
Tells the factory that we started declaring a slot.
virtual void addAttribute(const std::string &type, const std::string &name) override
Add an attribute to an interface.
virtual void endInterface() override
Tells the factory that we finished an interface declaration.
virtual void startInterface(const std::string &i, const std::string &ext="", bool delayInheritance=false) override
Tells the factory that we start an interface declaration.
virtual void continueInterface(const std::string &name) override
Continue the declaration of an interface.
A PRMReferenceSlot represent a relation between two PRMClassElementContainer.
This class represents a Probabilistic Relational PRMSystem<GUM_SCALAR>.
Definition PRM.h:74
The O3InterfaceElement is part of the AST of the O3PRM language.
Definition O3prm.h:342
Bulds gum::prm:PRMInterface from gum::prm::o3prm::O3Interface.
HashTable< std::string, O3Interface * > _interfaceMap_
HashTable< std::string, gum::NodeId > _nameMap_
bool _checkAttributeOverloadLegality_(O3Interface &i, O3InterfaceElement &elt)
O3InterfaceFactory(PRM< GUM_SCALAR > &prm, O3PRM &o3_prm, O3NameSolver< GUM_SCALAR > &solver, ErrorsContainer &errors)
O3InterfaceFactory< GUM_SCALAR > & operator=(const O3InterfaceFactory< GUM_SCALAR > &src)
bool _checkOverloadLegality_(O3Interface &i, O3InterfaceElement &elt)
bool _checkInterfaceElement_(O3Interface &i, O3InterfaceElement &elt)
std::vector< O3Interface * > _o3Interface_
bool _checkCyclicReference_(O3Interface &i, O3InterfaceElement &elt)
bool _checkReferenceOverloadLegality_(O3Interface &i, O3InterfaceElement &elt)
O3NameSolver< GUM_SCALAR > * _solver_
HashTable< NodeId, O3Interface * > _nodeMap_
The O3Interface is part of the AST of the O3PRM language.
Definition O3prm.h:375
std::string & label()
Definition O3prm.cpp:287
Resolves names for the different O3PRM factories.
The O3PRM is part of the AST of the O3PRM language.
Definition O3prm.h:913
namespace for all probabilistic relational models entities
Definition agrum.h:68
gum is the global namespace for all aGrUM entities
Definition agrum.h:46
STL namespace.