aGrUM 2.3.2
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-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
49#include <iostream>
50
54
55// to ease IDE parser
57
58namespace gum {
59 namespace prm {
60
61 template < typename GUM_SCALAR >
63 const std::string& name,
64 const PRMType& type,
66 PRMAttribute< GUM_SCALAR >(name), _type_(new PRMType(type)), _cpf_(0), _formulas_(impl),
67 _class_(&c) {
68 GUM_CONSTRUCTOR(PRMFormAttribute);
69 _formulas_->add(_type_->variable());
71 }
72
73 template < typename GUM_SCALAR >
75 GUM_DESTRUCTOR(PRMFormAttribute);
76 delete _type_;
77 delete _cpf_;
78 delete _formulas_;
79 }
80
81 template < typename GUM_SCALAR >
84 auto impl
85 = static_cast< MultiDimImplementation< std::string >* >(this->_formulas_->newFactory());
86 return new PRMFormAttribute< GUM_SCALAR >(c, this->name(), this->type(), impl);
87 }
88
89 template < typename GUM_SCALAR >
92 auto copy = new PRMFormAttribute< GUM_SCALAR >(*_class_, this->name(), this->type());
93 for (auto var: _formulas_->variablesSequence()) {
94 if (var != &(_type_->variable())) { copy->_formulas_->add(*var); }
95 }
96
97 Instantiation inst(*(copy->_formulas_)), jnst(*_formulas_);
98 for (inst.setFirst(), jnst.setFirst(); !(inst.end() || jnst.end()); inst.inc(), jnst.inc()) {
99 copy->_formulas_->set(inst, _formulas_->get(jnst));
100 }
101
102 GUM_ASSERT(copy->_formulas_->contains(copy->_type_->variable()));
103 return copy;
104 }
105
106 template < typename GUM_SCALAR >
109 const PRMAttribute< GUM_SCALAR >& source) {
110 delete _formulas_;
112
113 for (const auto& var: source.cpf().variablesSequence()) {
114 _formulas_->add(*(bij.second(var)));
115 }
116
117 if (dynamic_cast< const PRMFormAttribute< GUM_SCALAR >* >(&source)) {
118 const auto& src = static_cast< const PRMFormAttribute< GUM_SCALAR >& >(source);
119
120 Instantiation inst(_formulas_), jnst(src._formulas_);
121
122 for (inst.setFirst(), jnst.setFirst(); !(inst.end() || jnst.end());
123 inst.inc(), jnst.inc()) {
124 _formulas_->set(inst, src._formulas_->get(jnst));
125 }
126
127 GUM_ASSERT(inst.end() && jnst.end());
128
129 } else {
130 Instantiation inst(_formulas_), jnst(source.cpf());
131
132 for (inst.setFirst(), jnst.setFirst(); !(inst.end() || jnst.end());
133 inst.inc(), jnst.inc()) {
134 auto val = std::to_string(source.cpf().get(jnst));
135 _formulas_->set(inst, val);
136 }
137
138 GUM_ASSERT(inst.end() && jnst.end());
139 }
140
141 if (_cpf_) {
142 delete _cpf_;
143 _cpf_ = 0;
144 }
145
146 GUM_ASSERT(_formulas_->contains(_type_->variable()));
147 GUM_ASSERT(!_formulas_->contains(source.type().variable()));
148 }
149
150 template < typename GUM_SCALAR >
155
156 template < typename GUM_SCALAR >
160
161 template < typename GUM_SCALAR >
163 return *_type_;
164 }
165
166 template < typename GUM_SCALAR >
167 const Tensor< GUM_SCALAR >& PRMFormAttribute< GUM_SCALAR >::cpf() const {
168 if (_cpf_ == 0) { _fillCpf_(); }
169 return *_cpf_;
170 }
171
172 template < typename GUM_SCALAR >
174 try {
175 if (_cpf_) {
176 delete _cpf_;
177 _cpf_ = 0;
178 }
179 _formulas_->add(elt.type().variable());
180 } catch (DuplicateElement const&) {
181 GUM_ERROR(DuplicateElement, elt.name() << " as parent of " << this->name())
182 } catch (OperationNotAllowed const&) {
184 elt.name() << " of wrong type as parent of " << this->name();)
185 }
186
187 GUM_ASSERT(_formulas_->contains(_type_->variable()));
188 }
189
190 template < typename GUM_SCALAR >
192
193 template < typename GUM_SCALAR >
196
197 try {
198 cast = new PRMScalarAttribute< GUM_SCALAR >(this->name(), type().superType());
199 } catch (NotFound const&) {
200 GUM_ERROR(OperationNotAllowed, "this ScalarAttribute can not have cast descendant")
201 }
202
203 cast->addParent(*this);
204
205 const DiscreteVariable& my_var = type().variable();
206 DiscreteVariable& cast_var = cast->type().variable();
207 Instantiation inst(cast->cpf());
208
209 for (inst.setFirst(); !inst.end(); inst.inc()) {
210 if (type().label_map()[inst.val(my_var)] == inst.val(cast_var)) {
211 cast->cpf().set(inst, 1);
212 } else {
213 cast->cpf().set(inst, 0);
214 }
215 }
216
217 GUM_ASSERT(_formulas_->contains(_type_->variable()));
218 return cast;
219 }
220
221 template < typename GUM_SCALAR >
223 try {
224 type().setSuper(cast->type());
225 } catch (OperationNotAllowed const&) {
226 GUM_ERROR(OperationNotAllowed, "this ScalarAttribute can not have cast descendant")
227 } catch (TypeError const&) {
228 std::stringstream msg;
229 msg << type().name() << " is not a subtype of " << cast->type().name();
230 GUM_ERROR(TypeError, msg.str())
231 }
232
233 cast->becomeCastDescendant(type());
234 }
235
236 template < typename GUM_SCALAR >
238 delete _formulas_;
239
241 _formulas_->add(type().variable());
242 _formulas_->add(subtype.variable());
243
245
246 for (inst.setFirst(); !inst.end(); inst.inc()) {
247 auto my_pos = inst.pos(subtype.variable());
248 if (subtype.label_map()[my_pos] == inst.pos(type().variable())) {
249 _formulas_->set(inst, "1");
250 } else {
251 _formulas_->set(inst, "0");
252 }
253 }
254
255 if (_cpf_) {
256 delete _cpf_;
257 _cpf_ = nullptr;
258 }
259 }
260
261 template < typename GUM_SCALAR >
263 PRMAttribute< GUM_SCALAR >(source.name()) {
264 GUM_CONS_CPY(PRMFormAttribute);
265 GUM_ERROR(OperationNotAllowed, "Cannot copy FormAttribute")
266 }
267
268 template < typename GUM_SCALAR >
273
274 template < typename GUM_SCALAR >
276 try {
277 if (_cpf_) { delete _cpf_; }
278
279 _cpf_ = new Tensor< GUM_SCALAR >();
280
281 for (auto var: _formulas_->variablesSequence()) {
282 _cpf_->add(*var);
283 }
284
285 auto params = _class_->scope();
286
288 Instantiation jnst(_cpf_);
289
290 for (inst.setFirst(), jnst.setFirst(); !(inst.end() || jnst.end());
291 inst.inc(), jnst.inc()) {
292 // With CPT defined using rules, empty values can appear
293 auto val = _formulas_->get(inst);
294 if (val.empty()) { val = "0.0"; }
295
296 Formula f(val);
297
298 for (auto item: params) {
299 f.variables().insert(item.first, item.second->value());
300 }
301
302 _cpf_->set(jnst, (GUM_SCALAR)f.result());
303 }
304
305 GUM_ASSERT(inst.end() && jnst.end());
306
307 } catch (Exception const&) { GUM_ERROR(NotFound, "undefined value in cpt") }
308 GUM_ASSERT(_formulas_->contains(_type_->variable()))
309 }
310
311 template < typename GUM_SCALAR >
319
320 template < typename GUM_SCALAR >
324
325 template < typename GUM_SCALAR >
326 void PRMFormAttribute< GUM_SCALAR >::swap(const PRMType& old_type, const PRMType& new_type) {
327 if (&(old_type) == _type_) {
328 GUM_ERROR(OperationNotAllowed, "Cannot replace attribute own type")
329 }
330 if (old_type->domainSize() != new_type->domainSize()) {
331 GUM_ERROR(OperationNotAllowed, "Cannot replace types with difference domain size")
332 }
333 if (!_formulas_->contains(old_type.variable())) {
334 GUM_ERROR(NotFound, "could not find variable " + old_type.name())
335 }
336
337 auto old = _formulas_;
338
340
341 for (auto var: old->variablesSequence()) {
342 if (var != &(old_type.variable())) {
343 _formulas_->add(*var);
344 } else {
345 _formulas_->add(new_type.variable());
346 }
347 }
348
349 Instantiation inst(_formulas_), jnst(old);
350
351 for (inst.setFirst(), jnst.setFirst(); !(inst.end() || jnst.end()); inst.inc(), jnst.inc()) {
352 _formulas_->set(inst, old->get(jnst));
353 }
354
355 delete old;
356
357 if (_cpf_) {
358 delete _cpf_;
359 _cpf_ = 0;
360 }
361
362 GUM_ASSERT(inst.end() && jnst.end());
363 GUM_ASSERT(_formulas_->contains(_type_->variable()));
364 GUM_ASSERT(!_formulas_->contains(new_type.variable()));
365 GUM_ASSERT(_formulas_->contains(new_type.variable()));
366 }
367
368 template < typename GUM_SCALAR >
372
373 template < typename GUM_SCALAR >
375 if (_type_->variable().domainSize() != t->variable().domainSize()) {
376 GUM_ERROR(OperationNotAllowed, "Cannot replace types with difference domain size")
377 }
378 auto old = _formulas_;
379
381
382 for (auto var: old->variablesSequence()) {
383 if (var != &(_type_->variable())) {
384 _formulas_->add(*var);
385 } else {
386 _formulas_->add(t->variable());
387 }
388 }
389
390 Instantiation inst(_formulas_), jnst(old);
391
392 for (inst.setFirst(), jnst.setFirst(); !(inst.end() || jnst.end()); inst.inc(), jnst.inc()) {
393 _formulas_->set(inst, old->get(jnst));
394 }
395
396 delete old;
397
398 _type_ = t;
399
400 if (_cpf_) {
401 delete _cpf_;
402 _cpf_ = 0;
403 }
404
405 GUM_ASSERT(_formulas_->contains(_type_->variable()));
406 GUM_ASSERT(inst.end() && jnst.end());
407 }
408
409 } /* namespace prm */
410} /* 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:1594
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:118
Evaluates a string as a algebraic formula.
Definition formula.h:293
double result() const
Returns the result of this gum::Formula.
Definition formula.cpp:313
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.
Idx pos(const DiscreteVariable &v) const final
Returns the position of the variable v.
void inc()
Operator increment.
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.
virtual const Tensor< GUM_SCALAR > & cpf() const =0
See gum::PRMClassElement::cpf().
PRMAttribute(const std::string &name)
Destructor.
virtual PRMType & type()=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:75
<agrum/PRM/elements/formAttribute.h>
virtual void swap(const PRMType &old_type, const PRMType &new_type)
Swap old_type with new_type in the PRMClassElement cpt.
virtual MultiDimImplementation< std::string > & formulas()
virtual void addChild(const PRMClassElement< GUM_SCALAR > &elt)
See gum::prm::PRMAttribute.
const PRMClass< GUM_SCALAR > * _class_
A pointe toward the class of this attribute.
virtual PRMAttribute< GUM_SCALAR > * getCastDescendant() const
See gum::prm::PRMAttribute.
virtual PRMClassElement< GUM_SCALAR >::ClassElementType elt_type() const
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.
virtual void setAsCastDescendant(PRMAttribute< GUM_SCALAR > *attr)
See gum::prm::PRMAttribute.
virtual void becomeCastDescendant(PRMType &subtype)
Change this attribute to be a cast descendant of a an attribute with type subtype.
PRMType * _type_
The random variable type of this attribute.
virtual void copyCpf(const Bijection< const DiscreteVariable *, const DiscreteVariable * > &bif, const PRMAttribute< GUM_SCALAR > &source)
See gum::prm::PRMAttribute.
virtual PRMType & type()
See gum::prm::PRMAttribute.
virtual PRMAttribute< GUM_SCALAR > * copy(Bijection< const DiscreteVariable *, const DiscreteVariable * > bij) const
See gum::prm::PRMAttribute.
PRMFormAttribute & operator=(const PRMFormAttribute &source)
virtual void addParent(const PRMClassElement< GUM_SCALAR > &elt)
See gum::prm::PRMAttribute.
virtual PRMAttribute< GUM_SCALAR > * newFactory(const PRMClass< GUM_SCALAR > &c) const
See gum::prm::PRMAttribute.
PRMFormAttribute(const PRMClass< GUM_SCALAR > &c, const std::string &name, const PRMType &type, MultiDimImplementation< std::string > *impl=new MultiDimArray< std::string >())
virtual const Tensor< GUM_SCALAR > & cpf() const
See gum::prm::PRMAttribute.
const std::string & name() const
Returns the name of this object.
static std::string LEFT_CAST()
Enumeration of the different types of objects handled by a PRM.
Definition PRMObject.h:90
static std::string RIGHT_CAST()
Enumeration of the different types of objects handled by a PRM.
Definition PRMObject.h:92
<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:64
const std::string & name() const
Returns the name of this object.
Definition PRMType_inl.h:78
#define GUM_ERROR(type, msg)
Definition exceptions.h:72
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