piegy 2.3.1__tar.gz → 2.3.2__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.
Files changed (34) hide show
  1. {piegy-2.3.1/src/piegy.egg-info → piegy-2.3.2}/PKG-INFO +1 -1
  2. {piegy-2.3.1 → piegy-2.3.2}/pyproject.toml +1 -1
  3. {piegy-2.3.1 → piegy-2.3.2}/src/piegy/C_core/Makefile +1 -1
  4. {piegy-2.3.1 → piegy-2.3.2}/src/piegy/C_core/runner.c +2 -2
  5. {piegy-2.3.1 → piegy-2.3.2}/src/piegy/C_core/sim_funcs.c +15 -23
  6. {piegy-2.3.1 → piegy-2.3.2}/src/piegy/C_core/sim_funcs.h +102 -76
  7. {piegy-2.3.1 → piegy-2.3.2}/src/piegy/__version__.py +3 -1
  8. {piegy-2.3.1 → piegy-2.3.2}/src/piegy/figures.py +6 -6
  9. {piegy-2.3.1 → piegy-2.3.2/src/piegy.egg-info}/PKG-INFO +1 -1
  10. {piegy-2.3.1 → piegy-2.3.2}/LICENSE.txt +0 -0
  11. {piegy-2.3.1 → piegy-2.3.2}/MANIFEST.in +0 -0
  12. {piegy-2.3.1 → piegy-2.3.2}/README.md +0 -0
  13. {piegy-2.3.1 → piegy-2.3.2}/setup.cfg +0 -0
  14. {piegy-2.3.1 → piegy-2.3.2}/setup.py +0 -0
  15. {piegy-2.3.1 → piegy-2.3.2}/src/piegy/C_core/model.c +0 -0
  16. {piegy-2.3.1 → piegy-2.3.2}/src/piegy/C_core/model.h +0 -0
  17. {piegy-2.3.1 → piegy-2.3.2}/src/piegy/C_core/patch.c +0 -0
  18. {piegy-2.3.1 → piegy-2.3.2}/src/piegy/C_core/patch.h +0 -0
  19. {piegy-2.3.1 → piegy-2.3.2}/src/piegy/__init__.py +0 -0
  20. {piegy-2.3.1 → piegy-2.3.2}/src/piegy/analysis.py +0 -0
  21. {piegy-2.3.1 → piegy-2.3.2}/src/piegy/build_info.py +0 -0
  22. {piegy-2.3.1 → piegy-2.3.2}/src/piegy/data_tools.py +0 -0
  23. {piegy-2.3.1 → piegy-2.3.2}/src/piegy/simulation.py +0 -0
  24. {piegy-2.3.1 → piegy-2.3.2}/src/piegy/simulation_py.py +0 -0
  25. {piegy-2.3.1 → piegy-2.3.2}/src/piegy/test_var.py +0 -0
  26. {piegy-2.3.1 → piegy-2.3.2}/src/piegy/tools/__init__.py +0 -0
  27. {piegy-2.3.1 → piegy-2.3.2}/src/piegy/tools/figure_tools.py +0 -0
  28. {piegy-2.3.1 → piegy-2.3.2}/src/piegy/tools/file_tools.py +0 -0
  29. {piegy-2.3.1 → piegy-2.3.2}/src/piegy/tools/find_C.py +0 -0
  30. {piegy-2.3.1 → piegy-2.3.2}/src/piegy/videos.py +0 -0
  31. {piegy-2.3.1 → piegy-2.3.2}/src/piegy.egg-info/SOURCES.txt +0 -0
  32. {piegy-2.3.1 → piegy-2.3.2}/src/piegy.egg-info/dependency_links.txt +0 -0
  33. {piegy-2.3.1 → piegy-2.3.2}/src/piegy.egg-info/requires.txt +0 -0
  34. {piegy-2.3.1 → piegy-2.3.2}/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: 2.3.1
3
+ Version: 2.3.2
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
@@ -4,7 +4,7 @@ build-backend = 'setuptools.build_meta'
4
4
 
5
5
  [project]
6
6
  name = 'piegy'
7
- version = '2.3.1'
7
+ version = '2.3.2'
8
8
  description = 'Payoff-Driven Stochastic Spatial Model for Evolutionary Game Theory'
9
9
  readme = 'README.md'
10
10
  requires-python = '>=3.7'
@@ -5,7 +5,7 @@ CC = gcc
5
5
 
6
6
  ## Flags for Max Speed ##
7
7
  # standard
8
- CFLAGS_COMMON = -O3 -flto -std=c99 -DNDEBUG -ffp-contract=fast -MMD -MP
8
+ CFLAGS_COMMON = -O3 -march=native -flto -std=c99 -DNDEBUG -ffp-contract=fast -funroll-loops -fomit-frame-pointer -MMD -MP
9
9
  LDFLAGS_COMMON = -flto
10
10
 
11
11
  ## Flags for Debugging ##
@@ -11,9 +11,9 @@
11
11
  int main() {
12
12
  size_t N = 1;
13
13
  size_t M = 100;
14
- double maxtime = 200;
14
+ double maxtime = 100;
15
15
  double record_itv = 0.1;
16
- size_t sim_time = 200;
16
+ size_t sim_time = 10;
17
17
  bool boundary = true;
18
18
  uint32_t I_single[2] = {200, 100};
19
19
  double X_single[4] = {-1, 4, 0, 2};
@@ -128,7 +128,7 @@ static double single_init(const model_t* mod, patch_t* world, size_t* nb_indices
128
128
  ij = 0;
129
129
  for (size_t i = 0; i < N; i++) {
130
130
  for (size_t j = 0; j < M; j++) {
131
- uint8_t mig_result = update_mig_all(&world[ij], &(mod->P[ij * 6])); // init mig rates for all 4 directions
131
+ uint8_t mig_result = init_mig(&world[ij], &(mod->P[ij * 6])); // init mig rates for all 4 directions
132
132
  if (mig_result == SIM_OVERFLOW) {
133
133
  return -1 * SIM_OVERFLOW;
134
134
  }
@@ -157,7 +157,7 @@ static double single_init(const model_t* mod, patch_t* world, size_t* nb_indices
157
157
 
158
158
  // update patch based on signal
159
159
  change_popu(&world[sig_p->ij1], sig_p->e1);
160
- if (!sig_p->only_first) {
160
+ if (sig_p->rela_loc != NO_MIG) {
161
161
  change_popu(&world[sig_p->ij2], sig_p->e2);
162
162
  }
163
163
 
@@ -300,21 +300,15 @@ static uint8_t single_test(model_t* restrict mod, uint32_t update_sum_freq, char
300
300
  size_t si2 = signal.i2;
301
301
  size_t sij1 = signal.ij1;
302
302
  size_t sij2 = signal.ij2;
303
- bool only_first = signal.only_first;
304
- if (only_first) {
303
+ uint8_t rela_loc = signal.rela_loc;
304
+ if (rela_loc == NO_MIG) {
305
305
  // if only one
306
306
  double picked_rate = world[sij1].sum_pi_death_rates + world[sij1].sum_mig_rates;
307
307
  sum_rates_by_row[si1] -= picked_rate;
308
308
  sum_rates -= picked_rate;
309
309
 
310
310
  update_pi_k(&world[sij1], &(mod->X[sij1 * 4]), &(mod->P[sij1 * 6]));
311
- uint8_t mig_result = update_mig_all(&world[sij1], &(mod->P[sij1 * 6]));
312
- if (mig_result == SIM_OVERFLOW) {
313
- fprintf(stdout, "\nError: overflow at t = %f\n", time);
314
- fflush(stdout);
315
- single_test_free(&world, &nb_indices, &patch_rates, &sum_rates_by_row);
316
- return SIM_OVERFLOW;
317
- }
311
+ update_mig_just_rate(&world[sij1], &(mod->P[sij1 * 6]));
318
312
 
319
313
  picked_rate = world[sij1].sum_pi_death_rates + world[sij1].sum_mig_rates;
320
314
  patch_rates[sij1] = picked_rate;
@@ -331,9 +325,10 @@ static uint8_t single_test(model_t* restrict mod, uint32_t update_sum_freq, char
331
325
 
332
326
  update_pi_k(&world[sij1], &(mod->X[sij1 * 4]), &(mod->P[sij1 * 6])); // update both patches' payoffs first
333
327
  update_pi_k(&world[sij2], &(mod->X[sij2 * 4]), &(mod->P[sij2 * 6]));
334
- uint8_t mig_result1 = update_mig_all(&world[sij1], &(mod->P[sij1 * 6])); // and then mig rates
335
- uint8_t mig_result2 = update_mig_all(&world[sij2], &(mod->P[sij2 * 6]));
336
- if (mig_result1 == SIM_OVERFLOW || mig_result2 == SIM_OVERFLOW) {
328
+
329
+ if (update_mig_weight_rate(&world[sij1], &(mod->P[sij1 * 6]), rela_loc) == SIM_OVERFLOW ||
330
+ update_mig_weight_rate(&world[sij2], &(mod->P[sij2 * 6]), rela_loc ^ 1) == SIM_OVERFLOW) {
331
+
337
332
  fprintf(stdout, "\nError: overflow at t = %f\n", time);
338
333
  fflush(stdout);
339
334
  single_test_free(&world, &nb_indices, &patch_rates, &sum_rates_by_row);
@@ -352,19 +347,18 @@ static uint8_t single_test(model_t* restrict mod, uint32_t update_sum_freq, char
352
347
  }
353
348
 
354
349
  // update neighbors of last-changed patches
355
- if (only_first) {
350
+ if (rela_loc == NO_MIG) {
356
351
  for (uint8_t k = 0; k < 4; k++) {
357
352
  size_t nb_idx = nb_indices[sij1 * 4 + k];
358
353
  if (nb_idx == NM) { continue; } // invalid neighbor
359
354
  // all neighbors, as long as exists, need to change
360
- uint8_t mig_result = update_mig_one(&world[nb_idx], &(mod->P[nb_idx * 6]), k ^ 1);
361
- if (mig_result == SIM_OVERFLOW) {
355
+ if (update_mig_weight_rate(&world[nb_idx], &(mod->P[nb_idx * 6]), k ^ 1) == SIM_OVERFLOW) {
362
356
  fprintf(stdout, "\nError: overflow at t = %f\n", time);
363
357
  fflush(stdout);
364
358
  single_test_free(&world, &nb_indices, &patch_rates, &sum_rates_by_row);
365
359
  return SIM_OVERFLOW;
366
360
  }
367
- // sum_mig_rate is not changed
361
+ // patch_rates, and sums of rates is not changed
368
362
  }
369
363
  } else {
370
364
  // the first patch
@@ -372,8 +366,7 @@ static uint8_t single_test(model_t* restrict mod, uint32_t update_sum_freq, char
372
366
  size_t nb_idx = nb_indices[sij1 * 4 + k];
373
367
  if (nb_idx == NM) { continue; }
374
368
  if (nb_need_change(nb_idx, sij1, sij2)) {
375
- uint8_t mig_result = update_mig_one(&world[nb_idx], &(mod->P[nb_idx * 6]), k ^ 1);
376
- if (mig_result == SIM_OVERFLOW) {
369
+ if (update_mig_weight_rate(&world[nb_idx], &(mod->P[nb_idx * 6]), k ^ 1) == SIM_OVERFLOW) {
377
370
  fprintf(stdout, "\nError: overflow at t = %f\n", time);
378
371
  fflush(stdout);
379
372
  single_test_free(&world, &nb_indices, &patch_rates, &sum_rates_by_row);
@@ -386,8 +379,7 @@ static uint8_t single_test(model_t* restrict mod, uint32_t update_sum_freq, char
386
379
  size_t nb_idx = nb_indices[sij2 * 4 + k];
387
380
  if (nb_idx == NM) { continue; }
388
381
  if (nb_need_change(nb_idx, sij1, sij2)) {
389
- uint8_t mig_result = update_mig_one(&world[nb_idx], &(mod->P[nb_idx * 6]), k ^ 1);
390
- if (mig_result == SIM_OVERFLOW) {
382
+ if (update_mig_weight_rate(&world[nb_idx], &(mod->P[nb_idx * 6]), k ^ 1) == SIM_OVERFLOW) {
391
383
  fprintf(stdout, "\nError: overflow at t = %f\n", time);
392
384
  fflush(stdout);
393
385
  single_test_free(&world, &nb_indices, &patch_rates, &sum_rates_by_row);
@@ -415,7 +407,7 @@ static uint8_t single_test(model_t* restrict mod, uint32_t update_sum_freq, char
415
407
 
416
408
  // let the event happenn
417
409
  change_popu(&world[signal.ij1], signal.e1);
418
- if (!signal.only_first) {
410
+ if (signal.rela_loc != NO_MIG) {
419
411
  change_popu(&world[signal.ij2], signal.e2);
420
412
  }
421
413
 
@@ -28,12 +28,13 @@
28
28
  #define MIG_DOWN 1
29
29
  #define MIG_LEFT 2
30
30
  #define MIG_RIGHT 3
31
+ #define NO_MIG 4
31
32
 
32
33
  // results of single_test
33
34
  #define SUCCESS 0
34
35
  #define DATA_NOT_EMPTY 1
35
- #define SMALL_MAXTIME 2 // must > 1 for signal control in single test
36
- #define SIM_OVERFLOW 3 // must > 1 for signal control in single test
36
+ #define SMALL_MAXTIME 2
37
+ #define SIM_OVERFLOW 3
37
38
 
38
39
  // where exp(x) is considered overflow
39
40
  // below the actual bound (709) because the large numbers will be computed with close-to-0 ones (payoff rates), so higher accuracy is needed
@@ -59,8 +60,10 @@ typedef struct patch_picked_t {
59
60
  * index & event number in make_signal_*
60
61
  */
61
62
  typedef struct signal_t {
62
- // does the signal only have the first patch?
63
- bool only_first;
63
+ // relative location of the second patch to the first
64
+ // set to NO_MIG if the event only affects one patch
65
+ // otherwise set to MIG_* constants as defined above
66
+ uint8_t rela_loc;
64
67
 
65
68
  // the first patch
66
69
  size_t i1;
@@ -113,19 +116,19 @@ static inline void update_pi_k(patch_t* restrict p, const double* restrict M_sta
113
116
 
114
117
  double U = (double) p->U;
115
118
  double V = (double) p->V;
116
- double sum_minus_1 = U + V - 1.0;
119
+ double sum = U + V;
117
120
 
118
- if (sum_minus_1 > 0) {
121
+ if (sum > 0) {
119
122
  if (U != 0) {
120
- p->U_pi = ((U - 1) / sum_minus_1) * M_start[0] +
121
- (V / sum_minus_1) * M_start[1];
123
+ p->U_pi = (U / sum) * M_start[0] +
124
+ (V / sum) * M_start[1];
122
125
  } else {
123
126
  p->U_pi = 0.0;
124
127
  }
125
128
 
126
129
  if (V != 0) {
127
- p->V_pi = (U / sum_minus_1) * M_start[2] +
128
- ((V - 1) / sum_minus_1) * M_start[3];
130
+ p->V_pi = (U / sum) * M_start[2] +
131
+ (V / sum) * M_start[3];
129
132
  } else {
130
133
  p->V_pi = 0.0;
131
134
  }
@@ -138,8 +141,8 @@ static inline void update_pi_k(patch_t* restrict p, const double* restrict M_sta
138
141
  p->pi_death_rates[0] = fabs(U * p->U_pi);
139
142
  p->pi_death_rates[1] = fabs(V * p->V_pi);
140
143
 
141
- p->pi_death_rates[2] = P_start[4] * U * (sum_minus_1 + 1.0);
142
- p->pi_death_rates[3] = P_start[5] * V * (sum_minus_1 + 1.0);
144
+ p->pi_death_rates[2] = P_start[4] * U * sum;
145
+ p->pi_death_rates[3] = P_start[5] * V * sum;
143
146
 
144
147
  p->sum_pi_death_rates = 0.0;
145
148
  for (size_t i = 0; i < 4; i++) {
@@ -148,19 +151,37 @@ static inline void update_pi_k(patch_t* restrict p, const double* restrict M_sta
148
151
  }
149
152
 
150
153
 
151
- static inline uint8_t update_mig_one(patch_t* restrict p, const double* restrict P_start, uint8_t nb_loc) {
152
- // update mig rate for one direction
153
- // P_start: start index of p's patch variables, i.e., ij * 6
154
- // nb_loc: location of neighbor, up, down, left, right
154
+
155
+ static inline void update_mig_just_rate(patch_t* restrict p, const double* restrict P_start) {
156
+ // update migration weight for patch p, in location loc. Only rate is updated
157
+ // used by neighbors of last-changed patches, to update migration weights
158
+ double* p_U_weight = p->U_weight;
159
+ double* p_V_weight = p->V_weight;
155
160
 
156
161
  double mu1_U = P_start[0] * (double)p->U;
157
162
  double mu2_V = P_start[1] * (double)p->V;
163
+ double mu1_U_divide_sum = mu1_U / p->sum_U_weight;
164
+ double mu2_V_divide_sum = mu2_V / p->sum_V_weight;
165
+
166
+ for (uint8_t i = 0; i < 4; i++) {
167
+ p->mig_rates[i] = mu1_U_divide_sum * p_U_weight[i];
168
+ p->mig_rates[i + 4] = mu2_V_divide_sum * p_V_weight[i];
169
+ }
170
+ p->sum_mig_rates = mu1_U + mu2_V;
171
+ }
172
+
173
+
174
+ static inline uint8_t update_mig_weight_rate(patch_t* restrict p, const double* P_start, uint8_t loc) {
175
+ // update migration weight as well as rates, in one direction
176
+ // used by neighbors of last-changed patches
177
+ // also used by last-changed patches themselve, when there is only one patch changed, to update mig rates without having to update weights
178
+
158
179
  double* p_U_weight = p->U_weight;
159
180
  double* p_V_weight = p->V_weight;
160
181
 
161
- patch_t* nbi = p->nb[nb_loc];
162
- p->sum_U_weight -= p_U_weight[nb_loc];
163
- p->sum_V_weight -= p_V_weight[nb_loc];
182
+ patch_t* nbi = p->nb[loc];
183
+ p->sum_U_weight -= p_U_weight[loc];
184
+ p->sum_V_weight -= p_V_weight[loc];
164
185
 
165
186
  double w1_Upi = P_start[2] * nbi->U_pi;
166
187
  double w2_Vpi = P_start[3] * nbi->V_pi;
@@ -171,44 +192,45 @@ static inline uint8_t update_mig_one(patch_t* restrict p, const double* restrict
171
192
  return SIM_OVERFLOW;
172
193
  }
173
194
 
174
- switch(nb_loc) {
195
+ switch(loc) {
175
196
  case MIG_UP:
176
- p_U_weight[MIG_UP] = 1.0 + exp(w1_Upi);
177
- p_V_weight[MIG_UP] = 1.0 + exp(w2_Vpi);
197
+ p_U_weight[MIG_UP] = exp(w1_Upi);
198
+ p_V_weight[MIG_UP] = exp(w2_Vpi);
178
199
  break;
179
200
  case MIG_DOWN:
180
- p_U_weight[MIG_DOWN] = 1.0 + exp(w1_Upi);
181
- p_V_weight[MIG_DOWN] = 1.0 + exp(w2_Vpi);
201
+ p_U_weight[MIG_DOWN] = exp(w1_Upi);
202
+ p_V_weight[MIG_DOWN] = exp(w2_Vpi);
182
203
  break;
183
204
  case MIG_LEFT:
184
- p_U_weight[MIG_LEFT] = 1.0 + exp(w1_Upi);
185
- p_V_weight[MIG_LEFT] = 1.0 + exp(w2_Vpi);
205
+ p_U_weight[MIG_LEFT] = exp(w1_Upi);
206
+ p_V_weight[MIG_LEFT] = exp(w2_Vpi);
186
207
  break;
187
208
  default:
188
- p_U_weight[MIG_RIGHT] = 1.0 + exp(w1_Upi);
189
- p_V_weight[MIG_RIGHT] = 1.0 + exp(w2_Vpi);
209
+ p_U_weight[MIG_RIGHT] = exp(w1_Upi);
210
+ p_V_weight[MIG_RIGHT] = exp(w2_Vpi);
190
211
  break;
191
212
  }
192
- p->sum_U_weight += p_U_weight[nb_loc];
193
- p->sum_V_weight += p_V_weight[nb_loc];
213
+ p->sum_U_weight += p_U_weight[loc];
214
+ p->sum_V_weight += p_V_weight[loc];
194
215
 
216
+ double mu1_U = P_start[0] * (double)p->U;
217
+ double mu2_V = P_start[1] * (double)p->V;
195
218
  double mu1_U_divide_sum = mu1_U / p->sum_U_weight;
196
219
  double mu2_V_divide_sum = mu2_V / p->sum_V_weight;
197
220
 
198
- for (size_t i = 0; i < 4; i++) {
221
+ for (uint8_t i = 0; i < 4; i++) {
199
222
  p->mig_rates[i] = mu1_U_divide_sum * p_U_weight[i];
200
223
  p->mig_rates[i + 4] = mu2_V_divide_sum * p_V_weight[i];
201
224
  }
225
+ p->sum_mig_rates = mu1_U + mu2_V;
202
226
 
203
227
  return SUCCESS;
204
228
  }
205
229
 
206
230
 
207
231
 
208
- static inline uint8_t update_mig_all(patch_t* restrict p, const double* restrict P_start) {
232
+ static inline uint8_t init_mig(patch_t* restrict p, const double* restrict P_start) {
209
233
  // update migration rate for all directions
210
- double mu1_U = P_start[0] * (double)p->U;
211
- double mu2_V = P_start[1] * (double)p->V;
212
234
 
213
235
  double* p_U_weight = p->U_weight;
214
236
  double* p_V_weight = p->V_weight;
@@ -232,14 +254,17 @@ static inline uint8_t update_mig_all(patch_t* restrict p, const double* restrict
232
254
  if (w2_Vpi > EXP_OVERFLOW_BOUND) {
233
255
  return SIM_OVERFLOW;
234
256
  }
235
- p_U_weight[i] = 1.0 + exp(w1_Upi);
236
- p_V_weight[i] = 1.0 + exp(w2_Vpi);
257
+ p_U_weight[i] = exp(w1_Upi);
258
+ p_V_weight[i] = exp(w2_Vpi);
237
259
 
238
260
  p->sum_U_weight += p_U_weight[i];
239
261
  p->sum_V_weight += p_V_weight[i];
240
262
  }
241
263
  }
242
264
 
265
+
266
+ double mu1_U = P_start[0] * (double)p->U;
267
+ double mu2_V = P_start[1] * (double)p->V;
243
268
  double mu1_U_divide_sum = mu1_U / p->sum_U_weight;
244
269
  double mu2_V_divide_sum = mu2_V / p->sum_V_weight;
245
270
 
@@ -247,7 +272,6 @@ static inline uint8_t update_mig_all(patch_t* restrict p, const double* restrict
247
272
  p->mig_rates[i] = mu1_U_divide_sum * p_U_weight[i];
248
273
  p->mig_rates[i + 4] = mu2_V_divide_sum * p_V_weight[i];
249
274
  }
250
-
251
275
  p->sum_mig_rates = mu1_U + mu2_V;
252
276
 
253
277
  return SUCCESS;
@@ -337,23 +361,25 @@ static inline void find_patch(patch_picked_t* restrict picked, double expected_s
337
361
  size_t col = 0;
338
362
 
339
363
  // Find row
340
- if (expected_sum < sum_rates * 0.5) {
341
- current_sum = 0.0;
342
- row = 0;
343
- while (current_sum < expected_sum) {
344
- current_sum += sum_rates_by_row[row];
345
- row++;
346
- }
347
- row--;
348
- current_sum -= sum_rates_by_row[row];
349
- } else {
350
- current_sum = sum_rates;
351
- row = N - 1;
352
- while (current_sum > expected_sum) {
353
- current_sum -= sum_rates_by_row[row];
364
+ if (N != 1) {
365
+ if (expected_sum < sum_rates * 0.5) {
366
+ current_sum = 0.0;
367
+ row = 0;
368
+ while (current_sum < expected_sum) {
369
+ current_sum += sum_rates_by_row[row];
370
+ row++;
371
+ }
354
372
  row--;
373
+ current_sum -= sum_rates_by_row[row];
374
+ } else {
375
+ current_sum = sum_rates;
376
+ row = N - 1;
377
+ while (current_sum > expected_sum) {
378
+ current_sum -= sum_rates_by_row[row];
379
+ row--;
380
+ }
381
+ row++;
355
382
  }
356
- row++;
357
383
  }
358
384
 
359
385
  size_t row_M = row * M;
@@ -392,75 +418,75 @@ static inline void make_signal_zero_flux(size_t i, size_t j, uint8_t e, signal_t
392
418
  switch (e) {
393
419
  case 0:
394
420
  signal->e1 = 2;
395
- signal->only_first = true;
421
+ signal->rela_loc = NO_MIG;
396
422
  return;
397
423
  case 1:
398
424
  signal->e1 = 5;
399
- signal->only_first = true;
425
+ signal->rela_loc = NO_MIG;
400
426
  return;
401
427
  case 2:
402
428
  signal->e1 = 1;
403
- signal->only_first = true;
429
+ signal->rela_loc = NO_MIG;
404
430
  return;
405
431
  case 3:
406
432
  signal->e1 = 4;
407
- signal->only_first = true;
433
+ signal->rela_loc = NO_MIG;
408
434
  return;
409
435
  case 4:
410
436
  signal->e1 = 1;
411
437
  signal->i2 = i - 1;
412
438
  signal->j2 = j;
413
439
  signal->e2 = 0;
414
- signal->only_first = false;
440
+ signal->rela_loc = MIG_UP;
415
441
  return;
416
442
  case 5:
417
443
  signal->e1 = 1;
418
444
  signal->i2 = i + 1;
419
445
  signal->j2 = j;
420
446
  signal->e2 = 0;
421
- signal->only_first = false;
447
+ signal->rela_loc = MIG_DOWN;
422
448
  return;
423
449
  case 6:
424
450
  signal->e1 = 1;
425
451
  signal->i2 = i;
426
452
  signal->j2 = j - 1;
427
453
  signal->e2 = 0;
428
- signal->only_first = false;
454
+ signal->rela_loc = MIG_LEFT;
429
455
  return;
430
456
  case 7:
431
457
  signal->e1 = 1;
432
458
  signal->i2 = i;
433
459
  signal->j2 = j + 1;
434
460
  signal->e2 = 0;
435
- signal->only_first = false;
461
+ signal->rela_loc = MIG_RIGHT;
436
462
  return;
437
463
  case 8:
438
464
  signal->e1 = 4;
439
465
  signal->i2 = i - 1;
440
466
  signal->j2 = j;
441
467
  signal->e2 = 3;
442
- signal->only_first = false;
468
+ signal->rela_loc = MIG_UP;
443
469
  return;
444
470
  case 9:
445
471
  signal->e1 = 4;
446
472
  signal->i2 = i + 1;
447
473
  signal->j2 = j;
448
474
  signal->e2 = 3;
449
- signal->only_first = false;
475
+ signal->rela_loc = MIG_DOWN;
450
476
  return;
451
477
  case 10:
452
478
  signal->e1 = 4;
453
479
  signal->i2 = i;
454
480
  signal->j2 = j - 1;
455
481
  signal->e2 = 3;
456
- signal->only_first = false;
482
+ signal->rela_loc = MIG_LEFT;
457
483
  return;
458
484
  default:
459
485
  signal->e1 = 4;
460
486
  signal->i2 = i;
461
487
  signal->j2 = j + 1;
462
488
  signal->e2 = 3;
463
- signal->only_first = false;
489
+ signal->rela_loc = MIG_RIGHT;
464
490
  return;
465
491
  //default:
466
492
  // fprintf(stderr, "Bug: invalid case in make_signal_zf, i, j, e: %zu, %zu, %hhu\n", i, j, e);
@@ -478,75 +504,75 @@ static inline void make_signal_periodical(size_t N, size_t M, size_t i, size_t j
478
504
  switch (e) {
479
505
  case 0:
480
506
  signal->e1 = 2;
481
- signal->only_first = true;
507
+ signal->rela_loc = NO_MIG;
482
508
  return;
483
509
  case 1:
484
510
  signal->e1 = 5;
485
- signal->only_first = true;
511
+ signal->rela_loc = NO_MIG;
486
512
  return;
487
513
  case 2:
488
514
  signal->e1 = 1;
489
- signal->only_first = true;
515
+ signal->rela_loc = NO_MIG;
490
516
  return;
491
517
  case 3:
492
518
  signal->e1 = 4;
493
- signal->only_first = true;
519
+ signal->rela_loc = NO_MIG;
494
520
  return;
495
521
  case 4:
496
522
  signal->e1 = 1;
497
523
  signal->i2 = i != 0 ? i - 1 : N - 1;
498
524
  signal->j2 = j;
499
525
  signal->e2 = 0;
500
- signal->only_first = false;
526
+ signal->rela_loc = MIG_UP;
501
527
  return;
502
528
  case 5:
503
529
  signal->e1 = 1;
504
530
  signal->i2 = i != N - 1 ? i + 1 : 0;
505
531
  signal->j2 = j;
506
532
  signal->e2 = 0;
507
- signal->only_first = false;
533
+ signal->rela_loc = MIG_DOWN;
508
534
  return;
509
535
  case 6:
510
536
  signal->e1 = 1;
511
537
  signal->i2 = i;
512
538
  signal->j2 = j != 0 ? j - 1 : M - 1;
513
539
  signal->e2 = 0;
514
- signal->only_first = false;
540
+ signal->rela_loc = MIG_LEFT;
515
541
  return;
516
542
  case 7:
517
543
  signal->e1 = 1;
518
544
  signal->i2 = i;
519
545
  signal->j2 = j != M - 1 ? j + 1 : 0;
520
546
  signal->e2 = 0;
521
- signal->only_first = false;
547
+ signal->rela_loc = MIG_RIGHT;
522
548
  return;
523
549
  case 8:
524
550
  signal->e1 = 4;
525
551
  signal->i2 = i != 0 ? i - 1 : N - 1;
526
552
  signal->j2 = j;
527
553
  signal->e2 = 3;
528
- signal->only_first = false;
554
+ signal->rela_loc = MIG_UP;
529
555
  return;
530
556
  case 9:
531
557
  signal->e1 = 4;
532
558
  signal->i2 = i != N - 1 ? i + 1 : 0;
533
559
  signal->j2 = j;
534
560
  signal->e2 = 3;
535
- signal->only_first = false;
561
+ signal->rela_loc = MIG_DOWN;
536
562
  return;
537
563
  case 10:
538
564
  signal->e1 = 4;
539
565
  signal->i2 = i;
540
566
  signal->j2 = j != 0 ? j - 1 : M - 1;
541
567
  signal->e2 = 3;
542
- signal->only_first = false;
568
+ signal->rela_loc = MIG_LEFT;
543
569
  return;
544
570
  default:
545
571
  signal->e1 = 4;
546
572
  signal->i2 = i;
547
573
  signal->j2 = j != M - 1 ? j + 1 : 0;
548
574
  signal->e2 = 3;
549
- signal->only_first = false;
575
+ signal->rela_loc = MIG_RIGHT;
550
576
  return;
551
577
  //default:
552
578
  // fprintf(stderr, "Bug: invalid case in make_signal_pr, i, j, e: %zu, %zu, %hhu\n", i, j, e);
@@ -1,4 +1,4 @@
1
- __version__ = '2.3.1'
1
+ __version__ = '2.3.2'
2
2
 
3
3
  '''
4
4
  version history:
@@ -37,4 +37,6 @@ version history:
37
37
  2.2.3: raised rate calculation to higher accuracy (long double), and switched to 30-bit random number generator.
38
38
  2.3.1: roll back accuracy update. Decrease toleratable bound for exponent of exp() to 500.
39
39
  Add video_fig function to figures module, which plots change of patch popu/payoff overtime in a 2D figure. Add auto-sorting for values passed to test_var plot functions.
40
+ 2.3.2: allow play-with-self in payoff calculation. Changed migration function to e^(w*pi) (removed "1+" term).
41
+ Simplified update-migration functions, improve speed by ~10%. Add -march=native flag to Makefile.
40
42
  '''
@@ -491,19 +491,19 @@ def UV_pi(mod, ax_U = None, ax_V = None, U_color = 'violet', V_color = 'yellowgr
491
491
 
492
492
 
493
493
 
494
- def video_fig(mod, ax_list = None, num_itv = 100, U_color = 'Purples', V_color = 'Greens'):
494
+ def video_fig(mod, ax_list = None, num_grid = 100, U_color = 'Purples', V_color = 'Greens'):
495
495
  '''
496
496
  Plot distribution dynamics over time, of U, V population and payoff.
497
497
 
498
498
  mod: simulation.model object
499
499
  ax_list: a 2*2 list of ax, or None (a new 2*2 ax_list will be created)
500
- num_itv: how many time intervals to plot
500
+ num_grid: how many grid for the time axis
501
501
  U_color & V_color: matplotlib color map, color for U, V population and payoff.
502
502
  '''
503
503
 
504
- if num_itv > mod.max_record:
505
- raise ValueError('num_itv too large, larger than mod.max_record')
506
- idx_step = int(mod.max_record / num_itv)
504
+ if num_grid > mod.max_record:
505
+ raise ValueError('num_grid too large, larger than mod.max_record')
506
+ idx_step = int(mod.max_record / num_grid)
507
507
  ave_U = []
508
508
  ave_V = []
509
509
  ave_Upi = []
@@ -525,7 +525,7 @@ def video_fig(mod, ax_list = None, num_itv = 100, U_color = 'Purples', V_color =
525
525
  ax_list[i, j].spines['right'].set_visible(False)
526
526
  ax_list[i, j].set_xlabel('Patches')
527
527
  ax_list[i, j].set_ylabel('Time')
528
- ax_list[i, j].set_xlim([0, mod.M - 1])
528
+ ax_list[i, j].set_xlim([0, mod.M])
529
529
  ax_list[i, j].set_ylim([0, mod.maxtime])
530
530
 
531
531
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: piegy
3
- Version: 2.3.1
3
+ Version: 2.3.2
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
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes