piegy 1.0.0__tar.gz → 1.1.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.
- {piegy-1.0.0/src/piegy.egg-info → piegy-1.1.0}/PKG-INFO +9 -7
- {piegy-1.0.0 → piegy-1.1.0}/README.md +8 -5
- {piegy-1.0.0 → piegy-1.1.0}/pyproject.toml +1 -2
- {piegy-1.0.0 → piegy-1.1.0}/src/piegy/__version__.py +1 -0
- {piegy-1.0.0 → piegy-1.1.0}/src/piegy/data_tools.py +4 -2
- {piegy-1.0.0 → piegy-1.1.0}/src/piegy/figures.py +107 -91
- {piegy-1.0.0 → piegy-1.1.0}/src/piegy/model.py +2 -5
- {piegy-1.0.0 → piegy-1.1.0}/src/piegy/test_var.py +135 -77
- {piegy-1.0.0 → piegy-1.1.0}/src/piegy/tools/figure_tools.py +51 -19
- {piegy-1.0.0 → piegy-1.1.0}/src/piegy/videos.py +44 -66
- {piegy-1.0.0 → piegy-1.1.0/src/piegy.egg-info}/PKG-INFO +9 -7
- {piegy-1.0.0 → piegy-1.1.0}/src/piegy.egg-info/requires.txt +0 -1
- {piegy-1.0.0 → piegy-1.1.0}/LICENSE.txt +0 -0
- {piegy-1.0.0 → piegy-1.1.0}/MANIFEST.in +0 -0
- {piegy-1.0.0 → piegy-1.1.0}/setup.cfg +0 -0
- {piegy-1.0.0 → piegy-1.1.0}/src/piegy/__init__.py +0 -0
- {piegy-1.0.0 → piegy-1.1.0}/src/piegy/analysis.py +0 -0
- {piegy-1.0.0 → piegy-1.1.0}/src/piegy/tools/__init__.py +0 -0
- {piegy-1.0.0 → piegy-1.1.0}/src/piegy/tools/file_tools.py +0 -0
- {piegy-1.0.0 → piegy-1.1.0}/src/piegy.egg-info/SOURCES.txt +0 -0
- {piegy-1.0.0 → piegy-1.1.0}/src/piegy.egg-info/dependency_links.txt +0 -0
- {piegy-1.0.0 → piegy-1.1.0}/src/piegy.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: piegy
|
3
|
-
Version: 1.
|
3
|
+
Version: 1.1.0
|
4
4
|
Summary: Payoff-Driven Stochastic Spatial Model for Evolutionary Game Theory
|
5
5
|
Author-email: Chenning Xu <cxu7@caltech.edu>
|
6
6
|
License: BSD 3-Clause License
|
@@ -49,7 +49,6 @@ Description-Content-Type: text/markdown
|
|
49
49
|
License-File: LICENSE.txt
|
50
50
|
Requires-Dist: numpy
|
51
51
|
Requires-Dist: matplotlib
|
52
|
-
Requires-Dist: imageio>=2.37.0
|
53
52
|
Requires-Dist: moviepy>=2.1.1
|
54
53
|
Requires-Dist: seaborn>=0.13.2
|
55
54
|
Dynamic: license-file
|
@@ -62,20 +61,22 @@ Provides a stochastic spatial model for simulating the interaction and evolution
|
|
62
61
|
|
63
62
|
## Installation
|
64
63
|
|
64
|
+
To install *piegy*, run the following in terminal:
|
65
|
+
|
65
66
|
```bash
|
66
67
|
pip install piegy
|
67
68
|
```
|
68
69
|
|
69
70
|
## Documentation and Source
|
70
71
|
|
71
|
-
See source code at: [
|
72
|
-
The *piegy* documentation at: [piegy
|
72
|
+
See source code at: [piegy GitHub repository](https://github.com/Chenning04/piegy.git).
|
73
|
+
The *piegy* documentation at: [piegy Documentation](https://piegy.readthedocs.io/en/).
|
73
74
|
|
74
75
|
## How the Model Works
|
75
76
|
|
76
|
-
Our model can be summarized as "classical game theory endowed with
|
77
|
+
Our model can be summarized as "classical evolutionary game theory endowed with spatial structure and payoff-driven migration rules". Consider two species, predators and preys (denoted by *U* and *V*), in a rectangular region. We divide the region into N by M patches and simulate their interaction within a patch by classical game theory (i.e., payoff matrices and carrying capacity). Interactions across patches are simulated by payoff-driven migration rules. An individual migrates to a neighboring patch with probability weighted by payoff in the neighbors.
|
77
78
|
|
78
|
-
We use the Gillepie algorithm as the fundamental event-selection algorithm. At each time step, one event is selected and let happen; and step
|
79
|
+
We use the Gillepie algorithm as the fundamental event-selection algorithm. At each time step, one event is selected and let happen; and the step size is continuous, dependent on the current state in the space. Data are recorded every some specified time interval.
|
79
80
|
|
80
81
|
## Analytic Tools
|
81
82
|
|
@@ -95,10 +96,11 @@ dynamics = figures.UV_dyna(sim)
|
|
95
96
|
U_hmap, V_hmap = figures.UV_heatmap(sim)
|
96
97
|
```
|
97
98
|
|
98
|
-
The figures reveal the population dynamics and steady state distribution.
|
99
|
+
The figures reveal the population dynamics and steady state population distribution.
|
99
100
|
|
100
101
|
|
101
102
|
## Acknowledgments
|
102
103
|
|
103
104
|
- Thanks Professor Daniel Cooney at University of Illinois Urbana-Champaign. This package is developed alongside a project with Prof. Cooney and received enormous help from him.
|
104
105
|
- Special thanks to the open-source community for making this package possible.
|
106
|
+
|
@@ -6,20 +6,22 @@ Provides a stochastic spatial model for simulating the interaction and evolution
|
|
6
6
|
|
7
7
|
## Installation
|
8
8
|
|
9
|
+
To install *piegy*, run the following in terminal:
|
10
|
+
|
9
11
|
```bash
|
10
12
|
pip install piegy
|
11
13
|
```
|
12
14
|
|
13
15
|
## Documentation and Source
|
14
16
|
|
15
|
-
See source code at: [
|
16
|
-
The *piegy* documentation at: [piegy
|
17
|
+
See source code at: [piegy GitHub repository](https://github.com/Chenning04/piegy.git).
|
18
|
+
The *piegy* documentation at: [piegy Documentation](https://piegy.readthedocs.io/en/).
|
17
19
|
|
18
20
|
## How the Model Works
|
19
21
|
|
20
|
-
Our model can be summarized as "classical game theory endowed with
|
22
|
+
Our model can be summarized as "classical evolutionary game theory endowed with spatial structure and payoff-driven migration rules". Consider two species, predators and preys (denoted by *U* and *V*), in a rectangular region. We divide the region into N by M patches and simulate their interaction within a patch by classical game theory (i.e., payoff matrices and carrying capacity). Interactions across patches are simulated by payoff-driven migration rules. An individual migrates to a neighboring patch with probability weighted by payoff in the neighbors.
|
21
23
|
|
22
|
-
We use the Gillepie algorithm as the fundamental event-selection algorithm. At each time step, one event is selected and let happen; and step
|
24
|
+
We use the Gillepie algorithm as the fundamental event-selection algorithm. At each time step, one event is selected and let happen; and the step size is continuous, dependent on the current state in the space. Data are recorded every some specified time interval.
|
23
25
|
|
24
26
|
## Analytic Tools
|
25
27
|
|
@@ -39,10 +41,11 @@ dynamics = figures.UV_dyna(sim)
|
|
39
41
|
U_hmap, V_hmap = figures.UV_heatmap(sim)
|
40
42
|
```
|
41
43
|
|
42
|
-
The figures reveal the population dynamics and steady state distribution.
|
44
|
+
The figures reveal the population dynamics and steady state population distribution.
|
43
45
|
|
44
46
|
|
45
47
|
## Acknowledgments
|
46
48
|
|
47
49
|
- Thanks Professor Daniel Cooney at University of Illinois Urbana-Champaign. This package is developed alongside a project with Prof. Cooney and received enormous help from him.
|
48
50
|
- Special thanks to the open-source community for making this package possible.
|
51
|
+
|
@@ -4,7 +4,7 @@ build-backend = 'setuptools.build_meta'
|
|
4
4
|
|
5
5
|
[project]
|
6
6
|
name = 'piegy'
|
7
|
-
version = '1.
|
7
|
+
version = '1.1.0'
|
8
8
|
description = 'Payoff-Driven Stochastic Spatial Model for Evolutionary Game Theory'
|
9
9
|
readme = 'README.md'
|
10
10
|
requires-python = '>=3.6'
|
@@ -16,7 +16,6 @@ keywords = ['Game Theory', 'Evolutionary Game Theory', 'Spatial Model', 'Stochas
|
|
16
16
|
dependencies = [
|
17
17
|
'numpy',
|
18
18
|
'matplotlib',
|
19
|
-
'imageio>=2.37.0',
|
20
19
|
'moviepy>=2.1.1',
|
21
20
|
'seaborn>=0.13.2'
|
22
21
|
]
|
@@ -118,12 +118,14 @@ def read_data(dirs):
|
|
118
118
|
|
119
119
|
# outputs
|
120
120
|
try:
|
121
|
-
sim.set_data(False, data[2][0],
|
121
|
+
sim.set_data(data_empty = False, max_record = data[2][0], compress_itv = data[2][1],
|
122
|
+
U = data[2][2], V = data[2][3], U_pi = data[2][4], V_pi = data[2][5])
|
122
123
|
except:
|
123
124
|
raise ValueError('Invalid simulation results saved in data')
|
124
125
|
|
125
126
|
return sim
|
126
|
-
|
127
|
+
|
128
|
+
|
127
129
|
|
128
130
|
|
129
131
|
|
@@ -37,20 +37,20 @@ import matplotlib.pyplot as plt
|
|
37
37
|
import numpy as np
|
38
38
|
|
39
39
|
|
40
|
-
|
41
40
|
# curve type in plot
|
42
41
|
# used by UV_dyna, UV_std, and pi_dyna
|
43
42
|
CURVE_TYPE = '-'
|
44
43
|
|
45
44
|
|
46
45
|
|
47
|
-
def UV_heatmap(sim, U_color = 'Purples', V_color = 'Greens', start = 0.95, end = 1.0, annot = False, fmt = '.3g'):
|
46
|
+
def UV_heatmap(sim, ax_U = None, ax_V = None, U_color = 'Purples', V_color = 'Greens', start = 0.95, end = 1.0, annot = False, fmt = '.3g'):
|
48
47
|
'''
|
49
48
|
Makes two heatmaps for U, V average distribution over a time interval, respectively. Works best for 2D space.
|
50
49
|
1D works as well, but figures look bad.
|
51
50
|
|
52
51
|
Inputs:
|
53
52
|
sim: A model.simulation object.
|
53
|
+
ax_U, ax_V: matplotlib axes to plot on. New axes will be created if None is given.
|
54
54
|
U_color: Color for U's heatmap, uses matplotlib color maps.
|
55
55
|
V_color: Color for V's heatmap.
|
56
56
|
start: (0,1) float, where the interval should start from. Intended as a 'percentage'.
|
@@ -60,7 +60,7 @@ def UV_heatmap(sim, U_color = 'Purples', V_color = 'Greens', start = 0.95, end =
|
|
60
60
|
fmt: Number format for annotations. How many digits you want to keep. Please set annot = True first and then use fmt.
|
61
61
|
|
62
62
|
Returns:
|
63
|
-
|
63
|
+
ax_U, ax_V: matplotlib axes with heatmaps of U, V distribution plotted upon.
|
64
64
|
'''
|
65
65
|
|
66
66
|
start_index = int(start * sim.max_record)
|
@@ -77,20 +77,21 @@ def UV_heatmap(sim, U_color = 'Purples', V_color = 'Greens', start = 0.95, end =
|
|
77
77
|
V_title = figure_t.gen_title('V', start, end)
|
78
78
|
V_text = figure_t.gen_text(np.mean(V_ave), np.std(V_ave))
|
79
79
|
|
80
|
-
|
81
|
-
|
80
|
+
ax_U = figure_t.heatmap(U_ave, ax_U, U_color, annot, fmt, U_title, U_text)
|
81
|
+
ax_V = figure_t.heatmap(V_ave, ax_V, V_color, annot, fmt, V_title, V_text)
|
82
82
|
|
83
|
-
return
|
83
|
+
return ax_U, ax_V
|
84
84
|
|
85
85
|
|
86
86
|
|
87
|
-
def UV_bar(sim, U_color = 'purple', V_color = 'green', start = 0.95, end = 1.0):
|
87
|
+
def UV_bar(sim, ax_U = None, ax_V = None, U_color = 'purple', V_color = 'green', start = 0.95, end = 1.0):
|
88
88
|
'''
|
89
89
|
Makes two barplots for U, V average distribution over a time interval. Works best for 1D space.
|
90
90
|
2D works as well, but figures look bad.
|
91
91
|
|
92
92
|
Inputs:
|
93
93
|
sim: A model.simulation object.
|
94
|
+
ax_U, ax_V: matplotlib axes to plot on. New axes will be created if None is given.
|
94
95
|
U_color: Color of U's barplot. Uses Matplotlib colors.
|
95
96
|
See available colors at: https://matplotlib.org/stable/gallery/color/named_colors.html
|
96
97
|
V_color: Color of V's barplot. Uses Matplotlib colors.
|
@@ -98,7 +99,7 @@ def UV_bar(sim, U_color = 'purple', V_color = 'green', start = 0.95, end = 1.0):
|
|
98
99
|
end: (0,1) float. Where you want the interval to end.
|
99
100
|
|
100
101
|
Returns:
|
101
|
-
|
102
|
+
ax_U, ax_V: matplotlib axes with bar plots for U and V plotted upon.
|
102
103
|
'''
|
103
104
|
|
104
105
|
start_index = int(start * sim.max_record)
|
@@ -114,15 +115,15 @@ def UV_bar(sim, U_color = 'purple', V_color = 'green', start = 0.95, end = 1.0):
|
|
114
115
|
V_title = figure_t.gen_title('V', start, end)
|
115
116
|
V_text = figure_t.gen_text(np.mean(V_ave), np.std(V_ave))
|
116
117
|
|
117
|
-
|
118
|
-
|
118
|
+
ax_U = figure_t.bar(U_ave, ax = ax_U, color = U_color, xlabel = 'patches', ylabel = 'U', title = U_title, text = U_text)
|
119
|
+
ax_V = figure_t.bar(V_ave, ax = ax_V, color = V_color, xlabel = 'patches', ylabel = 'V', title = V_title, text = V_text)
|
119
120
|
|
120
|
-
return
|
121
|
+
return ax_U, ax_V
|
121
122
|
|
122
123
|
|
123
124
|
|
124
125
|
|
125
|
-
def UV_dyna(sim, interval = 20, grid = True):
|
126
|
+
def UV_dyna(sim, ax = None, interval = 20, grid = True):
|
126
127
|
'''
|
127
128
|
Plots how total U, V change overtime.
|
128
129
|
The curves are not directly based on every single data point.
|
@@ -132,13 +133,14 @@ def UV_dyna(sim, interval = 20, grid = True):
|
|
132
133
|
|
133
134
|
Inputs:
|
134
135
|
sim: A model.simulation object.
|
136
|
+
ax: matplotlib ax to plot on. New ax will be created if None is given.
|
135
137
|
interval: How many data points to take average over. Larger value makes curves smoother, but also loses local fluctuations.
|
136
138
|
NOTE: this interval doesn't overlap with sim.compress_itv.
|
137
139
|
e.g. you already took average over every 20 data points, then using interval <= 20 here has no smoothing effect.
|
138
140
|
grid: Whether to add grid lines to plot.
|
139
141
|
|
140
142
|
Returns:
|
141
|
-
|
143
|
+
ax: matplotlib ax, contains U's, V's, and sum of U & V population.
|
142
144
|
'''
|
143
145
|
|
144
146
|
# store the average values in lists
|
@@ -160,26 +162,29 @@ def UV_dyna(sim, interval = 20, grid = True):
|
|
160
162
|
#### plot ####
|
161
163
|
xaxis = np.linspace(0, sim.maxtime, len(U_curve))
|
162
164
|
|
163
|
-
|
165
|
+
if ax == None:
|
166
|
+
_, ax = plt.subplots()
|
164
167
|
ax.grid(grid)
|
165
168
|
ax.plot(xaxis, U_curve, CURVE_TYPE, label = 'U')
|
166
169
|
ax.plot(xaxis, V_curve, CURVE_TYPE, label = 'V')
|
167
170
|
ax.plot(xaxis, total_curve, CURVE_TYPE, label = 'total')
|
168
|
-
ax.
|
171
|
+
ax.set_xlabel('Time')
|
172
|
+
ax.set_ylabel('Population')
|
173
|
+
ax.set_title('Population U & V Over Time')
|
169
174
|
ax.legend()
|
170
175
|
|
171
|
-
return
|
176
|
+
return ax
|
172
177
|
|
173
178
|
|
174
179
|
|
175
180
|
|
176
|
-
def UV_hist(sim, U_color = 'purple', V_color = 'green', start = 0.95, end = 1.0):
|
181
|
+
def UV_hist(sim, ax_U = None, ax_V = None, U_color = 'purple', V_color = 'green', start = 0.95, end = 1.0):
|
177
182
|
'''
|
178
183
|
Makes density histograms for U, V's average distribution over an interval.
|
179
184
|
Sometimes it may not be shown in density plots due to matplotlib features.
|
180
185
|
|
181
186
|
Returns:
|
182
|
-
|
187
|
+
ax_U, ax_V: matplotlib axes with heatmaps of U, V population density plotted upon.
|
183
188
|
'''
|
184
189
|
|
185
190
|
start_index = int(start * sim.max_record)
|
@@ -190,30 +195,32 @@ def UV_hist(sim, U_color = 'purple', V_color = 'green', start = 0.95, end = 1.0)
|
|
190
195
|
|
191
196
|
#### plot ####
|
192
197
|
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
+
if ax_U == None:
|
199
|
+
_, ax_U = plt.subplots()
|
200
|
+
ax_U.set_xlabel('Population U')
|
201
|
+
ax_U.set_ylabel('Density')
|
202
|
+
ax_U.hist(U_ave, color = U_color, density = True)
|
203
|
+
ax_U.set_title(figure_t.gen_title('U Hist', start, end))
|
198
204
|
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
205
|
+
if ax_V == None:
|
206
|
+
_, ax_V = plt.subplots()
|
207
|
+
ax_V.set_xlabel('Population V')
|
208
|
+
ax_V.set_ylabel('Density')
|
209
|
+
ax_V.hist(V_ave, color = V_color, density = True)
|
210
|
+
ax_V.set_title(figure_t.gen_title('V Hist', start, end))
|
204
211
|
|
205
|
-
return
|
212
|
+
return ax_U, ax_V
|
206
213
|
|
207
214
|
|
208
215
|
|
209
216
|
|
210
|
-
def UV_std(sim, interval = 20, grid = True):
|
217
|
+
def UV_std(sim, ax = None, interval = 20, grid = True):
|
211
218
|
'''
|
212
219
|
Plots how standard deviation of U, V change over time.
|
213
220
|
Takes average over many small interval to smooth out local fluctuations.
|
214
221
|
|
215
222
|
Returns:
|
216
|
-
|
223
|
+
ax: matplotlib ax, contains U's and V's std curves.
|
217
224
|
'''
|
218
225
|
|
219
226
|
interval = figure_t.scale_interval(interval, sim.compress_itv)
|
@@ -232,15 +239,17 @@ def UV_std(sim, interval = 20, grid = True):
|
|
232
239
|
#### plot ####
|
233
240
|
xaxis = np.linspace(0, sim.maxtime, len(U_std))
|
234
241
|
|
235
|
-
|
242
|
+
if ax == None:
|
243
|
+
_, ax = plt.subplots()
|
236
244
|
ax.grid(grid)
|
237
245
|
ax.plot(xaxis, U_std, CURVE_TYPE, label = 'U std')
|
238
246
|
ax.plot(xaxis, V_std, CURVE_TYPE, label = 'V std')
|
239
247
|
ax.legend()
|
240
|
-
ax.set_xlabel('
|
241
|
-
ax.
|
242
|
-
|
243
|
-
|
248
|
+
ax.set_xlabel('Time')
|
249
|
+
ax.set_ylabel('Std Dev')
|
250
|
+
ax.set_title('Population Std-Dev Dynamics')
|
251
|
+
|
252
|
+
return ax
|
244
253
|
|
245
254
|
|
246
255
|
|
@@ -270,7 +279,7 @@ def UV_expected_val(sim):
|
|
270
279
|
|
271
280
|
|
272
281
|
|
273
|
-
def UV_expected(sim, U_color = 'Purples', V_color = 'Greens', annot = False, fmt = '.3g'):
|
282
|
+
def UV_expected(sim, ax_U = None, ax_V = None, U_color = 'Purples', V_color = 'Greens', annot = False, fmt = '.3g'):
|
274
283
|
'''
|
275
284
|
Calculate expected population distribution based on matrices, assuming no migration.
|
276
285
|
For the formulas, see stochastic_mode.expected_UV
|
@@ -279,8 +288,8 @@ def UV_expected(sim, U_color = 'Purples', V_color = 'Greens', annot = False, fmt
|
|
279
288
|
Note the colors are color maps.
|
280
289
|
|
281
290
|
Returns:
|
282
|
-
|
283
|
-
If 1D (N or M == 1), then
|
291
|
+
ax_U, ax_V: If 2D (N and M both > 1), then ax_U and ax_V are heatmaps.
|
292
|
+
If 1D (N or M == 1), then ax_U and ax_V are barplots.
|
284
293
|
'''
|
285
294
|
|
286
295
|
U_expected, V_expected = UV_expected_val(sim)
|
@@ -292,20 +301,20 @@ def UV_expected(sim, U_color = 'Purples', V_color = 'Greens', annot = False, fmt
|
|
292
301
|
|
293
302
|
if (sim.N != 1) and (sim.M != 1):
|
294
303
|
# 2D
|
295
|
-
|
296
|
-
|
304
|
+
ax_U = figure_t.heatmap(U_expected, ax_U, U_color, annot, fmt, title = 'Expected U', text = U_text)
|
305
|
+
ax_V = figure_t.heatmap(V_expected, ax_V, V_color, annot, fmt, title = 'Expected V', text = V_text)
|
297
306
|
|
298
307
|
else:
|
299
308
|
# 1D
|
300
|
-
|
301
|
-
|
309
|
+
ax_U = figure_t.bar(U_expected.flatten(), ax_U, color = U_color, xlabel = 'patches', ylabel = 'popu', title = 'Expected Population U', text = U_text)
|
310
|
+
ax_V = figure_t.bar(V_expected.flatten(), ax_V, color = V_color, xlabel = 'patches', ylabel = 'popu', title = 'Expected Population V', text = V_text)
|
302
311
|
|
303
|
-
return
|
312
|
+
return ax_U, ax_V
|
304
313
|
|
305
314
|
|
306
315
|
|
307
316
|
|
308
|
-
def pi_heatmap(sim, U_color = 'BuPu', V_color = 'YlGn', start = 0.95, end = 1.0, annot = False, fmt = '.3g'):
|
317
|
+
def pi_heatmap(sim, ax_U = None, ax_V = None, U_color = 'BuPu', V_color = 'YlGn', start = 0.95, end = 1.0, annot = False, fmt = '.3g'):
|
309
318
|
'''
|
310
319
|
Make heatmaps for payoff in a specified interval.
|
311
320
|
Works best for 2D. 1D works as well, but figures look bad.
|
@@ -314,7 +323,7 @@ def pi_heatmap(sim, U_color = 'BuPu', V_color = 'YlGn', start = 0.95, end = 1.0,
|
|
314
323
|
Note the colors are matplotlib color maps.
|
315
324
|
|
316
325
|
Returns:
|
317
|
-
|
326
|
+
ax_U, ax_V: Seaborn heatmaps, for U's & V's payoff distribution, respectively.
|
318
327
|
'''
|
319
328
|
|
320
329
|
start_index = int(sim.max_record * start)
|
@@ -323,26 +332,26 @@ def pi_heatmap(sim, U_color = 'BuPu', V_color = 'YlGn', start = 0.95, end = 1.0,
|
|
323
332
|
U_pi_ave = figure_t.ave_interval(sim.U_pi, start_index, end_index)
|
324
333
|
V_pi_ave = figure_t.ave_interval(sim.V_pi, start_index, end_index)
|
325
334
|
|
326
|
-
U_title = figure_t.gen_title('
|
335
|
+
U_title = figure_t.gen_title('Payoff ' + r'$p_U$', start, end)
|
327
336
|
U_text = figure_t.gen_text(np.mean(U_pi_ave), np.std(U_pi_ave))
|
328
|
-
V_title = figure_t.gen_title('
|
337
|
+
V_title = figure_t.gen_title('Payoff ' + r'$p_V$', start, end)
|
329
338
|
V_text = figure_t.gen_text(np.mean(V_pi_ave), np.std(V_pi_ave))
|
330
339
|
|
331
|
-
|
332
|
-
|
340
|
+
ax_U = figure_t.heatmap(U_pi_ave, ax_U, U_color, annot, fmt, U_title, U_text)
|
341
|
+
ax_V = figure_t.heatmap(V_pi_ave, ax_V, V_color, annot, fmt, V_title, V_text)
|
333
342
|
|
334
|
-
return
|
343
|
+
return ax_U, ax_V
|
335
344
|
|
336
345
|
|
337
346
|
|
338
347
|
|
339
|
-
def pi_bar(sim, U_color = 'violet', V_color = 'yellowgreen', start = 0.95, end = 1.0):
|
348
|
+
def pi_bar(sim, ax_U = None, ax_V = None, U_color = 'violet', V_color = 'yellowgreen', start = 0.95, end = 1.0):
|
340
349
|
'''
|
341
350
|
Make barplot for payoff in a specified interval.
|
342
351
|
Works best for 1D. 2D works as well, but figures look bad.
|
343
352
|
|
344
353
|
Returns:
|
345
|
-
|
354
|
+
ax_U, ax_V: matplotlib axes with barplots of U and V payoff distribution plotted upon.
|
346
355
|
'''
|
347
356
|
|
348
357
|
start_index = int(sim.max_record * start)
|
@@ -351,25 +360,25 @@ def pi_bar(sim, U_color = 'violet', V_color = 'yellowgreen', start = 0.95, end =
|
|
351
360
|
U_pi_ave = figure_t.ave_interval_1D(sim.U_pi, start_index, end_index)
|
352
361
|
V_pi_ave = figure_t.ave_interval_1D(sim.V_pi, start_index, end_index)
|
353
362
|
|
354
|
-
U_title = figure_t.gen_title('
|
363
|
+
U_title = figure_t.gen_title(r'$p_U$', start, end)
|
355
364
|
U_text = figure_t.gen_text(np.mean(U_pi_ave), np.std(U_pi_ave))
|
356
|
-
V_title = figure_t.gen_title('
|
365
|
+
V_title = figure_t.gen_title(r'$p_V$', start, end)
|
357
366
|
V_text = figure_t.gen_text(np.mean(V_pi_ave), np.std(V_pi_ave))
|
358
367
|
|
359
|
-
|
360
|
-
|
368
|
+
ax_U = figure_t.bar(U_pi_ave, ax_U, U_color, 'Patches', 'Payoff ' + r'$p_U$', U_title, U_text)
|
369
|
+
ax_V = figure_t.bar(V_pi_ave, ax_V, V_color, 'Patches', 'Payoff ' + r'$p_V$', V_title, V_text)
|
361
370
|
|
362
|
-
return
|
371
|
+
return ax_U, ax_V
|
363
372
|
|
364
373
|
|
365
374
|
|
366
375
|
|
367
|
-
def pi_dyna(sim, interval = 20, grid = True):
|
376
|
+
def pi_dyna(sim, ax = None, interval = 20, grid = True):
|
368
377
|
'''
|
369
378
|
Plot how payoffs change over time.
|
370
379
|
|
371
380
|
Returns:
|
372
|
-
|
381
|
+
ax: matplotlib ax of U's, V's, and sum of U & V payoff.
|
373
382
|
'''
|
374
383
|
|
375
384
|
U_curve = []
|
@@ -390,27 +399,30 @@ def pi_dyna(sim, interval = 20, grid = True):
|
|
390
399
|
#### plot ####
|
391
400
|
xaxis = np.linspace(0, sim.maxtime, len(U_curve))
|
392
401
|
|
393
|
-
|
402
|
+
if ax == None:
|
403
|
+
_, ax = plt.subplots()
|
394
404
|
ax.grid(grid)
|
395
|
-
ax.plot(xaxis, U_curve, CURVE_TYPE, label = '
|
396
|
-
ax.plot(xaxis, V_curve, CURVE_TYPE, label = '
|
405
|
+
ax.plot(xaxis, U_curve, CURVE_TYPE, label = r'$p_U$')
|
406
|
+
ax.plot(xaxis, V_curve, CURVE_TYPE, label = r'$p_V$')
|
397
407
|
ax.plot(xaxis, total_curve, CURVE_TYPE, label = 'total')
|
398
408
|
ax.set_xlim(0, sim.maxtime)
|
399
|
-
ax.
|
409
|
+
ax.set_xlabel('Time')
|
410
|
+
ax.set_ylabel('Payoff')
|
411
|
+
ax.set_title('Payoff ' + r'$p_U$' + ' & ' + r'$p_V$' + ' over time')
|
400
412
|
ax.legend()
|
401
413
|
|
402
|
-
return
|
414
|
+
return ax
|
403
415
|
|
404
416
|
|
405
417
|
|
406
418
|
|
407
|
-
def pi_hist(sim, U_color = 'violet', V_color = 'yellowgreen', start = 0.95, end = 1.0):
|
419
|
+
def pi_hist(sim, ax_U = None, ax_V = None, U_color = 'violet', V_color = 'yellowgreen', start = 0.95, end = 1.0):
|
408
420
|
'''
|
409
421
|
Makes deensity histograms of U's and V's payoffs in a sepcified interval.
|
410
422
|
Sometimes it may not be shown in density plots due to matplotlib features.
|
411
423
|
|
412
424
|
Returns:
|
413
|
-
|
425
|
+
ax_U, ax_V: histogram of U's and V's payoff.
|
414
426
|
'''
|
415
427
|
|
416
428
|
start_index = int(start * sim.max_record)
|
@@ -421,29 +433,31 @@ def pi_hist(sim, U_color = 'violet', V_color = 'yellowgreen', start = 0.95, end
|
|
421
433
|
|
422
434
|
#### plot ####
|
423
435
|
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
436
|
+
if ax_U == None:
|
437
|
+
_, ax_U = plt.subplots()
|
438
|
+
ax_U.set_xlabel('Payoff ' + r'$p_U$')
|
439
|
+
ax_U.set_ylabel('Density')
|
440
|
+
ax_U.hist(U_pi_ave, color = U_color, density = True)
|
441
|
+
ax_U.set_title(figure_t.gen_title('Payoff ' + r'$p_U$' + ' Hist', start, end))
|
429
442
|
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
443
|
+
if ax_V == None:
|
444
|
+
_, ax_V = plt.subplots()
|
445
|
+
ax_V.set_xlabel('Payoff ' + r'$p_V$')
|
446
|
+
ax_V.set_ylabel('Density')
|
447
|
+
ax_V.hist(V_pi_ave, color = V_color, density = True)
|
448
|
+
ax_V.set_title(figure_t.gen_title('Payoff ' + r'$p_V$' + ' Hist', start, end))
|
435
449
|
|
436
|
-
return
|
450
|
+
return ax_U, ax_V
|
437
451
|
|
438
452
|
|
439
453
|
|
440
454
|
|
441
|
-
def pi_std(sim, interval = 20, grid = True):
|
455
|
+
def pi_std(sim, ax = None, interval = 20, grid = True):
|
442
456
|
'''
|
443
457
|
Plots how standard deviation of payoff change over time.
|
444
458
|
|
445
459
|
Returns:
|
446
|
-
|
460
|
+
ax: matplotlib ax of the std of payoffs.
|
447
461
|
'''
|
448
462
|
|
449
463
|
|
@@ -463,26 +477,28 @@ def pi_std(sim, interval = 20, grid = True):
|
|
463
477
|
#### plot ####
|
464
478
|
xaxis = np.linspace(0, sim.maxtime, len(U_pi_std))
|
465
479
|
|
466
|
-
|
480
|
+
if ax == None:
|
481
|
+
_, ax = plt.subplots()
|
467
482
|
ax.grid(grid)
|
468
|
-
ax.plot(xaxis, U_pi_std, CURVE_TYPE, label = '
|
469
|
-
ax.plot(xaxis, V_pi_std, CURVE_TYPE, label = '
|
483
|
+
ax.plot(xaxis, U_pi_std, CURVE_TYPE, label = r'$p_U$' + ' std')
|
484
|
+
ax.plot(xaxis, V_pi_std, CURVE_TYPE, label = r'$p_V$' + ' std')
|
470
485
|
ax.legend()
|
471
|
-
ax.set_xlabel('
|
472
|
-
ax.
|
486
|
+
ax.set_xlabel('Time')
|
487
|
+
ax.set_ylabel('Std Dev')
|
488
|
+
ax.set_title('Payoff Std-Dev Dynamics')
|
473
489
|
|
474
|
-
return
|
490
|
+
return ax
|
475
491
|
|
476
492
|
|
477
493
|
|
478
494
|
|
479
|
-
def UV_pi(sim, U_color = 'violet', V_color = 'yellowgreen', alpha = 0.
|
495
|
+
def UV_pi(sim, ax_U = None, ax_V = None, U_color = 'violet', V_color = 'yellowgreen', alpha = 0.4, start = 0.95, end = 1.0):
|
480
496
|
'''
|
481
497
|
Make two scatter plots: x-axes are population and y-axes are payoff in a specified time interval.
|
482
498
|
Reveals relationship between population and payoff.
|
483
499
|
|
484
500
|
Returns:
|
485
|
-
|
501
|
+
ax_U, ax_V: matplotlib axes with U and V population-payoff scatter plots.
|
486
502
|
'''
|
487
503
|
|
488
504
|
start_index = int(start * sim.max_record)
|
@@ -495,9 +511,9 @@ def UV_pi(sim, U_color = 'violet', V_color = 'yellowgreen', alpha = 0.25, start
|
|
495
511
|
V_pi_ave = figure_t.ave_interval(sim.V_pi, start_index, end_index)
|
496
512
|
|
497
513
|
|
498
|
-
|
499
|
-
|
514
|
+
ax_U = figure_t.scatter(U_ave, U_pi_ave, ax_U, U_color, alpha, xlabel = 'U', ylabel = 'Payoff ' + r'$p_U$', title = 'U - ' + r'$p_U$')
|
515
|
+
ax_V = figure_t.scatter(V_ave, V_pi_ave, ax_V, V_color, alpha, xlabel = 'V', ylabel = 'Payoff ' + r'$p_V$', title = 'V - ' + r'$p_V$')
|
500
516
|
|
501
|
-
return
|
517
|
+
return ax_U, ax_V
|
502
518
|
|
503
519
|
|
@@ -358,14 +358,11 @@ class simulation:
|
|
358
358
|
if print_pct <= 0:
|
359
359
|
raise ValueError('Please use an int > 0 for print_pct or None for not printing progress.')
|
360
360
|
|
361
|
-
|
362
|
-
raise TypeError('Please use an int as seed')
|
363
|
-
if seed < 0:
|
364
|
-
raise ValueError('Please use a non-negative int as seed.')
|
361
|
+
# seed is checked by number
|
365
362
|
|
366
363
|
|
367
364
|
def check_valid_data(self, data_empty, max_record, compress_itv, U, V, U_pi, V_pi):
|
368
|
-
# check whether a set of data is valid
|
365
|
+
# check whether a set of data is valid, used when reading a saved model
|
369
366
|
if type(data_empty) != bool:
|
370
367
|
raise TypeError('data_empty not a bool')
|
371
368
|
|