game-resolver-cpp 0.1.0__tar.gz → 0.1.1__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.
- {game_resolver_cpp-0.1.0 → game_resolver_cpp-0.1.1}/CMakeLists.txt +1 -1
- {game_resolver_cpp-0.1.0 → game_resolver_cpp-0.1.1}/PKG-INFO +26 -4
- {game_resolver_cpp-0.1.0 → game_resolver_cpp-0.1.1}/README.md +2 -0
- {game_resolver_cpp-0.1.0 → game_resolver_cpp-0.1.1}/docs/README_for_pypi.md +25 -3
- {game_resolver_cpp-0.1.0 → game_resolver_cpp-0.1.1}/pyproject.toml +1 -1
- {game_resolver_cpp-0.1.0 → game_resolver_cpp-0.1.1}/python/game_resolver_cpp/bayesian_nash_equilibrium.py +16 -1
- {game_resolver_cpp-0.1.0 → game_resolver_cpp-0.1.1}/python/src/binding.cpp +51 -3
- {game_resolver_cpp-0.1.0 → game_resolver_cpp-0.1.1}/python/tests/test_compat.py +32 -0
- {game_resolver_cpp-0.1.0 → game_resolver_cpp-0.1.1}/src/version.cpp +1 -1
- {game_resolver_cpp-0.1.0 → game_resolver_cpp-0.1.1}/tests/smoke_test.cpp +1 -1
- {game_resolver_cpp-0.1.0 → game_resolver_cpp-0.1.1}/.clang-format +0 -0
- {game_resolver_cpp-0.1.0 → game_resolver_cpp-0.1.1}/.clang-tidy +0 -0
- {game_resolver_cpp-0.1.0 → game_resolver_cpp-0.1.1}/.gitignore +0 -0
- {game_resolver_cpp-0.1.0 → game_resolver_cpp-0.1.1}/LICENSE +0 -0
- {game_resolver_cpp-0.1.0 → game_resolver_cpp-0.1.1}/Makefile +0 -0
- {game_resolver_cpp-0.1.0 → game_resolver_cpp-0.1.1}/benchmarks/CMakeLists.txt +0 -0
- {game_resolver_cpp-0.1.0 → game_resolver_cpp-0.1.1}/benchmarks/benchmark.cpp +0 -0
- {game_resolver_cpp-0.1.0 → game_resolver_cpp-0.1.1}/cmake/game_resolverConfig.cmake.in +0 -0
- {game_resolver_cpp-0.1.0 → game_resolver_cpp-0.1.1}/examples/CMakeLists.txt +0 -0
- {game_resolver_cpp-0.1.0 → game_resolver_cpp-0.1.1}/examples/battle_of_sex.cpp +0 -0
- {game_resolver_cpp-0.1.0 → game_resolver_cpp-0.1.1}/examples/bayesian_battle_of_sex.cpp +0 -0
- {game_resolver_cpp-0.1.0 → game_resolver_cpp-0.1.1}/examples/cournot.cpp +0 -0
- {game_resolver_cpp-0.1.0 → game_resolver_cpp-0.1.1}/examples/hawk_dove.cpp +0 -0
- {game_resolver_cpp-0.1.0 → game_resolver_cpp-0.1.1}/examples/prisoners_dilemma.cpp +0 -0
- {game_resolver_cpp-0.1.0 → game_resolver_cpp-0.1.1}/include/game_resolver/action.hpp +0 -0
- {game_resolver_cpp-0.1.0 → game_resolver_cpp-0.1.1}/include/game_resolver/bayesian/bayesian_game.hpp +0 -0
- {game_resolver_cpp-0.1.0 → game_resolver_cpp-0.1.1}/include/game_resolver/bayesian/bayesian_nash_equilibrium.hpp +0 -0
- {game_resolver_cpp-0.1.0 → game_resolver_cpp-0.1.1}/include/game_resolver/bayesian/bayesian_player.hpp +0 -0
- {game_resolver_cpp-0.1.0 → game_resolver_cpp-0.1.1}/include/game_resolver/error.hpp +0 -0
- {game_resolver_cpp-0.1.0 → game_resolver_cpp-0.1.1}/include/game_resolver/game.hpp +0 -0
- {game_resolver_cpp-0.1.0 → game_resolver_cpp-0.1.1}/include/game_resolver/game_resolver.hpp +0 -0
- {game_resolver_cpp-0.1.0 → game_resolver_cpp-0.1.1}/include/game_resolver/nash_equilibrium.hpp +0 -0
- {game_resolver_cpp-0.1.0 → game_resolver_cpp-0.1.1}/include/game_resolver/ndarray.hpp +0 -0
- {game_resolver_cpp-0.1.0 → game_resolver_cpp-0.1.1}/include/game_resolver/payoff.hpp +0 -0
- {game_resolver_cpp-0.1.0 → game_resolver_cpp-0.1.1}/include/game_resolver/player.hpp +0 -0
- {game_resolver_cpp-0.1.0 → game_resolver_cpp-0.1.1}/include/game_resolver/solver/nash_solver.hpp +0 -0
- {game_resolver_cpp-0.1.0 → game_resolver_cpp-0.1.1}/include/game_resolver/version.hpp +0 -0
- {game_resolver_cpp-0.1.0 → game_resolver_cpp-0.1.1}/python/CMakeLists.txt +0 -0
- {game_resolver_cpp-0.1.0 → game_resolver_cpp-0.1.1}/python/benchmarks/compare_with_python.py +0 -0
- {game_resolver_cpp-0.1.0 → game_resolver_cpp-0.1.1}/python/game_resolver_cpp/__init__.py +0 -0
- {game_resolver_cpp-0.1.0 → game_resolver_cpp-0.1.1}/python/game_resolver_cpp/bayesian_game.py +0 -0
- {game_resolver_cpp-0.1.0 → game_resolver_cpp-0.1.1}/python/game_resolver_cpp/bayesian_player.py +0 -0
- {game_resolver_cpp-0.1.0 → game_resolver_cpp-0.1.1}/python/game_resolver_cpp/game.py +0 -0
- {game_resolver_cpp-0.1.0 → game_resolver_cpp-0.1.1}/python/game_resolver_cpp/nash_equilibrium.py +0 -0
- {game_resolver_cpp-0.1.0 → game_resolver_cpp-0.1.1}/python/game_resolver_cpp/payoff.py +0 -0
- {game_resolver_cpp-0.1.0 → game_resolver_cpp-0.1.1}/python/game_resolver_cpp/player.py +0 -0
- {game_resolver_cpp-0.1.0 → game_resolver_cpp-0.1.1}/src/action.cpp +0 -0
- {game_resolver_cpp-0.1.0 → game_resolver_cpp-0.1.1}/src/bayesian/bayesian_nash_equilibrium.cpp +0 -0
- {game_resolver_cpp-0.1.0 → game_resolver_cpp-0.1.1}/src/bayesian/bayesian_player.cpp +0 -0
- {game_resolver_cpp-0.1.0 → game_resolver_cpp-0.1.1}/src/nash_equilibrium.cpp +0 -0
- {game_resolver_cpp-0.1.0 → game_resolver_cpp-0.1.1}/src/payoff.cpp +0 -0
- {game_resolver_cpp-0.1.0 → game_resolver_cpp-0.1.1}/src/solver/nash_solver.cpp +0 -0
- {game_resolver_cpp-0.1.0 → game_resolver_cpp-0.1.1}/tests/CMakeLists.txt +0 -0
- {game_resolver_cpp-0.1.0 → game_resolver_cpp-0.1.1}/tests/action_test.cpp +0 -0
- {game_resolver_cpp-0.1.0 → game_resolver_cpp-0.1.1}/tests/bayesian_test.cpp +0 -0
- {game_resolver_cpp-0.1.0 → game_resolver_cpp-0.1.1}/tests/example_games.hpp +0 -0
- {game_resolver_cpp-0.1.0 → game_resolver_cpp-0.1.1}/tests/golden/battle_of_sex.txt +0 -0
- {game_resolver_cpp-0.1.0 → game_resolver_cpp-0.1.1}/tests/golden/bayesian_battle_of_sex.txt +0 -0
- {game_resolver_cpp-0.1.0 → game_resolver_cpp-0.1.1}/tests/golden/cournot.txt +0 -0
- {game_resolver_cpp-0.1.0 → game_resolver_cpp-0.1.1}/tests/golden/generate.py +0 -0
- {game_resolver_cpp-0.1.0 → game_resolver_cpp-0.1.1}/tests/golden/hawk_dove.txt +0 -0
- {game_resolver_cpp-0.1.0 → game_resolver_cpp-0.1.1}/tests/golden/prisoners_dilemma.txt +0 -0
- {game_resolver_cpp-0.1.0 → game_resolver_cpp-0.1.1}/tests/golden/verify_exact.py +0 -0
- {game_resolver_cpp-0.1.0 → game_resolver_cpp-0.1.1}/tests/golden_test.cpp +0 -0
- {game_resolver_cpp-0.1.0 → game_resolver_cpp-0.1.1}/tests/nash_equilibrium_test.cpp +0 -0
- {game_resolver_cpp-0.1.0 → game_resolver_cpp-0.1.1}/tests/nash_solver_test.cpp +0 -0
- {game_resolver_cpp-0.1.0 → game_resolver_cpp-0.1.1}/tests/ndarray_test.cpp +0 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
cmake_minimum_required(VERSION 3.21)
|
|
2
|
-
project(game_resolver_cpp VERSION 0.1.
|
|
2
|
+
project(game_resolver_cpp VERSION 0.1.1 LANGUAGES CXX)
|
|
3
3
|
|
|
4
4
|
option(GAME_RESOLVER_BUILD_TESTS "Build the test suite" ${PROJECT_IS_TOP_LEVEL})
|
|
5
5
|
option(GAME_RESOLVER_BUILD_EXAMPLES "Build the example programs" ${PROJECT_IS_TOP_LEVEL})
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.2
|
|
2
2
|
Name: game_resolver_cpp
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.1
|
|
4
4
|
Summary: C++ backed game equilibrium solver with the game_resolver interface
|
|
5
5
|
Keywords: game-theory,nash-equilibrium,bayesian-game
|
|
6
6
|
Author: nishino-lab
|
|
@@ -78,7 +78,11 @@ All four ways of defining payoffs work, exactly as in `game_resolver`:
|
|
|
78
78
|
|
|
79
79
|
Subclass `BayesianGame` and implement `posterior()`.
|
|
80
80
|
|
|
81
|
+
A Bayesian battle of the sexes. Each player has a type `A` / `B`, observes their own type,
|
|
82
|
+
and computes the expected payoff with the posterior over the other player's type.
|
|
83
|
+
|
|
81
84
|
```python
|
|
85
|
+
import numpy as np
|
|
82
86
|
from game_resolver_cpp.bayesian_game import BayesianGame
|
|
83
87
|
from game_resolver_cpp.bayesian_nash_equilibrium import BayesianNashEquilibrium
|
|
84
88
|
from game_resolver_cpp.bayesian_player import BayesianPlayer
|
|
@@ -97,14 +101,32 @@ class SampleGame(BayesianGame):
|
|
|
97
101
|
other = type_tuple[(player_id + 1) % 2]
|
|
98
102
|
return 1 / 4 if own == other else 3 / 4
|
|
99
103
|
|
|
100
|
-
# payoff functions take (own type, each player's action)
|
|
101
|
-
def male(self, type, male_action, female_action):
|
|
102
|
-
|
|
104
|
+
# payoff functions take (own type, each player's action), and must return a number
|
|
105
|
+
def male(self, type, male_action, female_action):
|
|
106
|
+
if male_action != female_action:
|
|
107
|
+
return 0.0
|
|
108
|
+
if type == "A":
|
|
109
|
+
return 2.0 if male_action == "Boxing" else 1.0
|
|
110
|
+
return 1.0 if male_action == "Boxing" else 2.0
|
|
111
|
+
|
|
112
|
+
def female(self, type, male_action, female_action):
|
|
113
|
+
if male_action != female_action:
|
|
114
|
+
return 0.0
|
|
115
|
+
if type == "A":
|
|
116
|
+
return 2.0 if female_action == "Boxing" else 1.0
|
|
117
|
+
return 1.0 if female_action == "Boxing" else 2.0
|
|
103
118
|
|
|
104
119
|
|
|
105
120
|
nash = BayesianNashEquilibrium(SampleGame()).get_nash_equilibrium()
|
|
121
|
+
print(nash["index"]) # [(0, 0), (1, 2), (2, 1), (3, 3)]
|
|
122
|
+
print(nash["profile"][0]) # [{'A': 'Boxing', 'B': 'Boxing'}, {'A': 'Boxing', 'B': 'Boxing'}]
|
|
123
|
+
print(nash["payoff"][0]) # [{'A': 2.0, 'B': 1.0}, {'A': 2.0, 'B': 1.0}]
|
|
106
124
|
```
|
|
107
125
|
|
|
126
|
+
`profile` and `payoff` are indexed by `[equilibrium][player][type]`. The types and actions
|
|
127
|
+
are handed back exactly as you passed them in, so with `np.array` they print as
|
|
128
|
+
`np.str_('A')`; pass plain lists if you want plain strings.
|
|
129
|
+
|
|
108
130
|
## What gets faster
|
|
109
131
|
|
|
110
132
|
Against the pure Python `game_resolver`, on an 11-core Apple M series machine.
|
|
@@ -235,6 +235,8 @@ class SampleGame : public BayesianGame {
|
|
|
235
235
|
};
|
|
236
236
|
```
|
|
237
237
|
|
|
238
|
+
The bodies left out here are in [examples/bayesian_battle_of_sex.cpp](examples/bayesian_battle_of_sex.cpp).
|
|
239
|
+
|
|
238
240
|
```cpp
|
|
239
241
|
SampleGame game;
|
|
240
242
|
BayesianNashEquilibrium equilibrium(game);
|
|
@@ -48,7 +48,11 @@ All four ways of defining payoffs work, exactly as in `game_resolver`:
|
|
|
48
48
|
|
|
49
49
|
Subclass `BayesianGame` and implement `posterior()`.
|
|
50
50
|
|
|
51
|
+
A Bayesian battle of the sexes. Each player has a type `A` / `B`, observes their own type,
|
|
52
|
+
and computes the expected payoff with the posterior over the other player's type.
|
|
53
|
+
|
|
51
54
|
```python
|
|
55
|
+
import numpy as np
|
|
52
56
|
from game_resolver_cpp.bayesian_game import BayesianGame
|
|
53
57
|
from game_resolver_cpp.bayesian_nash_equilibrium import BayesianNashEquilibrium
|
|
54
58
|
from game_resolver_cpp.bayesian_player import BayesianPlayer
|
|
@@ -67,14 +71,32 @@ class SampleGame(BayesianGame):
|
|
|
67
71
|
other = type_tuple[(player_id + 1) % 2]
|
|
68
72
|
return 1 / 4 if own == other else 3 / 4
|
|
69
73
|
|
|
70
|
-
# payoff functions take (own type, each player's action)
|
|
71
|
-
def male(self, type, male_action, female_action):
|
|
72
|
-
|
|
74
|
+
# payoff functions take (own type, each player's action), and must return a number
|
|
75
|
+
def male(self, type, male_action, female_action):
|
|
76
|
+
if male_action != female_action:
|
|
77
|
+
return 0.0
|
|
78
|
+
if type == "A":
|
|
79
|
+
return 2.0 if male_action == "Boxing" else 1.0
|
|
80
|
+
return 1.0 if male_action == "Boxing" else 2.0
|
|
81
|
+
|
|
82
|
+
def female(self, type, male_action, female_action):
|
|
83
|
+
if male_action != female_action:
|
|
84
|
+
return 0.0
|
|
85
|
+
if type == "A":
|
|
86
|
+
return 2.0 if female_action == "Boxing" else 1.0
|
|
87
|
+
return 1.0 if female_action == "Boxing" else 2.0
|
|
73
88
|
|
|
74
89
|
|
|
75
90
|
nash = BayesianNashEquilibrium(SampleGame()).get_nash_equilibrium()
|
|
91
|
+
print(nash["index"]) # [(0, 0), (1, 2), (2, 1), (3, 3)]
|
|
92
|
+
print(nash["profile"][0]) # [{'A': 'Boxing', 'B': 'Boxing'}, {'A': 'Boxing', 'B': 'Boxing'}]
|
|
93
|
+
print(nash["payoff"][0]) # [{'A': 2.0, 'B': 1.0}, {'A': 2.0, 'B': 1.0}]
|
|
76
94
|
```
|
|
77
95
|
|
|
96
|
+
`profile` and `payoff` are indexed by `[equilibrium][player][type]`. The types and actions
|
|
97
|
+
are handed back exactly as you passed them in, so with `np.array` they print as
|
|
98
|
+
`np.str_('A')`; pass plain lists if you want plain strings.
|
|
99
|
+
|
|
78
100
|
## What gets faster
|
|
79
101
|
|
|
80
102
|
Against the pure Python `game_resolver`, on an 11-core Apple M series machine.
|
|
@@ -4,7 +4,7 @@ build-backend = "scikit_build_core.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "game_resolver_cpp"
|
|
7
|
-
version = "0.1.
|
|
7
|
+
version = "0.1.1"
|
|
8
8
|
description = "C++ backed game equilibrium solver with the game_resolver interface"
|
|
9
9
|
readme = "docs/README_for_pypi.md"
|
|
10
10
|
requires-python = ">=3.9"
|
|
@@ -24,7 +24,22 @@ class _CoreBayesianGame(_core.BayesianGame):
|
|
|
24
24
|
self._game = game
|
|
25
25
|
|
|
26
26
|
def posterior(self, player_id: int, type_profile) -> float:
|
|
27
|
-
|
|
27
|
+
types = tuple(type_profile)
|
|
28
|
+
value = self._game.posterior(player_id, types)
|
|
29
|
+
try:
|
|
30
|
+
return float(value)
|
|
31
|
+
except (TypeError, ValueError):
|
|
32
|
+
# 素の float() のエラーはどの呼び出しで起きたか言わない。return の書き忘れが多い。
|
|
33
|
+
what = (
|
|
34
|
+
"何も返しませんでした (None)"
|
|
35
|
+
if value is None
|
|
36
|
+
else f"数値でない値 {value!r} を返しました"
|
|
37
|
+
)
|
|
38
|
+
raise TypeError(
|
|
39
|
+
f"{type(self._game).__name__}.posterior() が{what}。"
|
|
40
|
+
f"引数は (player_id={player_id}, type_tuple={types}) でした。"
|
|
41
|
+
"事後確率は実数を返してください"
|
|
42
|
+
) from None
|
|
28
43
|
|
|
29
44
|
|
|
30
45
|
class BayesianNashEquilibrium:
|
|
@@ -94,6 +94,42 @@ PayoffTable to_payoff_table(const py::dict& mapping) {
|
|
|
94
94
|
return table;
|
|
95
95
|
}
|
|
96
96
|
|
|
97
|
+
/// 呼び出し可能オブジェクトを、エラーメッセージ用の名前にする。
|
|
98
|
+
std::string describe_callable(const py::handle& function) {
|
|
99
|
+
if (py::hasattr(function, "__qualname__")) {
|
|
100
|
+
return py::str(function.attr("__qualname__")).cast<std::string>() + "()";
|
|
101
|
+
}
|
|
102
|
+
return py::repr(function).cast<std::string>();
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
std::string describe_arguments(const py::tuple& arguments) {
|
|
106
|
+
std::string text;
|
|
107
|
+
for (std::size_t i = 0; i < arguments.size(); ++i) {
|
|
108
|
+
if (i != 0) {
|
|
109
|
+
text += ", ";
|
|
110
|
+
}
|
|
111
|
+
text += py::repr(arguments[i]).cast<std::string>();
|
|
112
|
+
}
|
|
113
|
+
return text;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/// Python が返した値を利得の実数にする。
|
|
117
|
+
///
|
|
118
|
+
/// pybind11 の素の cast エラーは「NoneType を C++ の型 '?' に変換できません」としか言わず、
|
|
119
|
+
/// どの関数がどの引数で失敗したのか分からない。戻り値の書き忘れが一番多いので、ここで拾う。
|
|
120
|
+
double to_payoff_value(const py::object& result, const py::handle& function,
|
|
121
|
+
const py::tuple& arguments) {
|
|
122
|
+
try {
|
|
123
|
+
return result.cast<double>();
|
|
124
|
+
} catch (const py::cast_error&) {
|
|
125
|
+
const std::string what =
|
|
126
|
+
result.is_none() ? "何も返しませんでした (None)"
|
|
127
|
+
: "数値でない値 " + py::repr(result).cast<std::string>() + " を返しました";
|
|
128
|
+
throw py::type_error(describe_callable(function) + " が" + what + "。引数は (" +
|
|
129
|
+
describe_arguments(arguments) + ") でした。利得関数は実数を返してください");
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
97
133
|
/// Python の関数を 1 セルごとに呼ぶ利得関数。
|
|
98
134
|
///
|
|
99
135
|
/// 1 回の呼び出しにつき Python の呼び出しと引数変換が発生するので、セル数が多いゲームでは
|
|
@@ -105,7 +141,7 @@ PayoffFunction to_payoff_function(py::function function) {
|
|
|
105
141
|
for (std::size_t i = 0; i < profile.size(); ++i) {
|
|
106
142
|
arguments[i] = from_action(profile[i]);
|
|
107
143
|
}
|
|
108
|
-
return function(*arguments)
|
|
144
|
+
return to_payoff_value(function(*arguments), function, arguments);
|
|
109
145
|
};
|
|
110
146
|
}
|
|
111
147
|
|
|
@@ -130,7 +166,7 @@ BayesianPayoffFunction to_bayesian_payoff_function(py::function function) {
|
|
|
130
166
|
for (std::size_t i = 0; i < profile.size(); ++i) {
|
|
131
167
|
arguments[i + 1] = from_action(profile[i]);
|
|
132
168
|
}
|
|
133
|
-
return function(*arguments)
|
|
169
|
+
return to_payoff_value(function(*arguments), function, arguments);
|
|
134
170
|
};
|
|
135
171
|
}
|
|
136
172
|
|
|
@@ -149,7 +185,19 @@ class PyBayesianGame : public BayesianGame {
|
|
|
149
185
|
if (!override) {
|
|
150
186
|
throw py::value_error("posterior() が実装されていません");
|
|
151
187
|
}
|
|
152
|
-
|
|
188
|
+
const py::object result = override(player_id, types);
|
|
189
|
+
try {
|
|
190
|
+
return result.cast<double>();
|
|
191
|
+
} catch (const py::cast_error&) {
|
|
192
|
+
const std::string what = result.is_none()
|
|
193
|
+
? "何も返しませんでした (None)"
|
|
194
|
+
: "数値でない値 " + py::repr(result).cast<std::string>() +
|
|
195
|
+
" を返しました";
|
|
196
|
+
throw py::type_error("posterior() が" + what + "。引数は (player_id=" +
|
|
197
|
+
std::to_string(player_id) + ", type_profile=" +
|
|
198
|
+
py::repr(types).cast<std::string>() +
|
|
199
|
+
") でした。事後確率は実数を返してください");
|
|
200
|
+
}
|
|
153
201
|
}
|
|
154
202
|
};
|
|
155
203
|
|
|
@@ -237,6 +237,38 @@ def test_initialize_payoff_matrices_is_idempotent():
|
|
|
237
237
|
assert len(equilibrium.get_nash_equilibrium()["index"]) == 4
|
|
238
238
|
|
|
239
239
|
|
|
240
|
+
def test_reports_payoff_function_returning_none():
|
|
241
|
+
"""return を書き忘れた利得関数は、どの関数のどの呼び出しかを言って落ちる。"""
|
|
242
|
+
|
|
243
|
+
class ForgotToReturn(SampleGame):
|
|
244
|
+
def male(self, type, male_action, female_action):
|
|
245
|
+
pass
|
|
246
|
+
|
|
247
|
+
with pytest.raises(TypeError, match="ForgotToReturn.male"):
|
|
248
|
+
BayesianNashEquilibrium(ForgotToReturn()).get_nash_equilibrium()
|
|
249
|
+
|
|
250
|
+
|
|
251
|
+
def test_reports_posterior_returning_none():
|
|
252
|
+
class ForgotToReturn(SampleGame):
|
|
253
|
+
def posterior(self, player_id, type_tuple):
|
|
254
|
+
pass
|
|
255
|
+
|
|
256
|
+
with pytest.raises(TypeError, match="posterior"):
|
|
257
|
+
BayesianNashEquilibrium(ForgotToReturn()).get_nash_equilibrium()
|
|
258
|
+
|
|
259
|
+
|
|
260
|
+
def test_core_reports_payoff_callable_returning_none():
|
|
261
|
+
"""C++ から呼び戻す経路(_core.Player に関数を渡す)でも同じように言う。"""
|
|
262
|
+
from game_resolver_cpp import _core
|
|
263
|
+
|
|
264
|
+
game = _core.Game()
|
|
265
|
+
actions = ["C", "D"]
|
|
266
|
+
game.add(_core.Player(0, actions, lambda a, b: None))
|
|
267
|
+
game.add(_core.Player(1, actions, np.array([[3.0, 5.0], [0.0, 1.0]])))
|
|
268
|
+
with pytest.raises(TypeError, match="None"):
|
|
269
|
+
_core.NashEquilibrium(game)
|
|
270
|
+
|
|
271
|
+
|
|
240
272
|
# ---------------------------------------------------------------- その他
|
|
241
273
|
|
|
242
274
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{game_resolver_cpp-0.1.0 → game_resolver_cpp-0.1.1}/include/game_resolver/bayesian/bayesian_game.hpp
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{game_resolver_cpp-0.1.0 → game_resolver_cpp-0.1.1}/include/game_resolver/nash_equilibrium.hpp
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{game_resolver_cpp-0.1.0 → game_resolver_cpp-0.1.1}/include/game_resolver/solver/nash_solver.hpp
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{game_resolver_cpp-0.1.0 → game_resolver_cpp-0.1.1}/python/benchmarks/compare_with_python.py
RENAMED
|
File without changes
|
|
File without changes
|
{game_resolver_cpp-0.1.0 → game_resolver_cpp-0.1.1}/python/game_resolver_cpp/bayesian_game.py
RENAMED
|
File without changes
|
{game_resolver_cpp-0.1.0 → game_resolver_cpp-0.1.1}/python/game_resolver_cpp/bayesian_player.py
RENAMED
|
File without changes
|
|
File without changes
|
{game_resolver_cpp-0.1.0 → game_resolver_cpp-0.1.1}/python/game_resolver_cpp/nash_equilibrium.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{game_resolver_cpp-0.1.0 → game_resolver_cpp-0.1.1}/src/bayesian/bayesian_nash_equilibrium.cpp
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|