mdplib 1.0.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.
- mdplib-1.0.0/PKG-INFO +125 -0
- mdplib-1.0.0/README.md +108 -0
- mdplib-1.0.0/mdp/__init__.py +1 -0
- mdplib-1.0.0/mdp/_core/__init__.py +10 -0
- mdplib-1.0.0/mdp/_core/mdp_core.cpp +532 -0
- mdplib-1.0.0/mdp/algorithms/__init__.py +3 -0
- mdplib-1.0.0/mdp/algorithms/pi.py +64 -0
- mdplib-1.0.0/mdp/algorithms/rl.py +125 -0
- mdplib-1.0.0/mdp/algorithms/vi.py +115 -0
- mdplib-1.0.0/mdp/core.py +113 -0
- mdplib-1.0.0/mdp/utils.py +199 -0
- mdplib-1.0.0/mdplib.egg-info/PKG-INFO +125 -0
- mdplib-1.0.0/mdplib.egg-info/SOURCES.txt +20 -0
- mdplib-1.0.0/mdplib.egg-info/dependency_links.txt +1 -0
- mdplib-1.0.0/mdplib.egg-info/requires.txt +3 -0
- mdplib-1.0.0/mdplib.egg-info/top_level.txt +1 -0
- mdplib-1.0.0/pyproject.toml +28 -0
- mdplib-1.0.0/setup.cfg +4 -0
- mdplib-1.0.0/setup.py +30 -0
- mdplib-1.0.0/tests/test_pi.py +34 -0
- mdplib-1.0.0/tests/test_rl.py +38 -0
- mdplib-1.0.0/tests/test_vi.py +40 -0
mdplib-1.0.0/PKG-INFO
ADDED
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: mdplib
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Library of algorithms for infinite-horizon, discounted Markov Decision Processes, with a C++ core
|
|
5
|
+
Author-email: Lucca Giannelli <lucca.giannelli@gmail.com>
|
|
6
|
+
Project-URL: Repository, https://github.com/LuccaGiannelli/mdplib
|
|
7
|
+
Classifier: Development Status :: 4 - Beta
|
|
8
|
+
Classifier: Programming Language :: Python :: 3
|
|
9
|
+
Classifier: Operating System :: Microsoft :: Windows
|
|
10
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
11
|
+
Classifier: Operating System :: MacOS
|
|
12
|
+
Requires-Python: >=3.8
|
|
13
|
+
Description-Content-Type: text/markdown
|
|
14
|
+
Requires-Dist: numpy
|
|
15
|
+
Requires-Dist: pandas
|
|
16
|
+
Requires-Dist: pybind11>=2.11
|
|
17
|
+
|
|
18
|
+
# mdplib
|
|
19
|
+
|
|
20
|
+
[](https://pypi.org/project/mdplib/)
|
|
21
|
+
[](https://pypi.org/project/mdplib/)
|
|
22
|
+
|
|
23
|
+
A Python library of algorithms for solving infinite-horizon, discounted **Markov Decision Processes (MDPs)**, with a performance-critical core written in C++ (via [pybind11](https://github.com/pybind/pybind11)).
|
|
24
|
+
|
|
25
|
+
Implements:
|
|
26
|
+
|
|
27
|
+
- **Value Iteration** (Jacobi and Gauss-Seidel variants)
|
|
28
|
+
- **Policy Iteration**
|
|
29
|
+
- **Q-Learning** and **SARSA** (model-free reinforcement learning)
|
|
30
|
+
|
|
31
|
+
## Installation
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
pip install mdplib
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Prebuilt wheels are published for Linux, Windows and macOS (Python 3.10-3.14), so this does **not** require a C++ compiler on your machine. If your platform/Python version has no matching wheel, pip falls back to building from source, which does require a C++17 compiler (the extension is compiled at install time):
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
git clone https://github.com/LuccaGiannelli/mdp-solver.git
|
|
41
|
+
cd mdp-solver
|
|
42
|
+
pip install .
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Basic usage
|
|
46
|
+
|
|
47
|
+
```python
|
|
48
|
+
from mdp import MDP
|
|
49
|
+
|
|
50
|
+
S = [0, 1, 2] # states
|
|
51
|
+
A = [0, 1, 2] # actions
|
|
52
|
+
|
|
53
|
+
def Pt(sn, a, sn1):
|
|
54
|
+
# returns P(sn1 | sn, a)
|
|
55
|
+
...
|
|
56
|
+
|
|
57
|
+
def rt(sn, a, sn1):
|
|
58
|
+
# returns the reward
|
|
59
|
+
...
|
|
60
|
+
|
|
61
|
+
problem = MDP(S, A, Pt, rt)
|
|
62
|
+
|
|
63
|
+
# Value Iteration
|
|
64
|
+
problem.VI(gamma=0.9, tol=1e-6)
|
|
65
|
+
problem.print_results()
|
|
66
|
+
|
|
67
|
+
# Policy Iteration
|
|
68
|
+
problem.PI(gamma=0.9, tol=1e-6)
|
|
69
|
+
problem.print_results()
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
See [`examples/basic_example.py`](examples/basic_example.py) for a complete example (a machine maintenance problem).
|
|
73
|
+
|
|
74
|
+
## Available algorithms
|
|
75
|
+
|
|
76
|
+
| Method | Description |
|
|
77
|
+
|--------|-------------|
|
|
78
|
+
| `VI` | Value Iteration (Jacobi) |
|
|
79
|
+
| `VIGS` | Value Iteration with Gauss-Seidel |
|
|
80
|
+
| `PI` | Policy Iteration |
|
|
81
|
+
| `QLearning` | Q-Learning (off-policy TD control) |
|
|
82
|
+
| `SARSA` | SARSA (on-policy TD control) |
|
|
83
|
+
|
|
84
|
+
## Common parameters
|
|
85
|
+
|
|
86
|
+
| Parameter | Description |
|
|
87
|
+
|-----------|-------------|
|
|
88
|
+
| `gamma` | Discount factor (0 ≤ γ < 1) |
|
|
89
|
+
| `tol` | Convergence tolerance |
|
|
90
|
+
| `max_iter` | Maximum number of iterations |
|
|
91
|
+
| `v0` | Initial value vector (optional) |
|
|
92
|
+
| `verbose` | Print progress on completion |
|
|
93
|
+
| `norm_type` | 0 = relative sup norm, 1 = sup norm, 2 = euclidean norm |
|
|
94
|
+
| `epsilon` | Final epsilon for the epsilon-greedy policy (Q-Learning / SARSA) |
|
|
95
|
+
| `alpha` | Learning rate (Q-Learning / SARSA) |
|
|
96
|
+
|
|
97
|
+
## How it works
|
|
98
|
+
|
|
99
|
+
You define the state space `S`, action space `A`, a transition probability function `Pt(sn, a, sn1)`, and a reward function `rt(sn, a, sn1)`. The constructor enumerates all feasible transitions into a CSV (`sn,a,sn1,prob,reward`) and loads it into a NumPy array; the algorithms then hand that array to the C++ core, which does the inner loops with direct memory access for performance.
|
|
100
|
+
|
|
101
|
+
After solving, results are available as:
|
|
102
|
+
|
|
103
|
+
| Attribute | Description |
|
|
104
|
+
|-----------|-------------|
|
|
105
|
+
| `value` | optimal value for each state |
|
|
106
|
+
| `policy` | optimal action for each state |
|
|
107
|
+
| `time` | execution time (seconds) |
|
|
108
|
+
| `n_iterations` | number of iterations to convergence |
|
|
109
|
+
|
|
110
|
+
## Adding a new algorithm
|
|
111
|
+
|
|
112
|
+
1. Create `mdp/algorithms/new_algo.py` with a function `def NewAlgo(self, ...):`
|
|
113
|
+
2. Import it in `mdp/algorithms/__init__.py`
|
|
114
|
+
3. Attach it to the class in `mdp/core.py`: `NewAlgo = NewAlgo`
|
|
115
|
+
|
|
116
|
+
## Tests
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
pip install pytest
|
|
120
|
+
pytest tests/
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
## License
|
|
124
|
+
|
|
125
|
+
TBD.
|
mdplib-1.0.0/README.md
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
# mdplib
|
|
2
|
+
|
|
3
|
+
[](https://pypi.org/project/mdplib/)
|
|
4
|
+
[](https://pypi.org/project/mdplib/)
|
|
5
|
+
|
|
6
|
+
A Python library of algorithms for solving infinite-horizon, discounted **Markov Decision Processes (MDPs)**, with a performance-critical core written in C++ (via [pybind11](https://github.com/pybind/pybind11)).
|
|
7
|
+
|
|
8
|
+
Implements:
|
|
9
|
+
|
|
10
|
+
- **Value Iteration** (Jacobi and Gauss-Seidel variants)
|
|
11
|
+
- **Policy Iteration**
|
|
12
|
+
- **Q-Learning** and **SARSA** (model-free reinforcement learning)
|
|
13
|
+
|
|
14
|
+
## Installation
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
pip install mdplib
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Prebuilt wheels are published for Linux, Windows and macOS (Python 3.10-3.14), so this does **not** require a C++ compiler on your machine. If your platform/Python version has no matching wheel, pip falls back to building from source, which does require a C++17 compiler (the extension is compiled at install time):
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
git clone https://github.com/LuccaGiannelli/mdp-solver.git
|
|
24
|
+
cd mdp-solver
|
|
25
|
+
pip install .
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Basic usage
|
|
29
|
+
|
|
30
|
+
```python
|
|
31
|
+
from mdp import MDP
|
|
32
|
+
|
|
33
|
+
S = [0, 1, 2] # states
|
|
34
|
+
A = [0, 1, 2] # actions
|
|
35
|
+
|
|
36
|
+
def Pt(sn, a, sn1):
|
|
37
|
+
# returns P(sn1 | sn, a)
|
|
38
|
+
...
|
|
39
|
+
|
|
40
|
+
def rt(sn, a, sn1):
|
|
41
|
+
# returns the reward
|
|
42
|
+
...
|
|
43
|
+
|
|
44
|
+
problem = MDP(S, A, Pt, rt)
|
|
45
|
+
|
|
46
|
+
# Value Iteration
|
|
47
|
+
problem.VI(gamma=0.9, tol=1e-6)
|
|
48
|
+
problem.print_results()
|
|
49
|
+
|
|
50
|
+
# Policy Iteration
|
|
51
|
+
problem.PI(gamma=0.9, tol=1e-6)
|
|
52
|
+
problem.print_results()
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
See [`examples/basic_example.py`](examples/basic_example.py) for a complete example (a machine maintenance problem).
|
|
56
|
+
|
|
57
|
+
## Available algorithms
|
|
58
|
+
|
|
59
|
+
| Method | Description |
|
|
60
|
+
|--------|-------------|
|
|
61
|
+
| `VI` | Value Iteration (Jacobi) |
|
|
62
|
+
| `VIGS` | Value Iteration with Gauss-Seidel |
|
|
63
|
+
| `PI` | Policy Iteration |
|
|
64
|
+
| `QLearning` | Q-Learning (off-policy TD control) |
|
|
65
|
+
| `SARSA` | SARSA (on-policy TD control) |
|
|
66
|
+
|
|
67
|
+
## Common parameters
|
|
68
|
+
|
|
69
|
+
| Parameter | Description |
|
|
70
|
+
|-----------|-------------|
|
|
71
|
+
| `gamma` | Discount factor (0 ≤ γ < 1) |
|
|
72
|
+
| `tol` | Convergence tolerance |
|
|
73
|
+
| `max_iter` | Maximum number of iterations |
|
|
74
|
+
| `v0` | Initial value vector (optional) |
|
|
75
|
+
| `verbose` | Print progress on completion |
|
|
76
|
+
| `norm_type` | 0 = relative sup norm, 1 = sup norm, 2 = euclidean norm |
|
|
77
|
+
| `epsilon` | Final epsilon for the epsilon-greedy policy (Q-Learning / SARSA) |
|
|
78
|
+
| `alpha` | Learning rate (Q-Learning / SARSA) |
|
|
79
|
+
|
|
80
|
+
## How it works
|
|
81
|
+
|
|
82
|
+
You define the state space `S`, action space `A`, a transition probability function `Pt(sn, a, sn1)`, and a reward function `rt(sn, a, sn1)`. The constructor enumerates all feasible transitions into a CSV (`sn,a,sn1,prob,reward`) and loads it into a NumPy array; the algorithms then hand that array to the C++ core, which does the inner loops with direct memory access for performance.
|
|
83
|
+
|
|
84
|
+
After solving, results are available as:
|
|
85
|
+
|
|
86
|
+
| Attribute | Description |
|
|
87
|
+
|-----------|-------------|
|
|
88
|
+
| `value` | optimal value for each state |
|
|
89
|
+
| `policy` | optimal action for each state |
|
|
90
|
+
| `time` | execution time (seconds) |
|
|
91
|
+
| `n_iterations` | number of iterations to convergence |
|
|
92
|
+
|
|
93
|
+
## Adding a new algorithm
|
|
94
|
+
|
|
95
|
+
1. Create `mdp/algorithms/new_algo.py` with a function `def NewAlgo(self, ...):`
|
|
96
|
+
2. Import it in `mdp/algorithms/__init__.py`
|
|
97
|
+
3. Attach it to the class in `mdp/core.py`: `NewAlgo = NewAlgo`
|
|
98
|
+
|
|
99
|
+
## Tests
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
pip install pytest
|
|
103
|
+
pytest tests/
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
## License
|
|
107
|
+
|
|
108
|
+
TBD.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from mdp.core import MDP
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# Import the compiled C++ module
|
|
2
|
+
try:
|
|
3
|
+
from mdp._core import _mdp_core
|
|
4
|
+
except ImportError as e:
|
|
5
|
+
raise ImportError(
|
|
6
|
+
"The C++ module '_mdp_core' was not compiled. This usually means no "
|
|
7
|
+
"prebuilt wheel was available for your platform/Python version and "
|
|
8
|
+
"the source build failed. Install a C++17 compiler and re-run "
|
|
9
|
+
"'pip install mdplib' (or 'pip install .' from the repository root)."
|
|
10
|
+
) from e
|