30 #include <agrum/tools/core/math/formula.h> 32 #include <agrum/PRM/elements/PRMScalarAttribute.h> 33 #include <agrum/PRM/elements/PRMType.h> 36 #include <agrum/PRM/elements/PRMFormAttribute.h> 41 template <
typename GUM_SCALAR >
42 PRMFormAttribute< GUM_SCALAR >::PRMFormAttribute(
43 const PRMClass< GUM_SCALAR >& c,
44 const std::string& name,
46 MultiDimImplementation< std::string >* impl) :
47 PRMAttribute< GUM_SCALAR >(name),
48 type__(
new PRMType(type)), cpf__(0), formulas__(impl), class__(&c) {
49 GUM_CONSTRUCTOR(PRMFormAttribute);
50 formulas__->add(type__->variable());
51 this->safeName_ = PRMObject::LEFT_CAST() + type__->name()
52 + PRMObject::RIGHT_CAST() + name;
55 template <
typename GUM_SCALAR >
56 PRMFormAttribute< GUM_SCALAR >::~PRMFormAttribute() {
57 GUM_DESTRUCTOR(PRMFormAttribute);
63 template <
typename GUM_SCALAR >
64 PRMAttribute< GUM_SCALAR >* PRMFormAttribute< GUM_SCALAR >::newFactory(
65 const PRMClass< GUM_SCALAR >& c)
const {
66 auto impl =
static_cast< MultiDimImplementation< std::string >* >(
67 this->formulas__->newFactory());
68 return new PRMFormAttribute< GUM_SCALAR >(c,
74 template <
typename GUM_SCALAR >
75 PRMAttribute< GUM_SCALAR >* PRMFormAttribute< GUM_SCALAR >::copy(
76 Bijection<
const DiscreteVariable*,
const DiscreteVariable* > bij)
const {
77 auto copy =
new PRMFormAttribute< GUM_SCALAR >(*class__,
80 for (
auto var: formulas__->variablesSequence()) {
81 if (var != &(type__->variable())) { copy->formulas__->add(*var); }
84 Instantiation inst(*(copy->formulas__)), jnst(*formulas__);
85 for (inst.setFirst(), jnst.setFirst(); !(inst.end() || jnst.end());
86 inst.inc(), jnst.inc()) {
87 copy->formulas__->set(inst, formulas__->get(jnst));
90 GUM_ASSERT(copy->formulas__->contains(copy->type__->variable()));
94 template <
typename GUM_SCALAR >
95 void PRMFormAttribute< GUM_SCALAR >::copyCpf(
96 const Bijection<
const DiscreteVariable*,
const DiscreteVariable* >& bij,
97 const PRMAttribute< GUM_SCALAR >& source) {
99 formulas__ =
new MultiDimArray< std::string >();
101 for (
const auto& var: source.cpf().variablesSequence()) {
102 formulas__->add(*(bij.second(var)));
105 if (
dynamic_cast<
const PRMFormAttribute< GUM_SCALAR >* >(&source)) {
107 =
static_cast<
const PRMFormAttribute< GUM_SCALAR >& >(source);
109 Instantiation inst(formulas__), jnst(src.formulas__);
111 for (inst.setFirst(), jnst.setFirst(); !(inst.end() || jnst.end());
112 inst.inc(), jnst.inc()) {
113 formulas__->set(inst, src.formulas__->get(jnst));
116 GUM_ASSERT(inst.end() && jnst.end());
119 Instantiation inst(formulas__), jnst(source.cpf());
121 for (inst.setFirst(), jnst.setFirst(); !(inst.end() || jnst.end());
122 inst.inc(), jnst.inc()) {
123 auto val = std::to_string(source.cpf().get(jnst));
124 formulas__->set(inst, val);
127 GUM_ASSERT(inst.end() && jnst.end());
135 GUM_ASSERT(formulas__->contains(type__->variable()));
136 GUM_ASSERT(!formulas__->contains(source.type().variable()));
139 template <
typename GUM_SCALAR >
140 typename PRMClassElement< GUM_SCALAR >::ClassElementType
141 PRMFormAttribute< GUM_SCALAR >::elt_type()
const {
142 return this->prm_attribute;
145 template <
typename GUM_SCALAR >
146 PRMType& PRMFormAttribute< GUM_SCALAR >::type() {
150 template <
typename GUM_SCALAR >
151 const PRMType& PRMFormAttribute< GUM_SCALAR >::type()
const {
155 template <
typename GUM_SCALAR >
156 const Potential< GUM_SCALAR >& PRMFormAttribute< GUM_SCALAR >::cpf()
const {
157 if (cpf__ == 0) { fillCpf__(); }
161 template <
typename GUM_SCALAR >
162 void PRMFormAttribute< GUM_SCALAR >::addParent(
163 const PRMClassElement< GUM_SCALAR >& elt) {
169 formulas__->add(elt.type().variable());
170 }
catch (DuplicateElement&) {
171 GUM_ERROR(DuplicateElement,
172 elt.name() <<
" as parent of " <<
this->name());
173 }
catch (OperationNotAllowed&) {
174 GUM_ERROR(OperationNotAllowed,
175 elt.name() <<
" of wrong type as parent of " <<
this->name(););
178 GUM_ASSERT(formulas__->contains(type__->variable()));
181 template <
typename GUM_SCALAR >
182 void PRMFormAttribute< GUM_SCALAR >::addChild(
183 const PRMClassElement< GUM_SCALAR >& elt) {}
185 template <
typename GUM_SCALAR >
186 PRMAttribute< GUM_SCALAR >*
187 PRMFormAttribute< GUM_SCALAR >::getCastDescendant()
const {
188 PRMScalarAttribute< GUM_SCALAR >* cast = 0;
191 cast =
new PRMScalarAttribute< GUM_SCALAR >(
this->name(),
193 }
catch (NotFound&) {
194 GUM_ERROR(OperationNotAllowed,
195 "this ScalarAttribute can not have cast descendant");
198 cast->addParent(*
this);
200 const DiscreteVariable& my_var = type().variable();
201 DiscreteVariable& cast_var = cast->type().variable();
202 Instantiation inst(cast->cpf());
204 for (inst.setFirst(); !inst.end(); inst.inc()) {
205 if (type().label_map()[inst.val(my_var)] == inst.val(cast_var)) {
206 cast->cpf().set(inst, 1);
208 cast->cpf().set(inst, 0);
212 GUM_ASSERT(formulas__->contains(type__->variable()));
216 template <
typename GUM_SCALAR >
217 void PRMFormAttribute< GUM_SCALAR >::setAsCastDescendant(
218 PRMAttribute< GUM_SCALAR >* cast) {
220 type().setSuper(cast->type());
221 }
catch (OperationNotAllowed&) {
222 GUM_ERROR(OperationNotAllowed,
223 "this ScalarAttribute can not have cast descendant");
224 }
catch (TypeError&) {
225 std::stringstream msg;
226 msg << type().name() <<
" is not a subtype of " << cast->type().name();
227 GUM_ERROR(TypeError, msg.str());
230 cast->becomeCastDescendant(type());
233 template <
typename GUM_SCALAR >
234 void PRMFormAttribute< GUM_SCALAR >::becomeCastDescendant(PRMType& subtype) {
237 formulas__ =
new MultiDimArray< std::string >();
238 formulas__->add(type().variable());
239 formulas__->add(subtype.variable());
241 Instantiation inst(formulas__);
243 for (inst.setFirst(); !inst.end(); inst.inc()) {
244 auto my_pos = inst.pos(subtype.variable());
245 if (subtype.label_map()[my_pos] == inst.pos(type().variable())) {
246 formulas__->set(inst,
"1");
248 formulas__->set(inst,
"0");
258 template <
typename GUM_SCALAR >
259 PRMFormAttribute< GUM_SCALAR >::PRMFormAttribute(
260 const PRMFormAttribute& source) :
261 PRMAttribute< GUM_SCALAR >(source.name()) {
262 GUM_CONS_CPY(PRMFormAttribute);
263 GUM_ERROR(OperationNotAllowed,
"Cannot copy FormAttribute");
266 template <
typename GUM_SCALAR >
267 PRMFormAttribute< GUM_SCALAR >& PRMFormAttribute< GUM_SCALAR >::operator=(
268 const PRMFormAttribute< GUM_SCALAR >& source) {
269 GUM_ERROR(OperationNotAllowed,
"Cannot copy FormAttribute");
272 template <
typename GUM_SCALAR >
273 void PRMFormAttribute< GUM_SCALAR >::fillCpf__()
const {
275 if (cpf__) {
delete cpf__; }
277 cpf__ =
new Potential< GUM_SCALAR >();
279 for (
auto var: formulas__->variablesSequence()) {
283 auto params = class__->scope();
285 Instantiation inst(formulas__);
286 Instantiation jnst(cpf__);
288 for (inst.setFirst(), jnst.setFirst(); !(inst.end() || jnst.end());
289 inst.inc(), jnst.inc()) {
291 auto val = formulas__->get(inst);
292 if (val ==
"") { val =
"0.0"; }
296 for (
auto item: params) {
297 f.variables().insert(item.first, item.second->value());
300 cpf__->set(jnst, (GUM_SCALAR)f.result());
303 GUM_ASSERT(inst.end() && jnst.end());
305 }
catch (Exception&) { GUM_ERROR(NotFound,
"undefined value in cpt"); }
306 GUM_ASSERT(formulas__->contains(type__->variable()));
309 template <
typename GUM_SCALAR >
310 MultiDimImplementation< std::string >&
311 PRMFormAttribute< GUM_SCALAR >::formulas() {
319 template <
typename GUM_SCALAR >
320 const MultiDimImplementation< std::string >&
321 PRMFormAttribute< GUM_SCALAR >::formulas()
const {
325 template <
typename GUM_SCALAR >
326 void PRMFormAttribute< GUM_SCALAR >::swap(
const PRMType& old_type,
327 const PRMType& new_type) {
328 if (&(old_type) == type__) {
329 GUM_ERROR(OperationNotAllowed,
"Cannot replace attribute own type");
331 if (old_type->domainSize() != new_type->domainSize()) {
332 GUM_ERROR(OperationNotAllowed,
333 "Cannot replace types with difference domain size");
335 if (!formulas__->contains(old_type.variable())) {
336 GUM_ERROR(NotFound,
"could not find variable " + old_type.name());
339 auto old = formulas__;
341 formulas__ =
new MultiDimArray< std::string >();
343 for (
auto var: old->variablesSequence()) {
344 if (var != &(old_type.variable())) {
345 formulas__->add(*var);
347 formulas__->add(new_type.variable());
351 Instantiation inst(formulas__), jnst(old);
353 for (inst.setFirst(), jnst.setFirst(); !(inst.end() || jnst.end());
354 inst.inc(), jnst.inc()) {
355 formulas__->set(inst, old->get(jnst));
365 GUM_ASSERT(inst.end() && jnst.end());
366 GUM_ASSERT(formulas__->contains(type__->variable()));
367 GUM_ASSERT(!formulas__->contains(new_type.variable()));
368 GUM_ASSERT(formulas__->contains(new_type.variable()));
371 template <
typename GUM_SCALAR >
372 PRMType* PRMFormAttribute< GUM_SCALAR >::type_() {
376 template <
typename GUM_SCALAR >
377 void PRMFormAttribute< GUM_SCALAR >::type_(PRMType* t) {
378 if (type__->variable().domainSize() != t->variable().domainSize()) {
379 GUM_ERROR(OperationNotAllowed,
380 "Cannot replace types with difference domain size");
382 auto old = formulas__;
384 formulas__ =
new MultiDimArray< std::string >();
386 for (
auto var: old->variablesSequence()) {
387 if (var != &(type__->variable())) {
388 formulas__->add(*var);
390 formulas__->add(t->variable());
394 Instantiation inst(formulas__), jnst(old);
396 for (inst.setFirst(), jnst.setFirst(); !(inst.end() || jnst.end());
397 inst.inc(), jnst.inc()) {
398 formulas__->set(inst, old->get(jnst));
410 GUM_ASSERT(formulas__->contains(type__->variable()));
411 GUM_ASSERT(inst.end() && jnst.end());