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.
- {mdpsolver-0.11.0 → mdpsolver-0.12.0}/CPP_Source_Code/GeneralMDPmodel.cpp +43 -20
- {mdpsolver-0.11.0 → mdpsolver-0.12.0}/CPP_Source_Code/GeneralMDPmodel.h +23 -7
- mdpsolver-0.12.0/CPP_Source_Code/ModelType.h +53 -0
- {mdpsolver-0.11.0 → mdpsolver-0.12.0}/CPP_Source_Code/ModifiedPolicyIteration.cpp +410 -317
- {mdpsolver-0.11.0 → mdpsolver-0.12.0}/CPP_Source_Code/ModifiedPolicyIteration.h +18 -13
- mdpsolver-0.12.0/CPP_Source_Code/ModuleInterface.cpp +1514 -0
- {mdpsolver-0.11.0 → mdpsolver-0.12.0}/CPP_Source_Code/ModuleInterface.h +24 -9
- {mdpsolver-0.11.0 → mdpsolver-0.12.0}/CPP_Source_Code/PythonModule.cpp +2 -2
- {mdpsolver-0.11.0 → mdpsolver-0.12.0}/CPP_Source_Code/Rewards.cpp +12 -27
- mdpsolver-0.12.0/CPP_Source_Code/Rewards.h +78 -0
- mdpsolver-0.12.0/CPP_Source_Code/TransitionMatrix.cpp +98 -0
- mdpsolver-0.12.0/CPP_Source_Code/TransitionMatrix.h +137 -0
- mdpsolver-0.12.0/PKG-INFO +194 -0
- {mdpsolver-0.11.0 → mdpsolver-0.12.0}/Python/src/mdpsolver/model.py +150 -25
- {mdpsolver-0.11.0 → mdpsolver-0.12.0}/Python/tests/knownsolutions.py +21 -0
- mdpsolver-0.12.0/Python/tests/test_arrays.py +357 -0
- {mdpsolver-0.11.0 → mdpsolver-0.12.0}/Python/tests/test_imports.py +222 -23
- {mdpsolver-0.11.0 → mdpsolver-0.12.0}/Python/tests/test_large.py +11 -6
- {mdpsolver-0.11.0 → mdpsolver-0.12.0}/Python/tests/test_mpi.py +10 -3
- {mdpsolver-0.11.0 → mdpsolver-0.12.0}/Python/tests/test_output.py +51 -5
- {mdpsolver-0.11.0 → mdpsolver-0.12.0}/Python/tests/test_pi.py +10 -3
- {mdpsolver-0.11.0 → mdpsolver-0.12.0}/Python/tests/test_random.py +7 -3
- {mdpsolver-0.11.0 → mdpsolver-0.12.0}/Python/tests/test_reuse.py +14 -7
- mdpsolver-0.12.0/Python/tests/test_threads.py +222 -0
- {mdpsolver-0.11.0 → mdpsolver-0.12.0}/Python/tests/test_vi.py +11 -4
- mdpsolver-0.12.0/README.md +175 -0
- {mdpsolver-0.11.0 → mdpsolver-0.12.0}/pyproject.toml +3 -1
- mdpsolver-0.11.0/CPP_Source_Code/ModelType.h +0 -23
- mdpsolver-0.11.0/CPP_Source_Code/ModuleInterface.cpp +0 -858
- mdpsolver-0.11.0/CPP_Source_Code/Rewards.h +0 -64
- mdpsolver-0.11.0/CPP_Source_Code/TransitionMatrix.cpp +0 -99
- mdpsolver-0.11.0/CPP_Source_Code/TransitionMatrix.h +0 -76
- mdpsolver-0.11.0/PKG-INFO +0 -194
- mdpsolver-0.11.0/README.md +0 -176
- {mdpsolver-0.11.0 → mdpsolver-0.12.0}/.gitignore +0 -0
- {mdpsolver-0.11.0 → mdpsolver-0.12.0}/CPP_Source_Code/CBMmodel.cpp +0 -0
- {mdpsolver-0.11.0 → mdpsolver-0.12.0}/CPP_Source_Code/CBMmodel.h +0 -0
- {mdpsolver-0.11.0 → mdpsolver-0.12.0}/CPP_Source_Code/CMakeLists.txt +0 -0
- {mdpsolver-0.11.0 → mdpsolver-0.12.0}/CPP_Source_Code/ModelType.cpp +0 -0
- {mdpsolver-0.11.0 → mdpsolver-0.12.0}/CPP_Source_Code/Policy.cpp +0 -0
- {mdpsolver-0.11.0 → mdpsolver-0.12.0}/CPP_Source_Code/Policy.h +0 -0
- {mdpsolver-0.11.0 → mdpsolver-0.12.0}/CPP_Source_Code/TBMmodel.cpp +0 -0
- {mdpsolver-0.11.0 → mdpsolver-0.12.0}/CPP_Source_Code/TBMmodel.h +0 -0
- {mdpsolver-0.11.0 → mdpsolver-0.12.0}/CPP_Source_Code/ValueVector.cpp +0 -0
- {mdpsolver-0.11.0 → mdpsolver-0.12.0}/CPP_Source_Code/ValueVector.h +0 -0
- {mdpsolver-0.11.0 → mdpsolver-0.12.0}/LICENSE +0 -0
- {mdpsolver-0.11.0 → mdpsolver-0.12.0}/Python/src/mdpsolver/__init__.py +0 -0
- {mdpsolver-0.11.0 → mdpsolver-0.12.0}/Python/tests/loadmdpsolver.py +0 -0
- {mdpsolver-0.11.0 → mdpsolver-0.12.0}/Python/tests/test_checkmodel.py +0 -0
- {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
|
-
|
|
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
|
|
73
|
+
return csr.reward[pair(sidx,aidx)];
|
|
52
74
|
}
|
|
53
75
|
|
|
54
76
|
double GeneralMDPmodel::transProb(int &sidx, int &aidx, int &jidx){
|
|
55
|
-
//
|
|
56
|
-
//
|
|
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
|
|
80
|
+
return probability(entry(sidx,aidx,jidx));
|
|
60
81
|
}
|
|
61
82
|
|
|
62
83
|
int GeneralMDPmodel::getNumberOfJumps(int &sidx, int &aidx){
|
|
63
|
-
|
|
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
|
-
|
|
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==
|
|
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==
|
|
99
|
+
if (cidx==nJumps){
|
|
77
100
|
cidx=0;
|
|
78
101
|
}
|
|
79
|
-
nextState =
|
|
80
|
-
psj =
|
|
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
|
|
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 =
|
|
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=
|
|
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
|
|
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
|
-
//
|
|
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 /*
|
|
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
|