piegy 2.0.2__py3-none-any.whl → 2.0.4__py3-none-any.whl
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/C_core/piegyc.so +0 -0
- piegy/__init__.py +2 -42
- piegy/__version__.py +3 -1
- piegy/data_tools.py +2 -1
- piegy/figures.py +1 -28
- piegy/simulation.py +98 -41
- piegy/simulation_py.py +9 -0
- {piegy-2.0.2.dist-info → piegy-2.0.4.dist-info}/METADATA +2 -2
- piegy-2.0.4.dist-info/RECORD +18 -0
- piegy-2.0.2.dist-info/RECORD +0 -18
- {piegy-2.0.2.dist-info → piegy-2.0.4.dist-info}/WHEEL +0 -0
- {piegy-2.0.2.dist-info → piegy-2.0.4.dist-info}/licenses/LICENSE.txt +0 -0
- {piegy-2.0.2.dist-info → piegy-2.0.4.dist-info}/top_level.txt +0 -0
piegy/C_core/piegyc.so
CHANGED
Binary file
|
piegy/__init__.py
CHANGED
@@ -20,13 +20,13 @@ Last update: May 12, 2025
|
|
20
20
|
|
21
21
|
from .__version__ import __version__
|
22
22
|
|
23
|
-
from .simulation import model, run, demo_model
|
23
|
+
from .simulation import model, run, demo_model, UV_expected_val, check_overflow_func
|
24
24
|
from .videos import make_video, SUPPORTED_FIGURES
|
25
25
|
from .data_tools import save_data, read_data
|
26
26
|
|
27
27
|
from .analysis import rounds_expected, scale_maxtime, check_convergence, combine_sim
|
28
28
|
|
29
|
-
from .figures import (UV_heatmap, UV_bar, UV_dyna, UV_hist, UV_std,
|
29
|
+
from .figures import (UV_heatmap, UV_bar, UV_dyna, UV_hist, UV_std, UV_expected,
|
30
30
|
pi_heatmap, pi_bar, pi_dyna, pi_hist, pi_std, UV_pi)
|
31
31
|
|
32
32
|
from .test_var import (test_var1, var_UV1, var_pi1, var_convergence1, get_dirs1,
|
@@ -54,43 +54,3 @@ __all__ = simulation_memebers + videos_members + data_members + figures_members
|
|
54
54
|
|
55
55
|
|
56
56
|
|
57
|
-
|
58
|
-
|
59
|
-
# Below might be better suited for documents
|
60
|
-
'''
|
61
|
-
To run a simulation, start by defining some parameter. Here is a complete set of params::
|
62
|
-
|
63
|
-
>>> N = 5
|
64
|
-
>>> M = 5
|
65
|
-
>>> maxtime = 300
|
66
|
-
>>> sim_time = 3
|
67
|
-
>>> I = [[[22, 44] for i in range(N)] for j in range(M)]
|
68
|
-
>>> X = [[[-0.1, 0.4, 0, 0.2] for i in range(N)] for j in range(M)]
|
69
|
-
>>> X[1][1] = [0.1, 0.6, 0.2, 0.4]
|
70
|
-
>>> P = [[[0.5, 0.5, 100, 100, 0.001, 0.001] for i in range(N)] for j in range(M)]
|
71
|
-
>>> boundary = True
|
72
|
-
>>> print_pct = 5
|
73
|
-
>>> seed = None
|
74
|
-
|
75
|
-
These parameters essentially define the spatial size, initial population, payoff matrices...
|
76
|
-
For a detailed explanation, see simulation object.
|
77
|
-
|
78
|
-
Then create a 'simulation' object with those parameters::
|
79
|
-
|
80
|
-
>>> sim = simulation(N, M, maxtime, sim_time, I, X, P, boundary, print_pct, seed)
|
81
|
-
|
82
|
-
This 'sim' object will be the basis of our simulation. It carries all the necessary parameters
|
83
|
-
and storage bin for the results.
|
84
|
-
|
85
|
-
Now let's run the simulation (assuming you imported)::
|
86
|
-
|
87
|
-
>>> multi_test(sim)
|
88
|
-
|
89
|
-
And that's the simulation! It takes 30s ~ 1min. You can see the progress.
|
90
|
-
|
91
|
-
Now, to see the results, let's use figures::
|
92
|
-
|
93
|
-
>>> fig = UV_heatmap(sim)
|
94
|
-
|
95
|
-
|
96
|
-
'''
|
piegy/__version__.py
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
__version__ = '2.0.
|
1
|
+
__version__ = '2.0.4'
|
2
2
|
|
3
3
|
'''
|
4
4
|
version history:
|
@@ -24,4 +24,6 @@ version history:
|
|
24
24
|
2.0.0: update simulation core to C-based.
|
25
25
|
2.0.1: re-upload, the C core is not included in package.
|
26
26
|
2.0.2: update version number in __version__.py and update README.
|
27
|
+
2.0.3: speed boost & debugging in C core. Add check_overflow feature in simulation module, checks whether overflow/too large numbers might be encountered in simulation.
|
28
|
+
2.0.4: minor debuggings.
|
27
29
|
'''
|
piegy/data_tools.py
CHANGED
@@ -50,6 +50,7 @@ def save_data(mod, dirs = '', print_msg = True):
|
|
50
50
|
inputs.append(mod.P.tolist())
|
51
51
|
inputs.append(mod.print_pct)
|
52
52
|
inputs.append(mod.seed)
|
53
|
+
inputs.append(mod.check_overflow)
|
53
54
|
data.append(inputs)
|
54
55
|
|
55
56
|
# skipped rng
|
@@ -107,7 +108,7 @@ def read_data(dirs):
|
|
107
108
|
try:
|
108
109
|
mod = simulation.model(N = data[0][0], M = data[0][1], maxtime = data[0][2], record_itv = data[0][3],
|
109
110
|
sim_time = data[0][4], boundary = data[0][5], I = data[0][6], X = data[0][7], P = data[0][8],
|
110
|
-
print_pct = data[0][9], seed = data[0][10])
|
111
|
+
print_pct = data[0][9], seed = data[0][10], check_overflow = data[0][11])
|
111
112
|
except:
|
112
113
|
raise ValueError('Invalid input parameters saved in data')
|
113
114
|
|
piegy/figures.py
CHANGED
@@ -9,7 +9,6 @@ Plots for population:
|
|
9
9
|
- UV_dyna: Plot change of total U, V overtime.
|
10
10
|
- UV_hist: Make a histogram of U, V in a specified time interval.
|
11
11
|
- UV_std: Plot change of standard deviation of U, V over time.
|
12
|
-
- UV_expected_val: Calculate expected U, V distribution based on matrices, assuming no migration return values (np.array)
|
13
12
|
- UV_expected: Calculate expected distribution of U, V based on matrices, assuming no migration.
|
14
13
|
|
15
14
|
|
@@ -253,32 +252,6 @@ def UV_std(mod, ax = None, interval = 20, grid = True):
|
|
253
252
|
|
254
253
|
|
255
254
|
|
256
|
-
def UV_expected_val(mod):
|
257
|
-
'''
|
258
|
-
Calculate expected U & V distribution based on matrices, assume no migration.
|
259
|
-
To differentiate from UV_expected in figures.py: this one return arrays (values).
|
260
|
-
'''
|
261
|
-
|
262
|
-
U_expected = np.zeros((mod.N, mod.M))
|
263
|
-
V_expected = np.zeros((mod.N, mod.M))
|
264
|
-
|
265
|
-
for i in range(mod.N):
|
266
|
-
for j in range(mod.M):
|
267
|
-
# say matrix = [a, b, c, d]
|
268
|
-
# U_proportion = (d - b) / (a - b - c + d)
|
269
|
-
U_prop = (mod.X[i][j][3] - mod.X[i][j][1]) / (mod.X[i][j][0] - mod.X[i][j][1] - mod.X[i][j][2] + mod.X[i][j][3])
|
270
|
-
# equilibrium payoff, U_payoff = V_payoff
|
271
|
-
eq_payoff = U_prop * mod.X[i][j][0] + (1 - U_prop) * mod.X[i][j][1]
|
272
|
-
|
273
|
-
# payoff / kappa * proportion
|
274
|
-
U_expected[i][j] = eq_payoff / mod.P[i][j][4] * U_prop
|
275
|
-
V_expected[i][j] = eq_payoff / mod.P[i][j][5] * (1 - U_prop)
|
276
|
-
|
277
|
-
return U_expected, V_expected
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
255
|
def UV_expected(mod, ax_U = None, ax_V = None, U_color = 'Purples', V_color = 'Greens', annot = False, fmt = '.3g'):
|
283
256
|
'''
|
284
257
|
Calculate expected population distribution based on matrices, assuming no migration.
|
@@ -292,7 +265,7 @@ def UV_expected(mod, ax_U = None, ax_V = None, U_color = 'Purples', V_color = 'G
|
|
292
265
|
If 1D (N or M == 1), then ax_U and ax_V are barplots.
|
293
266
|
'''
|
294
267
|
|
295
|
-
U_expected, V_expected = UV_expected_val(mod)
|
268
|
+
U_expected, V_expected = simulation.UV_expected_val(mod)
|
296
269
|
|
297
270
|
U_text = figure_t.gen_text(np.mean(U_expected), np.std(U_expected))
|
298
271
|
V_text = figure_t.gen_text(np.mean(V_expected), np.std(V_expected))
|
piegy/simulation.py
CHANGED
@@ -4,26 +4,12 @@ Main Module of Stochastic Simulation
|
|
4
4
|
|
5
5
|
Contains all the necessary tools to build a model and run models based on Gillespie Algorithm.
|
6
6
|
|
7
|
-
|
8
|
-
-
|
9
|
-
|
10
|
-
-
|
11
|
-
|
12
|
-
|
13
|
-
Functions:
|
14
|
-
- find_nb_zero_flux: (Private) Return pointers to a patch's neighbors under zero-flux (no-boundary) boundary condition.
|
15
|
-
- find_nb_periodical: (Private) Return pointers to a patch's neighbors under periodical (with-booundary) boundary condition.
|
16
|
-
- find_event: (Private) Pick a random event to happen.
|
17
|
-
- make_signal_zero_flux: (Private) Expand event index (return value of find_event) to a detailed signal, under zero-flux boundary condition.
|
18
|
-
- make_signal_periodical: (Private) Expand event index (return value of find_event) to a detailed signal, under periodical boundary condition.
|
19
|
-
- single_init: (Private) Initialize a single model. Meaning of 'single': see single_test and run.
|
20
|
-
- single_test: (Private) Run a single model.
|
21
|
-
'single' means a single round of model. You can run many single rounds and then take the average --- that's done by <run> function.
|
22
|
-
- run: Run multiple models and then take the average. All the model will use the same parameters.
|
23
|
-
Set a seed for reproducible results.
|
24
|
-
- demo_model: Returns a demo model (a model object).
|
25
|
-
|
26
|
-
NOTE: Only model class and run function are intended for direct usages.
|
7
|
+
Class & Functions:
|
8
|
+
- model: creates a stochastic mode. Run the model by ``simulation.run(mod)``
|
9
|
+
- run: runs stochastic simulation on a model.
|
10
|
+
- demo_model: returns a demo model.
|
11
|
+
- UV_expected_val: calculates the expected population of U, V at steady state, assuming no migration and any stochastic process.
|
12
|
+
- check_overflow_func: check whether an overflow might happen in simulation. This is usually done automatically when init-ing a model.
|
27
13
|
'''
|
28
14
|
|
29
15
|
|
@@ -35,16 +21,19 @@ import numpy as np
|
|
35
21
|
from numpy.ctypeslib import ndpointer
|
36
22
|
|
37
23
|
|
24
|
+
# path to the C shared libary
|
25
|
+
C_LIB_PATH = os.path.join(os.path.dirname(__file__), 'C_core', 'piegyc.so')
|
26
|
+
|
27
|
+
# check whether overflow / too large values might be encountered
|
28
|
+
# these values are considered as exponents in exp()
|
29
|
+
EXP_OVERFLOW_BOUND = 709 # where exp(x) reaches overflow bound
|
30
|
+
EXP_TOO_LARGE_BOUND = 88 # where exp(x) reaches 1e20
|
38
31
|
|
39
32
|
|
40
33
|
'''
|
41
34
|
The C core
|
42
35
|
'''
|
43
36
|
|
44
|
-
# path to the C shared libary
|
45
|
-
C_LIB_PATH = os.path.join(os.path.dirname(__file__), 'C_core', 'piegyc.so')
|
46
|
-
|
47
|
-
|
48
37
|
class model_c(ctypes.Structure):
|
49
38
|
'''
|
50
39
|
The C-cored model
|
@@ -91,11 +80,15 @@ lib.mod_init.argtypes = [
|
|
91
80
|
]
|
92
81
|
lib.mod_init.restype = c_bool
|
93
82
|
|
83
|
+
lib.mod_free_py.argtypes = [ctypes.POINTER(model_c)]
|
84
|
+
lib.mod_free_py.restype = None
|
85
|
+
|
94
86
|
lib.run.argtypes = [ctypes.POINTER(model_c), ctypes.POINTER(c_char), c_size_t]
|
95
87
|
lib.run.restype = None
|
96
88
|
|
97
89
|
|
98
90
|
|
91
|
+
|
99
92
|
'''
|
100
93
|
For access by Python
|
101
94
|
'''
|
@@ -129,9 +122,9 @@ class model:
|
|
129
122
|
compress data by only storing average values
|
130
123
|
'''
|
131
124
|
|
132
|
-
def __init__(self, N, M, maxtime, record_itv, sim_time, boundary, I, X, P, print_pct = 25, seed = None):
|
125
|
+
def __init__(self, N, M, maxtime, record_itv, sim_time, boundary, I, X, P, print_pct = 25, seed = None, check_overflow = True):
|
133
126
|
|
134
|
-
self.check_valid_input(N, M, maxtime, record_itv, sim_time, boundary, I, X, P, print_pct)
|
127
|
+
self.check_valid_input(N, M, maxtime, record_itv, sim_time, boundary, I, X, P, print_pct, seed, check_overflow)
|
135
128
|
|
136
129
|
self.N = N # int, N x M is spatial dimension
|
137
130
|
self.M = M # int, can't be 1. If want to make 1D space, use N = 1. And this model doesn't work for 1x1 space (causes NaN)
|
@@ -142,8 +135,18 @@ class model:
|
|
142
135
|
self.I = np.array(I) # N x M x 2 np.array, initial population. Two init-popu for every patch (U and V)
|
143
136
|
self.X = np.array(X) # N x M x 4 np.array, matrices. The '4' comes from 2x2 matrix flattened to 1D
|
144
137
|
self.P = np.array(P) # N x M x 6 np.array, 'patch variables', i.e., mu1&2, w1&2, kappa1&2
|
145
|
-
|
146
|
-
|
138
|
+
if print_pct == None:
|
139
|
+
self.print_pct = -1
|
140
|
+
else:
|
141
|
+
self.print_pct = print_pct # int, print how much percent is done, need to be non-zero
|
142
|
+
if seed == None:
|
143
|
+
self.seed = -1 # non-negative int, seed for random number generation
|
144
|
+
else:
|
145
|
+
self.seed = seed
|
146
|
+
self.check_overflow = check_overflow
|
147
|
+
|
148
|
+
if check_overflow:
|
149
|
+
check_overflow_func(self)
|
147
150
|
|
148
151
|
self.init_storage() # initialize storage bins. Put in a separate function because might want to change maxtime
|
149
152
|
# and that doesn't need to initialze the whole object again
|
@@ -163,7 +166,7 @@ class model:
|
|
163
166
|
self.Vpi = None
|
164
167
|
|
165
168
|
|
166
|
-
def check_valid_input(self, N, M, maxtime, record_itv, sim_time, boundary, I, X, P, print_pct):
|
169
|
+
def check_valid_input(self, N, M, maxtime, record_itv, sim_time, boundary, I, X, P, print_pct, seed, check_overflow):
|
167
170
|
# check whether the inputs are valid
|
168
171
|
|
169
172
|
if (N < 1) or (M < 1):
|
@@ -196,9 +199,16 @@ class model:
|
|
196
199
|
if np.array(P).shape != (N, M, 6):
|
197
200
|
raise ValueError('Please set P as a N x M x 6 shape list or array. 6 is for mu1, mu2, w1, w2, kappa1, kappa2')
|
198
201
|
|
199
|
-
if print_pct
|
202
|
+
if not ((print_pct == None) or (isinstance(print_pct, int) and (print_pct >= -1))):
|
203
|
+
# if not the two acceptable values: None or >= -1 int
|
200
204
|
raise ValueError('Please use an int > 0 for print_pct or None for not printing progress.')
|
201
205
|
|
206
|
+
if not ((seed == None) or (isinstance(seed, int) and (seed >= -1))):
|
207
|
+
raise ValueError('Please use a non-negative int as seed, or use None for no seed.')
|
208
|
+
|
209
|
+
if not isinstance(check_overflow, bool):
|
210
|
+
raise ValueError('Please use a bool for check_overflow')
|
211
|
+
|
202
212
|
|
203
213
|
def check_valid_data(self, data_empty, max_record, compress_itv):
|
204
214
|
# check whether a set of data is valid, used when reading a saved model
|
@@ -228,6 +238,7 @@ class model:
|
|
228
238
|
self_str += 'boundary = ' + str(self.boundary) + '\n'
|
229
239
|
self_str += 'print_pct = ' + str(self.print_pct) + '\n'
|
230
240
|
self_str += 'seed = ' + str(self.seed) + '\n'
|
241
|
+
self_str += 'check_overflow = ' + str(self.check_overflow) + '\n'
|
231
242
|
self_str += 'data_empty = ' + str(self.data_empty) + '\n'
|
232
243
|
self_str += 'compress_itv = ' + str(self.compress_itv) + '\n'
|
233
244
|
self_str += '\n'
|
@@ -288,7 +299,7 @@ class model:
|
|
288
299
|
|
289
300
|
sim2 = model(N = self.N, M = self.M, maxtime = self.maxtime, record_itv = self.record_itv, sim_time = self.sim_time, boundary = self.boundary,
|
290
301
|
I = np.copy(self.I), X = np.copy(self.X), P = np.copy(self.P),
|
291
|
-
print_pct = self.print_pct, seed = self.seed)
|
302
|
+
print_pct = self.print_pct, seed = self.seed, check_overflow = self.check_overflow)
|
292
303
|
|
293
304
|
if copy_data:
|
294
305
|
# copy data as well
|
@@ -384,6 +395,10 @@ def run(mod, message = ""):
|
|
384
395
|
'''
|
385
396
|
C-cored simulation
|
386
397
|
'''
|
398
|
+
|
399
|
+
if not mod.data_empty:
|
400
|
+
raise ValueError('mod has non-empty data.')
|
401
|
+
|
387
402
|
msg_len = len(message)
|
388
403
|
msg_bytes = message.encode('utf-8')
|
389
404
|
msg_buffer = ctypes.create_string_buffer(msg_bytes, msg_len)
|
@@ -397,15 +412,17 @@ def run(mod, message = ""):
|
|
397
412
|
mod.N, mod.M, mod.maxtime, mod.record_itv, mod.sim_time, mod.boundary,
|
398
413
|
I, X, P, mod.print_pct, mod.seed)
|
399
414
|
if not success:
|
400
|
-
raise RuntimeError(
|
415
|
+
raise RuntimeError('mod_init failed')
|
401
416
|
|
402
417
|
lib.run(ctypes.byref(mod_c), msg_buffer, msg_len)
|
403
418
|
|
404
|
-
mod.
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
419
|
+
mod.set_data(False, mod.max_record, 1, mod_c.get_array('U1d').reshape(mod.N, mod.M, mod.max_record),
|
420
|
+
mod_c.get_array('V1d').reshape(mod.N, mod.M, mod.max_record),
|
421
|
+
mod_c.get_array('Upi_1d').reshape(mod.N, mod.M, mod.max_record),
|
422
|
+
mod_c.get_array('Vpi_1d').reshape(mod.N, mod.M, mod.max_record))
|
423
|
+
|
424
|
+
lib.mod_free_py(ctypes.byref(mod_c))
|
425
|
+
del mod_c
|
409
426
|
|
410
427
|
|
411
428
|
|
@@ -416,7 +433,7 @@ def demo_model():
|
|
416
433
|
|
417
434
|
N = 10 # Number of rows
|
418
435
|
M = 10 # Number of cols
|
419
|
-
maxtime =
|
436
|
+
maxtime = 30 # how long you want the model to run
|
420
437
|
record_itv = 0.1 # how often to record data.
|
421
438
|
sim_time = 1 # repeat model to reduce randomness
|
422
439
|
boundary = True # boundary condition.
|
@@ -425,12 +442,12 @@ def demo_model():
|
|
425
442
|
I = [[[44, 22] for _ in range(M)] for _ in range(N)]
|
426
443
|
|
427
444
|
# flattened payoff matrices, total resource is 0.4, cost of fighting is 0.1
|
428
|
-
X = [[[-
|
445
|
+
X = [[[-1, 4, 0, 2] for _ in range(M)] for _ in range(N)]
|
429
446
|
|
430
447
|
# patch variables
|
431
|
-
P = [[[0.5, 0.5,
|
448
|
+
P = [[[0.5, 0.5, 1, 1, 0.001, 0.001] for _ in range(M)] for _ in range(N)]
|
432
449
|
|
433
|
-
print_pct =
|
450
|
+
print_pct = 25 # print progress
|
434
451
|
seed = 36 # seed for random number generation
|
435
452
|
|
436
453
|
# create a model object
|
@@ -441,3 +458,43 @@ def demo_model():
|
|
441
458
|
|
442
459
|
|
443
460
|
|
461
|
+
def UV_expected_val(mod):
|
462
|
+
'''
|
463
|
+
Calculate expected U & V population and payoff based on matrices, assume no migration and any stochastic process.
|
464
|
+
To differentiate from UV_expected in figures.py: this one return arrays (values).
|
465
|
+
'''
|
466
|
+
|
467
|
+
U_expected = np.zeros((mod.N, mod.M)) # expected U population
|
468
|
+
V_expected = np.zeros((mod.N, mod.M)) # expected V population
|
469
|
+
pi_expected = np.zeros((mod.N, mod.M)) # expected payoff, which are equal for U and V
|
470
|
+
|
471
|
+
for i in range(mod.N):
|
472
|
+
for j in range(mod.M):
|
473
|
+
# say matrix = [a, b, c, d]
|
474
|
+
# U_proportion = (d - b) / (a - b - c + d)
|
475
|
+
U_prop = (mod.X[i][j][3] - mod.X[i][j][1]) / (mod.X[i][j][0] - mod.X[i][j][1] - mod.X[i][j][2] + mod.X[i][j][3])
|
476
|
+
# equilibrium payoff, U_payoff = V_payoff
|
477
|
+
eq_payoff = U_prop * mod.X[i][j][0] + (1 - U_prop) * mod.X[i][j][1]
|
478
|
+
|
479
|
+
# payoff / kappa * proportion
|
480
|
+
U_expected[i][j] = eq_payoff / mod.P[i][j][4] * U_prop
|
481
|
+
V_expected[i][j] = eq_payoff / mod.P[i][j][5] * (1 - U_prop)
|
482
|
+
pi_expected[i][j] = eq_payoff
|
483
|
+
|
484
|
+
return U_expected, V_expected, pi_expected
|
485
|
+
|
486
|
+
|
487
|
+
|
488
|
+
def check_overflow_func(mod):
|
489
|
+
_, _, pi_expected = UV_expected_val(mod)
|
490
|
+
for i in range(mod.N):
|
491
|
+
for j in range(mod.M):
|
492
|
+
w1_pi = pi_expected[i][j] * mod.P[i][j][2] # w1 * U_pi
|
493
|
+
w2_pi = pi_expected[i][j] * mod.P[i][j][3] # w2 * V_pi
|
494
|
+
if ((w1_pi > EXP_OVERFLOW_BOUND) or (w2_pi > EXP_OVERFLOW_BOUND)):
|
495
|
+
print("Warning: might cause overflow. \n\t w1, w2, or payoff matrix values too large")
|
496
|
+
return
|
497
|
+
if ((w1_pi > EXP_TOO_LARGE_BOUND) or (w2_pi > EXP_TOO_LARGE_BOUND)):
|
498
|
+
print("Warning: might encounter large values > 3e38 in simulation. \n\t w1, w2, or payoff matrix values too large")
|
499
|
+
return
|
500
|
+
|
piegy/simulation_py.py
CHANGED
@@ -6,6 +6,7 @@ But you can still run them by calling:
|
|
6
6
|
'''
|
7
7
|
|
8
8
|
from . import simulation
|
9
|
+
model = simulation.model
|
9
10
|
|
10
11
|
import math
|
11
12
|
import numpy as np
|
@@ -168,6 +169,9 @@ class patch:
|
|
168
169
|
def find_event(self, expected_sum):
|
169
170
|
# find the event within the 12 events based on expected sum-of-rates within this patch
|
170
171
|
|
172
|
+
if expected_sum > (self.sum_pi_death_rates + self.sum_mig_rates):
|
173
|
+
print("patch rate not large enough")
|
174
|
+
|
171
175
|
if expected_sum < self.sum_pi_death_rates:
|
172
176
|
# in the first 4 events (payoff and death events)
|
173
177
|
event = 0
|
@@ -756,6 +760,11 @@ def run_py(mod, predict_runtime = False, message = ''):
|
|
756
760
|
if not mod.data_empty:
|
757
761
|
raise RuntimeError('mod has non-empty data')
|
758
762
|
|
763
|
+
mod.U = np.zeros((mod.N, mod.M, mod.max_record))
|
764
|
+
mod.V = np.zeros((mod.N, mod.M, mod.max_record))
|
765
|
+
mod.Vpi = np.zeros((mod.N, mod.M, mod.max_record))
|
766
|
+
mod.Upi = np.zeros((mod.N, mod.M, mod.max_record))
|
767
|
+
|
759
768
|
start = timer() # runtime
|
760
769
|
|
761
770
|
mod.data_empty = False
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: piegy
|
3
|
-
Version: 2.0.
|
3
|
+
Version: 2.0.4
|
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
|
@@ -55,7 +55,7 @@ Dynamic: license-file
|
|
55
55
|
|
56
56
|
# piegy
|
57
57
|
|
58
|
-
The package full name is: Payoff-Driven Stochastic Spatial Model for Evolutionary Game Theory. "pi" refers to "payoff, and "egy"
|
58
|
+
The package full name is: Payoff-Driven Stochastic Spatial Model for Evolutionary Game Theory. "pi" refers to "payoff, and "egy" is taken from "Evolutionary Game Theory".
|
59
59
|
|
60
60
|
Provides a stochastic spatial model for simulating the interaction and evolution of two species in either 1D or 2D space, as well as analytic tools.
|
61
61
|
|
@@ -0,0 +1,18 @@
|
|
1
|
+
piegy/__init__.py,sha256=KlbuIi3_Z9YZ5dWSFTwKxwrX3jdgNO4C8ksDjyDHsbk,2064
|
2
|
+
piegy/__version__.py,sha256=ydhLHcMkt_o_Ob_FaaJr7zuqNyr_hAOzLuFTcGpm3UA,1400
|
3
|
+
piegy/analysis.py,sha256=2GBsBbi7LdstSEAM0-F2bfL2kHu3MElcrw8bxZ1x6LI,8719
|
4
|
+
piegy/data_tools.py,sha256=auliVb88qKQmCX7LEDgKQvhBcwFTCXBEWKtjJ4_-rTU,3446
|
5
|
+
piegy/figures.py,sha256=GwixvD3Flaqg4feSvqr42lDR7CwZK0_2qmZg6N6_1uE,17936
|
6
|
+
piegy/simulation.py,sha256=t6gusSvqKRMRc9RDEczUC36YMpDptCJEiB3I-NT3Q4o,19900
|
7
|
+
piegy/simulation_py.py,sha256=WtWhpHCosKQ457gZ-iJ-7v0N3NtyPqDfgXv4DL3aBKs,29523
|
8
|
+
piegy/test_var.py,sha256=EfItIK-FEApJTAW8rs15kdMs5xlv-8Bx6CtfpSoi8ys,23562
|
9
|
+
piegy/videos.py,sha256=QfSpOdwfaDsrQYRoiHmZ6gowzRQHom3m8kx1P65_8sM,10218
|
10
|
+
piegy/C_core/piegyc.so,sha256=sIUTEhKbLMhvUQPF22D-VZuBV2J-f-Rhq8MqPGRCatk,51320
|
11
|
+
piegy/tools/__init__.py,sha256=eYOl_HJHDonYexfrmKh3koOlxvtSo46vH6jHvCEEB4k,300
|
12
|
+
piegy/tools/figure_tools.py,sha256=54vJSJMReXidFnSPE_xFvedtgnJU3d55zQDPNBLGs98,6975
|
13
|
+
piegy/tools/file_tools.py,sha256=ncxFWeHfIE-GYLQlOrahFlhBgqPyuY3R5_93fpQeCEs,630
|
14
|
+
piegy-2.0.4.dist-info/licenses/LICENSE.txt,sha256=wfzEht_CxOcfGGmg3f3at4mWJb9rTBjA51mXLl_3O3g,1498
|
15
|
+
piegy-2.0.4.dist-info/METADATA,sha256=H_dX6oqqDCLZWT6Dw2PmLG2VkHtfqMOaKVisZxc-eM0,5452
|
16
|
+
piegy-2.0.4.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
17
|
+
piegy-2.0.4.dist-info/top_level.txt,sha256=k4QLYL8PqdqDuy95-4NZD_FVLqJDsmq67tpKkBn4vMw,6
|
18
|
+
piegy-2.0.4.dist-info/RECORD,,
|
piegy-2.0.2.dist-info/RECORD
DELETED
@@ -1,18 +0,0 @@
|
|
1
|
-
piegy/__init__.py,sha256=plq8y9IE9ilaKtEFIblJ_QexipAvPBXoalXhXLbs71Q,3244
|
2
|
-
piegy/__version__.py,sha256=5DvxDV6QF68xfqpnLA66LjfnG85J5lGVS2MxLSf8Two,1206
|
3
|
-
piegy/analysis.py,sha256=2GBsBbi7LdstSEAM0-F2bfL2kHu3MElcrw8bxZ1x6LI,8719
|
4
|
-
piegy/data_tools.py,sha256=cbWAxGpFPbvne1RzvJaVN6avvmNt1I165xoppOqxQME,3378
|
5
|
-
piegy/figures.py,sha256=TP9AoNnKwGZxBNmJGbplpb_ewr9US3jziBzOh1arGeY,19014
|
6
|
-
piegy/simulation.py,sha256=4J4pdDuobV0fVxTF3QMr0SzX49tLBwkh99svnjO3eTU,17698
|
7
|
-
piegy/simulation_py.py,sha256=BqHzVtFADUkqRRQGvncp3ambv-_wALwOc-ZRF2id8AM,29153
|
8
|
-
piegy/test_var.py,sha256=EfItIK-FEApJTAW8rs15kdMs5xlv-8Bx6CtfpSoi8ys,23562
|
9
|
-
piegy/videos.py,sha256=QfSpOdwfaDsrQYRoiHmZ6gowzRQHom3m8kx1P65_8sM,10218
|
10
|
-
piegy/C_core/piegyc.so,sha256=5tBwQbxyKzTYny0oMhMZGyShuBJNRb2HzRWkeRfxM0s,51768
|
11
|
-
piegy/tools/__init__.py,sha256=eYOl_HJHDonYexfrmKh3koOlxvtSo46vH6jHvCEEB4k,300
|
12
|
-
piegy/tools/figure_tools.py,sha256=54vJSJMReXidFnSPE_xFvedtgnJU3d55zQDPNBLGs98,6975
|
13
|
-
piegy/tools/file_tools.py,sha256=ncxFWeHfIE-GYLQlOrahFlhBgqPyuY3R5_93fpQeCEs,630
|
14
|
-
piegy-2.0.2.dist-info/licenses/LICENSE.txt,sha256=wfzEht_CxOcfGGmg3f3at4mWJb9rTBjA51mXLl_3O3g,1498
|
15
|
-
piegy-2.0.2.dist-info/METADATA,sha256=R8FKdQAxTR-iuJxj8UIq7PbkjjgnWvAEq1DjVODM-18,5453
|
16
|
-
piegy-2.0.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
17
|
-
piegy-2.0.2.dist-info/top_level.txt,sha256=k4QLYL8PqdqDuy95-4NZD_FVLqJDsmq67tpKkBn4vMw,6
|
18
|
-
piegy-2.0.2.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|