mdpsolver 0.9.9__tar.gz → 0.9.10__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 (42) hide show
  1. {mdpsolver-0.9.9/src/mdpsolver.egg-info → mdpsolver-0.9.10}/PKG-INFO +3 -7
  2. {mdpsolver-0.9.9 → mdpsolver-0.9.10}/README.md +1 -5
  3. {mdpsolver-0.9.9 → mdpsolver-0.9.10}/pyproject.toml +2 -2
  4. mdpsolver-0.9.10/src/mdpsolver/__pycache__/__init__.cpython-313.pyc +0 -0
  5. mdpsolver-0.9.10/src/mdpsolver/__pycache__/__init__.cpython-314.pyc +0 -0
  6. mdpsolver-0.9.10/src/mdpsolver/__pycache__/model.cpython-313.pyc +0 -0
  7. mdpsolver-0.9.10/src/mdpsolver/__pycache__/model.cpython-314.pyc +0 -0
  8. {mdpsolver-0.9.9 → mdpsolver-0.9.10}/src/mdpsolver/model.py +53 -31
  9. mdpsolver-0.9.10/src/mdpsolver/solvermodule.cp310-win_amd64.pyd +0 -0
  10. mdpsolver-0.9.10/src/mdpsolver/solvermodule.cp311-win_amd64.pyd +0 -0
  11. mdpsolver-0.9.10/src/mdpsolver/solvermodule.cp312-win_amd64.pyd +0 -0
  12. mdpsolver-0.9.10/src/mdpsolver/solvermodule.cp313-win_amd64.pyd +0 -0
  13. mdpsolver-0.9.10/src/mdpsolver/solvermodule.cp314-win_amd64.pyd +0 -0
  14. mdpsolver-0.9.10/src/mdpsolver/solvermodule.cpython-310-x86_64-linux-gnu.so +0 -0
  15. mdpsolver-0.9.10/src/mdpsolver/solvermodule.cpython-311-x86_64-linux-gnu.so +0 -0
  16. mdpsolver-0.9.10/src/mdpsolver/solvermodule.cpython-312-x86_64-linux-gnu.so +0 -0
  17. mdpsolver-0.9.10/src/mdpsolver/solvermodule.cpython-313-x86_64-linux-gnu.so +0 -0
  18. mdpsolver-0.9.10/src/mdpsolver/solvermodule.cpython-314-x86_64-linux-gnu.so +0 -0
  19. {mdpsolver-0.9.9 → mdpsolver-0.9.10/src/mdpsolver.egg-info}/PKG-INFO +3 -7
  20. {mdpsolver-0.9.9 → mdpsolver-0.9.10}/src/mdpsolver.egg-info/SOURCES.txt +9 -3
  21. mdpsolver-0.9.10/tests/test1.py +717 -0
  22. mdpsolver-0.9.10/tests/test2.py +91 -0
  23. mdpsolver-0.9.9/src/mdpsolver/problems/cbmaux.py +0 -40
  24. mdpsolver-0.9.9/src/mdpsolver/problems/tbmaux.py +0 -40
  25. mdpsolver-0.9.9/src/mdpsolver/solvermodule.cp310-win_amd64.pyd +0 -0
  26. mdpsolver-0.9.9/src/mdpsolver/solvermodule.cp311-win_amd64.pyd +0 -0
  27. mdpsolver-0.9.9/src/mdpsolver/solvermodule.cp312-win_amd64.pyd +0 -0
  28. mdpsolver-0.9.9/src/mdpsolver/solvermodule.cp313-win_amd64.pyd +0 -0
  29. mdpsolver-0.9.9/src/mdpsolver/solvermodule.cpython-310-x86_64-linux-gnu.so +0 -0
  30. mdpsolver-0.9.9/src/mdpsolver/solvermodule.cpython-311-x86_64-linux-gnu.so +0 -0
  31. mdpsolver-0.9.9/src/mdpsolver/solvermodule.cpython-312-x86_64-linux-gnu.so +0 -0
  32. mdpsolver-0.9.9/src/mdpsolver/solvermodule.cpython-313-x86_64-linux-gnu.so +0 -0
  33. {mdpsolver-0.9.9 → mdpsolver-0.9.10}/LICENSE +0 -0
  34. {mdpsolver-0.9.9 → mdpsolver-0.9.10}/MANIFEST.in +0 -0
  35. {mdpsolver-0.9.9 → mdpsolver-0.9.10}/setup.cfg +0 -0
  36. {mdpsolver-0.9.9 → mdpsolver-0.9.10}/src/mdpsolver/__init__.py +0 -0
  37. {mdpsolver-0.9.9 → mdpsolver-0.9.10}/src/mdpsolver/problems/__pycache__/cbmaux.cpython-310.pyc +0 -0
  38. {mdpsolver-0.9.9 → mdpsolver-0.9.10}/src/mdpsolver/problems/__pycache__/tbmaux.cpython-310.pyc +0 -0
  39. {mdpsolver-0.9.9 → mdpsolver-0.9.10}/src/mdpsolver.egg-info/dependency_links.txt +0 -0
  40. {mdpsolver-0.9.9 → mdpsolver-0.9.10}/src/mdpsolver.egg-info/top_level.txt +0 -0
  41. mdpsolver-0.9.9/tests/test1.py → mdpsolver-0.9.10/tests/test1_pip.py +1 -1
  42. mdpsolver-0.9.9/tests/test2.py → mdpsolver-0.9.10/tests/test2_pip.py +1 -1
@@ -1,11 +1,11 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mdpsolver
3
- Version: 0.9.9
3
+ Version: 0.9.10
4
4
  Summary: A fast solver for Markov Decision Processes
5
5
  Author-email: Anders Reenberg Andersen <andersra@live.dk>, Jesper Fink Andersen <jesperfinkandersen@gmail.com>
6
6
  Project-URL: Homepage, https://github.com/areenberg/MDPSolver
7
7
  Project-URL: Issues, https://github.com/areenberg/MDPSolver/issues
8
- Classifier: Development Status :: 3 - Alpha
8
+ Classifier: Development Status :: 4 - Beta
9
9
  Classifier: Programming Language :: Python :: 3
10
10
  Classifier: License :: OSI Approved :: MIT License
11
11
  Classifier: Operating System :: Microsoft :: Windows
@@ -17,8 +17,6 @@ Dynamic: license-file
17
17
 
18
18
  # MDPSolver
19
19
 
20
- <img src="https://github.com/areenberg/MDPSolver/blob/anders_development/Images/MDPSolver_logo_3.png" alt="Logo" width="180">
21
-
22
20
  MDPSolver is a Python package for large Markov Decision Processes (MDPs) with infinite-horizons.
23
21
 
24
22
  ## Features
@@ -40,11 +38,9 @@ Install directly from PyPI with:
40
38
  pip install mdpsolver
41
39
  ```
42
40
 
43
- MDPSolver works *out of the box* on Ubuntu 22 and newer.
44
-
45
41
  ### GLIBC not found
46
42
 
47
- Some users will encounter the `version 'GLIBC_2.32' not found` error when attempting to import MDPSolver in Python. In this case, it might help to manually compile and replace the SO-file for the optimization module in the MDPSolver package. See the steps on how to solve the issue in the [documentation](https://github.com/areenberg/MDPSolver/wiki#how-to-install).
43
+ Some users will encounter the `version 'GLIBC_2.38' not found` error when attempting to import MDPSolver in Python. The issue can be resolved by manually compiling and replacing the SO-file for the optimization module in the MDPSolver package. See the steps on how to solve the issue in the [documentation](https://github.com/areenberg/MDPSolver/wiki#how-to-install).
48
44
 
49
45
  ## Windows
50
46
 
@@ -1,7 +1,5 @@
1
1
  # MDPSolver
2
2
 
3
- <img src="https://github.com/areenberg/MDPSolver/blob/anders_development/Images/MDPSolver_logo_3.png" alt="Logo" width="180">
4
-
5
3
  MDPSolver is a Python package for large Markov Decision Processes (MDPs) with infinite-horizons.
6
4
 
7
5
  ## Features
@@ -23,11 +21,9 @@ Install directly from PyPI with:
23
21
  pip install mdpsolver
24
22
  ```
25
23
 
26
- MDPSolver works *out of the box* on Ubuntu 22 and newer.
27
-
28
24
  ### GLIBC not found
29
25
 
30
- Some users will encounter the `version 'GLIBC_2.32' not found` error when attempting to import MDPSolver in Python. In this case, it might help to manually compile and replace the SO-file for the optimization module in the MDPSolver package. See the steps on how to solve the issue in the [documentation](https://github.com/areenberg/MDPSolver/wiki#how-to-install).
26
+ Some users will encounter the `version 'GLIBC_2.38' not found` error when attempting to import MDPSolver in Python. The issue can be resolved by manually compiling and replacing the SO-file for the optimization module in the MDPSolver package. See the steps on how to solve the issue in the [documentation](https://github.com/areenberg/MDPSolver/wiki#how-to-install).
31
27
 
32
28
  ## Windows
33
29
 
@@ -10,7 +10,7 @@ where = ["src"]
10
10
 
11
11
  [project]
12
12
  name = "mdpsolver"
13
- version = "0.9.9"
13
+ version = "0.9.10"
14
14
  authors = [
15
15
  { name="Anders Reenberg Andersen", email="andersra@live.dk" },
16
16
  { name="Jesper Fink Andersen", email="jesperfinkandersen@gmail.com" },
@@ -19,7 +19,7 @@ description = "A fast solver for Markov Decision Processes"
19
19
  readme = "README.md"
20
20
  requires-python = ">=3.10"
21
21
  classifiers = [
22
- "Development Status :: 3 - Alpha",
22
+ "Development Status :: 4 - Beta",
23
23
  "Programming Language :: Python :: 3",
24
24
  "License :: OSI Approved :: MIT License",
25
25
  "Operating System :: Microsoft :: Windows",
@@ -6,9 +6,9 @@ and solve Markov Decision Processes (MDPs). It provides methods to configure the
6
6
  solve it, and extract the resulting policy and value vectors.
7
7
  """
8
8
 
9
+ import sys
9
10
  from mdpsolver import solvermodule
10
11
 
11
-
12
12
  class model:
13
13
  """
14
14
  Creates an MDPSolver object.
@@ -27,19 +27,19 @@ class model:
27
27
 
28
28
  def solve(
29
29
  self,
30
- algorithm="mpi",
31
- tolerance=1e-3,
32
- update="standard",
33
- criterion="discounted",
34
- parIterLim=100,
35
- SORrelaxation=1.0,
36
- initPolicy=list(),
37
- initValueVector=list(),
38
- verbose=False,
39
- postProcessing=True,
40
- makeFinalCheck=True,
41
- parallel=True,
42
- ):
30
+ algorithm: str = "mpi",
31
+ tolerance: float = 1e-3,
32
+ update: str = "standard",
33
+ criterion: str = "discounted",
34
+ parIterLim: int = 100,
35
+ SORrelaxation: float = 1.0,
36
+ initPolicy: list = list(),
37
+ initValueVector: list = list(),
38
+ verbose: bool = False,
39
+ postProcessing: bool = True,
40
+ makeFinalCheck: bool = True,
41
+ parallel: bool = True,
42
+ ) -> None:
43
43
  """
44
44
  Derive an epsilon-optimal policy for the selected MDP model.
45
45
 
@@ -60,6 +60,20 @@ class model:
60
60
  Returns:
61
61
  None
62
62
  """
63
+
64
+ if not (algorithm == "mpi" or algorithm == "pi" or algorithm == "vi"):
65
+ sys.exit("Error: Algorithm type not recognized. Select either: 'mpi', 'pi', or 'vi'.")
66
+ if tolerance <= 0.0:
67
+ sys.exit("Error: The tolerance needs to be a positive number.")
68
+ if not (update == "standard" or update == "gs" or update == "sor"):
69
+ sys.exit("Error: Update method not recognized. Select either: 'standard', 'gs', or 'sor'.")
70
+ if not (criterion == "discounted" or criterion == "average"):
71
+ sys.exit("Error: Optimality criterion not recognized. Select either: 'discounted' or 'average'.")
72
+ if parIterLim <= 0 and algorithm == "mpi":
73
+ sys.exit("Error: The partial evaluation limit needs to be a positive number.")
74
+ if (SORrelaxation <= 0.0 or SORrelaxation >= 2.0) and update == "sor":
75
+ sys.exit("Error: The relaxation parameter needs to be between 0.0 and 2.0 (i.e. 0 < SORrelaxation < 2).")
76
+
63
77
  self.mdl.solve(
64
78
  algorithm=algorithm,
65
79
  tolerance=tolerance,
@@ -75,7 +89,7 @@ class model:
75
89
  parallel=parallel,
76
90
  )
77
91
 
78
- def getRuntime(self):
92
+ def getRuntime(self) -> float:
79
93
  """
80
94
  Get the runtime of the last solver execution.
81
95
 
@@ -84,15 +98,15 @@ class model:
84
98
  """
85
99
  return self.mdl.getRuntime()
86
100
 
87
- def printPolicy(self):
101
+ def printPolicy(self) -> None:
88
102
  """Print the entire policy to the terminal."""
89
103
  self.mdl.printPolicy()
90
104
 
91
- def printValueVector(self):
105
+ def printValueVector(self) -> None:
92
106
  """Print the entire value vector to the terminal."""
93
107
  self.mdl.printValueVector()
94
108
 
95
- def getAction(self, stateIndex=0):
109
+ def getAction(self, stateIndex: int = 0) -> int:
96
110
  """
97
111
  Get the action from the optimized policy for a specific state.
98
112
 
@@ -104,7 +118,7 @@ class model:
104
118
  """
105
119
  return self.mdl.getAction(stateIndex=stateIndex)
106
120
 
107
- def getValue(self, stateIndex=0):
121
+ def getValue(self, stateIndex: int = 0) -> float:
108
122
  """
109
123
  Get the value from the optimized value vector for a specific state.
110
124
 
@@ -116,7 +130,7 @@ class model:
116
130
  """
117
131
  return self.mdl.getValue(stateIndex=stateIndex)
118
132
 
119
- def getPolicy(self):
133
+ def getPolicy(self) -> list:
120
134
  """
121
135
  Get the entire optimized policy.
122
136
 
@@ -134,7 +148,7 @@ class model:
134
148
  """
135
149
  return self.mdl.getValueVector()
136
150
 
137
- def saveToFile(self, fileName="result.csv", type="policy"):
151
+ def saveToFile(self, fileName: str = "result.csv", type: str = "policy") -> None:
138
152
  """
139
153
  Save the optimized policy or value vector to a file.
140
154
 
@@ -145,20 +159,24 @@ class model:
145
159
  Returns:
146
160
  None
147
161
  """
162
+
163
+ if not (type == "policy" or type == "value"):
164
+ sys.exit("Error: Type not recognized. Select either: 'policy' or 'value'.")
165
+
148
166
  return self.mdl.saveToFile(fileName=fileName, type=type)
149
167
 
150
168
  def mdp(
151
169
  self,
152
- discount=0.99,
153
- rewards=list(),
154
- rewardsElementwise=list(),
155
- rewardsFromFile="rewards.csv",
156
- tranMatWithZeros=list(),
157
- tranMatElementwise=list(),
158
- tranMatProbs=list(),
159
- tranMatColumns=list(),
160
- tranMatFromFile="transitions.csv",
161
- ):
170
+ discount: float = 0.99,
171
+ rewards: list = list(),
172
+ rewardsElementwise: list = list(),
173
+ rewardsFromFile: str = "rewards.csv",
174
+ tranMatWithZeros: list = list(),
175
+ tranMatElementwise: list = list(),
176
+ tranMatProbs: list = list(),
177
+ tranMatColumns: list = list(),
178
+ tranMatFromFile: str = "transitions.csv",
179
+ ) -> None:
162
180
  """
163
181
  Define the generic MDP model.
164
182
 
@@ -176,6 +194,10 @@ class model:
176
194
  Returns:
177
195
  None
178
196
  """
197
+
198
+ if discount <= 0.0 or discount >= 1.0:
199
+ sys.exit("Error: The discount needs to be in the interval between 0.0 and 1.0 (i.e. 0 < discount < 1).")
200
+
179
201
  self.mdl.mdp(
180
202
  discount=discount,
181
203
  rewards=rewards,
@@ -1,11 +1,11 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mdpsolver
3
- Version: 0.9.9
3
+ Version: 0.9.10
4
4
  Summary: A fast solver for Markov Decision Processes
5
5
  Author-email: Anders Reenberg Andersen <andersra@live.dk>, Jesper Fink Andersen <jesperfinkandersen@gmail.com>
6
6
  Project-URL: Homepage, https://github.com/areenberg/MDPSolver
7
7
  Project-URL: Issues, https://github.com/areenberg/MDPSolver/issues
8
- Classifier: Development Status :: 3 - Alpha
8
+ Classifier: Development Status :: 4 - Beta
9
9
  Classifier: Programming Language :: Python :: 3
10
10
  Classifier: License :: OSI Approved :: MIT License
11
11
  Classifier: Operating System :: Microsoft :: Windows
@@ -17,8 +17,6 @@ Dynamic: license-file
17
17
 
18
18
  # MDPSolver
19
19
 
20
- <img src="https://github.com/areenberg/MDPSolver/blob/anders_development/Images/MDPSolver_logo_3.png" alt="Logo" width="180">
21
-
22
20
  MDPSolver is a Python package for large Markov Decision Processes (MDPs) with infinite-horizons.
23
21
 
24
22
  ## Features
@@ -40,11 +38,9 @@ Install directly from PyPI with:
40
38
  pip install mdpsolver
41
39
  ```
42
40
 
43
- MDPSolver works *out of the box* on Ubuntu 22 and newer.
44
-
45
41
  ### GLIBC not found
46
42
 
47
- Some users will encounter the `version 'GLIBC_2.32' not found` error when attempting to import MDPSolver in Python. In this case, it might help to manually compile and replace the SO-file for the optimization module in the MDPSolver package. See the steps on how to solve the issue in the [documentation](https://github.com/areenberg/MDPSolver/wiki#how-to-install).
43
+ Some users will encounter the `version 'GLIBC_2.38' not found` error when attempting to import MDPSolver in Python. The issue can be resolved by manually compiling and replacing the SO-file for the optimization module in the MDPSolver package. See the steps on how to solve the issue in the [documentation](https://github.com/areenberg/MDPSolver/wiki#how-to-install).
48
44
 
49
45
  ## Windows
50
46
 
@@ -8,17 +8,23 @@ src/mdpsolver/solvermodule.cp310-win_amd64.pyd
8
8
  src/mdpsolver/solvermodule.cp311-win_amd64.pyd
9
9
  src/mdpsolver/solvermodule.cp312-win_amd64.pyd
10
10
  src/mdpsolver/solvermodule.cp313-win_amd64.pyd
11
+ src/mdpsolver/solvermodule.cp314-win_amd64.pyd
11
12
  src/mdpsolver/solvermodule.cpython-310-x86_64-linux-gnu.so
12
13
  src/mdpsolver/solvermodule.cpython-311-x86_64-linux-gnu.so
13
14
  src/mdpsolver/solvermodule.cpython-312-x86_64-linux-gnu.so
14
15
  src/mdpsolver/solvermodule.cpython-313-x86_64-linux-gnu.so
16
+ src/mdpsolver/solvermodule.cpython-314-x86_64-linux-gnu.so
15
17
  src/mdpsolver.egg-info/PKG-INFO
16
18
  src/mdpsolver.egg-info/SOURCES.txt
17
19
  src/mdpsolver.egg-info/dependency_links.txt
18
20
  src/mdpsolver.egg-info/top_level.txt
19
- src/mdpsolver/problems/cbmaux.py
20
- src/mdpsolver/problems/tbmaux.py
21
+ src/mdpsolver/__pycache__/__init__.cpython-313.pyc
22
+ src/mdpsolver/__pycache__/__init__.cpython-314.pyc
23
+ src/mdpsolver/__pycache__/model.cpython-313.pyc
24
+ src/mdpsolver/__pycache__/model.cpython-314.pyc
21
25
  src/mdpsolver/problems/__pycache__/cbmaux.cpython-310.pyc
22
26
  src/mdpsolver/problems/__pycache__/tbmaux.cpython-310.pyc
23
27
  tests/test1.py
24
- tests/test2.py
28
+ tests/test1_pip.py
29
+ tests/test2.py
30
+ tests/test2_pip.py
@@ -0,0 +1,717 @@
1
+ import random
2
+ import sys
3
+ import os
4
+ import numpy as np
5
+ from random import randint
6
+ project_root = os.path.dirname(os.path.abspath(__file__))
7
+ src_path = os.path.join(project_root, "..", "src")
8
+ sys.path.append(os.path.abspath(src_path))
9
+ import mdpsolver
10
+
11
+ # TEST 1
12
+ # Simple MDP with 3 states and 2 actions in each state.
13
+
14
+ # ---------------------------------------
15
+ # CONFIGURATION 1
16
+ # ---------------------------------------
17
+
18
+ # rewards
19
+ # 1st index: from (current) states
20
+ # 2nd index: actions
21
+ rewards = [[5, -1], [1, -2], [50, 0]]
22
+
23
+ # transition probabilities
24
+ # 1st index: from (current) states
25
+ # 2nd index: actions
26
+ # 3rd index: to (next) states
27
+ tranMatWithZeros = [
28
+ [[0.9, 0.1, 0.0], [0.1, 0.9, 0.0]],
29
+ [[0.4, 0.5, 0.1], [0.3, 0.5, 0.2]],
30
+ [[0.2, 0.2, 0.6], [0.5, 0.5, 0.0]],
31
+ ]
32
+
33
+ # initial policy
34
+ random.seed(10)
35
+ initPolicy = [randint(0, 1) for p in range(0, 3)]
36
+
37
+ # Model 1a (discounted reward, parallel)
38
+ mdl1a = mdpsolver.model()
39
+ mdl1a.mdp(discount=0.95, rewards=rewards, tranMatWithZeros=tranMatWithZeros)
40
+ mdl1a.solve(algorithm="mpi", update="standard", parallel=True, initPolicy=initPolicy)
41
+ if not np.array_equal(np.array(mdl1a.getPolicy()), np.array([1, 1, 0])):
42
+ sys.exit("Model 1a failed!")
43
+ if not np.array_equal(
44
+ np.round(np.array(mdl1a.getValueVector()), 3),
45
+ np.round(np.array([200.00114718191236, 212.86672887958622, 298.7090458676583]), 3),
46
+ ):
47
+ sys.exit("Model 1a failed!")
48
+
49
+ # Model 2a (discounted reward, parallel)
50
+ mdl2a = mdpsolver.model()
51
+ mdl2a.mdp(discount=0.95, rewards=rewards, tranMatWithZeros=tranMatWithZeros)
52
+ mdl2a.solve(algorithm="pi", update="standard", parallel=True, initPolicy=initPolicy)
53
+ if not np.array_equal(np.array(mdl2a.getPolicy()), np.array([1, 1, 0])):
54
+ sys.exit("Model 2a failed!")
55
+ if not np.array_equal(
56
+ np.round(np.array(mdl2a.getValueVector()), 3),
57
+ np.round(np.array([200.00114718191236, 212.86672887958622, 298.7090458676583]), 3),
58
+ ):
59
+ sys.exit("Model 2a failed!")
60
+
61
+ # Model 3a (discounted reward, parallel)
62
+ mdl3a = mdpsolver.model()
63
+ mdl3a.mdp(discount=0.95, rewards=rewards, tranMatWithZeros=tranMatWithZeros)
64
+ mdl3a.solve(algorithm="vi", update="standard", parallel=True)
65
+ if not np.array_equal(np.array(mdl3a.getPolicy()), np.array([1, 1, 0])):
66
+ sys.exit("Model 3a failed!")
67
+ if not np.array_equal(
68
+ np.round(np.array(mdl3a.getValueVector()), 3),
69
+ np.round(np.array([200.0013199959708, 212.86689665815788, 298.709197760198]), 3),
70
+ ):
71
+ sys.exit("Model 3a failed!")
72
+
73
+ # Model 1b (discounted reward, unparallel)
74
+ mdl1b = mdpsolver.model()
75
+ mdl1b.mdp(discount=0.95, rewards=rewards, tranMatWithZeros=tranMatWithZeros)
76
+ mdl1b.solve(algorithm="mpi", update="standard", parallel=False, initPolicy=initPolicy)
77
+ if not np.array_equal(np.array(mdl1b.getPolicy()), np.array([1, 1, 0])):
78
+ sys.exit("Model 1b failed!")
79
+ if not np.array_equal(
80
+ np.round(np.array(mdl1b.getValueVector()), 3),
81
+ np.round(np.array([200.00114718191236, 212.86672887958622, 298.7090458676583]), 3),
82
+ ):
83
+ sys.exit("Model 1b failed!")
84
+
85
+ # Model 2b (discounted reward, unparallel)
86
+ mdl2b = mdpsolver.model()
87
+ mdl2b.mdp(discount=0.95, rewards=rewards, tranMatWithZeros=tranMatWithZeros)
88
+ mdl2b.solve(algorithm="pi", update="standard", parallel=False, initPolicy=initPolicy)
89
+ if not np.array_equal(np.array(mdl2b.getPolicy()), np.array([1, 1, 0])):
90
+ sys.exit("Model 2b failed!")
91
+ if not np.array_equal(
92
+ np.round(np.array(mdl2b.getValueVector()), 3),
93
+ np.round(np.array([200.00114718191236, 212.86672887958622, 298.7090458676583]), 3),
94
+ ):
95
+ sys.exit("Model 2b failed!")
96
+
97
+ # Model 3b (discounted reward, unparallel)
98
+ mdl3b = mdpsolver.model()
99
+ mdl3b.mdp(discount=0.95, rewards=rewards, tranMatWithZeros=tranMatWithZeros)
100
+ mdl3b.solve(algorithm="vi", update="standard", parallel=False)
101
+ if not np.array_equal(np.array(mdl3b.getPolicy()), np.array([1, 1, 0])):
102
+ sys.exit("Model 3b failed!")
103
+ if not np.array_equal(
104
+ np.round(np.array(mdl3b.getValueVector()), 3),
105
+ np.round(np.array([200.0013199959708, 212.86689665815788, 298.709197760198]), 3),
106
+ ):
107
+ sys.exit("Model 3b failed!")
108
+
109
+ # Model 1a (average reward, parallel)
110
+ mdl1a = mdpsolver.model()
111
+ mdl1a.mdp(rewards=rewards, tranMatWithZeros=tranMatWithZeros)
112
+ mdl1a.solve(
113
+ algorithm="mpi",
114
+ update="standard",
115
+ criterion="average",
116
+ parallel=True,
117
+ initPolicy=initPolicy,
118
+ )
119
+ if not np.array_equal(np.array(mdl1a.getPolicy()), np.array([1, 1, 0])):
120
+ sys.exit("Model 1a failed!")
121
+ if not np.array_equal(
122
+ np.round(np.array(mdl1a.getValueVector()), 3),
123
+ np.round(np.array([354.2101307157537, 368.21018917357264, 457.21037278800077]), 3),
124
+ ):
125
+ sys.exit("Model 1a failed!")
126
+
127
+ # Model 2a (average reward, parallel)
128
+ mdl2a = mdpsolver.model()
129
+ mdl2a.mdp(rewards=rewards, tranMatWithZeros=tranMatWithZeros)
130
+ mdl2a.solve(
131
+ algorithm="pi",
132
+ update="standard",
133
+ criterion="average",
134
+ parallel=True,
135
+ initPolicy=initPolicy,
136
+ )
137
+ if not np.array_equal(np.array(mdl2a.getPolicy()), np.array([1, 1, 0])):
138
+ sys.exit("Model 2a failed!")
139
+ if not np.array_equal(
140
+ np.round(np.array(mdl2a.getValueVector()), 3),
141
+ np.round(np.array([354.2101307157537, 368.21018917357264, 457.21037278800077]), 3),
142
+ ):
143
+ sys.exit("Model 2a failed!")
144
+
145
+ # Model 3a (average reward, parallel)
146
+ mdl3a = mdpsolver.model()
147
+ mdl3a.mdp(rewards=rewards, tranMatWithZeros=tranMatWithZeros)
148
+ mdl3a.solve(algorithm="vi", update="standard", criterion="average", parallel=True)
149
+ if not np.array_equal(np.array(mdl3a.getPolicy()), np.array([1, 1, 0])):
150
+ sys.exit("Model 3a failed!")
151
+ if not np.array_equal(
152
+ np.round(np.array(mdl3a.getValueVector()), 3),
153
+ np.round(np.array([158.23345351808334, 172.23340169038516, 261.233237936489]), 3),
154
+ ):
155
+ sys.exit("Model 3a failed!")
156
+
157
+ # Model 1b (average reward, unparallel)
158
+ mdl1b = mdpsolver.model()
159
+ mdl1b.mdp(rewards=rewards, tranMatWithZeros=tranMatWithZeros)
160
+ mdl1b.solve(
161
+ algorithm="mpi",
162
+ update="standard",
163
+ criterion="average",
164
+ parallel=False,
165
+ initPolicy=initPolicy,
166
+ )
167
+ if not np.array_equal(np.array(mdl1b.getPolicy()), np.array([1, 1, 0])):
168
+ sys.exit("Model 1b failed!")
169
+ if not np.array_equal(
170
+ np.round(np.array(mdl1b.getValueVector()), 3),
171
+ np.round(np.array([354.2101307157537, 368.21018917357264, 457.21037278800077]), 3),
172
+ ):
173
+ sys.exit("Model 1b failed!")
174
+
175
+ # Model 2b (average reward, unparallel)
176
+ mdl2b = mdpsolver.model()
177
+ mdl2b.mdp(rewards=rewards, tranMatWithZeros=tranMatWithZeros)
178
+ mdl2b.solve(
179
+ algorithm="pi",
180
+ update="standard",
181
+ criterion="average",
182
+ parallel=False,
183
+ initPolicy=initPolicy,
184
+ )
185
+ if not np.array_equal(np.array(mdl2b.getPolicy()), np.array([1, 1, 0])):
186
+ sys.exit("Model 2b failed!")
187
+ if not np.array_equal(
188
+ np.round(np.array(mdl2b.getValueVector()), 3),
189
+ np.round(np.array([354.2101307157537, 368.21018917357264, 457.21037278800077]), 3),
190
+ ):
191
+ sys.exit("Model 2b failed!")
192
+
193
+ # Model 3b (average reward, unparallel)
194
+ mdl3b = mdpsolver.model()
195
+ mdl3b.mdp(rewards=rewards, tranMatWithZeros=tranMatWithZeros)
196
+ mdl3b.solve(algorithm="vi", update="standard", criterion="average", parallel=False)
197
+ if not np.array_equal(np.array(mdl3b.getPolicy()), np.array([1, 1, 0])):
198
+ sys.exit("Model 3b failed!")
199
+ if not np.array_equal(
200
+ np.round(np.array(mdl3b.getValueVector()), 3),
201
+ np.round(np.array([158.23345351808334, 172.23340169038516, 261.233237936489]), 3),
202
+ ):
203
+ sys.exit("Model 3b failed!")
204
+
205
+ # Model 1c (discounted, Gauss-Seidel)
206
+ mdl1c = mdpsolver.model()
207
+ mdl1c.mdp(discount=0.95, rewards=rewards, tranMatWithZeros=tranMatWithZeros)
208
+ mdl1c.solve(algorithm="mpi", update="gs", parallel=False, initPolicy=initPolicy)
209
+ if not np.array_equal(np.array(mdl1c.getPolicy()), np.array([1, 1, 0])):
210
+ sys.exit("Model 1c failed!")
211
+ if not np.array_equal(
212
+ np.round(np.array(mdl1c.getValueVector()), 3),
213
+ np.round(np.array([200.0012771893156, 212.86686671568802, 298.7091798650016]), 3),
214
+ ):
215
+ sys.exit("Model 1c failed!")
216
+
217
+ # Model 2c (Gauss-Seidel)
218
+ initPolicy = [1, 1, 1]
219
+ mdl2c = mdpsolver.model()
220
+ mdl2c.mdp(discount=0.95, rewards=rewards, tranMatWithZeros=tranMatWithZeros)
221
+ mdl2c.solve(algorithm="pi", update="gs", parallel=False, initPolicy=initPolicy)
222
+ if not np.array_equal(np.array(mdl2c.getPolicy()), np.array([1, 1, 0])):
223
+ sys.exit("Model 2c failed!")
224
+ if not np.array_equal(
225
+ np.round(np.array(mdl2c.getValueVector()), 3),
226
+ np.round(np.array([200.0012771893156, 212.86686671568802, 298.7091798650016]), 3),
227
+ ):
228
+ sys.exit("Model 2c failed!")
229
+
230
+ # Model 3c (Gauss-Seidel)
231
+ mdl3c = mdpsolver.model()
232
+ mdl3c.mdp(discount=0.95, rewards=rewards, tranMatWithZeros=tranMatWithZeros)
233
+ mdl3c.solve(algorithm="vi", update="gs", parallel=False)
234
+ if not np.array_equal(np.array(mdl3c.getPolicy()), np.array([1, 1, 0])):
235
+ sys.exit("Model 3c failed!")
236
+ if not np.array_equal(
237
+ np.round(np.array(mdl3c.getValueVector()), 3),
238
+ np.round(np.array([200.0010604606014, 212.86664512773723, 298.7089561808565]), 3),
239
+ ):
240
+ sys.exit("Model 3c failed!")
241
+
242
+ # Model 1d (SOR)
243
+ mdl1d = mdpsolver.model()
244
+ mdl1d.mdp(discount=0.95, rewards=rewards, tranMatWithZeros=tranMatWithZeros)
245
+ mdl1d.solve(
246
+ algorithm="mpi",
247
+ update="sor",
248
+ SORrelaxation=1.01,
249
+ parallel=False,
250
+ initPolicy=initPolicy,
251
+ )
252
+ if not np.array_equal(np.array(mdl1d.getPolicy()), np.array([1, 1, 0])):
253
+ sys.exit("Model 1d failed!")
254
+ if not np.array_equal(
255
+ np.round(np.array(mdl1d.getValueVector()), 3),
256
+ np.round(np.array([200.00127021272166, 212.86686059325598, 298.70917425463125]), 3),
257
+ ):
258
+ sys.exit("Model 1d failed!")
259
+
260
+ # Model 2d (SOR)
261
+ mdl2d = mdpsolver.model()
262
+ mdl2d.mdp(discount=0.95, rewards=rewards, tranMatWithZeros=tranMatWithZeros)
263
+ mdl2d.solve(
264
+ algorithm="pi",
265
+ update="sor",
266
+ SORrelaxation=1.01,
267
+ parallel=False,
268
+ initPolicy=initPolicy,
269
+ )
270
+ if not np.array_equal(np.array(mdl2d.getPolicy()), np.array([1, 1, 0])):
271
+ sys.exit("Model 2d failed!")
272
+ if not np.array_equal(
273
+ np.round(np.array(mdl2d.getValueVector()), 3),
274
+ np.round(np.array([200.00127021272166, 212.86686059325598, 298.70917425463125]), 3),
275
+ ):
276
+ sys.exit("Model 2d failed!")
277
+
278
+ # Model 3d (SOR)
279
+ mdl3d = mdpsolver.model()
280
+ mdl3d.mdp(discount=0.95, rewards=rewards, tranMatWithZeros=tranMatWithZeros)
281
+ mdl3d.solve(algorithm="vi", update="sor", SORrelaxation=1.01, parallel=False)
282
+ if not np.array_equal(np.array(mdl3d.getPolicy()), np.array([1, 1, 0])):
283
+ sys.exit("Model 3d failed!")
284
+ if not np.array_equal(
285
+ np.round(np.array(mdl3d.getValueVector()), 3),
286
+ np.round(np.array([206.69740452375487, 222.30968454932525, 305.91165352015094]), 3),
287
+ ):
288
+ sys.exit("Model 3d failed!")
289
+
290
+ # ---------------------------------------
291
+ # CONFIGURATION 2
292
+ # ---------------------------------------
293
+
294
+ # rewards
295
+ # 1st index: from (current) states
296
+ # 2nd index: actions
297
+ rewards = [[5, -1], [1, -2], [50, 0]]
298
+
299
+ # transition probabilities
300
+ # [from_state,action,to_state,probability]
301
+ tranMatElementwise = [
302
+ [0, 0, 0, 0.9],
303
+ [0, 0, 1, 0.1],
304
+ [0, 1, 0, 0.1],
305
+ [0, 1, 1, 0.9],
306
+ [1, 0, 0, 0.4],
307
+ [1, 0, 1, 0.5],
308
+ [1, 0, 2, 0.1],
309
+ [1, 1, 0, 0.3],
310
+ [1, 1, 1, 0.5],
311
+ [1, 1, 2, 0.2],
312
+ [2, 0, 0, 0.2],
313
+ [2, 0, 1, 0.2],
314
+ [2, 0, 2, 0.6],
315
+ [2, 1, 0, 0.5],
316
+ [2, 1, 1, 0.5],
317
+ ]
318
+
319
+ # initial policy
320
+ random.seed(10)
321
+ initPolicy = [randint(0, 1) for p in range(0, 3)]
322
+
323
+ # Model 1a
324
+ mdl1a = mdpsolver.model()
325
+ mdl1a.mdp(discount=0.95, rewards=rewards, tranMatElementwise=tranMatElementwise)
326
+ mdl1a.solve(algorithm="mpi", update="standard", parallel=True, initPolicy=initPolicy)
327
+ if not np.array_equal(np.array(mdl1a.getPolicy()), np.array([1, 1, 0])):
328
+ sys.exit("Model 1a failed!")
329
+ if not np.array_equal(
330
+ np.round(np.array(mdl1a.getValueVector()), 3),
331
+ np.round(np.array([200.00114718191236, 212.86672887958622, 298.7090458676583]), 3),
332
+ ):
333
+ sys.exit("Model 1a failed!")
334
+
335
+ # Model 2a
336
+ mdl2a = mdpsolver.model()
337
+ mdl2a.mdp(discount=0.95, rewards=rewards, tranMatElementwise=tranMatElementwise)
338
+ mdl2a.solve(algorithm="pi", update="standard", parallel=True, initPolicy=initPolicy)
339
+ if not np.array_equal(np.array(mdl2a.getPolicy()), np.array([1, 1, 0])):
340
+ sys.exit("Model 2a failed!")
341
+ if not np.array_equal(
342
+ np.round(np.array(mdl2a.getValueVector()), 3),
343
+ np.round(np.array([200.00114718191236, 212.86672887958622, 298.7090458676583]), 3),
344
+ ):
345
+ sys.exit("Model 2a failed!")
346
+
347
+ # Model 3a
348
+ mdl3a = mdpsolver.model()
349
+ mdl3a.mdp(discount=0.95, rewards=rewards, tranMatElementwise=tranMatElementwise)
350
+ mdl3a.solve(algorithm="vi", update="standard", parallel=True)
351
+ if not np.array_equal(np.array(mdl3a.getPolicy()), np.array([1, 1, 0])):
352
+ sys.exit("Model 3a failed!")
353
+ if not np.array_equal(
354
+ np.round(np.array(mdl3a.getValueVector()), 3),
355
+ np.round(np.array([200.0013199959708, 212.86689665815788, 298.709197760198]), 3),
356
+ ):
357
+ sys.exit("Model 3a failed!")
358
+
359
+ # Model 1b
360
+ mdl1b = mdpsolver.model()
361
+ mdl1b.mdp(discount=0.95, rewards=rewards, tranMatElementwise=tranMatElementwise)
362
+ mdl1b.solve(algorithm="mpi", update="standard", parallel=False, initPolicy=initPolicy)
363
+ if not np.array_equal(np.array(mdl1b.getPolicy()), np.array([1, 1, 0])):
364
+ sys.exit("Model 1b failed!")
365
+ if not np.array_equal(
366
+ np.round(np.array(mdl1b.getValueVector()), 3),
367
+ np.round(np.array([200.00114718191236, 212.86672887958622, 298.7090458676583]), 3),
368
+ ):
369
+ sys.exit("Model 1b failed!")
370
+
371
+ # Model 2b
372
+ mdl2b = mdpsolver.model()
373
+ mdl2b.mdp(discount=0.95, rewards=rewards, tranMatElementwise=tranMatElementwise)
374
+ mdl2b.solve(algorithm="pi", update="standard", parallel=False, initPolicy=initPolicy)
375
+ if not np.array_equal(np.array(mdl2b.getPolicy()), np.array([1, 1, 0])):
376
+ sys.exit("Model 2b failed!")
377
+ if not np.array_equal(
378
+ np.round(np.array(mdl2b.getValueVector()), 3),
379
+ np.round(np.array([200.00114718191236, 212.86672887958622, 298.7090458676583]), 3),
380
+ ):
381
+ sys.exit("Model 2b failed!")
382
+
383
+ # Model 3b
384
+ mdl3b = mdpsolver.model()
385
+ mdl3b.mdp(discount=0.95, rewards=rewards, tranMatElementwise=tranMatElementwise)
386
+ mdl3b.solve(algorithm="vi", update="standard", parallel=False)
387
+ if not np.array_equal(np.array(mdl3b.getPolicy()), np.array([1, 1, 0])):
388
+ sys.exit("Model 3b failed!")
389
+ if not np.array_equal(
390
+ np.round(np.array(mdl3b.getValueVector()), 3),
391
+ np.round(np.array([200.0013199959708, 212.86689665815788, 298.709197760198]), 3),
392
+ ):
393
+ sys.exit("Model 3b failed!")
394
+
395
+ # Model 1c
396
+ mdl1c = mdpsolver.model()
397
+ mdl1c.mdp(discount=0.95, rewards=rewards, tranMatElementwise=tranMatElementwise)
398
+ mdl1c.solve(algorithm="mpi", update="gs", parallel=False, initPolicy=initPolicy)
399
+ if not np.array_equal(np.array(mdl1c.getPolicy()), np.array([1, 1, 0])):
400
+ sys.exit("Model 1c failed!")
401
+ if not np.array_equal(
402
+ np.round(np.array(mdl1c.getValueVector()), 3),
403
+ np.round(np.array([200.0012771893156, 212.86686671568802, 298.7091798650016]), 3),
404
+ ):
405
+ sys.exit("Model 1c failed!")
406
+
407
+ # Model 2c
408
+ mdl2c = mdpsolver.model()
409
+ mdl2c.mdp(discount=0.95, rewards=rewards, tranMatElementwise=tranMatElementwise)
410
+ mdl2c.solve(algorithm="pi", update="gs", parallel=False, initPolicy=initPolicy)
411
+ if not np.array_equal(np.array(mdl2c.getPolicy()), np.array([1, 1, 0])):
412
+ sys.exit("Model 2c failed!")
413
+ if not np.array_equal(
414
+ np.round(np.array(mdl2c.getValueVector()), 3),
415
+ np.round(np.array([200.0012771893156, 212.86686671568802, 298.7091798650016]), 3),
416
+ ):
417
+ sys.exit("Model 2c failed!")
418
+
419
+ # Model 3c
420
+ mdl3c = mdpsolver.model()
421
+ mdl3c.mdp(discount=0.95, rewards=rewards, tranMatElementwise=tranMatElementwise)
422
+ mdl3c.solve(algorithm="vi", update="gs", parallel=False)
423
+ if not np.array_equal(np.array(mdl3c.getPolicy()), np.array([1, 1, 0])):
424
+ sys.exit("Model 3c failed!")
425
+ if not np.array_equal(
426
+ np.round(np.array(mdl3c.getValueVector()), 3),
427
+ np.round(np.array([200.0010604606014, 212.86664512773723, 298.7089561808565]), 3),
428
+ ):
429
+ sys.exit("Model 3c failed!")
430
+
431
+ # Model 1d
432
+ mdl1d = mdpsolver.model()
433
+ mdl1d.mdp(discount=0.95, rewards=rewards, tranMatElementwise=tranMatElementwise)
434
+ mdl1d.solve(
435
+ algorithm="mpi",
436
+ update="sor",
437
+ SORrelaxation=1.01,
438
+ parallel=False,
439
+ initPolicy=initPolicy,
440
+ )
441
+ if not np.array_equal(np.array(mdl1d.getPolicy()), np.array([1, 1, 0])):
442
+ sys.exit("Model 1d failed!")
443
+ if not np.array_equal(
444
+ np.round(np.array(mdl1d.getValueVector()), 3),
445
+ np.round(np.array([200.00127021272166, 212.86686059325598, 298.70917425463125]), 3),
446
+ ):
447
+ sys.exit("Model 1d failed!")
448
+
449
+ # Model 2d
450
+ mdl2d = mdpsolver.model()
451
+ mdl2d.mdp(discount=0.95, rewards=rewards, tranMatElementwise=tranMatElementwise)
452
+ mdl2d.solve(
453
+ algorithm="pi",
454
+ update="sor",
455
+ SORrelaxation=1.01,
456
+ parallel=False,
457
+ initPolicy=initPolicy,
458
+ )
459
+ if not np.array_equal(np.array(mdl2d.getPolicy()), np.array([1, 1, 0])):
460
+ sys.exit("Model 2d failed!")
461
+ if not np.array_equal(
462
+ np.round(np.array(mdl2d.getValueVector()), 3),
463
+ np.round(np.array([200.00127021272166, 212.86686059325598, 298.70917425463125]), 3),
464
+ ):
465
+ sys.exit("Model 2d failed!")
466
+
467
+ # Model 3d
468
+ mdl3d = mdpsolver.model()
469
+ mdl3d.mdp(discount=0.95, rewards=rewards, tranMatElementwise=tranMatElementwise)
470
+ mdl3d.solve(algorithm="vi", update="sor", SORrelaxation=1.01, parallel=False)
471
+ if not np.array_equal(np.array(mdl3d.getPolicy()), np.array([1, 1, 0])):
472
+ sys.exit("Model 3d failed!")
473
+ if not np.array_equal(
474
+ np.round(np.array(mdl3d.getValueVector()), 3),
475
+ np.round(np.array([206.69740452375487, 222.30968454932525, 305.91165352015094]), 3),
476
+ ):
477
+ sys.exit("Model 3d failed!")
478
+
479
+ # ---------------------------------------
480
+ # CONFIGURATION 3
481
+ # ---------------------------------------
482
+
483
+ # rewards
484
+ # 1st index: from (current) states
485
+ # 2nd index: actions
486
+ rewards = [[5, -1], [1, -2], [50, 0]]
487
+
488
+ # transition probabilities
489
+ tranMatProbs = [
490
+ [[0.9, 0.1], [0.1, 0.9]],
491
+ [[0.4, 0.5, 0.1], [0.3, 0.5, 0.2]],
492
+ [[0.2, 0.2, 0.6], [0.5, 0.5]],
493
+ ]
494
+
495
+ tranMatColumns = [[[0, 1], [0, 1]], [[0, 1, 2], [0, 1, 2]], [[0, 1, 2], [0, 1]]]
496
+
497
+ # initial policy
498
+ random.seed(10)
499
+ initPolicy = [randint(0, 1) for p in range(0, 3)]
500
+
501
+ # Model 1a
502
+ mdl1a = mdpsolver.model()
503
+ mdl1a.mdp(
504
+ discount=0.95,
505
+ rewards=rewards,
506
+ tranMatProbs=tranMatProbs,
507
+ tranMatColumns=tranMatColumns,
508
+ )
509
+ mdl1a.solve(algorithm="mpi", update="standard", parallel=True, initPolicy=initPolicy)
510
+ if not np.array_equal(np.array(mdl1a.getPolicy()), np.array([1, 1, 0])):
511
+ sys.exit("Model 1a failed!")
512
+ if not np.array_equal(
513
+ np.round(np.array(mdl1a.getValueVector()), 3),
514
+ np.round(np.array([200.00114718191236, 212.86672887958622, 298.7090458676583]), 3),
515
+ ):
516
+ sys.exit("Model 1a failed!")
517
+
518
+ # Model 2a
519
+ mdl2a = mdpsolver.model()
520
+ mdl2a.mdp(
521
+ discount=0.95,
522
+ rewards=rewards,
523
+ tranMatProbs=tranMatProbs,
524
+ tranMatColumns=tranMatColumns,
525
+ )
526
+ mdl2a.solve(algorithm="pi", update="standard", parallel=True, initPolicy=initPolicy)
527
+ if not np.array_equal(np.array(mdl2a.getPolicy()), np.array([1, 1, 0])):
528
+ sys.exit("Model 2a failed!")
529
+ if not np.array_equal(
530
+ np.round(np.array(mdl2a.getValueVector()), 3),
531
+ np.round(np.array([200.00114718191236, 212.86672887958622, 298.7090458676583]), 3),
532
+ ):
533
+ sys.exit("Model 2a failed!")
534
+
535
+ # Model 3a
536
+ mdl3a = mdpsolver.model()
537
+ mdl3a.mdp(
538
+ discount=0.95,
539
+ rewards=rewards,
540
+ tranMatProbs=tranMatProbs,
541
+ tranMatColumns=tranMatColumns,
542
+ )
543
+ mdl3a.solve(algorithm="vi", update="standard", parallel=True)
544
+ if not np.array_equal(np.array(mdl3a.getPolicy()), np.array([1, 1, 0])):
545
+ sys.exit("Model 3a failed!")
546
+ if not np.array_equal(
547
+ np.round(np.array(mdl3a.getValueVector()), 3),
548
+ np.round(np.array([200.0013199959708, 212.86689665815788, 298.709197760198]), 3),
549
+ ):
550
+ sys.exit("Model 3a failed!")
551
+
552
+ # Model 1b
553
+ mdl1b = mdpsolver.model()
554
+ mdl1b.mdp(
555
+ discount=0.95,
556
+ rewards=rewards,
557
+ tranMatProbs=tranMatProbs,
558
+ tranMatColumns=tranMatColumns,
559
+ )
560
+ mdl1b.solve(algorithm="mpi", update="standard", parallel=False, initPolicy=initPolicy)
561
+ if not np.array_equal(np.array(mdl1b.getPolicy()), np.array([1, 1, 0])):
562
+ sys.exit("Model 1b failed!")
563
+ if not np.array_equal(
564
+ np.round(np.array(mdl1b.getValueVector()), 3),
565
+ np.round(np.array([200.00114718191236, 212.86672887958622, 298.7090458676583]), 3),
566
+ ):
567
+ sys.exit("Model 1b failed!")
568
+
569
+ # Model 2b
570
+ mdl2b = mdpsolver.model()
571
+ mdl2b.mdp(
572
+ discount=0.95,
573
+ rewards=rewards,
574
+ tranMatProbs=tranMatProbs,
575
+ tranMatColumns=tranMatColumns,
576
+ )
577
+ mdl2b.solve(algorithm="pi", update="standard", parallel=False, initPolicy=initPolicy)
578
+ if not np.array_equal(np.array(mdl2b.getPolicy()), np.array([1, 1, 0])):
579
+ sys.exit("Model 2b failed!")
580
+ if not np.array_equal(
581
+ np.round(np.array(mdl2b.getValueVector()), 3),
582
+ np.round(np.array([200.00114718191236, 212.86672887958622, 298.7090458676583]), 3),
583
+ ):
584
+ sys.exit("Model 2b failed!")
585
+
586
+ # Model 3b
587
+ mdl3b = mdpsolver.model()
588
+ mdl3b.mdp(
589
+ discount=0.95,
590
+ rewards=rewards,
591
+ tranMatProbs=tranMatProbs,
592
+ tranMatColumns=tranMatColumns,
593
+ )
594
+ mdl3b.solve(algorithm="vi", update="standard", parallel=False)
595
+ if not np.array_equal(np.array(mdl3b.getPolicy()), np.array([1, 1, 0])):
596
+ sys.exit("Model 3b failed!")
597
+ if not np.array_equal(
598
+ np.round(np.array(mdl3b.getValueVector()), 3),
599
+ np.round(np.array([200.0013199959708, 212.86689665815788, 298.709197760198]), 3),
600
+ ):
601
+ sys.exit("Model 3b failed!")
602
+
603
+ # Model 1c
604
+ mdl1c = mdpsolver.model()
605
+ mdl1c.mdp(
606
+ discount=0.95,
607
+ rewards=rewards,
608
+ tranMatProbs=tranMatProbs,
609
+ tranMatColumns=tranMatColumns,
610
+ )
611
+ mdl1c.solve(algorithm="mpi", update="gs", parallel=False, initPolicy=initPolicy)
612
+ if not np.array_equal(np.array(mdl1c.getPolicy()), np.array([1, 1, 0])):
613
+ sys.exit("Model 1c failed!")
614
+ if not np.array_equal(
615
+ np.round(np.array(mdl1c.getValueVector()), 3),
616
+ np.round(np.array([200.0012771893156, 212.86686671568802, 298.7091798650016]), 3),
617
+ ):
618
+ sys.exit("Model 1c failed!")
619
+
620
+ # Model 2c
621
+ mdl2c = mdpsolver.model()
622
+ mdl2c.mdp(
623
+ discount=0.95,
624
+ rewards=rewards,
625
+ tranMatProbs=tranMatProbs,
626
+ tranMatColumns=tranMatColumns,
627
+ )
628
+ mdl2c.solve(algorithm="pi", update="gs", parallel=False, initPolicy=initPolicy)
629
+ if not np.array_equal(np.array(mdl2c.getPolicy()), np.array([1, 1, 0])):
630
+ sys.exit("Model 2c failed!")
631
+ if not np.array_equal(
632
+ np.round(np.array(mdl2c.getValueVector()), 3),
633
+ np.round(np.array([200.0012771893156, 212.86686671568802, 298.7091798650016]), 3),
634
+ ):
635
+ sys.exit("Model 2c failed!")
636
+
637
+ # Model 3c
638
+ mdl3c = mdpsolver.model()
639
+ mdl3c.mdp(
640
+ discount=0.95,
641
+ rewards=rewards,
642
+ tranMatProbs=tranMatProbs,
643
+ tranMatColumns=tranMatColumns,
644
+ )
645
+ mdl3c.solve(algorithm="vi", update="gs", parallel=False)
646
+ if not np.array_equal(np.array(mdl3c.getPolicy()), np.array([1, 1, 0])):
647
+ sys.exit("Model 3c failed!")
648
+ if not np.array_equal(
649
+ np.round(np.array(mdl3c.getValueVector()), 3),
650
+ np.round(np.array([200.0010604606014, 212.86664512773723, 298.7089561808565]), 3),
651
+ ):
652
+ sys.exit("Model 3c failed!")
653
+
654
+ # Model 1d
655
+ mdl1d = mdpsolver.model()
656
+ mdl1d.mdp(
657
+ discount=0.95,
658
+ rewards=rewards,
659
+ tranMatProbs=tranMatProbs,
660
+ tranMatColumns=tranMatColumns,
661
+ )
662
+ mdl1d.solve(
663
+ algorithm="mpi",
664
+ update="sor",
665
+ SORrelaxation=1.01,
666
+ parallel=False,
667
+ initPolicy=initPolicy,
668
+ )
669
+ if not np.array_equal(np.array(mdl1d.getPolicy()), np.array([1, 1, 0])):
670
+ sys.exit("Model 1d failed!")
671
+ if not np.array_equal(
672
+ np.round(np.array(mdl1d.getValueVector()), 3),
673
+ np.round(np.array([200.00127021272166, 212.86686059325598, 298.70917425463125]), 3),
674
+ ):
675
+ sys.exit("Model 1d failed!")
676
+
677
+ # Model 2d
678
+ mdl2d = mdpsolver.model()
679
+ mdl2d.mdp(
680
+ discount=0.95,
681
+ rewards=rewards,
682
+ tranMatProbs=tranMatProbs,
683
+ tranMatColumns=tranMatColumns,
684
+ )
685
+ mdl2d.solve(
686
+ algorithm="pi",
687
+ update="sor",
688
+ SORrelaxation=1.01,
689
+ parallel=False,
690
+ initPolicy=initPolicy,
691
+ )
692
+ if not np.array_equal(np.array(mdl2d.getPolicy()), np.array([1, 1, 0])):
693
+ sys.exit("Model 2d failed!")
694
+ if not np.array_equal(
695
+ np.round(np.array(mdl2d.getValueVector()), 3),
696
+ np.round(np.array([200.00127021272166, 212.86686059325598, 298.70917425463125]), 3),
697
+ ):
698
+ sys.exit("Model 2d failed!")
699
+
700
+ # Model 3d
701
+ mdl3d = mdpsolver.model()
702
+ mdl3d.mdp(
703
+ discount=0.95,
704
+ rewards=rewards,
705
+ tranMatProbs=tranMatProbs,
706
+ tranMatColumns=tranMatColumns,
707
+ )
708
+ mdl3d.solve(algorithm="vi", update="sor", SORrelaxation=1.01, parallel=False)
709
+ if not np.array_equal(np.array(mdl3d.getPolicy()), np.array([1, 1, 0])):
710
+ sys.exit("Model 3d failed!")
711
+ if not np.array_equal(
712
+ np.round(np.array(mdl3d.getValueVector()), 3),
713
+ np.round(np.array([206.69740452375487, 222.30968454932525, 305.91165352015094]), 3),
714
+ ):
715
+ sys.exit("Model 3d failed!")
716
+
717
+ print("Test 1 succesfully reproduced output!")
@@ -0,0 +1,91 @@
1
+ import example_model
2
+ import sys
3
+ import os
4
+ import numpy as np
5
+ project_root = os.path.dirname(os.path.abspath(__file__))
6
+ src_path = os.path.join(project_root, "..", "src")
7
+ sys.path.append(os.path.abspath(src_path))
8
+ import mdpsolver
9
+
10
+ # TEST 2
11
+ # In this test, we load the rewards and transition probabilities
12
+ # from two CSV-files (rewards_example.csv and transitions.csv).
13
+ # In addition, we test three optimization algorithms and compare
14
+ # the runtimes.
15
+
16
+ # PROBLEM DESCRIPTION: We derive the policy for a decision problem
17
+ # involving a queueing system with finite capacity and two customer
18
+ # types. The system is observed whenever a new customer arrives.
19
+ # Customers are not allowed to wait and can only be accepted if there
20
+ # are idle servers. Thus, with each arrival, we must choose whether
21
+ # to accept or reject the customer. We receive a low reward for
22
+ # accepting the first, more common type, and a high reward for
23
+ # accepting the second, rarer type.
24
+
25
+ # ---------------------------------------
26
+ # CREATE PARAMETERS
27
+ # ---------------------------------------
28
+
29
+ # rewards
30
+ capacity = 100
31
+ rewardCust1 = 1
32
+ rewardCust2 = 1000
33
+ example_model.rewards(capacity, rewardCust1, rewardCust2, "rewards_example2.csv")
34
+
35
+ # transitions
36
+ arrRate1 = 50
37
+ arrRate2 = 10
38
+ serRate = 3 / 4
39
+ example_model.tranMat(arrRate1, arrRate2, serRate, capacity, "transitions_example2.csv")
40
+
41
+ # ---------------------------------------
42
+ # VALUE ITERATION
43
+ # ---------------------------------------
44
+
45
+ mdl1 = mdpsolver.model()
46
+
47
+ mdl1.mdp(
48
+ discount=0.99,
49
+ rewardsFromFile="rewards_example2.csv",
50
+ tranMatFromFile="transitions_example2.csv",
51
+ )
52
+
53
+ mdl1.solve(algorithm="vi")
54
+ if not np.round(np.mean(mdl1.getValueVector()), 0) == 17075.0:
55
+ sys.exit("Model 1 failed!")
56
+
57
+ # ---------------------------------------
58
+ # POLICY ITERATION
59
+ # ---------------------------------------
60
+
61
+ mdl2 = mdpsolver.model()
62
+
63
+ mdl2.mdp(
64
+ discount=0.99,
65
+ rewardsFromFile="rewards_example2.csv",
66
+ tranMatFromFile="transitions_example2.csv",
67
+ )
68
+
69
+ mdl2.solve(algorithm="pi")
70
+
71
+ if not np.round(np.mean(mdl2.getValueVector()), 0) == 17075.0:
72
+ sys.exit("Model 2 failed!")
73
+
74
+ # ---------------------------------------
75
+ # MODIFIED POLICY ITERATION
76
+ # ---------------------------------------
77
+
78
+ mdl3 = mdpsolver.model()
79
+
80
+ mdl3.mdp(
81
+ discount=0.99,
82
+ rewardsFromFile="rewards_example2.csv",
83
+ tranMatFromFile="transitions_example2.csv",
84
+ )
85
+
86
+ mdl3.solve(algorithm="mpi")
87
+
88
+ if not np.round(np.mean(mdl3.getValueVector()), 0) == 17075.0:
89
+ sys.exit("Model 3 failed!")
90
+
91
+ print("Test 2 succesfully reproduced output!")
@@ -1,40 +0,0 @@
1
- import math
2
-
3
- # Condition-based maintenance problem
4
-
5
- # Note: The class is only used for retrieving/converting information
6
- # (i.e. returning an action of the policy). The policy is optimized
7
- # in the 'model' (model.py) class.
8
-
9
-
10
- class cbmaux:
11
-
12
- def __init__(self, components, stages):
13
- self.components = components
14
- self.stages = stages
15
-
16
- def compToState(self, compStates):
17
- # input: list containing the stage of each component
18
- # output: the associated state index
19
- prod = self.components * [1]
20
- if self.components > 1:
21
- for i in range(self.components - 2, -1, -1):
22
- prod[i] = prod[i + 1] * self.stages
23
- stateIndex = 0
24
- for i in range(self.components):
25
- stateIndex += compStates[i] * prod[i]
26
- return stateIndex
27
-
28
- def actionToReplace(self, actionIndex):
29
- # input: action index from the optimized policy
30
- # output: list of bools indicating which comps to replace
31
- prod = self.components * [1]
32
- if self.components > 1:
33
- for i in range(self.components - 2, -1, -1):
34
- prod[i] = prod[i + 1] * 2
35
- replace = self.components * [False]
36
- for i in range(self.components):
37
- if math.floor(actionIndex / prod[i]) > 0:
38
- replace[i] = True
39
- actionIndex -= prod[i]
40
- return replace
@@ -1,40 +0,0 @@
1
- import math
2
-
3
- # Time-based maintenance problem
4
-
5
- # Note: The class is only used for retrieving/converting information
6
- # (i.e. returning an action of the policy). The policy is optimized
7
- # in the 'model' (model.py) class.
8
-
9
-
10
- class tbmaux:
11
-
12
- def __init__(self, components, stages):
13
- self.components = components
14
- self.stages = stages
15
-
16
- def compToState(self, compStates):
17
- # input: list containing the stage of each component
18
- # output: the associated state index
19
- prod = self.components * [1]
20
- if self.components > 1:
21
- for i in range(self.components - 2, -1, -1):
22
- prod[i] = prod[i + 1] * self.stages
23
- stateIndex = 0
24
- for i in range(self.components):
25
- stateIndex += compStates[i] * prod[i]
26
- return stateIndex
27
-
28
- def actionToReplace(self, actionIndex):
29
- # input: action index from the optimized policy
30
- # output: list of bools indicating which comps to replace
31
- prod = self.components * [1]
32
- if self.components > 1:
33
- for i in range(self.components - 2, -1, -1):
34
- prod[i] = prod[i + 1] * 2
35
- replace = self.components * [False]
36
- for i in range(self.components):
37
- if math.floor(actionIndex / prod[i]) > 0:
38
- replace[i] = True
39
- actionIndex -= prod[i]
40
- return replace
File without changes
File without changes
File without changes
@@ -1,8 +1,8 @@
1
- import mdpsolver
2
1
  import random
3
2
  import sys
4
3
  import numpy as np
5
4
  from random import randint
5
+ import mdpsolver
6
6
 
7
7
  # TEST 1
8
8
  # Simple MDP with 3 states and 2 actions in each state.
@@ -1,7 +1,7 @@
1
- import mdpsolver
2
1
  import example_model
3
2
  import sys
4
3
  import numpy as np
4
+ import mdpsolver
5
5
 
6
6
  # TEST 2
7
7
  # In this test, we load the rewards and transition probabilities