aGrUM  0.20.2
a C++ library for (probabilistic) graphical models
PRMSystem_tpl.h
Go to the documentation of this file.
1 /**
2  *
3  * Copyright 2005-2020 Pierre-Henri WUILLEMIN(@LIP6) & Christophe GONZALES(@AMU)
4  * info_at_agrum_dot_org
5  *
6  * This library is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU Lesser General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public License
17  * along with this library. If not, see <http://www.gnu.org/licenses/>.
18  *
19  */
20 
21 
22 /**
23  * @file
24  * @brief Inline implementation of PRMSystem.
25  *
26  * @author Lionel TORTI and Pierre-Henri WUILLEMIN(@LIP6)
27  *
28  */
29 #include <agrum/PRM/elements/PRMSystem.h>
30 
31 #include <agrum/PRM/elements/PRMInstance.h>
32 
33 #include <agrum/tools/multidim/aggregators/exists.h>
34 #include <agrum/tools/multidim/aggregators/forall.h>
35 #include <agrum/tools/multidim/aggregators/max.h>
36 #include <agrum/tools/multidim/aggregators/min.h>
37 
38 namespace gum {
39  namespace prm {
40  template < typename GUM_SCALAR >
41  PRMSystem< GUM_SCALAR >::PRMSystem(const std::string& name) : PRMObject(name) {
42  GUM_CONSTRUCTOR(PRMSystem);
43  }
44 
45  template < typename GUM_SCALAR >
48 
49  for (const auto& elt: *this)
50  delete elt.second;
51 
52  for (const auto& elt: instanceMap_)
53  delete elt.second;
54 
55  for (const auto& elt: arrayMap_)
56  delete elt.second.second;
57  }
58 
59  template < typename GUM_SCALAR >
65  }
66 
67  template < typename GUM_SCALAR >
69  if (nameMap_.exists(i->name())) {
70  GUM_ERROR(
72  "an Instance<GUM_SCALAR> with the same is already in this System");
73  }
74 
77  nameMap_.insert(i->name(), i);
78 
79  try {
80  instanceMap_[&(i->type())]->insert(i);
81  } catch (NotFound&) {
82  instanceMap_.insert(&(i->type()), new Set< PRMInstance< GUM_SCALAR >* >());
83  instanceMap_[&(i->type())]->insert(i);
84  }
85 
86  return id;
87  }
88 
89  template < typename GUM_SCALAR >
93  factory.addNetworkProperty("name", name());
95 
96  // Adding nodes
98  ++iter) {
100  }
101 
102  // Adding arcs and filling CPTs
103  for (PRMSystem< GUM_SCALAR >::const_iterator iter = begin(); iter != end();
104  ++iter) {
105  groundRef__(*(iter.val()), factory);
106  }
107  }
108 
109  template < typename GUM_SCALAR >
111  const PRMInstance< GUM_SCALAR >& instance,
112  BayesNetFactory< GUM_SCALAR >& factory) const {
113  for (const auto node: instance.type().containerDag()) {
114  // Working a Class<GUM_SCALAR> level because PRMAggregate<GUM_SCALAR>
115  // are
116  // instantiated as PRMAttribute<GUM_SCALAR> in an
117  // PRMInstance<GUM_SCALAR>
118  switch (instance.type().get(node).elt_type()) {
120  // TODO: make a special case for noisy-or
122  elt_name << instance.name() << "."
123  << instance.type().get(node).safeName();
125  var->setName(elt_name.str());
126  factory.setVariable(*var); // var is copied by the factory
127  delete var;
128  break;
129  }
130 
133  elt_name << instance.name() << "."
134  << instance.type().get(node).safeName();
136  break;
137  }
138 
139  default:
140  break;
141  /* Do nothing */;
142  }
143  }
144  }
145 
146  template < typename GUM_SCALAR >
148  const PRMClassElement< GUM_SCALAR >& elt,
149  const std::string& name,
150  BayesNetFactory< GUM_SCALAR >& factory) const {
153 
155 
157 
159 
160  switch (var_type) {
161  case VarType::Labelized: {
162  const auto l = static_cast< const LabelizedVariable& >(agg_var);
163  for (Idx i = 0; i < l.domainSize(); ++i) {
165  }
166  break;
167  }
168  case VarType::Discretized: {
169  const auto d
170  = static_cast< const DiscretizedVariable< GUM_SCALAR >& >(agg_var);
171  for (Idx i = 0; i < d.domainSize(); ++i) {
172  factory.addTick(d.tick(i));
173  }
174  break;
175  }
176  case VarType::Range: {
177  const auto r = static_cast< const RangeVariable& >(agg_var);
178  factory.addMin(r.minVal());
179  factory.addMax(r.maxVal());
180  break;
181  }
182  case VarType::Continuous:
183  // Todo Error
184  break;
185  }
186 
187  const PRMAggregate< GUM_SCALAR >& agg
188  = static_cast< const PRMAggregate< GUM_SCALAR >& >(elt);
189 
190  switch (agg.agg_type()) {
193  new aggregator::Min< GUM_SCALAR >());
194  break;
195  }
196 
199  new aggregator::Max< GUM_SCALAR >());
200  break;
201  }
202 
205  new aggregator::Exists< GUM_SCALAR >(agg.label()));
206  break;
207  }
208 
211  new aggregator::Forall< GUM_SCALAR >(agg.label()));
212  break;
213  }
214 
217  new aggregator::Count< GUM_SCALAR >(agg.label()));
218  break;
219  }
220 
223  new aggregator::Median< GUM_SCALAR >());
224  break;
225  }
226 
229  new aggregator::Amplitude< GUM_SCALAR >());
230  break;
231  }
232 
235  break;
236  }
237 
240  new aggregator::And< GUM_SCALAR >());
241  break;
242  }
243 
246  new aggregator::Sum< GUM_SCALAR >());
247  break;
248  }
249 
250  default: {
251  GUM_ERROR(OperationNotAllowed, "Aggregator not handled yet");
252  break;
253  }
254  }
255 
257  }
258 
259  template < typename GUM_SCALAR >
261  const PRMInstance< GUM_SCALAR >& instance,
262  BayesNetFactory< GUM_SCALAR >& factory) const {
263  for (const auto& elt: instance) {
265  elt_name << instance.name() << "." << elt.second->safeName();
267 
268  for (const auto par:
270  switch (instance.type().get(par).elt_type()) {
274  parent_name << instance.name() << "."
275  << instance.get(par).safeName();
277  break;
278  }
279 
282  = static_cast< const PRMSlotChain< GUM_SCALAR >& >(
283  instance.type().get(par))
284  .lastElt()
285  .safeName();
286 
287  try {
288  for (const auto ref: instance.getInstances(par)) {
290  sBuff << ref->name() << "." << parent_name;
292  }
293  } catch (NotFound&) {
294  // No instances for this slotchain
295  }
296 
297  break;
298  }
299 
300  default:
301  break;
302  /* nothing to do by default */
303  }
304  }
305 
307 
308  // Checking if we need to ground the Potential (only for class level
309  // attributes since
310  // aggregates Potentials are generated)
314  }
315  }
316 
317  template < typename GUM_SCALAR >
319  const PRMInstance< GUM_SCALAR >& instance,
320  const PRMAttribute< GUM_SCALAR >& attr,
321  BayesNetFactory< GUM_SCALAR >& factory) const {
324  var_name << instance.name() << "." << attr.safeName();
326  &(factory.variable(var_name.str())));
327 
328  for (const auto parent: instance.type().containerDag().parents(attr.id())) {
329  switch (instance.type().get(parent).elt_type()) {
333  parent_name << instance.name() << "."
334  << instance.get(parent).safeName();
337  break;
338  }
339 
342  const PRMSlotChain< GUM_SCALAR >& sc
343  = static_cast< const PRMSlotChain< GUM_SCALAR >& >(
344  instance.type().get(parent));
345  parent_name << instance.getInstance(sc.id()).name() << "."
346  << sc.lastElt().safeName();
348  .get(sc.lastElt().safeName())
349  .type()
350  .variable()),
352  break;
353  }
354 
355  default: {
357  "invalid ClassElement<GUM_SCALAR> type as parent.");
358  break;
359  }
360  }
361  }
362 
363  // Copy Potential
364  // DO NOT USE MultiDimBijArray as they will wreck havok if you delete
365  // the prm befor its grounded BN (happens a lot in pyAgrum)
366  Potential< GUM_SCALAR >* p = new Potential< GUM_SCALAR >();
367  for (auto var: attr.cpf().variablesSequence()) {
368  p->add(*(bijection.second(var)));
369  }
371  for (inst.setFirst(), jnst.setFirst(); !(inst.end() || jnst.end());
372  inst.inc(), jnst.inc()) {
373  p->set(jnst, attr.cpf().get(inst));
374  }
375  GUM_ASSERT(inst.end() && jnst.end());
376  factory.setVariableCPT(var_name.str(), p, false);
377  }
378 
379  template < typename GUM_SCALAR >
381  PRMInstance< GUM_SCALAR >& i) {
382  return add(array, &i);
383  }
384 
385  template < typename GUM_SCALAR >
387  return skeleton_;
388  }
389 
390  template < typename GUM_SCALAR >
392  try {
393  return *(nodeIdMap_[id]);
394  } catch (NotFound&) {
395  GUM_ERROR(NotFound, "found no Instance<GUM_SCALAR> matching the given id");
396  }
397  }
398 
399  template < typename GUM_SCALAR >
400  INLINE const PRMInstance< GUM_SCALAR >&
402  try {
403  return *(nodeIdMap_[id]);
404  } catch (NotFound&) {
405  GUM_ERROR(NotFound, "found no Instance<GUM_SCALAR> matching the given id");
406  }
407  }
408 
409  template < typename GUM_SCALAR >
410  INLINE NodeId
412  try {
413  return nodeIdMap_.keyByVal(const_cast< PRMInstance< GUM_SCALAR >* >(&i));
414  } catch (NotFound&) {
415  GUM_ERROR(NotFound, "found no Instance<GUM_SCALAR> matching the given id");
416  }
417  }
418 
419  template < typename GUM_SCALAR >
421  return PRMObject::prm_type::SYSTEM;
422  }
423 
424  template < typename GUM_SCALAR >
426  return nodeIdMap_.size();
427  }
428 
429  template < typename GUM_SCALAR >
431  const PRMClass< GUM_SCALAR >& c) const {
432  return instanceMap_.exists(const_cast< PRMClass< GUM_SCALAR >* >(&c));
433  }
434 
435  template < typename GUM_SCALAR >
436  INLINE bool
438  return nameMap_.exists(name);
439  }
440 
441  template < typename GUM_SCALAR >
442  INLINE bool PRMSystem< GUM_SCALAR >::isArray(const std::string& name) const {
443  return arrayMap_.exists(name);
444  }
445 
446  template < typename GUM_SCALAR >
448  for (auto iter = begin(); iter != end(); ++iter) {
449  (*(iter.val())).instantiate();
450  }
451  }
452 
453  template < typename GUM_SCALAR >
456  try {
457  return *(nameMap_[name]);
458  } catch (NotFound&) {
460  "found no Instance<GUM_SCALAR> matching the given name");
461  }
462  }
463 
464  template < typename GUM_SCALAR >
465  INLINE const PRMInstance< GUM_SCALAR >&
466  PRMSystem< GUM_SCALAR >::get(const std::string& name) const {
467  try {
468  return *(nameMap_[name]);
469  } catch (NotFound&) {
471  "found no Instance<GUM_SCALAR> matching the given name");
472  }
473  }
474 
475  template < typename GUM_SCALAR >
476  INLINE const Set< PRMInstance< GUM_SCALAR >* >&
477 
479  try {
480  return *(instanceMap_[const_cast< PRMClass< GUM_SCALAR >* >(&type)]);
481  } catch (NotFound&) {
482  GUM_ERROR(
483  NotFound,
484  "the given Class<GUM_SCALAR> has no instantiation in this System");
485  }
486  }
487 
488  template < typename GUM_SCALAR >
489  INLINE const Sequence< PRMInstance< GUM_SCALAR >* >&
490 
492  try {
493  return *(arrayMap_[name].second);
494  } catch (NotFound&) {
495  GUM_ERROR(NotFound, "found no array matching the given name");
496  }
497  }
498 
499  template < typename GUM_SCALAR >
502  try {
503  return *(arrayMap_[name].first);
504  } catch (NotFound&) {
505  GUM_ERROR(NotFound, "found no array matching the given name");
506  }
507  }
508 
509  template < typename GUM_SCALAR >
512  try {
513  return *(arrayMap_[name].first);
514  } catch (NotFound&) {
515  GUM_ERROR(NotFound, "found no array matching the given name");
516  }
517  }
518 
519  template < typename GUM_SCALAR >
521  PRMInstance< GUM_SCALAR >* i) {
522  try {
523  if (i->type().isSubTypeOf(*(arrayMap_[array].first))) {
524  NodeId id = add(i);
526  return id;
527  } else {
529  "the given Instance<GUM_SCALAR> is of an incorrect "
530  "Class<GUM_SCALAR> type");
531  }
532  } catch (NotFound&) {
533  GUM_ERROR(NotFound, "found no array matching the given name");
534  }
535  }
536 
537  template < typename GUM_SCALAR >
539  const std::string& array,
541  if (arrayMap_.exists(array)) {
543  "an array '" << array << "' is already in this System");
544  }
545 
548  &type,
549  new Sequence< PRMInstance< GUM_SCALAR >* >()));
550  }
551 
552  template < typename GUM_SCALAR >
553  INLINE typename PRMSystem< GUM_SCALAR >::iterator
555  return nodeIdMap_.begin();
556  }
557 
558  template < typename GUM_SCALAR >
559  INLINE const typename PRMSystem< GUM_SCALAR >::iterator&
561  return nodeIdMap_.end();
562  }
563 
564  template < typename GUM_SCALAR >
566  PRMSystem< GUM_SCALAR >::begin() const {
567  return nodeIdMap_.begin();
568  }
569 
570  template < typename GUM_SCALAR >
571  INLINE const typename PRMSystem< GUM_SCALAR >::const_iterator&
572  PRMSystem< GUM_SCALAR >::end() const {
573  return nodeIdMap_.end();
574  }
575 
576  template < typename GUM_SCALAR >
579  try {
580  return arrayMap_[a].second->begin();
581  } catch (NotFound&) {
582  GUM_ERROR(NotFound, "found no array matching the given name");
583  }
584  }
585 
586  template < typename GUM_SCALAR >
587  INLINE const typename PRMSystem< GUM_SCALAR >::array_iterator&
589  try {
590  return arrayMap_[a].second->end();
591  } catch (NotFound&) {
592  GUM_ERROR(NotFound, "found no array matching the given name");
593  }
594  }
595 
596  template < typename GUM_SCALAR >
598  PRMSystem< GUM_SCALAR >::begin(const std::string& a) const {
599  try {
600  return arrayMap_[a].second->begin();
601  } catch (NotFound&) {
602  GUM_ERROR(NotFound, "found no array matching the given name");
603  }
604  }
605 
606  template < typename GUM_SCALAR >
607  INLINE const typename PRMSystem< GUM_SCALAR >::const_array_iterator&
608  PRMSystem< GUM_SCALAR >::end(const std::string& a) const {
609  try {
610  return arrayMap_[a].second->end();
611  } catch (NotFound&) {
612  GUM_ERROR(NotFound, "found no array matching the given name");
613  }
614  }
615 
616  template < typename GUM_SCALAR >
617  INLINE bool PRMSystem< GUM_SCALAR >::exists(const std::string& name) const {
618  return nameMap_.exists(name) || arrayMap_.exists(name);
619  }
620 
621  } /* namespace prm */
622 } /* namespace gum */
INLINE void emplace(Args &&... args)
Definition: set_tpl.h:669
ParamScopeData(const std::string &s, const PRMReferenceSlot< GUM_SCALAR > &ref, Idx d)