models.config

Experiment Configuration

This module provides the configuration dataclass and pre-defined phase configurations for Predator-Prey Hydra Effect experiments.

Classes

Config Central configuration dataclass with all experiment parameters.

Functions
get_phase_config: Retrieve configuration for a specific experimental phase.
Phase Configurations
  • PHASE1_CONFIG: Parameter sweep to find critical point
  • PHASE2_CONFIG: Self-organization (evolution toward criticality)
  • PHASE3_CONFIG: Finite-size scaling at critical point
  • PHASE4_CONFIG: Sensitivity analysis (4D parameter sweep)
  • PHASE5_CONFIG: Directed hunting comparison
Example
from models.config import Config, get_phase_config

# Use predefined phase config
cfg = get_phase_config(1)

# Create custom config
cfg = Config(grid_size=200, n_replicates=10)

# Generate parameter sweep values
prey_deaths = cfg.get_prey_deaths()
  1#!/usr/bin/env python3
  2"""
  3Experiment Configuration
  4========================
  5
  6This module provides the configuration dataclass and pre-defined phase
  7configurations for Predator-Prey Hydra Effect experiments.
  8
  9Classes
 10-------
 11Config
 12    Central configuration dataclass with all experiment parameters.
 13
 14Functions
 15---------
 16```python
 17get_phase_config: Retrieve configuration for a specific experimental phase.
 18````
 19
 20Phase Configurations
 21--------------------
 22- ``PHASE1_CONFIG``: Parameter sweep to find critical point
 23- ``PHASE2_CONFIG``: Self-organization (evolution toward criticality)
 24- ``PHASE3_CONFIG``: Finite-size scaling at critical point
 25- ``PHASE4_CONFIG``: Sensitivity analysis (4D parameter sweep)
 26- ``PHASE5_CONFIG``: Directed hunting comparison
 27
 28Example
 29-------
 30```python
 31from models.config import Config, get_phase_config
 32
 33# Use predefined phase config
 34cfg = get_phase_config(1)
 35
 36# Create custom config
 37cfg = Config(grid_size=200, n_replicates=10)
 38
 39# Generate parameter sweep values
 40prey_deaths = cfg.get_prey_deaths()
 41```
 42"""
 43from dataclasses import dataclass
 44from typing import Tuple
 45import numpy as np
 46
 47
 48@dataclass
 49class Config:
 50    """
 51    Central configuration for Predator-Prey Hydra Effect experiments.
 52
 53    Attributes
 54    ----------
 55    grid_size : int
 56        Side length of the square simulation grid.
 57    densities : Tuple[float, float]
 58        Initial population fractions for (prey, predator).
 59    grid_sizes : Tuple[int, ...]
 60        Grid dimensions for Finite-Size Scaling (FSS) analysis (Phase 3).
 61    prey_birth : float
 62        Global birth rate for prey species.
 63    prey_death : float
 64        Global death rate for prey species.
 65    predator_birth : float
 66        Global birth rate for predator species.
 67    predator_death : float
 68        Global death rate for predator species.
 69    critical_prey_birth : float
 70        Critical birth rate identified from Phase 1.
 71    critical_prey_death : float
 72        Critical death rate identified from Phase 1.
 73    prey_death_range : Tuple[float, float]
 74        Bounds for prey death rate sweep.
 75    n_prey_death : int
 76        Number of points in prey death rate sweep.
 77    n_replicates : int
 78        Independent stochastic runs per parameter set.
 79    warmup_steps : int
 80        Iterations before data collection begins.
 81    measurement_steps : int
 82        Iterations for collecting statistics.
 83    evolve_sd : float
 84        Standard deviation for parameter mutation.
 85    evolve_min : float
 86        Lower bound for evolving parameters.
 87    evolve_max : float
 88        Upper bound for evolving parameters.
 89    directed_hunting : bool
 90        Toggle for targeted predator movement.
 91    save_timeseries : bool
 92        Toggle for recording population time series.
 93    timeseries_subsample : int
 94        Subsample rate for time series data.
 95    collect_pcf : bool
 96        Toggle for Pair Correlation Function analysis.
 97    pcf_sample_rate : float
 98        Fraction of runs that compute PCFs.
 99    pcf_max_distance : float
100        Maximum radial distance for PCF.
101    pcf_n_bins : int
102        Number of bins in PCF histogram.
103    min_density_for_analysis : float
104        Population threshold for spatial analysis.
105    n_jobs : int
106        CPU cores for parallelization (-1 = all).
107    """
108
109    # Grid settings
110    grid_size: int = 1000
111    densities: Tuple[float, float] = (0.30, 0.15)
112    grid_sizes: Tuple[int, ...] = (50, 100, 250, 500, 1000, 2500)
113
114    # Species parameters
115    prey_birth: float = 0.2
116    prey_death: float = 0.05
117    predator_birth: float = 0.8
118    predator_death: float = 0.05
119
120    # Critical point (from Phase 1)
121    critical_prey_birth: float = 0.20
122    critical_prey_death: float = 0.0968
123
124    # Parameter sweep settings
125    prey_death_range: Tuple[float, float] = (0.0, 0.2)
126    n_prey_death: int = 20
127
128    # Replication
129    n_replicates: int = 15
130
131    # Simulation timing
132    warmup_steps: int = 300
133    measurement_steps: int = 500
134
135    # Evolution settings
136    evolve_sd: float = 0.10
137    evolve_min: float = 0.0
138    evolve_max: float = 0.10
139
140    # Model variant
141    directed_hunting: bool = False
142
143    # Time series collection
144    save_timeseries: bool = False
145    timeseries_subsample: int = 10
146
147    # PCF settings
148    collect_pcf: bool = True
149    pcf_sample_rate: float = 0.2
150    pcf_max_distance: float = 20.0
151    pcf_n_bins: int = 20
152
153    # Analysis thresholds
154    min_density_for_analysis: float = 0.002
155
156    # Parallelization
157    n_jobs: int = -1
158
159    def get_prey_deaths(self) -> np.ndarray:
160        """Generate array of prey death rates for parameter sweep."""
161        return np.linspace(
162            self.prey_death_range[0], self.prey_death_range[1], self.n_prey_death
163        )
164
165    def get_warmup_steps(self, L: int) -> int:
166        """Get warmup steps (can be extended for size-dependent scaling)."""
167        return self.warmup_steps
168
169    def get_measurement_steps(self, L: int) -> int:
170        """Get measurement steps (can be extended for size-dependent scaling)."""
171        return self.measurement_steps
172
173    def estimate_runtime(self, n_cores: int = 32) -> str:
174        """
175        Estimate wall-clock time for the experiment.
176
177        Parameters
178        ----------
179        n_cores : int
180            Number of available CPU cores.
181
182        Returns
183        -------
184        str
185            Human-readable runtime estimate.
186        """
187        ref_size = 100
188        ref_steps_per_sec = 1182
189
190        size_scaling = (self.grid_size / ref_size) ** 2
191        actual_steps_per_sec = ref_steps_per_sec / size_scaling
192
193        total_steps = self.warmup_steps + self.measurement_steps
194        base_time_s = total_steps / actual_steps_per_sec
195
196        pcf_time_s = (0.008 * size_scaling) if self.collect_pcf else 0
197
198        n_sims = self.n_prey_death * self.n_replicates
199
200        total_seconds = n_sims * (base_time_s + pcf_time_s * self.pcf_sample_rate)
201        total_seconds /= n_cores
202
203        hours = total_seconds / 3600
204        core_hours = n_sims * (base_time_s + pcf_time_s * self.pcf_sample_rate) / 3600
205
206        return f"{n_sims:,} sims, ~{hours:.1f}h on {n_cores} cores (~{core_hours:.0f} core-hours)"
207
208
209# =============================================================================
210# Phase Configurations
211# =============================================================================
212
213PHASE1_CONFIG = Config(
214    grid_size=1000,
215    n_prey_death=20,
216    prey_birth=0.2,
217    prey_death_range=(0.0963, 0.0973),
218    predator_birth=0.8,
219    predator_death=0.05,
220    n_replicates=30,
221    warmup_steps=1000,
222    measurement_steps=1000,
223    collect_pcf=False,
224    save_timeseries=False,
225    directed_hunting=False,
226)
227
228PHASE2_CONFIG = Config(
229    grid_size=1000,
230    n_prey_death=10,
231    n_replicates=10,
232    warmup_steps=1000,
233    measurement_steps=10000,
234    evolve_sd=0.01,
235    evolve_min=0.0,
236    evolve_max=0.20,
237    collect_pcf=False,
238    save_timeseries=False,
239)
240
241PHASE3_CONFIG = Config(
242    grid_sizes=(50, 100, 250, 500, 1000, 2500),
243    n_replicates=20,
244    warmup_steps=1000,
245    measurement_steps=1000,
246    critical_prey_birth=0.20,
247    critical_prey_death=0.0968,
248    collect_pcf=True,
249    pcf_sample_rate=1.0,
250    save_timeseries=False,
251    directed_hunting=False,
252)
253
254PHASE4_CONFIG = Config(
255    grid_size=250,
256    n_replicates=10,
257    warmup_steps=500,
258    measurement_steps=500,
259    collect_pcf=False,
260    save_timeseries=False,
261    directed_hunting=False,
262)
263
264PHASE5_CONFIG = Config(
265    grid_size=250,
266    n_replicates=10,
267    warmup_steps=500,
268    measurement_steps=500,
269    collect_pcf=False,
270    save_timeseries=False,
271    directed_hunting=True,
272)
273
274PHASE_CONFIGS = {
275    1: PHASE1_CONFIG,
276    2: PHASE2_CONFIG,
277    3: PHASE3_CONFIG,
278    4: PHASE4_CONFIG,
279    5: PHASE5_CONFIG,
280}
281
282
283def get_phase_config(phase: int) -> Config:
284    """
285    Retrieve configuration for a specific experimental phase.
286
287    Parameters
288    ----------
289    phase : int
290        Phase number (1-5).
291
292    Returns
293    -------
294    Config
295        Configuration instance for the requested phase.
296
297    Raises
298    ------
299    ValueError
300        If phase number is invalid.
301    """
302    if phase not in PHASE_CONFIGS:
303        raise ValueError(
304            f"Unknown phase {phase}. Valid phases: {list(PHASE_CONFIGS.keys())}"
305        )
306    return PHASE_CONFIGS[phase]
@dataclass
class Config:
 49@dataclass
 50class Config:
 51    """
 52    Central configuration for Predator-Prey Hydra Effect experiments.
 53
 54    Attributes
 55    ----------
 56    grid_size : int
 57        Side length of the square simulation grid.
 58    densities : Tuple[float, float]
 59        Initial population fractions for (prey, predator).
 60    grid_sizes : Tuple[int, ...]
 61        Grid dimensions for Finite-Size Scaling (FSS) analysis (Phase 3).
 62    prey_birth : float
 63        Global birth rate for prey species.
 64    prey_death : float
 65        Global death rate for prey species.
 66    predator_birth : float
 67        Global birth rate for predator species.
 68    predator_death : float
 69        Global death rate for predator species.
 70    critical_prey_birth : float
 71        Critical birth rate identified from Phase 1.
 72    critical_prey_death : float
 73        Critical death rate identified from Phase 1.
 74    prey_death_range : Tuple[float, float]
 75        Bounds for prey death rate sweep.
 76    n_prey_death : int
 77        Number of points in prey death rate sweep.
 78    n_replicates : int
 79        Independent stochastic runs per parameter set.
 80    warmup_steps : int
 81        Iterations before data collection begins.
 82    measurement_steps : int
 83        Iterations for collecting statistics.
 84    evolve_sd : float
 85        Standard deviation for parameter mutation.
 86    evolve_min : float
 87        Lower bound for evolving parameters.
 88    evolve_max : float
 89        Upper bound for evolving parameters.
 90    directed_hunting : bool
 91        Toggle for targeted predator movement.
 92    save_timeseries : bool
 93        Toggle for recording population time series.
 94    timeseries_subsample : int
 95        Subsample rate for time series data.
 96    collect_pcf : bool
 97        Toggle for Pair Correlation Function analysis.
 98    pcf_sample_rate : float
 99        Fraction of runs that compute PCFs.
100    pcf_max_distance : float
101        Maximum radial distance for PCF.
102    pcf_n_bins : int
103        Number of bins in PCF histogram.
104    min_density_for_analysis : float
105        Population threshold for spatial analysis.
106    n_jobs : int
107        CPU cores for parallelization (-1 = all).
108    """
109
110    # Grid settings
111    grid_size: int = 1000
112    densities: Tuple[float, float] = (0.30, 0.15)
113    grid_sizes: Tuple[int, ...] = (50, 100, 250, 500, 1000, 2500)
114
115    # Species parameters
116    prey_birth: float = 0.2
117    prey_death: float = 0.05
118    predator_birth: float = 0.8
119    predator_death: float = 0.05
120
121    # Critical point (from Phase 1)
122    critical_prey_birth: float = 0.20
123    critical_prey_death: float = 0.0968
124
125    # Parameter sweep settings
126    prey_death_range: Tuple[float, float] = (0.0, 0.2)
127    n_prey_death: int = 20
128
129    # Replication
130    n_replicates: int = 15
131
132    # Simulation timing
133    warmup_steps: int = 300
134    measurement_steps: int = 500
135
136    # Evolution settings
137    evolve_sd: float = 0.10
138    evolve_min: float = 0.0
139    evolve_max: float = 0.10
140
141    # Model variant
142    directed_hunting: bool = False
143
144    # Time series collection
145    save_timeseries: bool = False
146    timeseries_subsample: int = 10
147
148    # PCF settings
149    collect_pcf: bool = True
150    pcf_sample_rate: float = 0.2
151    pcf_max_distance: float = 20.0
152    pcf_n_bins: int = 20
153
154    # Analysis thresholds
155    min_density_for_analysis: float = 0.002
156
157    # Parallelization
158    n_jobs: int = -1
159
160    def get_prey_deaths(self) -> np.ndarray:
161        """Generate array of prey death rates for parameter sweep."""
162        return np.linspace(
163            self.prey_death_range[0], self.prey_death_range[1], self.n_prey_death
164        )
165
166    def get_warmup_steps(self, L: int) -> int:
167        """Get warmup steps (can be extended for size-dependent scaling)."""
168        return self.warmup_steps
169
170    def get_measurement_steps(self, L: int) -> int:
171        """Get measurement steps (can be extended for size-dependent scaling)."""
172        return self.measurement_steps
173
174    def estimate_runtime(self, n_cores: int = 32) -> str:
175        """
176        Estimate wall-clock time for the experiment.
177
178        Parameters
179        ----------
180        n_cores : int
181            Number of available CPU cores.
182
183        Returns
184        -------
185        str
186            Human-readable runtime estimate.
187        """
188        ref_size = 100
189        ref_steps_per_sec = 1182
190
191        size_scaling = (self.grid_size / ref_size) ** 2
192        actual_steps_per_sec = ref_steps_per_sec / size_scaling
193
194        total_steps = self.warmup_steps + self.measurement_steps
195        base_time_s = total_steps / actual_steps_per_sec
196
197        pcf_time_s = (0.008 * size_scaling) if self.collect_pcf else 0
198
199        n_sims = self.n_prey_death * self.n_replicates
200
201        total_seconds = n_sims * (base_time_s + pcf_time_s * self.pcf_sample_rate)
202        total_seconds /= n_cores
203
204        hours = total_seconds / 3600
205        core_hours = n_sims * (base_time_s + pcf_time_s * self.pcf_sample_rate) / 3600
206
207        return f"{n_sims:,} sims, ~{hours:.1f}h on {n_cores} cores (~{core_hours:.0f} core-hours)"

Central configuration for Predator-Prey Hydra Effect experiments.

Attributes
  • grid_size (int): Side length of the square simulation grid.
  • densities (Tuple[float, float]): Initial population fractions for (prey, predator).
  • grid_sizes (Tuple[int, ...]): Grid dimensions for Finite-Size Scaling (FSS) analysis (Phase 3).
  • prey_birth (float): Global birth rate for prey species.
  • prey_death (float): Global death rate for prey species.
  • predator_birth (float): Global birth rate for predator species.
  • predator_death (float): Global death rate for predator species.
  • critical_prey_birth (float): Critical birth rate identified from Phase 1.
  • critical_prey_death (float): Critical death rate identified from Phase 1.
  • prey_death_range (Tuple[float, float]): Bounds for prey death rate sweep.
  • n_prey_death (int): Number of points in prey death rate sweep.
  • n_replicates (int): Independent stochastic runs per parameter set.
  • warmup_steps (int): Iterations before data collection begins.
  • measurement_steps (int): Iterations for collecting statistics.
  • evolve_sd (float): Standard deviation for parameter mutation.
  • evolve_min (float): Lower bound for evolving parameters.
  • evolve_max (float): Upper bound for evolving parameters.
  • directed_hunting (bool): Toggle for targeted predator movement.
  • save_timeseries (bool): Toggle for recording population time series.
  • timeseries_subsample (int): Subsample rate for time series data.
  • collect_pcf (bool): Toggle for Pair Correlation Function analysis.
  • pcf_sample_rate (float): Fraction of runs that compute PCFs.
  • pcf_max_distance (float): Maximum radial distance for PCF.
  • pcf_n_bins (int): Number of bins in PCF histogram.
  • min_density_for_analysis (float): Population threshold for spatial analysis.
  • n_jobs (int): CPU cores for parallelization (-1 = all).
def get_prey_deaths(self) -> numpy.ndarray:
160    def get_prey_deaths(self) -> np.ndarray:
161        """Generate array of prey death rates for parameter sweep."""
162        return np.linspace(
163            self.prey_death_range[0], self.prey_death_range[1], self.n_prey_death
164        )

Generate array of prey death rates for parameter sweep.

def get_warmup_steps(self, L: int) -> int:
166    def get_warmup_steps(self, L: int) -> int:
167        """Get warmup steps (can be extended for size-dependent scaling)."""
168        return self.warmup_steps

Get warmup steps (can be extended for size-dependent scaling).

def get_measurement_steps(self, L: int) -> int:
170    def get_measurement_steps(self, L: int) -> int:
171        """Get measurement steps (can be extended for size-dependent scaling)."""
172        return self.measurement_steps

Get measurement steps (can be extended for size-dependent scaling).

def estimate_runtime(self, n_cores: int = 32) -> str:
174    def estimate_runtime(self, n_cores: int = 32) -> str:
175        """
176        Estimate wall-clock time for the experiment.
177
178        Parameters
179        ----------
180        n_cores : int
181            Number of available CPU cores.
182
183        Returns
184        -------
185        str
186            Human-readable runtime estimate.
187        """
188        ref_size = 100
189        ref_steps_per_sec = 1182
190
191        size_scaling = (self.grid_size / ref_size) ** 2
192        actual_steps_per_sec = ref_steps_per_sec / size_scaling
193
194        total_steps = self.warmup_steps + self.measurement_steps
195        base_time_s = total_steps / actual_steps_per_sec
196
197        pcf_time_s = (0.008 * size_scaling) if self.collect_pcf else 0
198
199        n_sims = self.n_prey_death * self.n_replicates
200
201        total_seconds = n_sims * (base_time_s + pcf_time_s * self.pcf_sample_rate)
202        total_seconds /= n_cores
203
204        hours = total_seconds / 3600
205        core_hours = n_sims * (base_time_s + pcf_time_s * self.pcf_sample_rate) / 3600
206
207        return f"{n_sims:,} sims, ~{hours:.1f}h on {n_cores} cores (~{core_hours:.0f} core-hours)"

Estimate wall-clock time for the experiment.

Parameters
  • n_cores (int): Number of available CPU cores.
Returns
  • str: Human-readable runtime estimate.
def get_phase_config(phase: int) -> Config:
284def get_phase_config(phase: int) -> Config:
285    """
286    Retrieve configuration for a specific experimental phase.
287
288    Parameters
289    ----------
290    phase : int
291        Phase number (1-5).
292
293    Returns
294    -------
295    Config
296        Configuration instance for the requested phase.
297
298    Raises
299    ------
300    ValueError
301        If phase number is invalid.
302    """
303    if phase not in PHASE_CONFIGS:
304        raise ValueError(
305            f"Unknown phase {phase}. Valid phases: {list(PHASE_CONFIGS.keys())}"
306        )
307    return PHASE_CONFIGS[phase]

Retrieve configuration for a specific experimental phase.

Parameters
  • phase (int): Phase number (1-5).
Returns
  • Config: Configuration instance for the requested phase.
Raises
  • ValueError: If phase number is invalid.