aGrUM 3.1.1
a C++ library for (probabilistic) graphical models
PRMFormAttribute_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
50#include <iostream>
51
55
56// to ease IDE parser
58
59namespace gum {
60 namespace prm {
61
62 template < GUM_Numeric GUM_SCALAR >
64 std::string_view name,
65 const PRMType& type,
67 PRMAttribute< GUM_SCALAR >(name), _type_(new PRMType(type)), _cpf_(0), _formulas_(impl),
68 _class_(&c) {
69 GUM_CONSTRUCTOR(PRMFormAttribute);
70 _formulas_->add(_type_->variable());
71 this->safeName_
72 = (PRMObject::LEFT_CAST() + _type_->name() + PRMObject::RIGHT_CAST()).append(name);
73 }
74
75 template < GUM_Numeric GUM_SCALAR >
77 GUM_DESTRUCTOR(PRMFormAttribute);
78 delete _type_;
79 delete _cpf_;
80 delete _formulas_;
81 }
82
83 template < GUM_Numeric GUM_SCALAR >
86 auto impl
87 = static_cast< MultiDimImplementation< std::string >* >(this->_formulas_->newFactory());
88 return new PRMFormAttribute< GUM_SCALAR >(c, this->name(), this->type(), impl);
89 }
90
91 template < GUM_Numeric GUM_SCALAR >
94 auto copy = new PRMFormAttribute< GUM_SCALAR >(*_class_, this->name(), this->type());
95 for (auto var: _formulas_->variablesSequence()) {
96 if (var != &(_type_->variable())) { copy->_formulas_->add(*var); }
97 }
98
99 Instantiation inst(*(copy->_formulas_)), jnst(*_formulas_);
100 for (inst.setFirst(), jnst.setFirst(); !(inst.end() || jnst.end()); inst.inc(), jnst.inc()) {
101 copy->_formulas_->set(inst, _formulas_->get(jnst));
102 }
103
104 GUM_ASSERT(copy->_formulas_->contains(copy->_type_->variable()));
105 return copy;
106 }
107
108 template < GUM_Numeric GUM_SCALAR >
111 const PRMAttribute< GUM_SCALAR >& source) {
112 delete _formulas_;
114
115 for (const auto& var: source.cpf().variablesSequence()) {
116 _formulas_->add(*(bij.second(var)));
117 }
118
119 if (dynamic_cast< const PRMFormAttribute< GUM_SCALAR >* >(&source)) {
120 const auto& src = static_cast< const PRMFormAttribute< GUM_SCALAR >& >(source);
121
122 Instantiation inst(_formulas_), jnst(src._formulas_);
123
124 for (inst.setFirst(), jnst.setFirst(); !(inst.end() || jnst.end());
125 inst.inc(), jnst.inc()) {
126 _formulas_->set(inst, src._formulas_->get(jnst));
127 }
128
129 GUM_ASSERT(inst.end() && jnst.end());
130
131 } else {
132 Instantiation inst(_formulas_), jnst(source.cpf());
133
134 for (inst.setFirst(), jnst.setFirst(); !(inst.end() || jnst.end());
135 inst.inc(), jnst.inc()) {
136 auto val = std::to_string(source.cpf().get(jnst));
137 _formulas_->set(inst, val);
138 }
139
140 GUM_ASSERT(inst.end() && jnst.end());
141 }
142
143 if (_cpf_) {
144 delete _cpf_;
145 _cpf_ = 0;
146 }
147
148 GUM_ASSERT(_formulas_->contains(_type_->variable()));
149 GUM_ASSERT(!_formulas_->contains(source.type().variable()));
150 }
151
152 template < GUM_Numeric GUM_SCALAR >
157
158 template < GUM_Numeric GUM_SCALAR >
162
163 template < GUM_Numeric GUM_SCALAR >
165 return *_type_;
166 }
167
168 template < GUM_Numeric GUM_SCALAR >
169 const Tensor< GUM_SCALAR >& PRMFormAttribute< GUM_SCALAR >::cpf() const {
170 if (_cpf_ == 0) { _fillCpf_(); }
171 return *_cpf_;
172 }
173
174 template < GUM_Numeric GUM_SCALAR >
176 try {
177 if (_cpf_) {
178 delete _cpf_;
179 _cpf_ = 0;
180 }
181 _formulas_->add(elt.type().variable());
182 } catch (DuplicateElement const&) {
183 GUM_ERROR(DuplicateElement, elt.name() << " as parent of " << this->name())
184 } catch (OperationNotAllowed const&) {
186 elt.name() << " of wrong type as parent of " << this->name();)
187 }
188
189 GUM_ASSERT(_formulas_->contains(_type_->variable()));
190 }
191
192 template < GUM_Numeric GUM_SCALAR >
194
195 template < GUM_Numeric GUM_SCALAR >
197 if (!type().isSubType()) {
198 GUM_ERROR(OperationNotAllowed, "this ScalarAttribute can not have cast descendant")
199 }
200 auto cast = new PRMScalarAttribute< GUM_SCALAR >(this->name(), type().superType());
201
202 cast->addParent(*this);
203
204 const DiscreteVariable& my_var = type().variable();
205 DiscreteVariable& cast_var = cast->type().variable();
206 Instantiation inst(cast->cpf());
207
208 for (inst.setFirst(); !inst.end(); inst.inc()) {
209 if (type().label_map()[inst.val(my_var)] == inst.val(cast_var)) {
210 cast->cpf().set(inst, 1);
211 } else {
212 cast->cpf().set(inst, 0);
213 }
214 }
215
216 GUM_ASSERT(_formulas_->contains(_type_->variable()));
217 return cast;
218 }
219
220 template < GUM_Numeric GUM_SCALAR >
222 try {
223 type().setSuper(cast->type());
224 } catch (OperationNotAllowed const&) {
225 GUM_ERROR(OperationNotAllowed, "this ScalarAttribute can not have cast descendant")
226 } catch (TypeError const&) {
228 std::format("{} is not a subtype of {}", type().name(), cast->type().name()))
229 }
230
231 cast->becomeCastDescendant(type());
232 }
233
234 template < GUM_Numeric GUM_SCALAR >
236 delete _formulas_;
237
239 _formulas_->add(type().variable());
240 _formulas_->add(subtype.variable());
241
243
244 for (inst.setFirst(); !inst.end(); inst.inc()) {
245 auto my_pos = inst.pos(subtype.variable());
246 if (subtype.label_map()[my_pos] == inst.pos(type().variable())) {
247 _formulas_->set(inst, "1");
248 } else {
249 _formulas_->set(inst, "0");
250 }
251 }
252
253 if (_cpf_) {
254 delete _cpf_;
255 _cpf_ = nullptr;
256 }
257 }
258
259 template < GUM_Numeric GUM_SCALAR >
261 PRMAttribute< GUM_SCALAR >(source.name()) {
262 GUM_CONS_CPY(PRMFormAttribute);
263 GUM_ERROR(OperationNotAllowed, "Cannot copy FormAttribute")
264 }
265
266 template < GUM_Numeric GUM_SCALAR >
271
272 template < GUM_Numeric GUM_SCALAR >
274 try {
275 if (_cpf_) { delete _cpf_; }
276
277 _cpf_ = new Tensor< GUM_SCALAR >();
278
279 for (auto var: _formulas_->variablesSequence()) {
280 _cpf_->add(*var);
281 }
282
283 auto params = _class_->scope();
284
286 Instantiation jnst(_cpf_);
287
288 for (inst.setFirst(), jnst.setFirst(); !(inst.end() || jnst.end());
289 inst.inc(), jnst.inc()) {
290 // With CPT defined using rules, empty values can appear
291 auto val = _formulas_->get(inst);
292 if (val.empty()) { val = "0.0"; }
293
294 Formula f(val);
295
296 for (auto item: params) {
297 f.variables().insert(item.first, item.second->value());
298 }
299
300 _cpf_->set(jnst, (GUM_SCALAR)f.result());
301 }
302
303 GUM_ASSERT(inst.end() && jnst.end());
304
305 } catch (Exception const&) { GUM_ERROR(NotFound, "undefined value in cpt") }
306 GUM_ASSERT(_formulas_->contains(_type_->variable()))
307 }
308
309 template < GUM_Numeric GUM_SCALAR >
317
318 template < GUM_Numeric GUM_SCALAR >
322
323 template < GUM_Numeric GUM_SCALAR >
324 void PRMFormAttribute< GUM_SCALAR >::swap(const PRMType& old_type, const PRMType& new_type) {
325 if (&(old_type) == _type_) {
326 GUM_ERROR(OperationNotAllowed, "Cannot replace attribute own type")
327 }
328 if (old_type->domainSize() != new_type->domainSize()) {
329 GUM_ERROR(OperationNotAllowed, "Cannot replace types with difference domain size")
330 }
331 if (!_formulas_->contains(old_type.variable())) {
332 GUM_ERROR(NotFound, "could not find variable " + old_type.name())
333 }
334
335 auto old = _formulas_;
336
338
339 for (auto var: old->variablesSequence()) {
340 if (var != &(old_type.variable())) {
341 _formulas_->add(*var);
342 } else {
343 _formulas_->add(new_type.variable());
344 }
345 }
346
347 Instantiation inst(_formulas_), jnst(old);
348
349 for (inst.setFirst(), jnst.setFirst(); !(inst.end() || jnst.end()); inst.inc(), jnst.inc()) {
350 _formulas_->set(inst, old->get(jnst));
351 }
352
353 delete old;
354
355 if (_cpf_) {
356 delete _cpf_;
357 _cpf_ = 0;
358 }
359
360 GUM_ASSERT(inst.end() && jnst.end());
361 GUM_ASSERT(_formulas_->contains(_type_->variable()));
362 GUM_ASSERT(!_formulas_->contains(new_type.variable()));
363 GUM_ASSERT(_formulas_->contains(new_type.variable()));
364 }
365
366 template < GUM_Numeric GUM_SCALAR >
370
371 template < GUM_Numeric GUM_SCALAR >
373 if (_type_->variable().domainSize() != t->variable().domainSize()) {
374 GUM_ERROR(OperationNotAllowed, "Cannot replace types with difference domain size")
375 }
376 auto old = _formulas_;
377
379
380 for (auto var: old->variablesSequence()) {
381 if (var != &(_type_->variable())) {
382 _formulas_->add(*var);
383 } else {
384 _formulas_->add(t->variable());
385 }
386 }
387
388 Instantiation inst(_formulas_), jnst(old);
389
390 for (inst.setFirst(), jnst.setFirst(); !(inst.end() || jnst.end()); inst.inc(), jnst.inc()) {
391 _formulas_->set(inst, old->get(jnst));
392 }
393
394 delete old;
395
396 _type_ = t;
397
398 if (_cpf_) {
399 delete _cpf_;
400 _cpf_ = 0;
401 }
402
403 GUM_ASSERT(_formulas_->contains(_type_->variable()));
404 GUM_ASSERT(inst.end() && jnst.end());
405 }
406
407 } /* namespace prm */
408} /* namespace gum */
Headers of gum::PRMFormAttribute.
Headers of gum::PRMScalarAttribute.
Headers of Class.
const T2 & second(const T1 &first) const
Returns the second value of a pair given its first value.
Set of pairs of elements with fast search for both elements.
Definition bijection.h:1640
Base class for discrete random variable.
virtual Size domainSize() const =0
Exception : a similar element already exists.
Base class for all aGrUM's exceptions.
Definition exceptions.h:122
Evaluates a string as a algebraic formula.
Definition formula.h:293
double result() const
Returns the result of this gum::Formula.
Definition formula.cpp:304
HashTable< std::string, double > & variables()
Returns the variables used by this gum::Formula.
value_type & insert(const Key &key, const Val &val)
Adds a new element (actually a copy of this element) into the hash table.
Class for assigning/browsing values to tuples of discrete variables.
bool end() const
Returns true if the Instantiation reached the end.
void inc()
Operator increment.
Idx pos(const DiscreteVariable &v) const final
Returns the position of the variable v.
Idx val(Idx i) const
Returns the current value of the variable at position i.
void setFirst()
Assign the first values to the tuple of the Instantiation.
Multidimensional matrix stored as an array in memory.
Exception : the element we looked for cannot be found.
Exception : operation not allowed.
Exception : wrong type for this operation.
PRMAttribute is a member of a Class in a PRM.
PRMAttribute(std::string_view name)
Destructor.
const Tensor< GUM_SCALAR > & cpf() const override=0
See gum::PRMClassElement::cpf().
PRMType & type() override=0
See gum::PRMClassElement::type().
Abstract class representing an element of PRM class.
virtual std::string cast(const PRMType &t) const
Returns the name of the cast descendant with PRMType t of this PRMClassElement.
ClassElementType
Returns true if obj_ptr is of type PRMReferenceSlot.
virtual PRMType & type()=0
Return a reference over the gum::PRMType of this class element.
std::string safeName_
The safe name of this PRMClassElement.
A PRMClass is an object of a PRM representing a fragment of a Bayesian network which can be instantia...
Definition PRMClass.h:77
<agrum/PRM/elements/formAttribute.h>
PRMAttribute< GUM_SCALAR > * newFactory(const PRMClass< GUM_SCALAR > &c) const override
See gum::prm::PRMAttribute.
void copyCpf(const Bijection< const DiscreteVariable *, const DiscreteVariable * > &bif, const PRMAttribute< GUM_SCALAR > &source) override
See gum::prm::PRMAttribute.
virtual MultiDimImplementation< std::string > & formulas()
void addParent(const PRMClassElement< GUM_SCALAR > &elt) override
See gum::prm::PRMAttribute.
const PRMClass< GUM_SCALAR > * _class_
A pointe toward the class of this attribute.
PRMClassElement< GUM_SCALAR >::ClassElementType elt_type() const override
See gum::prm::PRMAttribute.
PRMType & type() override
See gum::prm::PRMAttribute.
Tensor< GUM_SCALAR > * _cpf_
A pointer on the Tensor of this attribute.
MultiDimImplementation< std::string > * _formulas_
A pointer on the Tensor of this attribute.
PRMFormAttribute(const PRMClass< GUM_SCALAR > &c, std::string_view name, const PRMType &type, MultiDimImplementation< std::string > *impl=new MultiDimArray< std::string >())
PRMAttribute< GUM_SCALAR > * copy(Bijection< const DiscreteVariable *, const DiscreteVariable * > bij) const override
See gum::prm::PRMAttribute.
PRMAttribute< GUM_SCALAR > * getCastDescendant() const override
See gum::prm::PRMAttribute.
PRMType * _type_
The random variable type of this attribute.
void becomeCastDescendant(PRMType &subtype) override
Change this attribute to be a cast descendant of a an attribute with type subtype.
const Tensor< GUM_SCALAR > & cpf() const override
See gum::prm::PRMAttribute.
void addChild(const PRMClassElement< GUM_SCALAR > &elt) override
See gum::prm::PRMAttribute.
PRMFormAttribute & operator=(const PRMFormAttribute &source)
void setAsCastDescendant(PRMAttribute< GUM_SCALAR > *attr) override
See gum::prm::PRMAttribute.
void swap(const PRMType &old_type, const PRMType &new_type) override
Swap old_type with new_type in the PRMClassElement cpt.
const std::string & name() const
Returns the name of this object.
static std::string RIGHT_CAST()
Enumeration of the different types of objects handled by a PRM.
static std::string LEFT_CAST()
Enumeration of the different types of objects handled by a PRM.
<agrum/PRM/elements/scalarAttribute.h>
This is a decoration of the DiscreteVariable class.
Definition PRMType.h:78
const std::vector< Idx > & label_map() const
Returns the vector in which the i-th element is the Idx of the super type's label for the i-th label ...
Definition PRMType_inl.h:98
DiscreteVariable & variable()
Return a reference on the DiscreteVariable contained in this.
Definition PRMType_inl.h:65
const std::string & name() const
Returns the name of this object.
Definition PRMType_inl.h:79
#define GUM_ERROR(type, msg)
Definition exceptions.h:76
Headers files for the gum::FormulaPart and gum::Formula classes.
namespace for all probabilistic relational models entities
Definition agrum.h:68
gum is the global namespace for all aGrUM entities
Definition agrum.h:46