aGrUM  0.20.2
a C++ library for (probabilistic) graphical models
fmdpFactory_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 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) :
58  fmdp__(fmdp) {
60 
62  resetVerbose();
63  actionIdcpt__ = 1;
64  }
65 
66 
67  // Destructor
68 
69  template < typename GUM_SCALAR >
72  }
73 
74  /* ****************************************************************************************************
75  * **/
76  /* ** **/
77  /* ** Getter and
78  * setters **/
79  /* ** **/
80  /* ****************************************************************************************************
81  * **/
82 
83 
84  // Returns the IBayesNet created by this factory.
85 
86  template < typename GUM_SCALAR >
88  if (state() != FMDPfactory_state::NONE)
90  "Illegal state to return the factored "
91  "markov decision process: it is not yet "
92  "finished.");
93 
94  return fmdp__;
95  }
96 
97 
98  // Returns the current state of the factory.
99 
100  template < typename GUM_SCALAR >
102  // This is ok because there is alway at least the state
103  // FMDPfactory_state::NONE in the stack.
104  return states__.back();
105  }
106 
107 
108  // Returns a constant reference on a variable given it's name.
109  // @throw NotFound Raised if no variable matches the name.
110 
111  template < typename GUM_SCALAR >
112  INLINE const DiscreteVariable*
114  for (const auto& elt: varNameMap__)
115  if (elt.first.compare(name) == 0) return elt.second;
116 
118 
119  return nullptr;
120  }
121 
122 
123  /* ****************************************************************************************************
124  * **/
125  /* ** **/
126  /* ** Variable declaration methods (FMDPfactory_state::NONE <->
127  * FMDPfactory_state::VARIABLE) **/
128  /* ** **/
129  /* ****************************************************************************************************
130  * **/
131 
132 
133  // Tells the factory that we're in a variable declaration.
134 
135  template < typename GUM_SCALAR >
137  if (state() != FMDPfactory_state::NONE)
138  illegalStateError__("startVariableDeclaration");
139  else {
141  stringBag__.push_back("name");
142  stringBag__.push_back("desc");
143  }
144 
145  // VERBOSITY ( " starting variable" );
146  }
147 
148 
149  // Tells the factory the current variable's name.
150 
151  template < typename GUM_SCALAR >
153  if (state() != FMDPfactory_state::VARIABLE)
154  illegalStateError__("variableName");
155  else {
156  if (varNameMap__.exists(name))
157  GUM_ERROR(DuplicateElement, "Name already used: " + name);
158 
159  foo_flag__ = true;
160  stringBag__[0] = name;
161  // VERBOSITY ( " -- variable " << name );
162  }
163  }
164 
165 
166  // Tells the factory the current variable's description.
167 
168  template < typename GUM_SCALAR >
169  INLINE void
171  if (state() != FMDPfactory_state::VARIABLE)
172  illegalStateError__("variableDescription");
173  else {
174  bar_flag__ = true;
175  stringBag__[1] = desc;
176  }
177  }
178 
179 
180  // Adds a modality to the current variable.
181  // @throw DuplicateElement If the current variable already has a modality
182  // with the same name.
183 
184  template < typename GUM_SCALAR >
186  if (state() != FMDPfactory_state::VARIABLE)
187  illegalStateError__("addModality");
188  else {
191  }
192  }
193 
194 
195  // Check if in stringBag__ there is no other modality with the same name.
196 
197  template < typename GUM_SCALAR >
198  INLINE void
200  for (size_t i = 2; i < stringBag__.size(); ++i)
201  if (mod == stringBag__[i])
202  GUM_ERROR(DuplicateElement, "Modality" << mod << " already exists.");
203  }
204 
205 
206  // Tells the factory that we're out of a variable declaration.
207 
208  template < typename GUM_SCALAR >
210  if (state() != FMDPfactory_state::VARIABLE)
211  illegalStateError__("endVariableDeclaration");
212  else if (foo_flag__ && (stringBag__.size() > 3)) {
215  (bar_flag__) ? stringBag__[1] : "",
216  0);
217 
218  for (size_t i = 2; i < stringBag__.size(); ++i) {
220  }
221 
225  fmdp__->main2prime(var));
226 
227  resetParts__();
228  states__.pop_back();
229 
230  // VERBOSITY ( " variable " << var->name() << " OK" );
231 
232  } else {
234  msg << "Not enough modalities (";
235 
236  if (stringBag__.size() > 2)
237  msg << stringBag__.size() - 2;
238  else
239  msg << 0;
240 
241  msg << ") declared for variable ";
242 
243  if (foo_flag__)
244  msg << stringBag__[0];
245  else
246  msg << "unknown";
247 
248  resetParts__();
249  states__.pop_back();
250 
252  }
253  }
254 
255 
256  /* ****************************************************************************************************
257  * **/
258  /* ** **/
259  /* ** Action declaration methods (FMDPfactory_state::NONE <->
260  * FMDPfactory_state::ACTION) **/
261  /* ** **/
262  /* ****************************************************************************************************
263  * **/
264 
265 
266  // Tells the factory that we're declaring action
267 
268  template < typename GUM_SCALAR >
270  if (state() != FMDPfactory_state::NONE)
271  illegalStateError__("startActionDeclaration");
272  else {
273  foo_flag__ = true;
275  }
276 
277  // VERBOSITY ( "starting action declaration" );
278  }
279 
280 
281  // Tells the factory to add an action
282 
283  template < typename GUM_SCALAR >
285  if (state() != FMDPfactory_state::ACTION)
286  illegalStateError__("addAction");
287  else {
290  }
291  }
292 
293 
294  // Tells the factory that we're out of an action declaration.
295 
296  template < typename GUM_SCALAR >
298  if (state() != FMDPfactory_state::ACTION)
299  illegalStateError__("endActionDeclaration");
300  else {
301  states__.pop_back();
302  resetParts__();
303  }
304 
305  // VERBOSITY ( "action OK" );
306  }
307 
308 
309  /* ****************************************************************************************************
310  * **/
311  /* ** **/
312  /* ** Transition declaration methods **/
313  /* ** (FMDPfactory_state::NONE <-> FMDPfactory_state::TRANSITION <->
314  * FMDPfactory_state::ACTION) **/
315  /* ** **/
316  /* ****************************************************************************************************
317  * **/
318 
319 
320  // Tells the factory that we're declaring transition
321 
322  template < typename GUM_SCALAR >
325  illegalStateError__("startTransitionDeclaration");
326  else
328 
329  // VERBOSITY ( "starting transition declaration" );
331  }
332 
333 
334  // Tells the factory to add an action
335 
336  template < typename GUM_SCALAR >
338  const std::string& var,
341  = reinterpret_cast< const MultiDimImplementation< GUM_SCALAR >* >(
342  transition);
343 
345  illegalStateError__("addTransition");
346  else if (foo_flag__)
348  varNameMap__[var],
349  t);
350  else
352  }
353 
354 
355  // Tells the factory to add a transition table to the current fmdp.
356  // This transition table will be extracted from incorporated
357  // multiDimFunctionGraph.
358 
359  template < typename GUM_SCALAR >
362  illegalStateError__("addTransition");
363  else {
364  this->finalizeFunctionGraph__();
365 
366  if (foo_flag__) {
367  this->FunctionGraph__->setTableName("ACTION :" + stringBag__[0]
368  + " - VARIABLE : " + var);
370  varNameMap__[var],
371  this->FunctionGraph__);
372  } else {
374  }
375  }
376  }
377 
378 
379  // Tells the factory that we're out of a transition declaration.
380 
381  template < typename GUM_SCALAR >
384  illegalStateError__("endTransitionDeclaration");
385  else
386  states__.pop_back();
387 
388  // VERBOSITY ( "transition OK" );
389  }
390 
391 
392  /* ****************************************************************************************************
393  * **/
394  /* ** **/
395  /* ** Cost declaration methods **/
396  /* ** (FMDPfactory_state::NONE <-> FMDPfactory_state::COST <->
397  * FMDPfactory_state::ACTION) **/
398  /* ** **/
399  /* ****************************************************************************************************
400  * **/
401 
402 
403  // Tells the factory that we're declaring cost
404 
405  template < typename GUM_SCALAR >
408  illegalStateError__("startTransitionDeclaration");
409  else
411 
412  // VERBOSITY ( "starting Cost declaration" );
414  }
415 
416 
417  // Tells the factory to add a cost
418 
419  template < typename GUM_SCALAR >
422  = reinterpret_cast< const MultiDimImplementation< GUM_SCALAR >* >(cost);
423 
424  if (state() != FMDPfactory_state::COST)
425  illegalStateError__("addCost");
426  else if (foo_flag__)
428  else
429  fmdp__->addCost(c);
430  }
431 
432 
433  // Tells the factory to add a cost
434  // This cost table will be extracted from incorporated multiDimFunctionGraph.
435 
436  template < typename GUM_SCALAR >
438  if (state() != FMDPfactory_state::COST)
439  illegalStateError__("addCost");
440  else {
441  this->finalizeFunctionGraph__();
442 
443  if (foo_flag__)
445  this->FunctionGraph__);
446  else
448  }
449  }
450 
451 
452  // Tells the factory that we're out of a cost declaration.
453 
454  template < typename GUM_SCALAR >
456  if (state() != FMDPfactory_state::COST)
457  illegalStateError__("endCostDeclaration");
458  else
459  states__.pop_back();
460 
461  // VERBOSITY ( "Cost OK" );
462  }
463 
464 
465  /* ****************************************************************************************************
466  * **/
467  /* ** **/
468  /* ** Reward declaration methods **/
469  /* ** (FMDPfactory_state::NONE <-> FMDPfactory_state::REWARD <->
470  * FMDPfactory_state::ACTION) **/
471  /* ** **/
472  /* ****************************************************************************************************
473  * **/
474 
475 
476  // Tells the factory that we're declaring reward
477 
478  template < typename GUM_SCALAR >
481  illegalStateError__("startRewardDeclaration");
482  else
484 
485  // VERBOSITY ( "starting reward declaration" );
487  }
488 
489 
490  // Tells the factory that we're in a reward declaration mode where the global
491  // reward diagram is an operation between simplier dd
492 
493  template < typename GUM_SCALAR >
494  INLINE void
496  foo_flag__ = true;
499  }
500 
501 
502  // Tells the factory to add a reward
503 
504  template < typename GUM_SCALAR >
505  INLINE void
508  = reinterpret_cast< const MultiDimImplementation< GUM_SCALAR >* >(reward);
509 
510  if (state() != FMDPfactory_state::REWARD)
511  illegalStateError__("addReward");
512  else
513  fmdp__->addReward(r);
514  }
515 
516 
517  // Tells the factory to add a reward
518  // This reward table will be extracted from incorporated
519  // multiDimFunctionGraph.
520 
521  template < typename GUM_SCALAR >
523  if (state() != FMDPfactory_state::REWARD)
524  illegalStateError__("addReward");
525  else {
526  this->finalizeFunctionGraph__();
527  FunctionGraph__->setTableName("Reward");
528 
529  if (foo_flag__)
531  else
533  }
534  }
535 
536 
537  // Tells the factory that we're out of a reward declaration.
538 
539  template < typename GUM_SCALAR >
541  if (state() != FMDPfactory_state::REWARD)
542  illegalStateError__("endRewardDeclaration");
543  else {
544  if (foo_flag__) {
545  MultiDimImplementation< GUM_SCALAR >* res = nullptr;
547 
548  for (const auto elt: ddBag__) {
549  temp = res;
550 
551  switch (stringBag__[0][0]) {
552  case '+':
554  break;
555 
556  case '-':
558  break;
559 
560  case '*':
562  break;
563 
564  case '/':
566  break;
567 
568  default:
569  break;
570  }
571 
572  delete elt;
573 
574  if (temp != nullptr) delete temp;
575  }
576  reinterpret_cast< MultiDimFunctionGraph< GUM_SCALAR >* >(res)
577  ->setTableName("Reward");
578  fmdp__->addReward(res);
579  }
580 
581  resetParts__();
582  states__.pop_back();
583  }
584  // VERBOSITY ( "reward OK" );
585  }
586 
587 
588  /* ****************************************************************************************************
589  * **/
590  /* ** **/
591  /* ** Discount declaration methods **/
592  /* ** (FMDPfactory_state::NONE <-> FMDPfactory_state::DISCOUNT <->
593  * FMDPfactory_state::ACTION) **/
594  /* ** **/
595  /* ****************************************************************************************************
596  * **/
597 
598 
599  // Tells the factory that we're declaring discount
600  template < typename GUM_SCALAR >
602  if (state() != FMDPfactory_state::NONE)
603  illegalStateError__("startDiscountDeclaration");
604  else
606 
607  // VERBOSITY ( "starting discount declaration" );
608  }
609 
610 
611  // Tells the factory to add a discount
612 
613  template < typename GUM_SCALAR >
615  if (state() != FMDPfactory_state::DISCOUNT) illegalStateError__("addDiscount");
616  // else
617  // fmdp__->setDiscount ( ( GUM_SCALAR ) discount );
618  }
619 
620 
621  // Tells the factory that we're out of a discount declaration.
622 
623  template < typename GUM_SCALAR >
625  if (state() != FMDPfactory_state::DISCOUNT)
626  illegalStateError__("endDiscountDeclaration");
627  else
628  states__.pop_back();
629 
630  // VERBOSITY ( "discount OK" );
631  }
632 
633 
634  /* ****************************************************************************************************
635  * **/
636  /* ** **/
637  /* ** Discount declaration methods **/
638  /* ** (FMDPfactory_state::NONE <-> FMDPfactory_state::DISCOUNT <->
639  * FMDPfactory_state::ACTION) **/
640  /* ** **/
641  /* ****************************************************************************************************
642  * **/
643 
644 
645  // Insert in diagram a non terminal node
646 
647  template < typename GUM_SCALAR >
648  INLINE NodeId
651  }
652 
653 
654  // Insert in diagram a terminal node
655 
656  template < typename GUM_SCALAR >
659  }
660 
661 
662  // Insert an arc in diagram
663  template < typename GUM_SCALAR >
664  INLINE void
667  }
668 
669 
670  template < typename GUM_SCALAR >
673  }
674 
675  /* ****************************************************************************************************
676  * **/
677  /* ** **/
678  /* ** Various Private Methods **/
679  /* ** **/
680  /* ****************************************************************************************************
681  * **/
682 
683 
684  // Raise an OperationNotAllowed with the message "Illegal state."
685 
686  template < typename GUM_SCALAR >
687  INLINE void
689  std::string msg = "Illegal state call (";
690  msg += s;
691  msg += ") in state ";
692 
693  switch (state()) {
694  case FMDPfactory_state::NONE:
695  msg += "FMDPfactory_state::NONE";
696  break;
697 
699  msg += "FMDPfactory_state::VARIABLE";
700  break;
701 
703  msg += "FMDPfactory_state::ACTION";
704  break;
705 
707  msg += "FMDPfactory_state::TRANSITION";
708  break;
709 
710  case FMDPfactory_state::COST:
711  msg += "FMDPfactory_state::COST";
712  break;
713 
715  msg += "FMDPfactory_state::REWARD";
716  break;
717 
719  msg += "FMDPfactory_state::DISCOUNT";
720  break;
721 
722  default:
723  msg += "Unknown state";
724  }
725 
727  }
728 
729 
730  // Reset the different parts used to constructed the IBayesNet.
731 
732  template < typename GUM_SCALAR >
734  foo_flag__ = false;
735  bar_flag__ = false;
736  stringBag__.clear();
737  ddBag__.clear();
738  }
739 
740 
741  template < typename GUM_SCALAR >
743  this->FunctionGraph__
745  // Recopie des variables principales dans le graphe de décision
746  for (auto varIter = fmdp__->beginVariables();
748  ++varIter) {
750  }
751 
752  // Recopie des version primes des variables dans le graphe de décision
753  for (auto varIter = fmdp__->beginVariables();
755  ++varIter) {
757  }
758  }
759 
760 
761  template < typename GUM_SCALAR >
763  this->FunctionGraph__->manager()->reduce();
764  this->FunctionGraph__->manager()->clean();
765  }
766 
767  //~ ==============
768  //~ // Check if a variable with the given name exists, if not raise an
769  // NotFound
770  //~ // exception.
771  //~ ==============
772  //~ template<typename GUM_SCALAR> INLINE
773  //~ void
774  //~ FMDPFactory<GUM_SCALAR>::checkVariableName__ ( const std::string& name ) {
775  //~ if ( !varNameMap__.exists ( name ) )
776  //~ GUM_ERROR ( NotFound, name );
777  //~ }
778 
779 
780  // Copy operator is illegal, use only copy constructor.
781 
782  template < typename GUM_SCALAR >
784  const FMDPFactory< GUM_SCALAR >& source) {
785  GUM_ERROR(FatalError, "Illegal!");
786  // For noisy compilers
787  return *this;
788  }
789 } /* namespace gum */
INLINE void emplace(Args &&... args)
Definition: set_tpl.h:669