aGrUM  0.14.2
fmdp_tpl.h
Go to the documentation of this file.
1 /***************************************************************************
2  * Copyright (C) 2005 by Pierre-Henri WUILLEMIN et Christophe GONZALES *
3  * {prenom.nom}_at_lip6.fr *
4  * *
5  * This program is free software; you can redistribute it and/or modify *
6  * it under the terms of the GNU General Public License as published by *
7  * the Free Software Foundation; either version 2 of the License, or *
8  * (at your option) any later version. *
9  * *
10  * This program is distributed in the hope that it will be useful, *
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13  * GNU General Public License for more details. *
14  * *
15  * You should have received a copy of the GNU General Public License *
16  * along with this program; if not, write to the *
17  * Free Software Foundation, Inc., *
18  * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19  ***************************************************************************/
27 //======================================================================
28 #include <cstdio>
29 #include <iostream>
30 //======================================================================
31 #include <agrum/FMDP/fmdp.h>
32 //======================================================================
33 #define RECAST(x) reinterpret_cast< const MultiDimFunctionGraph< GUM_SCALAR >* >(x)
34 
35 namespace gum {
36 
37 
38  /* **************************************************************************************************
39  * **/
40  /* ** **/
41  /* ** Constructors / Destructors **/
42  /* ** **/
43  /* **************************************************************************************************
44  * **/
45 
46  // ===========================================================================
47  // Default constructor.
48  // ===========================================================================
49  template < typename GUM_SCALAR >
50  INLINE FMDP< GUM_SCALAR >::FMDP(bool onDestructionDeleteVar) {
51  GUM_CONSTRUCTOR(FMDP);
52  __onDestructionDeleteVars = onDestructionDeleteVar;
53 
54  // Default Action initialisation
55  __actionMap.insert(0, new std::string("DEFAULT"));
56  __actionTransitionTable.insert(0, new VarTransitionTable< GUM_SCALAR >());
57  __actionCostTable.insert(0, nullptr);
58  __actionRewardTable.insert(0, nullptr);
59  }
60 
61  // ===========================================================================
62  // Destructor.
63  // ===========================================================================
64  template < typename GUM_SCALAR >
66  // Action Transition Graph deletion
67  for (auto iterA = __actionTransitionTable.beginSafe();
68  iterA != __actionTransitionTable.endSafe();
69  ++iterA) {
70  if (iterA.val()) {
71  for (auto iterH = (iterA.val())->beginSafe();
72  iterH != (iterA.val())->endSafe();
73  ++iterH)
74  if (iterH.val()) delete iterH.val();
75  delete iterA.val();
76  }
77  }
78 
79  // Action cost graph deletion
80  for (auto iterA = __actionCostTable.beginSafe();
81  iterA != __actionCostTable.endSafe();
82  ++iterA)
83  if (iterA.val()) delete iterA.val();
84 
85  // Action reward graph deletion
86  for (auto iterA = __actionRewardTable.beginSafe();
87  iterA != __actionRewardTable.endSafe();
88  ++iterA)
89  if (iterA.val()) delete iterA.val();
90 
91  // Action Name deletion
92  for (auto iterId = __actionMap.beginSafe(); iterId != __actionMap.endSafe();
93  ++iterId)
94  delete iterId.second();
95 
96  // Primed Variables deletion
97  for (auto varIter = __main2primed.beginSafe();
98  varIter != __main2primed.endSafe();
99  ++varIter) {
100  delete varIter.second();
101  if (__onDestructionDeleteVars) delete varIter.first();
102  }
103 
104  GUM_DESTRUCTOR(FMDP);
105  }
106 
107 
108  /* **************************************************************************************************
109  * **/
110  /* ** **/
111  /* ** Variable Handling Methods. **/
112  /* ** **/
113  /* **************************************************************************************************
114  * **/
115 
116  // ===========================================================================
117  // Adds a variable to FMDP description
118  // @throw DuplicateElement if a similar variable already exists
119  // ===========================================================================
120  template < typename GUM_SCALAR >
122  if (__varSeq.exists(var))
124  " Variable " << var->name()
125  << " has already been inserted in FMDP.");
126 
127 
128  __varSeq.insert(var);
129 
130  // Prime version creation
131  DiscreteVariable* primeVar = var->clone();
132  primeVar->setName(var->name() + "'");
133  __main2primed.insert(var, primeVar);
134  }
135 
136 
137  /* **************************************************************************************************
138  * **/
139  /* ** **/
140  /* ** Variable Handling Methods. **/
141  /* ** **/
142  /* **************************************************************************************************
143  * **/
144 
145  // ===========================================================================
146  // Adds an action to FMDP description
147  // @throw DuplicateElement if an action with same name already exists
148  // ===========================================================================
149  template < typename GUM_SCALAR >
150  INLINE void FMDP< GUM_SCALAR >::addAction(Idx actionId,
151  const std::string& action) {
152  if (actionId == 0) GUM_ERROR(DuplicateElement, " Action Id 0 is reserved.");
153 
155  __actionMap.beginSafe();
156  actIter != __actionMap.endSafe();
157  ++actIter)
158  if (*(actIter.second()) == action)
160  " Action "
161  << action
162  << " has already been inserted in FMDP with this name.");
163 
164  if (__actionMap.existsFirst(actionId))
166  " An action with same id (" << actionId
167  << ") has already been inserted.");
168 
169  __actionMap.insert(actionId, new std::string(action));
170 
171  __actionTransitionTable.insert(actionId,
173  __actionCostTable.insert(actionId, nullptr);
174  __actionRewardTable.insert(actionId, nullptr);
175 
176  __actionSeq.insert(actionId);
177  }
178 
179 
180  /* **************************************************************************************************
181  * **/
182  /* ** **/
183  /* ** Transition methods. **/
184  /* ** **/
185  /* **************************************************************************************************
186  * **/
187 
188  // ===========================================================================
189  // Adds a variable transition table to specified action
190  // @throw NotFound if action or var does not exists
191  // @throw DuplicateElement if variable already has a transition for this
192  // action
193  // ===========================================================================
194  template < typename GUM_SCALAR >
196  Idx actionId,
197  const DiscreteVariable* var,
198  const MultiDimImplementation< GUM_SCALAR >* transition) {
199  if (!__varSeq.exists(var))
201  " Variable " << var->name() << " has not been declared before.");
202 
203  if (!__actionTransitionTable.exists(actionId))
205  " Action " << actionName(actionId)
206  << " has not been declared before.");
207 
208  if (__actionTransitionTable[actionId]->exists(var))
210  " Variable " << var->name()
211  << " already has a transition table in " << actionId
212  << " table.");
213 
214  __actionTransitionTable[actionId]->insert(var, transition);
215  }
216 
217 
218  // ===========================================================================
219  // Returns transition associated to given in parameter variable and given
220  // action
221  // ===========================================================================
222  template < typename GUM_SCALAR >
225  const DiscreteVariable* v) const {
226  if (!__actionTransitionTable.exists(actionId))
228  " Action " << actionName(actionId)
229  << " has not been declared before.");
230 
231  if (__actionTransitionTable[actionId]->exists(v))
232  return (*__actionTransitionTable[actionId])[v];
233  else
234  return (*__actionTransitionTable[0]).exists(v)
235  ? (*__actionTransitionTable[0])[v]
236  : nullptr;
237  }
238 
239 
240  /* **************************************************************************************************
241  * **/
242  /* ** **/
243  /* ** Cost methods. **/
244  /* ** **/
245  /* **************************************************************************************************
246  * **/
247 
248  // ===========================================================================
249  // Adds a cost table to specified action
250  // @throw NotFound if action does not exists
251  // @throw DuplicateElement if action already has a cost
252  // ===========================================================================
253  template < typename GUM_SCALAR >
255  Idx actionId, const MultiDimImplementation< GUM_SCALAR >* cost) {
256  if (!__actionCostTable.exists(actionId))
258  " Action " << actionName(actionId)
259  << " has not been declared before.");
260 
261  if (__actionCostTable[actionId] != nullptr)
263  " Action " << actionName(actionId) << " already has a cost table");
264 
265  __actionCostTable[actionId] = cost;
266  }
267 
268 
269  // ===========================================================================
270  // Returns transition associated to given in parameter variable and given
271  // action
272  // ===========================================================================
273  template < typename GUM_SCALAR >
275  FMDP< GUM_SCALAR >::cost(Idx actionId) const {
276  if (!__actionCostTable.exists(actionId))
278  " Action " << actionName(actionId)
279  << " has not been declared before.");
280 
281  if (__actionCostTable[actionId]) return __actionCostTable[actionId];
282  return __actionCostTable[0];
283  }
284 
285 
286  /* **************************************************************************************************
287  * **/
288  /* ** **/
289  /* ** Cost methods. **/
290  /* ** **/
291  /* **************************************************************************************************
292  * **/
293 
294  // ===========================================================================
295  // Adds a default variable reward
296  // @throw DuplicateElement if a default reward exists already
297  // ===========================================================================
298  template < typename GUM_SCALAR >
300  Idx actionId, const MultiDimImplementation< GUM_SCALAR >* reward) {
301  if (!__actionRewardTable.exists(actionId))
303  " Action " << actionName(actionId)
304  << " has not been declared before.");
305 
306  if (__actionRewardTable[actionId] != nullptr)
308  " Action " << actionName(actionId)
309  << " already has a reward table");
310 
311  __actionRewardTable[actionId] = reward;
312  }
313 
314 
315  // ===========================================================================
316  // Returns transition associated to given in parameter variable and given
317  // action
318  // ===========================================================================
319  template < typename GUM_SCALAR >
321  FMDP< GUM_SCALAR >::reward(Idx actionId) const {
322  if (!__actionRewardTable.exists(actionId))
324  " Action " << actionName(actionId)
325  << " has not been declared before.");
326 
327  if (__actionRewardTable[actionId]) return __actionRewardTable[actionId];
328  return __actionRewardTable[0];
329  }
330 
331 
332  /* **************************************************************************************************
333  * **/
334  /* ** **/
335  /* ** Miscelleanous methods. **/
336  /* ** **/
337  /* **************************************************************************************************
338  * **/
339 
340  // ===========================================================================
341  // Returns name of action given in parameter
342  // ===========================================================================
343  template < typename GUM_SCALAR >
344  INLINE const std::string& FMDP< GUM_SCALAR >::actionName(Idx actionId) const {
345  if (!__actionMap.existsFirst(actionId))
346  GUM_ERROR(NotFound, "No action with " << actionId << " as identifiant.");
347 
348  return *(__actionMap.second(actionId));
349  }
350 
351  // ===========================================================================
352  // Returns action id
353  // ===========================================================================
354  template < typename GUM_SCALAR >
355  INLINE Idx FMDP< GUM_SCALAR >::actionId(const std::string& action) const {
357  __actionMap.begin();
358  actIter != __actionMap.end();
359  ++actIter)
360  if (*(actIter.second()) == action) { return actIter.first(); }
361 
362  GUM_ERROR(NotFound, " Action " << action << " has not been declared before.");
363  }
364 
365 
366  template < typename GUM_SCALAR >
367  INLINE std::string FMDP< GUM_SCALAR >::toString() const {
368  std::stringstream fmdpCore;
369 
370  for (auto actionIter = beginActions(); actionIter != endActions();
371  ++actionIter) {
372  for (auto varIter = beginVariables(); varIter != endVariables(); ++varIter)
373  if (this->transition(*actionIter, *varIter))
374  fmdpCore << RECAST(this->transition(*actionIter, *varIter))->toDot()
375  << std::endl;
376  if (this->reward(*actionIter))
377  fmdpCore << RECAST(this->reward(*actionIter))->toDot() << std::endl;
378  }
379 
380  for (auto varIter = beginVariables(); varIter != endVariables(); ++varIter)
381  if (this->transition(0, *varIter))
382  fmdpCore << RECAST(this->transition(0, *varIter))->toDot() << std::endl;
383  if (this->reward()) fmdpCore << RECAST(this->reward())->toDot() << std::endl;
384  return fmdpCore.str();
385  }
386 
387 
388  template < typename GUM_SCALAR >
390  Size s = 0;
391  for (auto actionIter = beginActions(); actionIter != endActions();
392  ++actionIter) {
393  for (auto varIter = beginVariables(); varIter != endVariables(); ++varIter)
394  if (this->transition(*actionIter, *varIter))
395  s += this->transition(*actionIter, *varIter)->realSize();
396  if (this->reward(*actionIter)) s += this->reward(*actionIter)->realSize();
397  }
398 
399  for (auto varIter = beginVariables(); varIter != endVariables(); ++varIter)
400  if (this->transition(0, *varIter))
401  s += this->transition(0, *varIter)->realSize();
402  if (this->reward()) s += this->reward()->realSize();
403  return s;
404  }
405 } // namespace gum
void setName(const std::string &theValue)
sets the name of the variable
~FMDP()
Default destructor.
Definition: fmdp_tpl.h:65
Idx actionId(const std::string &) const
Returns action id.
Definition: fmdp_tpl.h:355
Safe iterators for bijectionIterator.
Definition: bijection.h:1409
const std::string & actionName(Idx actionId) const
Returns name of action given in parameter.
Definition: fmdp_tpl.h:344
virtual DiscreteVariable * clone() const =0
Copy Factory.
void addCostForAction(Idx actionId, const MultiDimImplementation< GUM_SCALAR > *cost)
Adds a cost table to specified action.
Definition: fmdp_tpl.h:254
This class is used to implement factored decision process.
Definition: fmdp.h:54
Base class for discrete random variable.
gum is the global namespace for all aGrUM entities
Definition: agrum.h:25
The class for generic Hash Tables.
Definition: hashTable.h:676
Class for implementation of factored markov decision process.
void addVariable(const DiscreteVariable *var)
Adds a variable to FMDP description.
Definition: fmdp_tpl.h:121
void addTransitionForAction(Idx actionId, const DiscreteVariable *var, const MultiDimImplementation< GUM_SCALAR > *transition)
Adds a variable transition table to specified action.
Definition: fmdp_tpl.h:195
const MultiDimImplementation< GUM_SCALAR > * transition(Idx actionId, const DiscreteVariable *v) const
Returns transition associated to given in parameter variable and the given action.
Definition: fmdp_tpl.h:224
FMDP(bool onDestructionDeleteVar=false)
Default constructor.
Definition: fmdp_tpl.h:50
Size size() const
Returns the map binding main variables and prime variables.
Definition: fmdp_tpl.h:389
const MultiDimImplementation< GUM_SCALAR > * reward(Idx actionId=0) const
Returns the reward table of mdp.
Definition: fmdp_tpl.h:321
void addRewardForAction(Idx actionId, const MultiDimImplementation< GUM_SCALAR > *reward)
Adds a default variable reward.
Definition: fmdp_tpl.h:299
Unsafe iterators for bijection.
Definition: bijection.h:1607
#define RECAST(x)
Definition: fmdp_tpl.h:33
const MultiDimImplementation< GUM_SCALAR > * cost(Idx actionId=0) const
Returns the reward table of mdp.
Definition: fmdp_tpl.h:275
<agrum/multidim/multiDimImplementation.h>
Size Idx
Type for indexes.
Definition: types.h:50
std::size_t Size
In aGrUM, hashed values are unsigned long int.
Definition: types.h:45
const std::string & name() const
returns the name of the variable
void addAction(Idx actionId, const std::string &action)
Adds an action to FMDP description.
Definition: fmdp_tpl.h:150
#define GUM_ERROR(type, msg)
Definition: exceptions.h:52
std::string toString() const
Displays the FMDP in a Dot format.
Definition: fmdp_tpl.h:367