aGrUM  0.20.3
a C++ library for (probabilistic) graphical models
fmdpFactory_tpl.h
Go to the documentation of this file.
1 /**
2  *
3  * Copyright (c) 2005-2021 by 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 Template Implementation of the FMDPFactory class.
25  *
26  * @author Pierre-Henri WUILLEMIN(@LIP6) and Jean-Christophe MAGNAN and Christophe
27  * GONZALES(@AMU)
28  */
29 
30 #include <agrum/FMDP/fmdpFactory.h>
31 
32 #include <agrum/tools/multidim/implementations/multiDimImplementation.h>
33 #include <agrum/tools/multidim/potential.h>
34 
35 
36 // #define FMDP_VERBOSITY(x) { if (isVerbose()) std::cerr << "[FMDP factory]
37 // "<< x << std::endl; }
38 
39 
40 namespace gum {
41 
42  /* ****************************************************************************************************
43  * **/
44  /* ** **/
45  /* ** Constructor &
46  * Destructor **/
47  /* ** **/
48  /* ****************************************************************************************************
49  * **/
50 
51 
52  // Default constructor.
53  // @param fmdp A pointer over the Factored Markov Decision Process filled by
54  // this factory.
55 
56  template < typename GUM_SCALAR >
57  INLINE FMDPFactory< GUM_SCALAR >::FMDPFactory(FMDP< GUM_SCALAR >* fmdp) : _fmdp_(fmdp) {
59 
61  resetVerbose();
62  _actionIdcpt_ = 1;
63  }
64 
65 
66  // Destructor
67 
68  template < typename GUM_SCALAR >
71  }
72 
73  /* ****************************************************************************************************
74  * **/
75  /* ** **/
76  /* ** Getter and
77  * setters **/
78  /* ** **/
79  /* ****************************************************************************************************
80  * **/
81 
82 
83  // Returns the IBayesNet created by this factory.
84 
85  template < typename GUM_SCALAR >
87  if (state() != FMDPfactory_state::NONE)
89  "Illegal state to return the factored "
90  "markov decision process: it is not yet "
91  "finished.");
92 
93  return _fmdp_;
94  }
95 
96 
97  // Returns the current state of the factory.
98 
99  template < typename GUM_SCALAR >
101  // This is ok because there is alway at least the state
102  // FMDPfactory_state::NONE in the stack.
103  return _states_.back();
104  }
105 
106 
107  // Returns a constant reference on a variable given it's name.
108  // @throw NotFound Raised if no variable matches the name.
109 
110  template < typename GUM_SCALAR >
111  INLINE const DiscreteVariable*
113  for (const auto& elt: _varNameMap_)
114  if (elt.first.compare(name) == 0) return elt.second;
115 
117 
118  return nullptr;
119  }
120 
121 
122  /* ****************************************************************************************************
123  * **/
124  /* ** **/
125  /* ** Variable declaration methods (FMDPfactory_state::NONE <->
126  * FMDPfactory_state::VARIABLE) **/
127  /* ** **/
128  /* ****************************************************************************************************
129  * **/
130 
131 
132  // Tells the factory that we're in a variable declaration.
133 
134  template < typename GUM_SCALAR >
136  if (state() != FMDPfactory_state::NONE)
137  _illegalStateError_("startVariableDeclaration");
138  else {
140  _stringBag_.push_back("name");
141  _stringBag_.push_back("desc");
142  }
143 
144  // VERBOSITY ( " starting variable" );
145  }
146 
147 
148  // Tells the factory the current variable's name.
149 
150  template < typename GUM_SCALAR >
152  if (state() != FMDPfactory_state::VARIABLE)
153  _illegalStateError_("variableName");
154  else {
155  if (_varNameMap_.exists(name)) GUM_ERROR(DuplicateElement, "Name already used: " + name)
156 
157  _foo_flag_ = true;
158  _stringBag_[0] = name;
159  // VERBOSITY ( " -- variable " << name );
160  }
161  }
162 
163 
164  // Tells the factory the current variable's description.
165 
166  template < typename GUM_SCALAR >
168  if (state() != FMDPfactory_state::VARIABLE)
169  _illegalStateError_("variableDescription");
170  else {
171  _bar_flag_ = true;
172  _stringBag_[1] = desc;
173  }
174  }
175 
176 
177  // Adds a modality to the current variable.
178  // @throw DuplicateElement If the current variable already has a modality
179  // with the same name.
180 
181  template < typename GUM_SCALAR >
183  if (state() != FMDPfactory_state::VARIABLE)
184  _illegalStateError_("addModality");
185  else {
188  }
189  }
190 
191 
192  // Check if in _stringBag_ there is no other modality with the same name.
193 
194  template < typename GUM_SCALAR >
196  for (size_t i = 2; i < _stringBag_.size(); ++i)
197  if (mod == _stringBag_[i])
198  GUM_ERROR(DuplicateElement, "Modality" << mod << " already exists.")
199  }
200 
201 
202  // Tells the factory that we're out of a variable declaration.
203 
204  template < typename GUM_SCALAR >
206  if (state() != FMDPfactory_state::VARIABLE)
207  _illegalStateError_("endVariableDeclaration");
208  else if (_foo_flag_ && (_stringBag_.size() > 3)) {
210  = new LabelizedVariable(_stringBag_[0], (_bar_flag_) ? _stringBag_[1] : "", 0);
211 
212  for (size_t i = 2; i < _stringBag_.size(); ++i) {
214  }
215 
219 
220  _resetParts_();
221  _states_.pop_back();
222 
223  // VERBOSITY ( " variable " << var->name() << " OK" );
224 
225  } else {
227  msg << "Not enough modalities (";
228 
229  if (_stringBag_.size() > 2)
230  msg << _stringBag_.size() - 2;
231  else
232  msg << 0;
233 
234  msg << ") declared for variable ";
235 
236  if (_foo_flag_)
237  msg << _stringBag_[0];
238  else
239  msg << "unknown";
240 
241  _resetParts_();
242  _states_.pop_back();
243 
245  }
246  }
247 
248 
249  /* ****************************************************************************************************
250  * **/
251  /* ** **/
252  /* ** Action declaration methods (FMDPfactory_state::NONE <->
253  * FMDPfactory_state::ACTION) **/
254  /* ** **/
255  /* ****************************************************************************************************
256  * **/
257 
258 
259  // Tells the factory that we're declaring action
260 
261  template < typename GUM_SCALAR >
263  if (state() != FMDPfactory_state::NONE)
264  _illegalStateError_("startActionDeclaration");
265  else {
266  _foo_flag_ = true;
268  }
269 
270  // VERBOSITY ( "starting action declaration" );
271  }
272 
273 
274  // Tells the factory to add an action
275 
276  template < typename GUM_SCALAR >
278  if (state() != FMDPfactory_state::ACTION)
279  _illegalStateError_("addAction");
280  else {
283  }
284  }
285 
286 
287  // Tells the factory that we're out of an action declaration.
288 
289  template < typename GUM_SCALAR >
291  if (state() != FMDPfactory_state::ACTION)
292  _illegalStateError_("endActionDeclaration");
293  else {
294  _states_.pop_back();
295  _resetParts_();
296  }
297 
298  // VERBOSITY ( "action OK" );
299  }
300 
301 
302  /* ****************************************************************************************************
303  * **/
304  /* ** **/
305  /* ** Transition declaration methods **/
306  /* ** (FMDPfactory_state::NONE <-> FMDPfactory_state::TRANSITION <->
307  * FMDPfactory_state::ACTION) **/
308  /* ** **/
309  /* ****************************************************************************************************
310  * **/
311 
312 
313  // Tells the factory that we're declaring transition
314 
315  template < typename GUM_SCALAR >
318  _illegalStateError_("startTransitionDeclaration");
319  else
321 
322  // VERBOSITY ( "starting transition declaration" );
324  }
325 
326 
327  // Tells the factory to add an action
328 
329  template < typename GUM_SCALAR >
333  = reinterpret_cast< const MultiDimImplementation< GUM_SCALAR >* >(transition);
334 
336  _illegalStateError_("addTransition");
337  else if (_foo_flag_)
339  else
341  }
342 
343 
344  // Tells the factory to add a transition table to the current fmdp.
345  // This transition table will be extracted from incorporated
346  // multiDimFunctionGraph.
347 
348  template < typename GUM_SCALAR >
351  _illegalStateError_("addTransition");
352  else {
353  this->_finalizeFunctionGraph_();
354 
355  if (_foo_flag_) {
356  this->_FunctionGraph_->setTableName("ACTION :" + _stringBag_[0] + " - VARIABLE : " + var);
358  _varNameMap_[var],
359  this->_FunctionGraph_);
360  } else {
362  }
363  }
364  }
365 
366 
367  // Tells the factory that we're out of a transition declaration.
368 
369  template < typename GUM_SCALAR >
372  _illegalStateError_("endTransitionDeclaration");
373  else
374  _states_.pop_back();
375 
376  // VERBOSITY ( "transition OK" );
377  }
378 
379 
380  /* ****************************************************************************************************
381  * **/
382  /* ** **/
383  /* ** Cost declaration methods **/
384  /* ** (FMDPfactory_state::NONE <-> FMDPfactory_state::COST <->
385  * FMDPfactory_state::ACTION) **/
386  /* ** **/
387  /* ****************************************************************************************************
388  * **/
389 
390 
391  // Tells the factory that we're declaring cost
392 
393  template < typename GUM_SCALAR >
396  _illegalStateError_("startTransitionDeclaration");
397  else
399 
400  // VERBOSITY ( "starting Cost declaration" );
402  }
403 
404 
405  // Tells the factory to add a cost
406 
407  template < typename GUM_SCALAR >
410  = reinterpret_cast< const MultiDimImplementation< GUM_SCALAR >* >(cost);
411 
412  if (state() != FMDPfactory_state::COST)
413  _illegalStateError_("addCost");
414  else if (_foo_flag_)
416  else
417  _fmdp_->addCost(c);
418  }
419 
420 
421  // Tells the factory to add a cost
422  // This cost table will be extracted from incorporated multiDimFunctionGraph.
423 
424  template < typename GUM_SCALAR >
426  if (state() != FMDPfactory_state::COST)
427  _illegalStateError_("addCost");
428  else {
429  this->_finalizeFunctionGraph_();
430 
431  if (_foo_flag_)
433  else
435  }
436  }
437 
438 
439  // Tells the factory that we're out of a cost declaration.
440 
441  template < typename GUM_SCALAR >
443  if (state() != FMDPfactory_state::COST)
444  _illegalStateError_("endCostDeclaration");
445  else
446  _states_.pop_back();
447 
448  // VERBOSITY ( "Cost OK" );
449  }
450 
451 
452  /* ****************************************************************************************************
453  * **/
454  /* ** **/
455  /* ** Reward declaration methods **/
456  /* ** (FMDPfactory_state::NONE <-> FMDPfactory_state::REWARD <->
457  * FMDPfactory_state::ACTION) **/
458  /* ** **/
459  /* ****************************************************************************************************
460  * **/
461 
462 
463  // Tells the factory that we're declaring reward
464 
465  template < typename GUM_SCALAR >
468  _illegalStateError_("startRewardDeclaration");
469  else
471 
472  // VERBOSITY ( "starting reward declaration" );
474  }
475 
476 
477  // Tells the factory that we're in a reward declaration mode where the global
478  // reward diagram is an operation between simplier dd
479 
480  template < typename GUM_SCALAR >
482  _foo_flag_ = true;
485  }
486 
487 
488  // Tells the factory to add a reward
489 
490  template < typename GUM_SCALAR >
493  = reinterpret_cast< const MultiDimImplementation< GUM_SCALAR >* >(reward);
494 
495  if (state() != FMDPfactory_state::REWARD)
496  _illegalStateError_("addReward");
497  else
498  _fmdp_->addReward(r);
499  }
500 
501 
502  // Tells the factory to add a reward
503  // This reward table will be extracted from incorporated
504  // multiDimFunctionGraph.
505 
506  template < typename GUM_SCALAR >
508  if (state() != FMDPfactory_state::REWARD)
509  _illegalStateError_("addReward");
510  else {
511  this->_finalizeFunctionGraph_();
512  _FunctionGraph_->setTableName("Reward");
513 
514  if (_foo_flag_)
516  else
518  }
519  }
520 
521 
522  // Tells the factory that we're out of a reward declaration.
523 
524  template < typename GUM_SCALAR >
526  if (state() != FMDPfactory_state::REWARD)
527  _illegalStateError_("endRewardDeclaration");
528  else {
529  if (_foo_flag_) {
530  MultiDimImplementation< GUM_SCALAR >* res = nullptr;
532 
533  for (const auto elt: _ddBag_) {
534  temp = res;
535 
536  switch (_stringBag_[0][0]) {
537  case '+':
539  break;
540 
541  case '-':
543  break;
544 
545  case '*':
547  break;
548 
549  case '/':
551  break;
552 
553  default:
554  break;
555  }
556 
557  delete elt;
558 
559  if (temp != nullptr) delete temp;
560  }
561  reinterpret_cast< MultiDimFunctionGraph< GUM_SCALAR >* >(res)->setTableName("Reward");
562  _fmdp_->addReward(res);
563  }
564 
565  _resetParts_();
566  _states_.pop_back();
567  }
568  // VERBOSITY ( "reward OK" );
569  }
570 
571 
572  /* ****************************************************************************************************
573  * **/
574  /* ** **/
575  /* ** Discount declaration methods **/
576  /* ** (FMDPfactory_state::NONE <-> FMDPfactory_state::DISCOUNT <->
577  * FMDPfactory_state::ACTION) **/
578  /* ** **/
579  /* ****************************************************************************************************
580  * **/
581 
582 
583  // Tells the factory that we're declaring discount
584  template < typename GUM_SCALAR >
586  if (state() != FMDPfactory_state::NONE)
587  _illegalStateError_("startDiscountDeclaration");
588  else
590 
591  // VERBOSITY ( "starting discount declaration" );
592  }
593 
594 
595  // Tells the factory to add a discount
596 
597  template < typename GUM_SCALAR >
599  if (state() != FMDPfactory_state::DISCOUNT) _illegalStateError_("addDiscount");
600  // else
601  // _fmdp_->setDiscount ( ( GUM_SCALAR ) discount );
602  }
603 
604 
605  // Tells the factory that we're out of a discount declaration.
606 
607  template < typename GUM_SCALAR >
609  if (state() != FMDPfactory_state::DISCOUNT)
610  _illegalStateError_("endDiscountDeclaration");
611  else
612  _states_.pop_back();
613 
614  // VERBOSITY ( "discount OK" );
615  }
616 
617 
618  /* ****************************************************************************************************
619  * **/
620  /* ** **/
621  /* ** Discount declaration methods **/
622  /* ** (FMDPfactory_state::NONE <-> FMDPfactory_state::DISCOUNT <->
623  * FMDPfactory_state::ACTION) **/
624  /* ** **/
625  /* ****************************************************************************************************
626  * **/
627 
628 
629  // Insert in diagram a non terminal node
630 
631  template < typename GUM_SCALAR >
634  }
635 
636 
637  // Insert in diagram a terminal node
638 
639  template < typename GUM_SCALAR >
642  }
643 
644 
645  // Insert an arc in diagram
646  template < typename GUM_SCALAR >
649  }
650 
651 
652  template < typename GUM_SCALAR >
655  }
656 
657  /* ****************************************************************************************************
658  * **/
659  /* ** **/
660  /* ** Various Private Methods **/
661  /* ** **/
662  /* ****************************************************************************************************
663  * **/
664 
665 
666  // Raise an OperationNotAllowed with the message "Illegal state."
667 
668  template < typename GUM_SCALAR >
670  std::string msg = "Illegal state call (";
671  msg += s;
672  msg += ") in state ";
673 
674  switch (state()) {
675  case FMDPfactory_state::NONE:
676  msg += "FMDPfactory_state::NONE";
677  break;
678 
680  msg += "FMDPfactory_state::VARIABLE";
681  break;
682 
684  msg += "FMDPfactory_state::ACTION";
685  break;
686 
688  msg += "FMDPfactory_state::TRANSITION";
689  break;
690 
691  case FMDPfactory_state::COST:
692  msg += "FMDPfactory_state::COST";
693  break;
694 
696  msg += "FMDPfactory_state::REWARD";
697  break;
698 
700  msg += "FMDPfactory_state::DISCOUNT";
701  break;
702 
703  default:
704  msg += "Unknown state";
705  }
706 
708  }
709 
710 
711  // Reset the different parts used to constructed the IBayesNet.
712 
713  template < typename GUM_SCALAR >
715  _foo_flag_ = false;
716  _bar_flag_ = false;
717  _stringBag_.clear();
718  _ddBag_.clear();
719  }
720 
721 
722  template < typename GUM_SCALAR >
725  // Recopie des variables principales dans le graphe de décision
726  for (auto varIter = _fmdp_->beginVariables(); varIter != _fmdp_->endVariables(); ++varIter) {
728  }
729 
730  // Recopie des version primes des variables dans le graphe de décision
731  for (auto varIter = _fmdp_->beginVariables(); varIter != _fmdp_->endVariables(); ++varIter) {
733  }
734  }
735 
736 
737  template < typename GUM_SCALAR >
739  this->_FunctionGraph_->manager()->reduce();
740  this->_FunctionGraph_->manager()->clean();
741  }
742 
743  //~ ==============
744  //~ // Check if a variable with the given name exists, if not raise an
745  // NotFound
746  //~ // exception.
747  //~ ==============
748  //~ template<typename GUM_SCALAR> INLINE
749  //~ void
750  //~ FMDPFactory<GUM_SCALAR>:: _checkVariableName_ ( const std::string& name ) {
751  //~ if ( ! _varNameMap_.exists ( name ) )
752  //~ GUM_ERROR ( NotFound, name )
753  //~ }
754 
755 
756  // Copy operator is illegal, use only copy constructor.
757 
758  template < typename GUM_SCALAR >
761  GUM_ERROR(FatalError, "Illegal!")
762  // For noisy compilers
763  return *this;
764  }
765 } /* namespace gum */
INLINE void emplace(Args &&... args)
Definition: set_tpl.h:643