mdpsolver 0.11.0__tar.gz → 0.12.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. {mdpsolver-0.11.0 → mdpsolver-0.12.0}/CPP_Source_Code/GeneralMDPmodel.cpp +43 -20
  2. {mdpsolver-0.11.0 → mdpsolver-0.12.0}/CPP_Source_Code/GeneralMDPmodel.h +23 -7
  3. mdpsolver-0.12.0/CPP_Source_Code/ModelType.h +53 -0
  4. {mdpsolver-0.11.0 → mdpsolver-0.12.0}/CPP_Source_Code/ModifiedPolicyIteration.cpp +410 -317
  5. {mdpsolver-0.11.0 → mdpsolver-0.12.0}/CPP_Source_Code/ModifiedPolicyIteration.h +18 -13
  6. mdpsolver-0.12.0/CPP_Source_Code/ModuleInterface.cpp +1514 -0
  7. {mdpsolver-0.11.0 → mdpsolver-0.12.0}/CPP_Source_Code/ModuleInterface.h +24 -9
  8. {mdpsolver-0.11.0 → mdpsolver-0.12.0}/CPP_Source_Code/PythonModule.cpp +2 -2
  9. {mdpsolver-0.11.0 → mdpsolver-0.12.0}/CPP_Source_Code/Rewards.cpp +12 -27
  10. mdpsolver-0.12.0/CPP_Source_Code/Rewards.h +78 -0
  11. mdpsolver-0.12.0/CPP_Source_Code/TransitionMatrix.cpp +98 -0
  12. mdpsolver-0.12.0/CPP_Source_Code/TransitionMatrix.h +137 -0
  13. mdpsolver-0.12.0/PKG-INFO +194 -0
  14. {mdpsolver-0.11.0 → mdpsolver-0.12.0}/Python/src/mdpsolver/model.py +150 -25
  15. {mdpsolver-0.11.0 → mdpsolver-0.12.0}/Python/tests/knownsolutions.py +21 -0
  16. mdpsolver-0.12.0/Python/tests/test_arrays.py +357 -0
  17. {mdpsolver-0.11.0 → mdpsolver-0.12.0}/Python/tests/test_imports.py +222 -23
  18. {mdpsolver-0.11.0 → mdpsolver-0.12.0}/Python/tests/test_large.py +11 -6
  19. {mdpsolver-0.11.0 → mdpsolver-0.12.0}/Python/tests/test_mpi.py +10 -3
  20. {mdpsolver-0.11.0 → mdpsolver-0.12.0}/Python/tests/test_output.py +51 -5
  21. {mdpsolver-0.11.0 → mdpsolver-0.12.0}/Python/tests/test_pi.py +10 -3
  22. {mdpsolver-0.11.0 → mdpsolver-0.12.0}/Python/tests/test_random.py +7 -3
  23. {mdpsolver-0.11.0 → mdpsolver-0.12.0}/Python/tests/test_reuse.py +14 -7
  24. mdpsolver-0.12.0/Python/tests/test_threads.py +222 -0
  25. {mdpsolver-0.11.0 → mdpsolver-0.12.0}/Python/tests/test_vi.py +11 -4
  26. mdpsolver-0.12.0/README.md +175 -0
  27. {mdpsolver-0.11.0 → mdpsolver-0.12.0}/pyproject.toml +3 -1
  28. mdpsolver-0.11.0/CPP_Source_Code/ModelType.h +0 -23
  29. mdpsolver-0.11.0/CPP_Source_Code/ModuleInterface.cpp +0 -858
  30. mdpsolver-0.11.0/CPP_Source_Code/Rewards.h +0 -64
  31. mdpsolver-0.11.0/CPP_Source_Code/TransitionMatrix.cpp +0 -99
  32. mdpsolver-0.11.0/CPP_Source_Code/TransitionMatrix.h +0 -76
  33. mdpsolver-0.11.0/PKG-INFO +0 -194
  34. mdpsolver-0.11.0/README.md +0 -176
  35. {mdpsolver-0.11.0 → mdpsolver-0.12.0}/.gitignore +0 -0
  36. {mdpsolver-0.11.0 → mdpsolver-0.12.0}/CPP_Source_Code/CBMmodel.cpp +0 -0
  37. {mdpsolver-0.11.0 → mdpsolver-0.12.0}/CPP_Source_Code/CBMmodel.h +0 -0
  38. {mdpsolver-0.11.0 → mdpsolver-0.12.0}/CPP_Source_Code/CMakeLists.txt +0 -0
  39. {mdpsolver-0.11.0 → mdpsolver-0.12.0}/CPP_Source_Code/ModelType.cpp +0 -0
  40. {mdpsolver-0.11.0 → mdpsolver-0.12.0}/CPP_Source_Code/Policy.cpp +0 -0
  41. {mdpsolver-0.11.0 → mdpsolver-0.12.0}/CPP_Source_Code/Policy.h +0 -0
  42. {mdpsolver-0.11.0 → mdpsolver-0.12.0}/CPP_Source_Code/TBMmodel.cpp +0 -0
  43. {mdpsolver-0.11.0 → mdpsolver-0.12.0}/CPP_Source_Code/TBMmodel.h +0 -0
  44. {mdpsolver-0.11.0 → mdpsolver-0.12.0}/CPP_Source_Code/ValueVector.cpp +0 -0
  45. {mdpsolver-0.11.0 → mdpsolver-0.12.0}/CPP_Source_Code/ValueVector.h +0 -0
  46. {mdpsolver-0.11.0 → mdpsolver-0.12.0}/LICENSE +0 -0
  47. {mdpsolver-0.11.0 → mdpsolver-0.12.0}/Python/src/mdpsolver/__init__.py +0 -0
  48. {mdpsolver-0.11.0 → mdpsolver-0.12.0}/Python/tests/loadmdpsolver.py +0 -0
  49. {mdpsolver-0.11.0 → mdpsolver-0.12.0}/Python/tests/test_checkmodel.py +0 -0
  50. {mdpsolver-0.11.0 → mdpsolver-0.12.0}/Python/tests/test_order.py +0 -0
@@ -23,6 +23,7 @@
23
23
  */
24
24
 
25
25
  #include "GeneralMDPmodel.h"
26
+ #include <limits>
26
27
 
27
28
  GeneralMDPmodel::GeneralMDPmodel(Rewards * rw, TransitionMatrix * tm, double discount):
28
29
  rewards(rw),
@@ -40,48 +41,70 @@ GeneralMDPmodel::~GeneralMDPmodel() {
40
41
 
41
42
 
42
43
  void GeneralMDPmodel::initialize(){
43
- numberOfStates=tranMat->numberOfRows();
44
+ tranMat->fillTables(csr);
45
+ numberOfStates=csr.numberOfStates;
44
46
  cidx=0;
47
+
48
+ //The tables need one reward per pair of the transition probabilities. In a well-formed
49
+ //model the rewards have the same numbers of actions, and so the same numbering, and
50
+ //their array is used as it is. Otherwise (which checkModel() reports) a copy numbered
51
+ //like the pairs is made, so that the solver reads no memory outside the rewards.
52
+ bool aligned = rewards->numberOfRows() >= numberOfStates;
53
+ for (int sidx=0; aligned && sidx<numberOfStates; sidx++){
54
+ aligned = rewards->numberOfActions(sidx) == tranMat->numberOfActions(sidx);
55
+ }
56
+ if (aligned){
57
+ csr.reward = rewards->data();
58
+ }else{
59
+ alignedRewards.assign(csr.stateStart[numberOfStates], numeric_limits<double>::quiet_NaN());
60
+ for (int sidx=0; sidx<numberOfStates && sidx<rewards->numberOfRows(); sidx++){
61
+ for (int aidx=0; aidx<tranMat->numberOfActions(sidx) && aidx<rewards->numberOfActions(sidx); aidx++){
62
+ alignedRewards[pair(sidx,aidx)] = rewards->getReward(sidx,aidx);
63
+ }
64
+ }
65
+ csr.reward = alignedRewards.data();
66
+ }
45
67
  }
46
-
68
+
47
69
  double GeneralMDPmodel::reward(int &sidx, int &aidx){
48
70
  //calculates and returns the reward of taking action
49
71
  //aidx when in current state sidx
50
72
 
51
- return rewards->getReward(sidx,aidx);
73
+ return csr.reward[pair(sidx,aidx)];
52
74
  }
53
75
 
54
76
  double GeneralMDPmodel::transProb(int &sidx, int &aidx, int &jidx){
55
- //calculates the probability of jumping to state jidx from
56
- //the current state sidx when taking action aidx.
57
- //returns the calculated probability.
77
+ //returns the jidx-th non-zero transition probability of taking
78
+ //action aidx in state sidx (jidx counts the non-zero probabilities)
58
79
 
59
- return tranMat->getProb(sidx,aidx,jidx);
80
+ return probability(entry(sidx,aidx,jidx));
60
81
  }
61
82
 
62
83
  int GeneralMDPmodel::getNumberOfJumps(int &sidx, int &aidx){
63
- return tranMat->numberOfColumns(sidx,aidx);
84
+ int64_t i = pair(sidx,aidx);
85
+ return (int)(csr.pairStart[i+1] - csr.pairStart[i]);
64
86
  }
65
87
 
66
88
  void GeneralMDPmodel::updateNextState(int &sidx, int &aidx, int &jidx){
67
89
  //updates the next possible state, nextState, and the associated
68
- //transition probability, psj.
69
- while (tranMat->getColumn(sidx,aidx,cidx)!=jidx){ //this will in many cases immediately evaluate to False
90
+ //transition probability, psj.
91
+ int nJumps = getNumberOfJumps(sidx,aidx);
92
+ while (csr.column[entry(sidx,aidx,cidx)]!=jidx){ //this will in many cases immediately evaluate to False
70
93
  cidx++;
71
- if (cidx==tranMat->numberOfColumns(sidx,aidx)){ //to make sure cidx is always feasible
94
+ if (cidx==nJumps){ //to make sure cidx is always feasible
72
95
  cidx=0;
73
- }
96
+ }
74
97
  }
75
98
  cidx++; //move one additional step
76
- if (cidx==tranMat->numberOfColumns(sidx,aidx)){
99
+ if (cidx==nJumps){
77
100
  cidx=0;
78
101
  }
79
- nextState = tranMat->getColumn(sidx,aidx,cidx);
80
- psj = tranMat->getProb(sidx,aidx,cidx);
81
- }
102
+ nextState = csr.column[entry(sidx,aidx,cidx)];
103
+ psj = probability(entry(sidx,aidx,cidx));
104
+ }
82
105
 
83
106
  int GeneralMDPmodel::getColumnIdx(int &sidx, int &aidx, int &cidx){
84
- return tranMat->getColumn(sidx,aidx,cidx);
107
+ return csr.column[entry(sidx,aidx,cidx)];
85
108
  }
86
109
 
87
110
  int GeneralMDPmodel::postDecisionIdx(int &sidx, int &aidx){
@@ -90,7 +113,7 @@ int GeneralMDPmodel::postDecisionIdx(int &sidx, int &aidx){
90
113
  //both returns the value of the first new state, and
91
114
  //stores it in the variable nextState.
92
115
  cidx=0;
93
- nextState = tranMat->getColumn(sidx,aidx,cidx);
116
+ nextState = csr.column[entry(sidx,aidx,cidx)];
94
117
  return nextState;
95
118
  }
96
119
 
@@ -103,7 +126,7 @@ int GeneralMDPmodel::getNumberOfStates(){
103
126
  }
104
127
 
105
128
  void GeneralMDPmodel::updateNumberOfActions(int &sidx){
106
- numberOfActions=tranMat->numberOfActions(sidx);
129
+ numberOfActions=(int)(csr.stateStart[sidx+1] - csr.stateStart[sidx]);
107
130
  }
108
131
 
109
132
  int GeneralMDPmodel::getNumberOfActions(){
@@ -111,7 +134,7 @@ int GeneralMDPmodel::getNumberOfActions(){
111
134
  }
112
135
 
113
136
  int GeneralMDPmodel::getNumberOfActions(int &sidx){
114
- return tranMat->numberOfActions(sidx);
137
+ return (int)(csr.stateStart[sidx+1] - csr.stateStart[sidx]);
115
138
  }
116
139
 
117
140
  int * GeneralMDPmodel::getNextState(){
@@ -34,9 +34,12 @@
34
34
 
35
35
  using namespace std;
36
36
 
37
+ //The general MDP model: the transition probabilities and rewards the user gave to mdp(),
38
+ //held as CSR tables (ModelType.h), which the solver reads directly. The methods of
39
+ //ModelType read the same tables, for the code that goes through them.
37
40
  class GeneralMDPmodel : public ModelType{
38
41
  public:
39
-
42
+
40
43
  //CONSTRUCTOR AND DESCTRUCTOR
41
44
  GeneralMDPmodel() {}; //dummy-constructor
42
45
  GeneralMDPmodel(Rewards * rw, TransitionMatrix * tm, double discount);
@@ -48,15 +51,18 @@ public:
48
51
 
49
52
  double discount;
50
53
  int numberOfStates, numberOfActions;
51
-
54
+
52
55
  //auxiliary variables
53
56
  int nextState; //a new state that the current state can jump to
54
57
  double psj; //transition probability from the current state to nextState
55
-
58
+
56
59
  //METHODS
57
60
  void initialize();
58
-
59
- //GENERIC METHODS
61
+
62
+ //the tables, which the solver's fast loops read
63
+ const CSRTables* tables() override { return &csr; }
64
+
65
+ //GENERIC METHODS
60
66
  double reward(int &sidx, int &aidx) override;
61
67
  double transProb(int &sidx, int &aidx, int &jidx) override;
62
68
  void updateNextState(int &sidx, int &aidx, int &jidx) override;
@@ -76,9 +82,19 @@ private:
76
82
  //VARIABLES
77
83
  Rewards * rewards;
78
84
  TransitionMatrix * tranMat;
85
+ CSRTables csr;
86
+ //the rewards numbered like the pairs of the transition probabilities, made only when the
87
+ //rewards have other numbers of actions or states (a malformed model); rewards the input
88
+ //lacks are NaN here, and those it has beyond the transition probabilities are left out
89
+ vector<double> alignedRewards;
79
90
  int cidx;
80
-
91
+
92
+ //METHODS
93
+ int64_t pair(int sidx, int aidx) const { return csr.stateStart[sidx] + aidx; }
94
+ int64_t entry(int sidx, int aidx, int cidx) const { return csr.pairStart[pair(sidx,aidx)] + cidx; }
95
+ double probability(int64_t k) const { return csr.prob32 ? (double)csr.prob32[k] : csr.prob[k]; }
81
96
 
82
97
  };
83
98
 
84
- #endif /* TBMMODEL_H */
99
+ #endif /* GENERALMDPMODEL_H */
100
+
@@ -0,0 +1,53 @@
1
+ #ifndef MODELTYPE_H
2
+ #define MODELTYPE_H
3
+
4
+ #include <cstdint>
5
+
6
+ //The transitions and rewards of a model, stored as tables in compressed sparse row (CSR)
7
+ //form. The state-action pairs are numbered state by state, and within a state in the order
8
+ //of its actions, so that pair stateStart[s] + a is action a of state s.
9
+ struct CSRTables {
10
+ int numberOfStates = 0;
11
+ const int64_t* stateStart = nullptr; //numberOfStates+1 entries: the pairs of state s are stateStart[s], ..., stateStart[s+1]-1
12
+ const int64_t* pairStart = nullptr; //one entry more than there are pairs: the non-zero transition probabilities of pair i are pairStart[i], ..., pairStart[i+1]-1
13
+ const int* column = nullptr; //the next state of each non-zero transition probability
14
+ const double* prob = nullptr; //and the probability itself, in double precision,
15
+ const float* prob32 = nullptr; //or in single precision (float32): exactly one of the two is set
16
+ const double* reward = nullptr; //the reward of each pair
17
+ };
18
+
19
+ //A model the solver can solve. There are two ways to supply one:
20
+ // - Store the transitions and rewards as CSR tables and return them from tables(), as the
21
+ // general MDP model does. The solver then reads the arrays directly in its inner loops,
22
+ // which is much faster than calling the methods below for every transition.
23
+ // - Compute the transitions on the fly in the methods below, as the built-in TBM and CBM
24
+ // models do, and leave tables() returning nullptr. The solver then runs its routines for
25
+ // such models, which call these methods. This suits models whose transitions follow a
26
+ // formula and would take too much memory to store.
27
+ //(A special-case model of the second kind can also fill CSR tables once from its formulas
28
+ //and return them, if they fit in memory, to be solved with the fast loops.)
29
+ class ModelType {
30
+ public:
31
+
32
+ virtual ~ModelType() {}
33
+
34
+ //the model's CSR tables, or nullptr if it computes its transitions on the fly
35
+ virtual const CSRTables* tables() { return nullptr; }
36
+
37
+ virtual double getDiscount() = 0;
38
+ virtual int getNumberOfStates() = 0;
39
+ virtual void updateNumberOfActions(int &sidx) = 0;
40
+ virtual int getNumberOfActions() = 0;
41
+ virtual int getNumberOfActions(int &sidx) = 0;
42
+ virtual int * getNextState() = 0;
43
+ virtual double getPsj() = 0;
44
+ virtual double reward(int &sidx, int &aidx) = 0;
45
+ virtual double transProb(int &sidx, int &aidx, int &jidx) = 0;
46
+ virtual void updateNextState(int &sidx, int &aidx, int &jidx) = 0;
47
+ virtual int postDecisionIdx(int &sidx, int &aidx) = 0;
48
+ virtual int getColumnIdx(int &sidx, int &aidx, int &cidx) = 0;
49
+ virtual int getNumberOfJumps(int &sidx, int &aidx) = 0;
50
+
51
+ };
52
+
53
+ #endif // MODELTYPE_H