aGrUM  0.20.3
a C++ library for (probabilistic) graphical models
fmdp_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 FMDP/FMDP.h classes.
25  *
26  * @author Pierre-Henri WUILLEMIN(@LIP6) and Jean-Christophe MAGNAN and Christophe
27  * GONZALES(@AMU)
28  */
29 
30 //======================================================================
31 #include <cstdio>
32 #include <iostream>
33 //======================================================================
34 #include <agrum/FMDP/fmdp.h>
35 //======================================================================
36 #define RECAST(x) reinterpret_cast< const MultiDimFunctionGraph< GUM_SCALAR >* >(x)
37 
38 namespace gum {
39 
40 
41  /* **************************************************************************************************
42  * **/
43  /* ** **/
44  /* ** Constructors / Destructors **/
45  /* ** **/
46  /* **************************************************************************************************
47  * **/
48 
49  // ===========================================================================
50  // Default constructor.
51  // ===========================================================================
52  template < typename GUM_SCALAR >
53  INLINE FMDP< GUM_SCALAR >::FMDP(bool onDestructionDeleteVar) {
54  GUM_CONSTRUCTOR(FMDP);
55  _onDestructionDeleteVars_ = onDestructionDeleteVar;
56 
57  // Default Action initialisation
58  _actionMap_.insert(0, new std::string("DEFAULT"));
59  _actionTransitionTable_.insert(0, new VarTransitionTable< GUM_SCALAR >());
60  _actionCostTable_.insert(0, nullptr);
61  _actionRewardTable_.insert(0, nullptr);
62  }
63 
64  // ===========================================================================
65  // Destructor.
66  // ===========================================================================
67  template < typename GUM_SCALAR >
68  FMDP< GUM_SCALAR >::~FMDP() {
69  // Action Transition Graph deletion
70  for (auto iterA = _actionTransitionTable_.beginSafe();
71  iterA != _actionTransitionTable_.endSafe();
72  ++iterA) {
73  if (iterA.val()) {
74  for (auto iterH = (iterA.val())->beginSafe(); iterH != (iterA.val())->endSafe(); ++iterH)
75  if (iterH.val()) delete iterH.val();
76  delete iterA.val();
77  }
78  }
79 
80  // Action cost graph deletion
81  for (auto iterA = _actionCostTable_.beginSafe(); iterA != _actionCostTable_.endSafe(); ++iterA)
82  if (iterA.val()) delete iterA.val();
83 
84  // Action reward graph deletion
85  for (auto iterA = _actionRewardTable_.beginSafe(); iterA != _actionRewardTable_.endSafe();
86  ++iterA)
87  if (iterA.val()) delete iterA.val();
88 
89  // Action Name deletion
90  for (auto iterId = _actionMap_.beginSafe(); iterId != _actionMap_.endSafe(); ++iterId)
91  delete iterId.second();
92 
93  // Primed Variables deletion
94  for (auto varIter = _main2primed_.beginSafe(); varIter != _main2primed_.endSafe(); ++varIter) {
95  delete varIter.second();
96  if (_onDestructionDeleteVars_) delete varIter.first();
97  }
98 
99  GUM_DESTRUCTOR(FMDP);
100  }
101 
102 
103  /* **************************************************************************************************
104  * **/
105  /* ** **/
106  /* ** Variable Handling Methods. **/
107  /* ** **/
108  /* **************************************************************************************************
109  * **/
110 
111  // ===========================================================================
112  // Adds a variable to FMDP description
113  // @throw DuplicateElement if a similar variable already exists
114  // ===========================================================================
115  template < typename GUM_SCALAR >
116  INLINE void FMDP< GUM_SCALAR >::addVariable(const DiscreteVariable* var) {
117  if (_varSeq_.exists(var))
118  GUM_ERROR(DuplicateElement,
119  " Variable " << var->name() << " has already been inserted in FMDP.");
120 
121 
122  _varSeq_.insert(var);
123 
124  // Prime version creation
125  DiscreteVariable* primeVar = var->clone();
126  primeVar->setName(var->name() + "'");
127  _main2primed_.insert(var, primeVar);
128  }
129 
130 
131  /* **************************************************************************************************
132  * **/
133  /* ** **/
134  /* ** Variable Handling Methods. **/
135  /* ** **/
136  /* **************************************************************************************************
137  * **/
138 
139  // ===========================================================================
140  // Adds an action to FMDP description
141  // @throw DuplicateElement if an action with same name already exists
142  // ===========================================================================
143  template < typename GUM_SCALAR >
144  INLINE void FMDP< GUM_SCALAR >::addAction(Idx actionId, const std::string& action) {
145  if (actionId == 0) GUM_ERROR(DuplicateElement, " Action Id 0 is reserved.")
146 
147  for (BijectionIteratorSafe< Idx, const std::string* > actIter = _actionMap_.beginSafe();
148  actIter != _actionMap_.endSafe();
149  ++actIter)
150  if (*(actIter.second()) == action)
151  GUM_ERROR(DuplicateElement,
152  " Action " << action << " has already been inserted in FMDP with this name.");
153 
154  if (_actionMap_.existsFirst(actionId))
155  GUM_ERROR(DuplicateElement,
156  " An action with same id (" << actionId << ") has already been inserted.");
157 
158  _actionMap_.insert(actionId, new std::string(action));
159 
160  _actionTransitionTable_.insert(actionId, new VarTransitionTable< GUM_SCALAR >());
161  _actionCostTable_.insert(actionId, nullptr);
162  _actionRewardTable_.insert(actionId, nullptr);
163 
164  _actionSeq_.insert(actionId);
165  }
166 
167 
168  /* **************************************************************************************************
169  * **/
170  /* ** **/
171  /* ** Transition methods. **/
172  /* ** **/
173  /* **************************************************************************************************
174  * **/
175 
176  // ===========================================================================
177  // Adds a variable transition table to specified action
178  // @throw NotFound if action or var does not exists
179  // @throw DuplicateElement if variable already has a transition for this
180  // action
181  // ===========================================================================
182  template < typename GUM_SCALAR >
183  INLINE void FMDP< GUM_SCALAR >::addTransitionForAction(
184  Idx actionId,
185  const DiscreteVariable* var,
186  const MultiDimImplementation< GUM_SCALAR >* transition) {
187  if (!_varSeq_.exists(var))
188  GUM_ERROR(NotFound, " Variable " << var->name() << " has not been declared before.")
189 
190  if (!_actionTransitionTable_.exists(actionId))
191  GUM_ERROR(NotFound, " Action " << actionName(actionId) << " has not been declared before.");
192 
193  if (_actionTransitionTable_[actionId]->exists(var))
194  GUM_ERROR(DuplicateElement,
195  " Variable " << var->name() << " already has a transition table in " << actionId
196  << " table.");
197 
198  _actionTransitionTable_[actionId]->insert(var, transition);
199  }
200 
201 
202  // ===========================================================================
203  // Returns transition associated to given in parameter variable and given
204  // action
205  // ===========================================================================
206  template < typename GUM_SCALAR >
207  INLINE const MultiDimImplementation< GUM_SCALAR >*
208  FMDP< GUM_SCALAR >::transition(Idx actionId, const DiscreteVariable* v) const {
209  if (!_actionTransitionTable_.exists(actionId))
210  GUM_ERROR(NotFound, " Action " << actionName(actionId) << " has not been declared before.");
211 
212  if (_actionTransitionTable_[actionId]->exists(v))
213  return (*_actionTransitionTable_[actionId])[v];
214  else
215  return (*_actionTransitionTable_[0]).exists(v) ? (*_actionTransitionTable_[0])[v] : nullptr;
216  }
217 
218 
219  /* **************************************************************************************************
220  * **/
221  /* ** **/
222  /* ** Cost methods. **/
223  /* ** **/
224  /* **************************************************************************************************
225  * **/
226 
227  // ===========================================================================
228  // Adds a cost table to specified action
229  // @throw NotFound if action does not exists
230  // @throw DuplicateElement if action already has a cost
231  // ===========================================================================
232  template < typename GUM_SCALAR >
233  INLINE void
234  FMDP< GUM_SCALAR >::addCostForAction(Idx actionId,
235  const MultiDimImplementation< GUM_SCALAR >* cost) {
236  if (!_actionCostTable_.exists(actionId))
237  GUM_ERROR(NotFound, " Action " << actionName(actionId) << " has not been declared before.");
238 
239  if (_actionCostTable_[actionId] != nullptr)
240  GUM_ERROR(DuplicateElement, " Action " << actionName(actionId) << " already has a cost table")
241 
242  _actionCostTable_[actionId] = cost;
243  }
244 
245 
246  // ===========================================================================
247  // Returns transition associated to given in parameter variable and given
248  // action
249  // ===========================================================================
250  template < typename GUM_SCALAR >
251  INLINE const MultiDimImplementation< GUM_SCALAR >* FMDP< GUM_SCALAR >::cost(Idx actionId) const {
252  if (!_actionCostTable_.exists(actionId))
253  GUM_ERROR(NotFound, " Action " << actionName(actionId) << " has not been declared before.");
254 
255  if (_actionCostTable_[actionId]) return _actionCostTable_[actionId];
256  return _actionCostTable_[0];
257  }
258 
259 
260  /* **************************************************************************************************
261  * **/
262  /* ** **/
263  /* ** Cost methods. **/
264  /* ** **/
265  /* **************************************************************************************************
266  * **/
267 
268  // ===========================================================================
269  // Adds a default variable reward
270  // @throw DuplicateElement if a default reward exists already
271  // ===========================================================================
272  template < typename GUM_SCALAR >
273  INLINE void
274  FMDP< GUM_SCALAR >::addRewardForAction(Idx actionId,
275  const MultiDimImplementation< GUM_SCALAR >* reward) {
276  if (!_actionRewardTable_.exists(actionId))
277  GUM_ERROR(NotFound, " Action " << actionName(actionId) << " has not been declared before.");
278 
279  if (_actionRewardTable_[actionId] != nullptr)
280  GUM_ERROR(DuplicateElement,
281  " Action " << actionName(actionId) << " already has a reward table");
282 
283  _actionRewardTable_[actionId] = reward;
284  }
285 
286 
287  // ===========================================================================
288  // Returns transition associated to given in parameter variable and given
289  // action
290  // ===========================================================================
291  template < typename GUM_SCALAR >
292  INLINE const MultiDimImplementation< GUM_SCALAR >*
293  FMDP< GUM_SCALAR >::reward(Idx actionId) const {
294  if (!_actionRewardTable_.exists(actionId))
295  GUM_ERROR(NotFound, " Action " << actionName(actionId) << " has not been declared before.");
296 
297  if (_actionRewardTable_[actionId]) return _actionRewardTable_[actionId];
298  return _actionRewardTable_[0];
299  }
300 
301 
302  /* **************************************************************************************************
303  * **/
304  /* ** **/
305  /* ** Miscelleanous methods. **/
306  /* ** **/
307  /* **************************************************************************************************
308  * **/
309 
310  // ===========================================================================
311  // Returns name of action given in parameter
312  // ===========================================================================
313  template < typename GUM_SCALAR >
314  INLINE const std::string& FMDP< GUM_SCALAR >::actionName(Idx actionId) const {
315  if (!_actionMap_.existsFirst(actionId))
316  GUM_ERROR(NotFound, "No action with " << actionId << " as identifiant.")
317 
318  return *(_actionMap_.second(actionId));
319  }
320 
321  // ===========================================================================
322  // Returns action id
323  // ===========================================================================
324  template < typename GUM_SCALAR >
325  INLINE Idx FMDP< GUM_SCALAR >::actionId(const std::string& action) const {
326  for (BijectionIterator< Idx, const std::string* > actIter = _actionMap_.begin();
327  actIter != _actionMap_.end();
328  ++actIter)
329  if (*(actIter.second()) == action) { return actIter.first(); }
330 
331  GUM_ERROR(NotFound, " Action " << action << " has not been declared before.")
332  }
333 
334 
335  template < typename GUM_SCALAR >
336  INLINE std::string FMDP< GUM_SCALAR >::toString() const {
337  std::stringstream fmdpCore;
338 
339  for (auto actionIter = beginActions(); actionIter != endActions(); ++actionIter) {
340  for (auto varIter = beginVariables(); varIter != endVariables(); ++varIter)
341  if (this->transition(*actionIter, *varIter))
342  fmdpCore << RECAST(this->transition(*actionIter, *varIter))->toDot() << std::endl;
343  if (this->reward(*actionIter))
344  fmdpCore << RECAST(this->reward(*actionIter))->toDot() << std::endl;
345  }
346 
347  for (auto varIter = beginVariables(); varIter != endVariables(); ++varIter)
348  if (this->transition(0, *varIter))
349  fmdpCore << RECAST(this->transition(0, *varIter))->toDot() << std::endl;
350  if (this->reward()) fmdpCore << RECAST(this->reward())->toDot() << std::endl;
351  return fmdpCore.str();
352  }
353 
354 
355  template < typename GUM_SCALAR >
356  INLINE Size FMDP< GUM_SCALAR >::size() const {
357  Size s = 0;
358  for (auto actionIter = beginActions(); actionIter != endActions(); ++actionIter) {
359  for (auto varIter = beginVariables(); varIter != endVariables(); ++varIter)
360  if (this->transition(*actionIter, *varIter))
361  s += this->transition(*actionIter, *varIter)->realSize();
362  if (this->reward(*actionIter)) s += this->reward(*actionIter)->realSize();
363  }
364 
365  for (auto varIter = beginVariables(); varIter != endVariables(); ++varIter)
366  if (this->transition(0, *varIter)) s += this->transition(0, *varIter)->realSize();
367  if (this->reward()) s += this->reward()->realSize();
368  return s;
369  }
370 } // namespace gum
#define RECAST(x)
Definition: fmdp_tpl.h:36