AIToolbox
A library that offers tools for AI problem solving.
SparseModel.hpp
Go to the documentation of this file.
1 #ifndef AI_TOOLBOX_POMDP_SPARSE_MODEL_HEADER_FILE
2 #define AI_TOOLBOX_POMDP_SPARSE_MODEL_HEADER_FILE
3 
4 #include <random>
5 
6 #include <AIToolbox/Seeder.hpp>
13 
14 namespace AIToolbox::POMDP {
15  template <MDP::IsModel M>
16  class SparseModel;
17 
18  // Declaration to warn the compiler that this is a template function
19  template <MDP::IsModel M>
20  std::istream& operator>>(std::istream &is, SparseModel<M> & m);
21 
77  template <MDP::IsModel M>
78  class SparseModel : public M {
79  public:
81 
92  template <typename... Args>
93  SparseModel(size_t o, Args&&... parameters);
94 
122  // Check that ObFun is a triple-matrix, otherwise we'll call the other constructor!
123  template <IsNaive3DMatrix ObFun, typename... Args>
124  SparseModel(size_t o, ObFun && of, Args&&... parameters);
125 
141  template <typename PM>
142  requires IsModel<PM> && std::constructible_from<M, PM>
143  SparseModel(const PM& model);
144 
160  template <typename... Args>
161  SparseModel(NoCheck, size_t o, ObservationMatrix && ot, Args&&... parameters);
162 
180  template <IsNaive3DMatrix ObFun>
181  void setObservationFunction(const ObFun & of);
182 
199  void setObservationFunction(const ObservationMatrix & of);
200 
220  std::tuple<size_t,size_t, double> sampleSOR(size_t s,size_t a) const;
221 
238  std::tuple<size_t, double> sampleOR(size_t s,size_t a,size_t s1) const;
239 
249  double getObservationProbability(size_t s1, size_t a, size_t o) const;
250 
260  double getObservationProbability(const Belief & b, size_t o, size_t a) const;
261 
269  const SparseMatrix2D & getObservationFunction(size_t a) const;
270 
276  size_t getO() const;
277 
284 
285  private:
286  size_t O;
287  ObservationMatrix observations_;
288  // We need this because we don't know if our parent already has one,
289  // and we wouldn't know how to access it!
290  mutable RandomEngine rand_;
291  };
292 
293  template <MDP::IsModel M>
294  template <typename... Args>
295  SparseModel<M>::SparseModel(const size_t o, Args&&... params) :
296  M(std::forward<Args>(params)...), O(o), observations_(this->getA(),
297  SparseMatrix2D(this->getS(), O)), rand_(Seeder::getSeed())
298  {
299  for ( size_t a = 0; a < this->getA(); ++a ) {
300  for ( size_t s1 = 0; s1 < this->getS(); ++s1 )
301  observations_[a].insert(s1, 0) = 1.0;
302  observations_[a].makeCompressed();
303  }
304  }
305 
306  template <MDP::IsModel M>
307  template <IsNaive3DMatrix ObFun, typename... Args>
308  SparseModel<M>::SparseModel(const size_t o, ObFun && of, Args&&... params) :
309  M(std::forward<Args>(params)...), O(o),
310  observations_(this->getA(), SparseMatrix2D(this->getS(), O)), rand_(Seeder::getSeed())
311  {
313  }
314 
315  template <MDP::IsModel M>
316  template <typename... Args>
317  SparseModel<M>::SparseModel(NoCheck, size_t o, ObservationMatrix && ot, Args&&... params) :
318  M(std::forward<Args>(params)...), O(o),
319  observations_(std::move(ot))
320  {}
321 
322  template <MDP::IsModel M>
323  template <typename PM>
324  requires IsModel<PM> && std::constructible_from<M, PM>
325  SparseModel<M>::SparseModel(const PM& model) :
326  M(model), O(model.getO()), observations_(this->getA(), SparseMatrix2D(this->getS(), O)),
327  rand_(Seeder::getSeed())
328  {
329  for ( size_t a = 0; a < this->getA(); ++a ) {
330  for ( size_t s1 = 0; s1 < this->getS(); ++s1 ) {
331  for ( size_t o = 0; o < O; ++o ) {
332  const double p = model.getObservationProbability(s1, a, o);
333  if ( p < 0.0 || p > 1.0 )
334  throw std::invalid_argument("Input observation matrix contains an invalid value.");
335 
336  if ( checkDifferentSmall( p, 0.0 ) ) observations_[a].insert(s1, o) = p;
337  }
338  if ( checkDifferentSmall(1.0, observations_[a].row(s1).sum()) )
339  throw std::invalid_argument("Input observation matrix contains an invalid row.");
340  }
341  observations_[a].makeCompressed();
342  }
343  }
344 
345  template <MDP::IsModel M>
346  template <IsNaive3DMatrix ObFun>
347  void SparseModel<M>::setObservationFunction(const ObFun & of) {
348  for ( size_t s1 = 0; s1 < this->getS(); ++s1 )
349  for ( size_t a = 0; a < this->getA(); ++a )
350  if ( !isProbability(O, of[s1][a]) )
351  throw std::invalid_argument("Input observation matrix does not contain valid probabilities.");
352 
353  for ( size_t a = 0; a < this->getA(); ++a ) {
354  observations_[a].setZero();
355  for ( size_t s1 = 0; s1 < this->getS(); ++s1 )
356  for ( size_t o = 0; o < O; ++o ) {
357  const double p = of[s1][a][o];
358  if ( checkDifferentSmall( p, 0.0 ) )
359  observations_[a].insert(s1, o) = p;
360  }
361  }
362 
363  for ( size_t a = 0; a < this->getA(); ++a )
364  observations_[a].makeCompressed();
365  }
366 
367  template <MDP::IsModel M>
369  if (!isProbability(of))
370  throw std::invalid_argument("Input observation matrix does not contain valid probabilities.");
371  // Then we copy.
372  observations_ = of;
373  }
374 
375  template <MDP::IsModel M>
376  double SparseModel<M>::getObservationProbability(const size_t s1, const size_t a, const size_t o) const {
377  return observations_[a].coeff(s1, o);
378  }
379 
380  template <MDP::IsModel M>
382  return observations_[a];
383  }
384 
385  template <MDP::IsModel M>
386  size_t SparseModel<M>::getO() const {
387  return O;
388  }
389 
390  template <MDP::IsModel M>
392  return observations_;
393  }
394 
395  template <MDP::IsModel M>
396  std::tuple<size_t,size_t, double> SparseModel<M>::sampleSOR(const size_t s, const size_t a) const {
397  const auto [s1, r] = this->sampleSR(s, a);
398  const auto o = sampleProbability(O, observations_[a].row(s1), rand_);
399  return std::make_tuple(s1, o, r);
400  }
401 
402  template <MDP::IsModel M>
403  std::tuple<size_t, double> SparseModel<M>::sampleOR(const size_t s, const size_t a, const size_t s1) const {
404  const size_t o = sampleProbability(O, observations_[a].row(s1), rand_);
405  const double r = this->getExpectedReward(s, a, s1);
406  return std::make_tuple(o, r);
407  }
408 }
409 
410 #endif
AIToolbox::checkDifferentSmall
bool checkDifferentSmall(const double a, const double b)
This function checks if two doubles near [0,1] are reasonably different.
Definition: Core.hpp:60
AIToolbox::POMDP
Definition: AMDP.hpp:14
Core.hpp
AIToolbox::POMDP::SparseModel::getObservationProbability
double getObservationProbability(size_t s1, size_t a, size_t o) const
This function returns the stored observation probability for the specified state-action pair.
Definition: SparseModel.hpp:376
AIToolbox::POMDP::SparseModel::sampleSOR
std::tuple< size_t, size_t, double > sampleSOR(size_t s, size_t a) const
This function samples the POMDP for the specified state action pair.
Definition: SparseModel.hpp:396
AIToolbox::POMDP::SparseModel::getO
size_t getO() const
This function returns the number of observations possible.
Definition: SparseModel.hpp:386
TypeTraits.hpp
AIToolbox::Seeder
This class is an internal class used to seed all random engines in the library.
Definition: Seeder.hpp:15
AIToolbox::SparseMatrix3D
std::vector< SparseMatrix2D > SparseMatrix3D
Definition: Types.hpp:22
AIToolbox::POMDP::SparseModel
This class represents a Partially Observable Markov Decision Process.
Definition: SparseModel.hpp:16
AIToolbox::POMDP::SparseModel::ObservationMatrix
SparseMatrix3D ObservationMatrix
Definition: SparseModel.hpp:80
AIToolbox::POMDP::SparseModel::SparseModel
SparseModel(size_t o, Args &&... parameters)
Basic constructor.
Definition: SparseModel.hpp:295
AIToolbox::POMDP::SparseModel::getObservationFunction
const ObservationMatrix & getObservationFunction() const
This function returns the observation matrix for inspection.
Definition: SparseModel.hpp:391
AIToolbox::isProbability
bool isProbability(const size_t size, const T &in)
This function checks whether the supplied 1D container is a valid discrete distribution.
Definition: Probability.hpp:38
Seeder.hpp
AIToolbox::RandomEngine
std::mt19937 RandomEngine
Definition: Types.hpp:14
Types.hpp
AIToolbox::sampleProbability
size_t sampleProbability(const size_t d, const T &in, G &generator)
This function samples an index from a probability vector.
Definition: Probability.hpp:188
AIToolbox::IsNaive3DMatrix
concept IsNaive3DMatrix
This concept checks for a simple 3D accessible matrix.
Definition: TypeTraits.hpp:42
AIToolbox::POMDP::SparseModel::sampleOR
std::tuple< size_t, double > sampleOR(size_t s, size_t a, size_t s1) const
This function samples the POMDP for the specified state action pair.
Definition: SparseModel.hpp:403
AIToolbox::NoCheck
This is used to tag functions that avoid runtime checks.
Definition: Types.hpp:44
Types.hpp
TypeTraits.hpp
AIToolbox::POMDP::SparseModel::setObservationFunction
void setObservationFunction(const ObFun &of)
This function replaces the SparseModel observation function with the one provided.
Definition: SparseModel.hpp:347
AIToolbox::POMDP::Belief
ProbabilityVector Belief
This represents a belief, which is a probability distribution over states.
Definition: Types.hpp:12
AIToolbox::SparseMatrix2D
Eigen::SparseMatrix< double, Eigen::RowMajor > SparseMatrix2D
Definition: Types.hpp:19
AIToolbox::POMDP::operator>>
std::istream & operator>>(std::istream &is, Model< M > &m)
This function parses a Model from a stream.
Definition: IO.hpp:62
Probability.hpp