aGrUM 3.1.1
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-2026 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-2026 *
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
41#pragma once
42
43
51
53
54namespace gum {
55 namespace prm {
56 namespace o3prm {
57
58 template < GUM_Numeric GUM_SCALAR >
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 < GUM_Numeric GUM_SCALAR >
73
74 template < GUM_Numeric GUM_SCALAR >
80
81 template < GUM_Numeric GUM_SCALAR >
85
86 template < GUM_Numeric GUM_SCALAR >
89 if (this == &src) { return *this; }
90 _prm_ = src._prm_;
91 _o3_prm_ = src._o3_prm_;
92 _solver_ = src._solver_;
93 _errors_ = src._errors_;
94 return *this;
95 }
96
97 template < GUM_Numeric GUM_SCALAR >
100 if (this == &src) { return *this; }
101 _prm_ = std::move(src._prm_);
102 _o3_prm_ = std::move(src._o3_prm_);
103 _solver_ = std::move(src._solver_);
104 _errors_ = std::move(src._errors_);
105 return *this;
106 }
107
108 template < GUM_Numeric GUM_SCALAR >
111 if (_checkO3Interfaces_()) {
113
114 for (auto i: _o3Interface_) {
115 if (_solver_->resolveInterface(i->superLabel())) {
116 factory.startInterface(i->name().label(), i->superLabel().label(), true);
117 factory.endInterface();
118 }
119 }
120 }
121 }
122
123 template < GUM_Numeric GUM_SCALAR >
127
128 template < GUM_Numeric GUM_SCALAR >
130 // Adding nodes to the type inheritance graph
131 for (auto& i: _o3_prm_->interfaces()) {
132 auto id = _dag_.addNode();
133 try {
134 _nameMap_.insert(i->name().label(), id);
135 _interfaceMap_.insert(i->name().label(), i.get());
136 _nodeMap_.insert(id, i.get());
137
138 } catch (DuplicateElement const&) {
139 // Raised if duplicate type names
140 O3PRM_INTERFACE_DUPLICATE(i->name(), *_errors_);
141 return false;
142 }
143 }
144 return true;
145 }
146
147 template < GUM_Numeric GUM_SCALAR >
149 // Adding arcs to the graph inheritance graph
150 for (auto& i: _o3_prm_->interfaces()) {
151 if (i->superLabel().label() != "") {
152 if (!_solver_->resolveInterface(i->superLabel())) { return false; }
153
154 auto head = _nameMap_[i->superLabel().label()];
155 auto tail = _nameMap_[i->name().label()];
156
157 try {
158 _dag_.addArc(tail, head);
159
160 } catch (InvalidDirectedCycle const&) {
161 // Cyclic inheritance
162 O3PRM_INTERFACE_CYCLIC_INHERITANCE(i->name(), i->superLabel(), *_errors_);
163 return false;
164 }
165 }
166 }
167 return true;
168 }
169
170 template < GUM_Numeric GUM_SCALAR >
172 auto topo_order = _dag_.topologicalOrder();
173 for (auto id = topo_order.rbegin(); id != topo_order.rend(); --id) {
174 _o3Interface_.push_back(_nodeMap_[*id]);
175 }
176 }
177
178 template < GUM_Numeric GUM_SCALAR >
181
182 for (auto i: _o3Interface_) {
183 _prm_->getInterface(i->name().label()).inheritInterface();
184
185 factory.continueInterface(i->name().label());
186
187 for (auto& elt: i->elements()) {
188 if (_checkInterfaceElement_(*i, elt)) {
189 try {
190 if (_prm_->isType(elt.type().label())) {
191 factory.addAttribute(elt.type().label(), elt.name().label());
192 } else {
193 factory.addReferenceSlot(elt.type().label(), elt.name().label(), elt.isArray());
194 }
195
196 } catch (OperationNotAllowed const&) {
197 // Duplicate or Wrong overload
198 O3PRM_INTERFACE_DUPLICATE_ELEMENT(elt, *_errors_);
199 }
200 }
201 }
202 factory.endInterface();
203 }
204 }
205
206 template < GUM_Numeric GUM_SCALAR >
208 O3InterfaceElement& elt) {
209 if (!_solver_->resolveClassElement(elt.type())) { return false; }
210
211 if (_prm_->isType(elt.type().label()) && elt.isArray()) {
212 O3PRM_INTERFACE_ILLEGAL_ARRAY(elt.name(), *_errors_);
213 return false;
214 }
215
216 const auto& real_i = _prm_->getInterface(i.name().label());
217
218 if (real_i.exists(elt.name().label())) {
219 if (!_checkOverloadLegality_(i, elt)) { return false; }
220 }
221
222 if (!_checkCyclicReference_(i, elt)) { return false; }
223
224 return true;
225 }
226
227 template < GUM_Numeric GUM_SCALAR >
229 O3InterfaceElement& elt) {
230 const auto& real_i = _prm_->getInterface(i.name().label());
231 const auto& real_elt = real_i.get(elt.name().label());
232
235 }
236
239 }
240
241 return false;
242 }
243
244 template < GUM_Numeric GUM_SCALAR >
246 O3Interface& i,
247 O3InterfaceElement& elt) {
248 const auto& real_i = _prm_->getInterface(i.name().label());
249 const auto& real_elt = real_i.get(elt.name().label());
250
251 const auto& sub_type = _prm_->type(elt.type().label());
252 const auto& super_type = real_elt.type();
253
254 if (!sub_type.isSubTypeOf(super_type)) {
255 O3PRM_INTERFACE_ILLEGAL_OVERLOAD(elt, *_errors_);
256 return false;
257 }
258
259 if (sub_type.name() == super_type.name()) {
260 O3PRM_INTERFACE_DUPLICATE_ELEMENT(elt, *_errors_);
261 return false;
262 }
263
264 return true;
265 }
266
267 template < GUM_Numeric GUM_SCALAR >
269 O3Interface& i,
270 O3InterfaceElement& elt) {
271 const auto& real_i = _prm_->getInterface(i.name().label());
272 const auto& real_elt
273 = static_cast< const PRMReferenceSlot< GUM_SCALAR >& >(real_i.get(elt.name().label()));
274
275 auto sub_type = (const PRMClassElementContainer< GUM_SCALAR >*)nullptr;
276
277 if (_prm_->isClass(elt.type().label())) {
278 sub_type = &(_prm_->getClass(elt.type().label()));
279 } else {
280 sub_type = &(_prm_->getInterface(elt.type().label()));
281 }
282
283 auto super_type = &(real_elt.slotType());
284
285 if (!sub_type->isSubTypeOf(*super_type)) {
286 O3PRM_INTERFACE_ILLEGAL_OVERLOAD(elt, *_errors_);
287 return false;
288 }
289
290 if (sub_type->name() == super_type->name()) {
291 O3PRM_INTERFACE_DUPLICATE_ELEMENT(elt, *_errors_);
292 return false;
293 }
294
295 return true;
296 }
297
298 template < GUM_Numeric GUM_SCALAR >
300 O3InterfaceElement& elt) {
301 if (_prm_->isInterface(elt.type().label()) || _prm_->isClass(elt.type().label())) {
302 auto ref_type = (const PRMClassElementContainer< GUM_SCALAR >*)nullptr;
303
304 if (_prm_->isInterface(elt.type().label())) {
305 ref_type = &(_prm_->getInterface(elt.type().label()));
306 } else {
307 ref_type = &(_prm_->getClass(elt.type().label()));
308 }
309
310 const auto& real_i = _prm_->getInterface(i.name().label());
311
312 if (&real_i == ref_type) {
313 O3PRM_INTERFACE_SELF_REFERENCE(i, elt, *_errors_);
314 return false;
315 }
316
317 if (ref_type->isSubTypeOf(real_i)) {
318 O3PRM_INTERFACE_ILLEGAL_SUB_REFERENCE(i, elt, *_errors_);
319 return false;
320 }
321 }
322
323 return true;
324 }
325
326 } // namespace o3prm
327 } // namespace prm
328} // 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:90
void addReferenceSlot(std::string_view type, std::string_view name, bool isArray) override
Tells the factory that we started declaring a slot.
void endInterface() override
Tells the factory that we finished an interface declaration.
void startInterface(std::string_view i, std::string_view ext="", bool delayInheritance=false) override
Tells the factory that we start an interface declaration.
void addAttribute(std::string_view type, std::string_view name) override
Add an attribute to an interface.
void continueInterface(std::string_view 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:344
Bulds gum::prm:PRMInterface from gum::prm::o3prm::O3Interface.
O3InterfaceFactory< GUM_SCALAR > & operator=(const O3InterfaceFactory< GUM_SCALAR > &src)
HashTable< std::string, O3Interface * > _interfaceMap_
bool _checkOverloadLegality_(O3Interface &i, O3InterfaceElement &elt)
bool _checkInterfaceElement_(O3Interface &i, O3InterfaceElement &elt)
HashTable< std::string, gum::NodeId > _nameMap_
bool _checkAttributeOverloadLegality_(O3Interface &i, O3InterfaceElement &elt)
bool _checkCyclicReference_(O3Interface &i, O3InterfaceElement &elt)
std::vector< O3Interface * > _o3Interface_
O3InterfaceFactory(PRM< GUM_SCALAR > &prm, O3PRM &o3_prm, O3NameSolver< GUM_SCALAR > &solver, ErrorsContainer &errors)
O3NameSolver< GUM_SCALAR > * _solver_
bool _checkReferenceOverloadLegality_(O3Interface &i, O3InterfaceElement &elt)
HashTable< NodeId, O3Interface * > _nodeMap_
The O3Interface is part of the AST of the O3PRM language.
Definition O3prm.h:377
std::string & label()
Definition O3prm.cpp:286
Resolves names for the different O3PRM factories.
The O3PRM is part of the AST of the O3PRM language.
Definition O3prm.h:915
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.