piegy 1.1.2__py3-none-any.whl → 1.1.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/__init__.py +4 -4
- piegy/__version__.py +3 -1
- piegy/analysis.py +58 -58
- piegy/data_tools.py +35 -35
- piegy/figures.py +80 -80
- piegy/{model.py → simulation.py} +109 -109
- piegy/test_var.py +25 -25
- piegy/tools/figure_tools.py +3 -3
- piegy/videos.py +21 -18
- {piegy-1.1.2.dist-info → piegy-1.1.4.dist-info}/METADATA +10 -7
- piegy-1.1.4.dist-info/RECORD +16 -0
- piegy-1.1.2.dist-info/RECORD +0 -16
- {piegy-1.1.2.dist-info → piegy-1.1.4.dist-info}/WHEEL +0 -0
- {piegy-1.1.2.dist-info → piegy-1.1.4.dist-info}/licenses/LICENSE.txt +0 -0
- {piegy-1.1.2.dist-info → piegy-1.1.4.dist-info}/top_level.txt +0 -0
piegy/{model.py → simulation.py}
RENAMED
@@ -1,13 +1,13 @@
|
|
1
1
|
'''
|
2
|
-
Main Module of Stochastic
|
3
|
-
|
2
|
+
Main Module of Stochastic Simulation
|
3
|
+
-------------------------------------------
|
4
4
|
|
5
|
-
Contains all the necessary tools to build a model and run
|
5
|
+
Contains all the necessary tools to build a model and run models based on Gillespie Algorithm.
|
6
6
|
|
7
7
|
Classes:
|
8
8
|
- patch: (Private) Simulates a single patch in the N x M space. Assume no spatial structure within a patch.
|
9
9
|
All spatial movements are based on patches.
|
10
|
-
-
|
10
|
+
- model: Stores input parameters and data generated during simulation.
|
11
11
|
|
12
12
|
|
13
13
|
Functions:
|
@@ -16,14 +16,14 @@ Functions:
|
|
16
16
|
- find_event: (Private) Pick a random event to happen.
|
17
17
|
- make_signal_zero_flux: (Private) Expand event index (return value of find_event) to a detailed signal, under zero-flux boundary condition.
|
18
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
|
20
|
-
- single_test: (Private) Run a single
|
21
|
-
'single' means a single round of
|
22
|
-
- run: Run multiple
|
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
23
|
Set a seed for reproducible results.
|
24
|
-
- demo_model: Returns a demo model (a
|
24
|
+
- demo_model: Returns a demo model (a model object).
|
25
25
|
|
26
|
-
NOTE: Only
|
26
|
+
NOTE: Only model class and run function are intended for direct usages.
|
27
27
|
'''
|
28
28
|
|
29
29
|
|
@@ -32,10 +32,10 @@ import numpy as np
|
|
32
32
|
from timeit import default_timer as timer
|
33
33
|
|
34
34
|
|
35
|
-
# data type used by
|
35
|
+
# data type used by model.U and model.V
|
36
36
|
UV_DTYPE = 'float64'
|
37
37
|
|
38
|
-
# data type used by
|
38
|
+
# data type used by model.U_pi and V_pi
|
39
39
|
PI_DTYPE = 'float64'
|
40
40
|
|
41
41
|
# data type for storing rates in single_test an single_init
|
@@ -122,7 +122,7 @@ class patch:
|
|
122
122
|
|
123
123
|
def set_nb_pointers(self, nb):
|
124
124
|
# nb is a list of pointers (point to patches)
|
125
|
-
# nb is passed from the
|
125
|
+
# nb is passed from the model class
|
126
126
|
self.nb = nb
|
127
127
|
|
128
128
|
|
@@ -220,7 +220,7 @@ class patch:
|
|
220
220
|
|
221
221
|
|
222
222
|
def change_popu(self, s):
|
223
|
-
# convert s (a signal, passed from
|
223
|
+
# convert s (a signal, passed from model class) to a change in population
|
224
224
|
|
225
225
|
# s = 0, 1, 2 are for U
|
226
226
|
# s = 0 for migration IN, receive an immigrant
|
@@ -251,23 +251,23 @@ class patch:
|
|
251
251
|
|
252
252
|
|
253
253
|
|
254
|
-
class
|
254
|
+
class model:
|
255
255
|
'''
|
256
|
-
Store
|
257
|
-
Initialize a
|
256
|
+
Store model data and input parameters.
|
257
|
+
Initialize a model object to run models.
|
258
258
|
|
259
259
|
Public Class Functions:
|
260
260
|
|
261
261
|
__init__:
|
262
|
-
Create a
|
262
|
+
Create a model object. Also initialize data storage.
|
263
263
|
|
264
264
|
__str__:
|
265
|
-
Print
|
265
|
+
Print model object in a nice way.
|
266
266
|
|
267
267
|
copy:
|
268
268
|
Return a deep copy of self. Can choose whether to copy data as well. Default is to copy.
|
269
269
|
|
270
|
-
|
270
|
+
clear_data:
|
271
271
|
clear all data stored, set U, V, U_pi, V_pi to zero arrays
|
272
272
|
|
273
273
|
change_maxtime:
|
@@ -276,7 +276,7 @@ class simulation:
|
|
276
276
|
set_seed:
|
277
277
|
Set a new seed.
|
278
278
|
|
279
|
-
|
279
|
+
compress_data:
|
280
280
|
compress data by only storing average values
|
281
281
|
'''
|
282
282
|
|
@@ -286,7 +286,7 @@ class simulation:
|
|
286
286
|
|
287
287
|
self.N = N # int, N x M is spatial dimension
|
288
288
|
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)
|
289
|
-
self.maxtime = maxtime # float or int, run
|
289
|
+
self.maxtime = maxtime # float or int, run model for how long time
|
290
290
|
self.record_itv = record_itv # float, record data every record_itv of time
|
291
291
|
self.sim_time = sim_time # int, run this many of rounds (of single_test)
|
292
292
|
self.boundary = boundary # bool, the N x M space have boundary or not (i.e., zero-flux (True) or periodical (False))
|
@@ -296,7 +296,7 @@ class simulation:
|
|
296
296
|
self.print_pct = print_pct # int, print how much percent is done, need to be non-zero
|
297
297
|
self.seed = seed # non-negative int, seed for random generator
|
298
298
|
self.UV_dtype = UV_dtype # what data type to store population, should be a float format. This value is passed to np.array.
|
299
|
-
# Default is '
|
299
|
+
# Default is 'float64', use lower accuracy to reduce data size.
|
300
300
|
self.pi_dtype = pi_dtype # what data type to store payoff, should be a float format. This value is passed to np.array.
|
301
301
|
# Default is 'float64'
|
302
302
|
|
@@ -309,7 +309,7 @@ class simulation:
|
|
309
309
|
self.data_empty = True # whether data storage bins are empty. model.run will refuse to run (raise error) if not empty.
|
310
310
|
self.max_record = int(self.maxtime / self.record_itv) # int, how many data points to store sin total
|
311
311
|
self.compress_itv = 1 # int, intended to reduce size of data (if not 1). Updated by compress_data function
|
312
|
-
# if set to an int, say 20,
|
312
|
+
# if set to an int, say 20, mod will take average over every 20 data points and save them as new data.
|
313
313
|
# May be used over and over again to recursively reduce data size.
|
314
314
|
# Default is 1, not to take average.
|
315
315
|
self.U = np.zeros((self.N, self.M, self.max_record), dtype = self.UV_dtype) # N x M x max_record np.array, float32, stores population of U in every patch over tiem
|
@@ -373,7 +373,7 @@ class simulation:
|
|
373
373
|
|
374
374
|
|
375
375
|
def __str__(self):
|
376
|
-
# print this
|
376
|
+
# print this mod in a nice format
|
377
377
|
|
378
378
|
self_str = ''
|
379
379
|
self_str += 'N = ' + str(self.N) + '\n'
|
@@ -443,7 +443,7 @@ class simulation:
|
|
443
443
|
if type(copy_data) != bool:
|
444
444
|
raise TypeError('Please give a bool as argument: whether to copy data or not')
|
445
445
|
|
446
|
-
sim2 =
|
446
|
+
sim2 = model(N = self.N, M = self.M, maxtime = self.maxtime, record_itv = self.record_itv, sim_time = self.sim_time, boundary = self.boundary,
|
447
447
|
I = np.copy(self.I), X = np.copy(self.X), P = np.copy(self.P),
|
448
448
|
print_pct = self.print_pct, seed = self.seed, UV_dtype = self.UV_dtype, pi_dtype = self.pi_dtype)
|
449
449
|
|
@@ -455,7 +455,7 @@ class simulation:
|
|
455
455
|
|
456
456
|
|
457
457
|
def calculate_ave(self):
|
458
|
-
# get the average value over sim_time many
|
458
|
+
# get the average value over sim_time many models
|
459
459
|
if self.sim_time != 1:
|
460
460
|
for i in range(self.N):
|
461
461
|
for j in range(self.M):
|
@@ -481,7 +481,7 @@ class simulation:
|
|
481
481
|
self.seed = seed
|
482
482
|
|
483
483
|
|
484
|
-
def
|
484
|
+
def clear_data(self):
|
485
485
|
# clear all data stored, set all to 0
|
486
486
|
self.init_storage()
|
487
487
|
|
@@ -500,7 +500,7 @@ class simulation:
|
|
500
500
|
self.V_pi = np.copy(V_pi)
|
501
501
|
|
502
502
|
|
503
|
-
def
|
503
|
+
def compress_data(self, compress_itv = 5):
|
504
504
|
# compress data by only storing average values
|
505
505
|
|
506
506
|
if type(compress_itv) != int:
|
@@ -811,33 +811,33 @@ def nb_need_change(ni, signal):
|
|
811
811
|
|
812
812
|
|
813
813
|
|
814
|
-
def single_init(
|
814
|
+
def single_init(mod, rng):
|
815
815
|
'''
|
816
816
|
The first major function for the model.
|
817
817
|
Initialize all variables and run 1 round, then pass variables and results to single_test.
|
818
818
|
|
819
819
|
Input:
|
820
|
-
|
820
|
+
mod is a model object
|
821
821
|
rng is random number generator (np.random.default_rng), initialized by model.run
|
822
822
|
'''
|
823
823
|
|
824
824
|
#### Initialize Data Storage ####
|
825
825
|
|
826
|
-
world = [[patch(
|
827
|
-
patch_rates = np.zeros((
|
828
|
-
sum_rates_by_row = np.zeros((
|
826
|
+
world = [[patch(mod.I[i][j][0], mod.I[i][j][1], mod.X[i][j], mod.P[i][j]) for j in range(mod.M)] for i in range(mod.N)] # N x M patches
|
827
|
+
patch_rates = np.zeros((mod.N, mod.M), dtype = RATES_DTYPE) # every patch's sum-of-12-srates
|
828
|
+
sum_rates_by_row = np.zeros((mod.N), dtype = RATES_DTYPE) # every row's sum-of-patch, i.e., sum of 12 * M rates in every row.
|
829
829
|
sum_rates = 0 # sum of all N x M x 12 rates
|
830
830
|
|
831
831
|
signal = None
|
832
832
|
|
833
833
|
nb_indices = None
|
834
|
-
if
|
835
|
-
nb_indices = [[find_nb_zero_flux(
|
834
|
+
if mod.boundary:
|
835
|
+
nb_indices = [[find_nb_zero_flux(mod.N, mod.M, i, j) for j in range(mod.M)] for i in range(mod.N)]
|
836
836
|
else:
|
837
|
-
nb_indices = [[find_nb_periodical(
|
837
|
+
nb_indices = [[find_nb_periodical(mod.N, mod.M, i, j) for j in range(mod.M)] for i in range(mod.N)]
|
838
838
|
|
839
|
-
for i in range(
|
840
|
-
for j in range(
|
839
|
+
for i in range(mod.N):
|
840
|
+
for j in range(mod.M):
|
841
841
|
nb = []
|
842
842
|
for k in range(4):
|
843
843
|
if nb_indices[i][j][k] != None:
|
@@ -853,13 +853,13 @@ def single_init(sim, rng):
|
|
853
853
|
#### Begin Running ####
|
854
854
|
|
855
855
|
# initialize payoff & natural death rates
|
856
|
-
for i in range(
|
857
|
-
for j in range(
|
856
|
+
for i in range(mod.N):
|
857
|
+
for j in range(mod.M):
|
858
858
|
world[i][j].update_pi_k()
|
859
859
|
|
860
860
|
# initialize migration rates & the rates list
|
861
|
-
for i in range(
|
862
|
-
for j in range(
|
861
|
+
for i in range(mod.N):
|
862
|
+
for j in range(mod.M):
|
863
863
|
world[i][j].update_mig()
|
864
864
|
# store rates & sum of rates
|
865
865
|
patch_rates[i][j] = world[i][j].get_sum_rates()
|
@@ -875,10 +875,10 @@ def single_init(sim, rng):
|
|
875
875
|
e0 = world[i0][j0].find_event(expected_sum - current_sum)
|
876
876
|
|
877
877
|
# initialize signal
|
878
|
-
if
|
878
|
+
if mod.boundary:
|
879
879
|
signal = make_signal_zero_flux(i0, j0, e0) # walls around world
|
880
880
|
else:
|
881
|
-
signal = make_signal_periodical(
|
881
|
+
signal = make_signal_periodical(mod.N, mod.M, i0, j0, e0) # no walls around world
|
882
882
|
|
883
883
|
# change U&V based on signal
|
884
884
|
for si in signal:
|
@@ -888,15 +888,15 @@ def single_init(sim, rng):
|
|
888
888
|
time = (1 / sum_rates) * math.log(1 / rng.random())
|
889
889
|
|
890
890
|
# record
|
891
|
-
if time >
|
892
|
-
record_index = int(time /
|
893
|
-
for i in range(
|
894
|
-
for j in range(
|
891
|
+
if time > mod.record_itv:
|
892
|
+
record_index = int(time / mod.record_itv)
|
893
|
+
for i in range(mod.N):
|
894
|
+
for j in range(mod.M):
|
895
895
|
for k in range(record_index):
|
896
|
-
|
897
|
-
|
898
|
-
|
899
|
-
|
896
|
+
mod.U[i][j][k] += world[i][j].U
|
897
|
+
mod.V[i][j][k] += world[i][j].V
|
898
|
+
mod.U_pi[i][j][k] += world[i][j].U_pi
|
899
|
+
mod.V_pi[i][j][k] += world[i][j].V_pi
|
900
900
|
# we simply add to that entry, and later divide by sim_time to get the average (division in run function)
|
901
901
|
|
902
902
|
return time, world, nb_indices, patch_rates, sum_rates_by_row, sum_rates, signal
|
@@ -904,54 +904,54 @@ def single_init(sim, rng):
|
|
904
904
|
|
905
905
|
|
906
906
|
|
907
|
-
def single_test(
|
907
|
+
def single_test(mod, front_info, end_info, update_sum_frequency, rng):
|
908
908
|
'''
|
909
|
-
Runs a single
|
909
|
+
Runs a single model, from time = 0 to mod.maxtime.
|
910
910
|
run recursively calls single_test to get the average data.
|
911
911
|
|
912
912
|
Inputs:
|
913
|
-
sim: a
|
913
|
+
sim: a model object, created by user and carries all parameters & storage bins.
|
914
914
|
front_info, end_info: passed by run to show messages, like the current round number in run. Not intended for direct usages.
|
915
|
-
update_sum_frequency: re-calculate sums this many times in
|
915
|
+
update_sum_frequency: re-calculate sums this many times in model.
|
916
916
|
Our sums are gradually updated over time. So might have precision errors for large maxtime.
|
917
917
|
rng: np.random.default_rng. Initialized by model.run
|
918
918
|
'''
|
919
919
|
|
920
920
|
# initialize helper variables
|
921
921
|
# used to print progress, i.e., how much percent is done
|
922
|
-
one_time =
|
922
|
+
one_time = mod.maxtime / max(100, update_sum_frequency)
|
923
923
|
one_progress = 0
|
924
|
-
if
|
924
|
+
if mod.print_pct != None:
|
925
925
|
# print progress, x%
|
926
926
|
print(front_info + ' 0%' + end_info, end = '\r')
|
927
|
-
one_progress =
|
927
|
+
one_progress = mod.maxtime * mod.print_pct / 100
|
928
928
|
else:
|
929
|
-
one_progress = 2 *
|
929
|
+
one_progress = 2 * mod.maxtime # not printing
|
930
930
|
|
931
931
|
# our sums (sum_rates_by_row and sum_rates) are gradually updated over time. This may have precision errors for large maxtime.
|
932
932
|
# So re-sum everything every some percentage of maxtime.
|
933
|
-
one_update_sum =
|
933
|
+
one_update_sum = mod.maxtime / update_sum_frequency
|
934
934
|
|
935
935
|
current_time = one_time
|
936
936
|
current_progress = one_progress
|
937
937
|
current_update_sum = one_update_sum
|
938
938
|
|
939
|
-
max_record = int(
|
939
|
+
max_record = int(mod.maxtime / mod.record_itv)
|
940
940
|
|
941
941
|
|
942
942
|
# initialize
|
943
|
-
time, world, nb_indices, patch_rates, sum_rates_by_row, sum_rates, signal = single_init(
|
944
|
-
record_index = int(time /
|
943
|
+
time, world, nb_indices, patch_rates, sum_rates_by_row, sum_rates, signal = single_init(mod, rng)
|
944
|
+
record_index = int(time / mod.record_itv)
|
945
945
|
# record_time is how much time has passed since the last record
|
946
946
|
# if record_time > record_itv:
|
947
947
|
# we count how many record_itvs are there in record_time, denote the number by multi_records
|
948
948
|
# then store the current data in multi_records number of cells in the list
|
949
949
|
# and subtract record_time by the multiple of record_itv, so that record_time < record_itv
|
950
|
-
record_time = time - record_index *
|
950
|
+
record_time = time - record_index * mod.record_itv
|
951
951
|
|
952
952
|
### Large while loop ###
|
953
953
|
|
954
|
-
while time <
|
954
|
+
while time < mod.maxtime:
|
955
955
|
|
956
956
|
# print progress & correct error of sum_rates
|
957
957
|
if time > current_time:
|
@@ -959,12 +959,12 @@ def single_test(sim, front_info, end_info, update_sum_frequency, rng):
|
|
959
959
|
current_time += one_time
|
960
960
|
if time > current_progress:
|
961
961
|
# print progress
|
962
|
-
print(front_info + ' ' + str(round(time /
|
962
|
+
print(front_info + ' ' + str(round(time / mod.maxtime * 100)) + '%' + end_info, end = '\r')
|
963
963
|
current_progress += one_progress
|
964
964
|
|
965
965
|
if time > current_update_sum:
|
966
966
|
current_update_sum += one_update_sum
|
967
|
-
for i in range(
|
967
|
+
for i in range(mod.N):
|
968
968
|
sum_rates_by_row[i] = sum(patch_rates[i])
|
969
969
|
sum_rates = sum(sum_rates_by_row)
|
970
970
|
|
@@ -1011,10 +1011,10 @@ def single_test(sim, front_info, end_info, update_sum_frequency, rng):
|
|
1011
1011
|
e0 = world[i0][j0].find_event(expected_sum - current_sum)
|
1012
1012
|
|
1013
1013
|
# make signal
|
1014
|
-
if
|
1014
|
+
if mod.boundary:
|
1015
1015
|
signal = make_signal_zero_flux(i0, j0, e0)
|
1016
1016
|
else:
|
1017
|
-
signal = make_signal_periodical(
|
1017
|
+
signal = make_signal_periodical(mod.N, mod.M, i0, j0, e0)
|
1018
1018
|
|
1019
1019
|
# let the event happen
|
1020
1020
|
for si in signal:
|
@@ -1026,91 +1026,91 @@ def single_test(sim, front_info, end_info, update_sum_frequency, rng):
|
|
1026
1026
|
time += dt
|
1027
1027
|
record_time += dt
|
1028
1028
|
|
1029
|
-
if time <
|
1029
|
+
if time < mod.maxtime:
|
1030
1030
|
# if not exceeds maxtime
|
1031
|
-
if record_time >
|
1032
|
-
multi_records = int(record_time /
|
1033
|
-
record_time -= multi_records *
|
1031
|
+
if record_time > mod.record_itv:
|
1032
|
+
multi_records = int(record_time / mod.record_itv)
|
1033
|
+
record_time -= multi_records * mod.record_itv
|
1034
1034
|
|
1035
|
-
for i in range(
|
1036
|
-
for j in range(
|
1035
|
+
for i in range(mod.N):
|
1036
|
+
for j in range(mod.M):
|
1037
1037
|
for k in range(record_index, record_index + multi_records):
|
1038
|
-
|
1039
|
-
|
1040
|
-
|
1041
|
-
|
1038
|
+
mod.U[i][j][k] += world[i][j].U
|
1039
|
+
mod.V[i][j][k] += world[i][j].V
|
1040
|
+
mod.U_pi[i][j][k] += world[i][j].U_pi
|
1041
|
+
mod.V_pi[i][j][k] += world[i][j].V_pi
|
1042
1042
|
record_index += multi_records
|
1043
1043
|
else:
|
1044
1044
|
# if already exceeds maxtime
|
1045
|
-
for i in range(
|
1046
|
-
for j in range(
|
1045
|
+
for i in range(mod.N):
|
1046
|
+
for j in range(mod.M):
|
1047
1047
|
for k in range(record_index, max_record):
|
1048
|
-
|
1049
|
-
|
1050
|
-
|
1051
|
-
|
1048
|
+
mod.U[i][j][k] += world[i][j].U
|
1049
|
+
mod.V[i][j][k] += world[i][j].V
|
1050
|
+
mod.U_pi[i][j][k] += world[i][j].U_pi
|
1051
|
+
mod.V_pi[i][j][k] += world[i][j].V_pi
|
1052
1052
|
|
1053
1053
|
### Large while loop ends ###
|
1054
1054
|
|
1055
|
-
if
|
1055
|
+
if mod.print_pct != None:
|
1056
1056
|
print(front_info + ' 100%' + ' ' * 20, end = '\r') # empty spaces to overwrite predicted runtime
|
1057
1057
|
|
1058
1058
|
|
1059
1059
|
|
1060
1060
|
|
1061
|
-
def run(
|
1061
|
+
def run(mod, predict_runtime = False, message = ''):
|
1062
1062
|
'''
|
1063
|
-
Main function. Recursively calls single_test to run many
|
1063
|
+
Main function. Recursively calls single_test to run many models and then takes the average.
|
1064
1064
|
|
1065
1065
|
Inputs:
|
1066
|
-
-
|
1066
|
+
- mod is a model object.
|
1067
1067
|
- predict_runtime = False will not predict how much time still needed, set to True if you want to see.
|
1068
1068
|
- message is used by some functions in figures.py to print messages.
|
1069
1069
|
'''
|
1070
1070
|
|
1071
|
-
if not
|
1072
|
-
raise RuntimeError('
|
1071
|
+
if not mod.data_empty:
|
1072
|
+
raise RuntimeError('mod has non-empty data')
|
1073
1073
|
|
1074
1074
|
start = timer() # runtime
|
1075
1075
|
|
1076
|
-
|
1077
|
-
rng = np.random.default_rng(
|
1076
|
+
mod.data_empty = False
|
1077
|
+
rng = np.random.default_rng(mod.seed)
|
1078
1078
|
|
1079
1079
|
# passed to single_test to print progress
|
1080
|
-
if
|
1081
|
-
|
1080
|
+
if mod.print_pct == 0:
|
1081
|
+
mod.print_pct = 5 # default print_pct
|
1082
1082
|
|
1083
1083
|
update_sum_frequency = 4 # re-calculate sums this many times. See input desciption of single_test
|
1084
1084
|
|
1085
|
-
###
|
1085
|
+
### models ###
|
1086
1086
|
i = 0
|
1087
1087
|
|
1088
|
-
while i <
|
1088
|
+
while i < mod.sim_time:
|
1089
1089
|
# use while loop so that can go backwards if got numerical issues
|
1090
1090
|
|
1091
1091
|
end_info = ''
|
1092
1092
|
if predict_runtime:
|
1093
1093
|
if i > 0:
|
1094
1094
|
time_elapsed = timer() - start
|
1095
|
-
pred_runtime = time_elapsed / i * (
|
1095
|
+
pred_runtime = time_elapsed / i * (mod.sim_time - i)
|
1096
1096
|
end_info = ', ~' + str(round(pred_runtime, 2)) + 's left'
|
1097
1097
|
|
1098
1098
|
front_info = ''
|
1099
|
-
if
|
1099
|
+
if mod.print_pct != None:
|
1100
1100
|
front_info = message + 'round ' + str(i) + ':'
|
1101
1101
|
print(front_info + ' ' * 30, end = '\r') # the blank spaces are to overwrite percentages, e.g. 36 %
|
1102
1102
|
|
1103
1103
|
try:
|
1104
|
-
single_test(
|
1104
|
+
single_test(mod, front_info, end_info, update_sum_frequency, rng)
|
1105
1105
|
i += 1
|
1106
1106
|
except IndexError:
|
1107
1107
|
update_sum_frequency *= 4
|
1108
1108
|
print('Numerical issue at round ' + str(i) + '. Trying higher precision now. See doc if err repeats')
|
1109
1109
|
# not increasing i: redo current round.
|
1110
1110
|
|
1111
|
-
###
|
1111
|
+
### models end ###
|
1112
1112
|
|
1113
|
-
|
1113
|
+
mod.calculate_ave()
|
1114
1114
|
|
1115
1115
|
stop = timer()
|
1116
1116
|
print(' ' * 30, end = '\r') # overwrite all previous prints
|
@@ -1122,14 +1122,14 @@ def run(sim, predict_runtime = False, message = ''):
|
|
1122
1122
|
|
1123
1123
|
def demo_model():
|
1124
1124
|
'''
|
1125
|
-
Returns a demo model.
|
1125
|
+
Returns a demo model.model object
|
1126
1126
|
'''
|
1127
1127
|
|
1128
1128
|
N = 10 # Number of rows
|
1129
1129
|
M = 10 # Number of cols
|
1130
1130
|
maxtime = 300 # how long you want the model to run
|
1131
1131
|
record_itv = 0.1 # how often to record data.
|
1132
|
-
sim_time = 1 # repeat
|
1132
|
+
sim_time = 1 # repeat model to reduce randomness
|
1133
1133
|
boundary = True # boundary condition.
|
1134
1134
|
|
1135
1135
|
# initial population for the N x M patches.
|
@@ -1146,10 +1146,10 @@ def demo_model():
|
|
1146
1146
|
UV_dtype = 'float32' # data type for population
|
1147
1147
|
pi_dyna = 'float64' # data type for payoff
|
1148
1148
|
|
1149
|
-
# create a
|
1150
|
-
|
1149
|
+
# create a model object
|
1150
|
+
mod = model(N, M, maxtime, record_itv, sim_time, boundary, I, X, P,
|
1151
1151
|
print_pct = print_pct, seed = seed, UV_dtype = UV_dtype, pi_dtype = pi_dyna)
|
1152
1152
|
|
1153
|
-
return
|
1153
|
+
return mod
|
1154
1154
|
|
1155
1155
|
|