piegy 2.1.8__cp37-cp37m-win32.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/Makefile +97 -0
- piegy/C_core/model.c +108 -0
- piegy/C_core/model.h +54 -0
- piegy/C_core/patch.c +43 -0
- piegy/C_core/patch.h +43 -0
- piegy/C_core/piegyc.cp37-win32.pyd +0 -0
- piegy/C_core/piegyc.h +49 -0
- piegy/C_core/runner.c +61 -0
- piegy/C_core/sim_funcs.c +561 -0
- piegy/C_core/sim_funcs.h +547 -0
- piegy/__init__.py +57 -0
- piegy/__version__.py +33 -0
- piegy/analysis.py +222 -0
- piegy/build_info.py +12 -0
- piegy/data_tools.py +127 -0
- piegy/figures.py +491 -0
- piegy/find_C.py +17 -0
- piegy/simulation.py +509 -0
- piegy/simulation_py.py +816 -0
- piegy/test_var.py +583 -0
- piegy/tools/__init__.py +15 -0
- piegy/tools/figure_tools.py +238 -0
- piegy/tools/file_tools.py +29 -0
- piegy/videos.py +303 -0
- piegy-2.1.8.dist-info/LICENSE.txt +28 -0
- piegy-2.1.8.dist-info/METADATA +112 -0
- piegy-2.1.8.dist-info/RECORD +29 -0
- piegy-2.1.8.dist-info/WHEEL +5 -0
- piegy-2.1.8.dist-info/top_level.txt +1 -0
piegy/C_core/sim_funcs.h
ADDED
@@ -0,0 +1,547 @@
|
|
1
|
+
/**
|
2
|
+
* This .h defines the simulation functions in piegy.simulation
|
3
|
+
*/
|
4
|
+
|
5
|
+
#ifndef SIM_FUNCS
|
6
|
+
#define SIM_FUNCS
|
7
|
+
|
8
|
+
#include <stdlib.h>
|
9
|
+
#include <stdint.h>
|
10
|
+
#include <stdio.h>
|
11
|
+
#include <stdbool.h>
|
12
|
+
#include <string.h>
|
13
|
+
#include <time.h>
|
14
|
+
#include <math.h>
|
15
|
+
|
16
|
+
#include "patch.h"
|
17
|
+
#include "model.h"
|
18
|
+
|
19
|
+
|
20
|
+
|
21
|
+
// upper bound for RNG is 2^24 + 1
|
22
|
+
#define RAND_UPPER_PLUS_2 (double) (0xffffffu + 2)
|
23
|
+
|
24
|
+
// directions of migration
|
25
|
+
// so that 3 - mig_dir = reflection of it. Used to track neighbors
|
26
|
+
// the actual implementation of signals still uses this order: up, down, left, right
|
27
|
+
#define MIG_UP 0
|
28
|
+
#define MIG_DOWN 1
|
29
|
+
#define MIG_LEFT 2
|
30
|
+
#define MIG_RIGHT 3
|
31
|
+
|
32
|
+
// results of single_test
|
33
|
+
#define SUCCESS 0
|
34
|
+
#define GENERAL_FAILURE 1
|
35
|
+
#define SMALL_MAXTIME 2
|
36
|
+
#define OVERFLOW 3
|
37
|
+
|
38
|
+
// where exp(x) reaches overflow bound (just below it)
|
39
|
+
#define EXP_OVERFLOW_BOUND 700
|
40
|
+
|
41
|
+
|
42
|
+
static uint64_t pcg_state = 0;
|
43
|
+
static uint64_t pcg_inc = 0;
|
44
|
+
|
45
|
+
|
46
|
+
|
47
|
+
|
48
|
+
/**
|
49
|
+
* index of patch in find_patch
|
50
|
+
*/
|
51
|
+
typedef struct patch_picked_t {
|
52
|
+
size_t i;
|
53
|
+
size_t j;
|
54
|
+
double current_sum;
|
55
|
+
} patch_picked_t;
|
56
|
+
|
57
|
+
/**
|
58
|
+
* index & event number in make_signal_*
|
59
|
+
*/
|
60
|
+
typedef struct signal_t {
|
61
|
+
// does the signal only have the first patch?
|
62
|
+
bool only_first;
|
63
|
+
|
64
|
+
// the first patch
|
65
|
+
size_t i1;
|
66
|
+
size_t j1;
|
67
|
+
size_t ij1; // i1 * M + j1
|
68
|
+
uint8_t e1;
|
69
|
+
|
70
|
+
// the second patch
|
71
|
+
size_t i2;
|
72
|
+
size_t j2;
|
73
|
+
size_t ij2;
|
74
|
+
uint8_t e2;
|
75
|
+
} signal_t;
|
76
|
+
|
77
|
+
|
78
|
+
|
79
|
+
/**
|
80
|
+
* Defined in .c
|
81
|
+
*/
|
82
|
+
static void find_nb_zero_flux(size_t* restrict nb, size_t i, size_t j, size_t N, size_t M, size_t NM);
|
83
|
+
static void find_nb_periodical(size_t* restrict nb, size_t i, size_t j, size_t N, size_t M, size_t NM);
|
84
|
+
static double single_init(const model_t* mod, patch_t* world, size_t* nb_indices,
|
85
|
+
double* patch_rates, double* sum_rates_by_row, double* sum_rates, signal_t* sig_p, patch_picked_t* picked_p) ;
|
86
|
+
static void single_test(model_t* restrict mod, uint32_t update_sum_frequency, uint32_t* result, char* message);
|
87
|
+
static void single_test_free(patch_t* world, size_t* nb_indices, double* patch_rates, double* sum_rates_by_row);
|
88
|
+
void run(model_t* mod, char* message, size_t msg_len);
|
89
|
+
|
90
|
+
|
91
|
+
/**
|
92
|
+
* Inline Functions
|
93
|
+
*/
|
94
|
+
|
95
|
+
static inline double random01() {
|
96
|
+
// generate a 24 bit random int, then convert to a (0, 1) ranged double
|
97
|
+
uint32_t r1 = rand() & 0x7fff; // RAND_MAX is different across machines, ensure 15 bits
|
98
|
+
uint32_t r2 = rand() & 0x7fff;
|
99
|
+
|
100
|
+
double r_combined = ((r1 >> 3) << 12) + (r2 >> 3); // discard the lower 3 bits, which are unstable
|
101
|
+
return (r_combined + 1) / RAND_UPPER_PLUS_2;
|
102
|
+
}
|
103
|
+
|
104
|
+
/**
|
105
|
+
* patch functions
|
106
|
+
*/
|
107
|
+
|
108
|
+
static inline void update_pi_k(patch_t* restrict p, const double* restrict M_start, const double* restrict P_kappa_start) {
|
109
|
+
// M_start: start index of patch (i, j)'s matrix
|
110
|
+
// P_kappa_start: start index of patch (i, j)'s kappa values (the 4th and 5th, 0-indexed)
|
111
|
+
|
112
|
+
double U = (double) p->U;
|
113
|
+
double V = (double) p->V;
|
114
|
+
double sum_minus_1 = U + V - 1.0;
|
115
|
+
|
116
|
+
if (sum_minus_1 > 0) {
|
117
|
+
if (U != 0) {
|
118
|
+
p->U_pi = ((U - 1) / sum_minus_1) * M_start[0] +
|
119
|
+
(V / sum_minus_1) * M_start[1];
|
120
|
+
} else {
|
121
|
+
p->U_pi = 0.0;
|
122
|
+
}
|
123
|
+
|
124
|
+
if (V != 0) {
|
125
|
+
p->V_pi = (U / sum_minus_1) * M_start[2] +
|
126
|
+
((V - 1) / sum_minus_1) * M_start[3];
|
127
|
+
} else {
|
128
|
+
p->V_pi = 0.0;
|
129
|
+
}
|
130
|
+
|
131
|
+
} else {
|
132
|
+
p->U_pi = 0.0;
|
133
|
+
p->V_pi = 0.0;
|
134
|
+
}
|
135
|
+
|
136
|
+
p->pi_death_rates[0] = fabs(U * p->U_pi);
|
137
|
+
p->pi_death_rates[1] = fabs(V * p->V_pi);
|
138
|
+
|
139
|
+
p->pi_death_rates[2] = P_kappa_start[0] * U * (sum_minus_1 + 1.0);
|
140
|
+
p->pi_death_rates[3] = P_kappa_start[1] * V * (sum_minus_1 + 1.0);
|
141
|
+
|
142
|
+
p->sum_pi_death_rates = 0.0;
|
143
|
+
for (size_t i = 0; i < 4; i++) {
|
144
|
+
p->sum_pi_death_rates += p->pi_death_rates[i];
|
145
|
+
}
|
146
|
+
}
|
147
|
+
|
148
|
+
|
149
|
+
static inline void update_mig_one(patch_t* restrict p, const double* restrict P_start, uint8_t nb_loc) {
|
150
|
+
// update mig rate for one direction
|
151
|
+
// P_start: start index of p's patch variables, i.e., ij * 6
|
152
|
+
// nb_loc: location of neighbor, up, down, left, right
|
153
|
+
|
154
|
+
double mu1_U = P_start[0] * (double)p->U;
|
155
|
+
double mu2_V = P_start[1] * (double)p->V;
|
156
|
+
double* p_U_weight = p->U_weight;
|
157
|
+
double* p_V_weight = p->V_weight;
|
158
|
+
|
159
|
+
patch_t* nbi = p->nb[nb_loc];
|
160
|
+
p->sum_U_weight -= p_U_weight[nb_loc];
|
161
|
+
p->sum_V_weight -= p_V_weight[nb_loc];
|
162
|
+
|
163
|
+
switch(nb_loc) {
|
164
|
+
case MIG_UP:
|
165
|
+
p_U_weight[MIG_UP] = 1.0 + exp(P_start[2] * nbi->U_pi);
|
166
|
+
p_V_weight[MIG_UP] = 1.0 + exp(P_start[3] * nbi->V_pi);
|
167
|
+
break;
|
168
|
+
case MIG_DOWN:
|
169
|
+
p_U_weight[MIG_DOWN] = 1.0 + exp(P_start[2] * nbi->U_pi);
|
170
|
+
p_V_weight[MIG_DOWN] = 1.0 + exp(P_start[3] * nbi->V_pi);
|
171
|
+
break;
|
172
|
+
case MIG_LEFT:
|
173
|
+
p_U_weight[MIG_LEFT] = 1.0 + exp(P_start[2] * nbi->U_pi);
|
174
|
+
p_V_weight[MIG_LEFT] = 1.0 + exp(P_start[3] * nbi->V_pi);
|
175
|
+
break;
|
176
|
+
default:
|
177
|
+
p_U_weight[MIG_RIGHT] = 1.0 + exp(P_start[2] * nbi->U_pi);
|
178
|
+
p_V_weight[MIG_RIGHT] = 1.0 + exp(P_start[3] * nbi->V_pi);
|
179
|
+
break;
|
180
|
+
}
|
181
|
+
p->sum_U_weight += p_U_weight[nb_loc];
|
182
|
+
p->sum_V_weight += p_V_weight[nb_loc];
|
183
|
+
|
184
|
+
double mu1_U_divide_sum = mu1_U / p->sum_U_weight;
|
185
|
+
double mu2_V_divide_sum = mu2_V / p->sum_V_weight;
|
186
|
+
|
187
|
+
for (size_t i = 0; i < 4; i++) {
|
188
|
+
p->mig_rates[i] = mu1_U_divide_sum * p_U_weight[i];
|
189
|
+
p->mig_rates[i + 4] = mu2_V_divide_sum * p_V_weight[i];
|
190
|
+
}
|
191
|
+
|
192
|
+
}
|
193
|
+
|
194
|
+
|
195
|
+
|
196
|
+
static inline void update_mig_all(patch_t* restrict p, const double* restrict P_start) {
|
197
|
+
// update migration rate for all directions
|
198
|
+
double mu1_U = P_start[0] * (double)p->U;
|
199
|
+
double mu2_V = P_start[1] * (double)p->V;
|
200
|
+
|
201
|
+
double* p_U_weight = p->U_weight;
|
202
|
+
double* p_V_weight = p->V_weight;
|
203
|
+
|
204
|
+
p->sum_U_weight = 0.0;
|
205
|
+
p->sum_V_weight = 0.0;
|
206
|
+
|
207
|
+
double w1 = P_start[2];
|
208
|
+
double w2 = P_start[3];
|
209
|
+
|
210
|
+
for (uint8_t i = 0; i < 4; i++) {
|
211
|
+
patch_t* nbi = p->nb[i];
|
212
|
+
|
213
|
+
if (nbi) {
|
214
|
+
// not NULL
|
215
|
+
p_U_weight[i] = 1.0 + exp(w1 * nbi->U_pi);
|
216
|
+
p_V_weight[i] = 1.0 + exp(w2 * nbi->V_pi);
|
217
|
+
|
218
|
+
p->sum_U_weight += p_U_weight[i];
|
219
|
+
p->sum_V_weight += p_V_weight[i];
|
220
|
+
}
|
221
|
+
}
|
222
|
+
|
223
|
+
double mu1_U_divide_sum = mu1_U / p->sum_U_weight;
|
224
|
+
double mu2_V_divide_sum = mu2_V / p->sum_V_weight;
|
225
|
+
|
226
|
+
for (uint8_t i = 0; i < 4; i++) {
|
227
|
+
p->mig_rates[i] = mu1_U_divide_sum * p_U_weight[i];
|
228
|
+
p->mig_rates[i + 4] = mu2_V_divide_sum * p_V_weight[i];
|
229
|
+
}
|
230
|
+
|
231
|
+
p->sum_mig_rates = mu1_U + mu2_V;
|
232
|
+
}
|
233
|
+
|
234
|
+
|
235
|
+
|
236
|
+
static inline size_t find_event(const patch_t* restrict p, double expected_sum) {
|
237
|
+
size_t event = 0;
|
238
|
+
double current_sum;
|
239
|
+
|
240
|
+
//if (expected_sum > (p->sum_pi_death_rates + p->sum_mig_rates)) {
|
241
|
+
// fprintf(stderr, "Bug: patch rate not enough in find_event.\n");
|
242
|
+
//}
|
243
|
+
|
244
|
+
if (expected_sum < p->sum_pi_death_rates) {
|
245
|
+
// First 4 events (payoff and death)
|
246
|
+
current_sum = 0.0;
|
247
|
+
while (current_sum < expected_sum) {
|
248
|
+
current_sum += p->pi_death_rates[event];
|
249
|
+
event++;
|
250
|
+
}
|
251
|
+
event--; // step back to correct event index
|
252
|
+
} else {
|
253
|
+
// Last 8 events (migration)2
|
254
|
+
current_sum = p->sum_pi_death_rates;
|
255
|
+
while (current_sum < expected_sum) {
|
256
|
+
current_sum += p->mig_rates[event];
|
257
|
+
event++;
|
258
|
+
}
|
259
|
+
event += 3; // -1 and then +4
|
260
|
+
}
|
261
|
+
|
262
|
+
return event;
|
263
|
+
}
|
264
|
+
|
265
|
+
|
266
|
+
static inline void change_popu(patch_t* restrict p, uint8_t s) {
|
267
|
+
switch (s) {
|
268
|
+
case 0:
|
269
|
+
// Migration IN for U
|
270
|
+
p->U += 1;
|
271
|
+
return;
|
272
|
+
case 1:
|
273
|
+
// Migration OUT / death due to carrying capacity for U
|
274
|
+
p->U -= (p->U > 0);
|
275
|
+
return;
|
276
|
+
case 2:
|
277
|
+
// Natural birth/death for U due to payoff
|
278
|
+
if (p->U_pi > 0.0) {
|
279
|
+
p->U += 1;
|
280
|
+
} else if (p->U > 0) {
|
281
|
+
p->U -= 1;
|
282
|
+
}
|
283
|
+
return;
|
284
|
+
case 3:
|
285
|
+
// Migration IN for V
|
286
|
+
p->V += 1;
|
287
|
+
return;
|
288
|
+
case 4:
|
289
|
+
// Migration OUT / death due to carrying capacity for V
|
290
|
+
p->V -= (p->V > 0);
|
291
|
+
return;
|
292
|
+
default:
|
293
|
+
// Natural birth/death for V due to payoff
|
294
|
+
if (p->V_pi > 0.0) {
|
295
|
+
p->V += 1;
|
296
|
+
} else if (p->V > 0) {
|
297
|
+
p->V -= 1;
|
298
|
+
}
|
299
|
+
return;
|
300
|
+
//default:
|
301
|
+
// fprintf(stderr, "Bug: invalid event number in change_popu: %hhu\n", s);
|
302
|
+
// return;
|
303
|
+
}
|
304
|
+
}
|
305
|
+
|
306
|
+
|
307
|
+
/**
|
308
|
+
* Main Simulation Functions
|
309
|
+
*/
|
310
|
+
|
311
|
+
static inline void find_patch(patch_picked_t* restrict picked, double expected_sum, const double* restrict patch_rates, const double* restrict sum_rates_by_row, double sum_rates, size_t N, size_t M) {
|
312
|
+
double current_sum = 0;
|
313
|
+
size_t row = 0;
|
314
|
+
size_t col = 0;
|
315
|
+
|
316
|
+
// Find row
|
317
|
+
if (expected_sum < sum_rates * 0.5) {
|
318
|
+
current_sum = 0.0;
|
319
|
+
row = 0;
|
320
|
+
while (current_sum < expected_sum) {
|
321
|
+
current_sum += sum_rates_by_row[row];
|
322
|
+
row++;
|
323
|
+
}
|
324
|
+
row--;
|
325
|
+
current_sum -= sum_rates_by_row[row];
|
326
|
+
} else {
|
327
|
+
current_sum = sum_rates;
|
328
|
+
row = N - 1;
|
329
|
+
while (current_sum > expected_sum) {
|
330
|
+
current_sum -= sum_rates_by_row[row];
|
331
|
+
row--;
|
332
|
+
}
|
333
|
+
row++;
|
334
|
+
}
|
335
|
+
|
336
|
+
size_t row_M = row * M;
|
337
|
+
|
338
|
+
// Find col in that row
|
339
|
+
if ((expected_sum - current_sum) < sum_rates_by_row[row] * 0.5) {
|
340
|
+
col = 0;
|
341
|
+
while (current_sum < expected_sum) {
|
342
|
+
current_sum += patch_rates[row_M + col];
|
343
|
+
col++;
|
344
|
+
}
|
345
|
+
col--;
|
346
|
+
current_sum -= patch_rates[row_M + col];
|
347
|
+
} else {
|
348
|
+
current_sum += sum_rates_by_row[row];
|
349
|
+
col = M - 1;
|
350
|
+
while (current_sum > expected_sum) {
|
351
|
+
current_sum -= patch_rates[row_M + col];
|
352
|
+
col--;
|
353
|
+
}
|
354
|
+
col++;
|
355
|
+
}
|
356
|
+
|
357
|
+
picked->i = row;
|
358
|
+
picked->j = col;
|
359
|
+
picked->current_sum = current_sum;
|
360
|
+
}
|
361
|
+
|
362
|
+
|
363
|
+
|
364
|
+
static inline void make_signal_zero_flux(size_t i, size_t j, uint8_t e, signal_t* restrict signal) {
|
365
|
+
// this is always the case for the first one
|
366
|
+
signal->i1 = i;
|
367
|
+
signal->j1 = j;
|
368
|
+
|
369
|
+
switch (e) {
|
370
|
+
case 0:
|
371
|
+
signal->e1 = 2;
|
372
|
+
signal->only_first = true;
|
373
|
+
return;
|
374
|
+
case 1:
|
375
|
+
signal->e1 = 5;
|
376
|
+
signal->only_first = true;
|
377
|
+
return;
|
378
|
+
case 2:
|
379
|
+
signal->e1 = 1;
|
380
|
+
signal->only_first = true;
|
381
|
+
return;
|
382
|
+
case 3:
|
383
|
+
signal->e1 = 4;
|
384
|
+
signal->only_first = true;
|
385
|
+
return;
|
386
|
+
case 4:
|
387
|
+
signal->e1 = 1;
|
388
|
+
signal->i2 = i - 1;
|
389
|
+
signal->j2 = j;
|
390
|
+
signal->e2 = 0;
|
391
|
+
signal->only_first = false;
|
392
|
+
return;
|
393
|
+
case 5:
|
394
|
+
signal->e1 = 1;
|
395
|
+
signal->i2 = i + 1;
|
396
|
+
signal->j2 = j;
|
397
|
+
signal->e2 = 0;
|
398
|
+
signal->only_first = false;
|
399
|
+
return;
|
400
|
+
case 6:
|
401
|
+
signal->e1 = 1;
|
402
|
+
signal->i2 = i;
|
403
|
+
signal->j2 = j - 1;
|
404
|
+
signal->e2 = 0;
|
405
|
+
signal->only_first = false;
|
406
|
+
return;
|
407
|
+
case 7:
|
408
|
+
signal->e1 = 1;
|
409
|
+
signal->i2 = i;
|
410
|
+
signal->j2 = j + 1;
|
411
|
+
signal->e2 = 0;
|
412
|
+
signal->only_first = false;
|
413
|
+
return;
|
414
|
+
case 8:
|
415
|
+
signal->e1 = 4;
|
416
|
+
signal->i2 = i - 1;
|
417
|
+
signal->j2 = j;
|
418
|
+
signal->e2 = 3;
|
419
|
+
signal->only_first = false;
|
420
|
+
return;
|
421
|
+
case 9:
|
422
|
+
signal->e1 = 4;
|
423
|
+
signal->i2 = i + 1;
|
424
|
+
signal->j2 = j;
|
425
|
+
signal->e2 = 3;
|
426
|
+
signal->only_first = false;
|
427
|
+
return;
|
428
|
+
case 10:
|
429
|
+
signal->e1 = 4;
|
430
|
+
signal->i2 = i;
|
431
|
+
signal->j2 = j - 1;
|
432
|
+
signal->e2 = 3;
|
433
|
+
signal->only_first = false;
|
434
|
+
return;
|
435
|
+
default:
|
436
|
+
signal->e1 = 4;
|
437
|
+
signal->i2 = i;
|
438
|
+
signal->j2 = j + 1;
|
439
|
+
signal->e2 = 3;
|
440
|
+
signal->only_first = false;
|
441
|
+
return;
|
442
|
+
//default:
|
443
|
+
// fprintf(stderr, "Bug: invalid case in make_signal_zf, i, j, e: %zu, %zu, %hhu\n", i, j, e);
|
444
|
+
// return;
|
445
|
+
}
|
446
|
+
}
|
447
|
+
|
448
|
+
|
449
|
+
|
450
|
+
static inline void make_signal_periodical(size_t N, size_t M, size_t i, size_t j, uint8_t e, signal_t* restrict signal) {
|
451
|
+
// this is always the case for the first one
|
452
|
+
signal->i1 = i;
|
453
|
+
signal->j1 = j;
|
454
|
+
|
455
|
+
switch (e) {
|
456
|
+
case 0:
|
457
|
+
signal->e1 = 2;
|
458
|
+
signal->only_first = true;
|
459
|
+
return;
|
460
|
+
case 1:
|
461
|
+
signal->e1 = 5;
|
462
|
+
signal->only_first = true;
|
463
|
+
return;
|
464
|
+
case 2:
|
465
|
+
signal->e1 = 1;
|
466
|
+
signal->only_first = true;
|
467
|
+
return;
|
468
|
+
case 3:
|
469
|
+
signal->e1 = 4;
|
470
|
+
signal->only_first = true;
|
471
|
+
return;
|
472
|
+
case 4:
|
473
|
+
signal->e1 = 1;
|
474
|
+
signal->i2 = i != 0 ? i - 1 : N - 1;
|
475
|
+
signal->j2 = j;
|
476
|
+
signal->e2 = 0;
|
477
|
+
signal->only_first = false;
|
478
|
+
return;
|
479
|
+
case 5:
|
480
|
+
signal->e1 = 1;
|
481
|
+
signal->i2 = i != N - 1 ? i + 1 : 0;
|
482
|
+
signal->j2 = j;
|
483
|
+
signal->e2 = 0;
|
484
|
+
signal->only_first = false;
|
485
|
+
return;
|
486
|
+
case 6:
|
487
|
+
signal->e1 = 1;
|
488
|
+
signal->i2 = i;
|
489
|
+
signal->j2 = j != 0 ? j - 1 : M - 1;
|
490
|
+
signal->e2 = 0;
|
491
|
+
signal->only_first = false;
|
492
|
+
return;
|
493
|
+
case 7:
|
494
|
+
signal->e1 = 1;
|
495
|
+
signal->i2 = i;
|
496
|
+
signal->j2 = j != M - 1 ? j + 1 : 0;
|
497
|
+
signal->e2 = 0;
|
498
|
+
signal->only_first = false;
|
499
|
+
return;
|
500
|
+
case 8:
|
501
|
+
signal->e1 = 4;
|
502
|
+
signal->i2 = i != 0 ? i - 1 : N - 1;
|
503
|
+
signal->j2 = j;
|
504
|
+
signal->e2 = 3;
|
505
|
+
signal->only_first = false;
|
506
|
+
return;
|
507
|
+
case 9:
|
508
|
+
signal->e1 = 4;
|
509
|
+
signal->i2 = i != N - 1 ? i + 1 : 0;
|
510
|
+
signal->j2 = j;
|
511
|
+
signal->e2 = 3;
|
512
|
+
signal->only_first = false;
|
513
|
+
return;
|
514
|
+
case 10:
|
515
|
+
signal->e1 = 4;
|
516
|
+
signal->i2 = i;
|
517
|
+
signal->j2 = j != 0 ? j - 1 : M - 1;
|
518
|
+
signal->e2 = 3;
|
519
|
+
signal->only_first = false;
|
520
|
+
return;
|
521
|
+
default:
|
522
|
+
signal->e1 = 4;
|
523
|
+
signal->i2 = i;
|
524
|
+
signal->j2 = j != M - 1 ? j + 1 : 0;
|
525
|
+
signal->e2 = 3;
|
526
|
+
signal->only_first = false;
|
527
|
+
return;
|
528
|
+
//default:
|
529
|
+
// fprintf(stderr, "Bug: invalid case in make_signal_pr, i, j, e: %zu, %zu, %hhu\n", i, j, e);
|
530
|
+
// return;
|
531
|
+
}
|
532
|
+
}
|
533
|
+
|
534
|
+
|
535
|
+
static inline bool nb_need_change(size_t nb_idx, size_t sij1, size_t sij2) {
|
536
|
+
// a nb doesn't need change only if two patches are updated
|
537
|
+
|
538
|
+
// or, can try this 1-line version
|
539
|
+
// return (nb_idx != sij1) && (nb_idx != sij2);
|
540
|
+
if ((nb_idx == sij1) || (nb_idx == sij2)) {
|
541
|
+
return false;
|
542
|
+
}
|
543
|
+
return true; // need to change
|
544
|
+
}
|
545
|
+
|
546
|
+
|
547
|
+
#endif
|
piegy/__init__.py
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
'''
|
2
|
+
Payoff-Driven Stochastic Spatial Model for Evolutionary Game Theory
|
3
|
+
-----------------------------------------------------------------------------
|
4
|
+
|
5
|
+
Provides:
|
6
|
+
1. A stochastic spatial model for simulating the interaction and evolution of two species in either 1D or 2D space
|
7
|
+
2. Plot & video functions to visualize simulation results.
|
8
|
+
3. Module to test influence of certain variables on results.
|
9
|
+
4. Data saving & reading module.
|
10
|
+
4. Additional analytical tools.
|
11
|
+
|
12
|
+
Websites:
|
13
|
+
- The *piegy* documentation: https://piegy.readthedocs.io/en/
|
14
|
+
- GitHub repository at: https://github.com/Chenning04/piegy.git
|
15
|
+
- PyPI page: https://pypi.org/project/piegy/
|
16
|
+
|
17
|
+
|
18
|
+
Last update: May 12, 2025
|
19
|
+
'''
|
20
|
+
|
21
|
+
from .__version__ import __version__
|
22
|
+
from .build_info import build_info
|
23
|
+
|
24
|
+
from .simulation import model, run, demo_model, UV_expected_val, check_overflow_func
|
25
|
+
from .videos import make_video, SUPPORTED_FIGURES
|
26
|
+
from .data_tools import save_data, read_data
|
27
|
+
|
28
|
+
from .analysis import rounds_expected, scale_maxtime, check_convergence, combine_sim
|
29
|
+
|
30
|
+
from .figures import (UV_heatmap, UV_bar, UV_dyna, UV_hist, UV_std, UV_expected,
|
31
|
+
pi_heatmap, pi_bar, pi_dyna, pi_hist, pi_std, UV_pi)
|
32
|
+
|
33
|
+
from .test_var import (test_var1, var_UV1, var_pi1, var_convergence1, get_dirs1,
|
34
|
+
test_var2, var_UV2, var_pi2, var_convergence2, get_dirs2)
|
35
|
+
|
36
|
+
|
37
|
+
simulation_memebers = ['model', 'run', 'demo_model']
|
38
|
+
|
39
|
+
videos_members = ['make_video', 'SUPPORTED_FIGURES']
|
40
|
+
|
41
|
+
data_members = ['save_data', 'read_data']
|
42
|
+
|
43
|
+
analysis_members = ['expected_rounds', 'scale_maxtime', 'check_convergence', 'combine_mod']
|
44
|
+
|
45
|
+
figures_members = ['UV_heatmap', 'UV_bar', 'UV_dyna', 'UV_hist', 'UV_std', 'UV_expected_val', 'UV_expected',
|
46
|
+
'pi_heatmap', 'pi_bar', 'pi_dyna', 'pi_hist', 'pi_std', 'UV_pi']
|
47
|
+
|
48
|
+
test_var_members = ['test_var1', 'var_UV1', 'var_pi1', 'var_convergence1', 'get_dirs1',
|
49
|
+
'test_var2', 'var_UV2', 'var_pi2', 'var_convergence2', 'get_dirs2']
|
50
|
+
|
51
|
+
|
52
|
+
__all__ = simulation_memebers + videos_members + data_members + figures_members + analysis_members + test_var_members
|
53
|
+
|
54
|
+
|
55
|
+
|
56
|
+
|
57
|
+
|
piegy/__version__.py
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
__version__ = '2.1.8'
|
2
|
+
|
3
|
+
'''
|
4
|
+
version history:
|
5
|
+
|
6
|
+
0.1.0: first publishing, May 11, 2025
|
7
|
+
0.1.1: fix dependency errors
|
8
|
+
0.1.2: fixing module not find error
|
9
|
+
0.1.3: restructuring package
|
10
|
+
0.1.4 ~ 0.1.6: fixing moviepy import issue
|
11
|
+
0.1.7: changed name back to 'piegy'
|
12
|
+
0.1.8: updated installation in README
|
13
|
+
0.1.9: first round of full debugging
|
14
|
+
|
15
|
+
1.0.0: first version in PyPI.
|
16
|
+
1.1.0: debugging. Updated a range of functions, in the following modules: figures, videos, test_var, model, figure_tools
|
17
|
+
1.1.1: minor debugging in model module.
|
18
|
+
1.1.2: fix text bad location in figure_tools, update labeling and titling in figures and test_var. Add dpi param to make_video in videos. Remove reset_data function in model.
|
19
|
+
1.1.3: update README.
|
20
|
+
1.1.4: changed name: ``model`` module to ``simulation``, and ``model.simulation`` class to ``simulation.model``. Bug fix in videos.
|
21
|
+
1.1.5: update README.
|
22
|
+
1.1.6: change name of variables in model class -- for compatability with the new C core. 1.1.6 is the last verion of v1. From v2 on, the piegy package has C core.
|
23
|
+
|
24
|
+
2.0.0: update simulation core to C-based.
|
25
|
+
2.0.1: re-upload, the C core is not included in package.
|
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.
|
29
|
+
2.0.5: fix error in random number generator.
|
30
|
+
2.1.0: redo random number generator. Update package upload so that more compatible across platforms.
|
31
|
+
2.1.1: fix import bug for the C core.
|
32
|
+
2.1.2 ~ 2.1.8: updating wheel.
|
33
|
+
'''
|