Simulation
╔══════════════════════════════════════════════════════════╗ ║ simulation « walking strategy simulators » ║ ╚══════════════════════════════════════════════════════════╝
Provides two agent classes that move through a toroidal 2-D arena and collect food items:
MarkovWalker— HMM-driven replay of empirical prototypical-movement sequences (dark-fly or OregonR).LevyWalker— Lévy-flight / random-walk agent with configurable step-size distributions.
- class satyre.simulation.MarkovWalker(transition_matrix, pm_index, velocity_array, *, n_trials=1000, border=10000.0, max_steps=10000, total_food=1000, food_mode='random', condition='dark')[source]
Simulate fly locomotion using a Hidden-Markov-Model of prototypical movements derived from experimental data.
The transition-probability matrix drives the selection of successive PMs. Each PM carries thrust, slip, and yaw velocities that determine displacement and body rotation.
- Parameters:
transition_matrix (
ndarray[tuple[Any,...],dtype[floating]]) – Cumulative transition-probability matrix of shape(N, N)whereNis the number of prototypical movements.pm_index (
ndarray[tuple[Any,...],dtype[floating]]) – Row-sorted PM index matrix of shape(N, N). Each row maps cumulative-probability columns back to PM identifiers.velocity_array (
ndarray[tuple[Any,...],dtype[floating]]) – Array of shape(N, 3)holding[thrust, slip, yaw]velocities for each PM (units: mm s⁻¹ / rad s⁻¹).n_trials (
int) – Number of independent simulation trials executed bysimulate_multiple().border (
float) – Half-width of the square toroidal arena (mm).max_steps (
int) – Maximum number of PM steps per trial.total_food (
int) – Number of food items scattered in the arena at the start of each trial.food_mode (
str) – Food-distribution mode —'random'or'clustered'.condition (
str) – Sensory condition —'dark'(tactile body-overlap detection) or'light'(visual detection within a 20 mm radius).
- food_found_total
Number of food items collected in the most recent single trial.
- all_performed_pms
List of PM indices visited during the most recent trial.
- psi_angles
Drift (ψ) angles between body heading and trajectory direction.
Example
>>> import numpy as np >>> from satyre import MarkovWalker >>> trans = np.eye(5, dtype=float) # dummy identity >>> trans = np.cumsum(trans, axis=1) >>> pm_idx = np.tile(np.arange(5), (5, 1)).astype(float) >>> velos = np.random.randn(5, 3) * 0.5 >>> walker = MarkovWalker(trans, pm_idx, velos, ... max_steps=100, n_trials=2) >>> walker.simulate()
- simulate()[source]
Run a single foraging trial.
Resets the agent, scatters food, then steps through PMs until max_steps is reached. Populates
food_found_totalandpsi_angles.- Return type:
- simulate_multiple()[source]
Run n_trials independent trials and collect results.
- Return type:
dict[str,ndarray[tuple[Any,...],dtype[TypeVar(_ScalarT, bound=generic)]]]- Returns:
Dictionary with the following keys (each value is an
ndarrayindexed by trial number). Column count is determined by the longest trial (hyperspace wrapping can add sub-steps); shorter trials are NaN-padded.food_found— shape(n_trials,)step_sizes— shape(n_trials, n_cols)psi_angles— shape(n_trials, n_psi)position_x— shape(n_trials, n_cols)position_y— shape(n_trials, n_cols)head_x,head_y,tail_x,tail_y
- class satyre.simulation.LevyWalker(cauchy_alpha=1.0, *, n_trials=1000, border=10000.0, mode='cauchy', max_steps=1000, total_food=10000, food_mode='random')[source]
Simulate Lévy-flight or random-walk foraging in a toroidal arena.
The agent draws step sizes from either a Cauchy-derived heavy-tailed distribution (Lévy flight) or a Gaussian (uniform random walk), chooses a uniformly random direction, and checks for food overlap after each step.
- Parameters:
cauchy_alpha (
float) – Shape parameter for the Cauchy step-size distribution. Higher values produce shorter tails. Ignored when mode is'uniform'.n_trials (
int) – Number of independent simulation trials executed bysimulate_multiple().border (
float) – Half-width of the square toroidal arena (mm).mode (
str) – Step-size distribution —'cauchy'for Lévy flight or'uniform'for Gaussian random walk.max_steps (
int) – Maximum number of steps per trial.total_food (
int) – Number of food items placed at the start of each trial.food_mode (
str) – Food distribution —'random'or'clustered'.
- food_found_total
Items collected in the most recent single trial.
- step_size_arr
Step-size array from the most recent trial.
Example
>>> from satyre import LevyWalker >>> walker = LevyWalker(cauchy_alpha=1.5, mode='cauchy', ... max_steps=500, n_trials=10) >>> walker.simulate() >>> print(walker.food_found_total)
- simulate()[source]
Run a single foraging trial.
Resets the agent, scatters food, steps until max_steps, and populates
food_found_total.- Return type:
- simulate_multiple()[source]
Run n_trials independent trials.
- Returns:
food_found— shape(n_trials,)step_sizes— shape(n_trials, n_cols)
Column count n_cols is determined by the longest trial (hyperspace wrapping can add sub-steps beyond max_steps). Shorter trials are NaN-padded.
- Return type:
dict[str,ndarray[tuple[Any,...],dtype[TypeVar(_ScalarT, bound=generic)]]]
MarkovWalker
- class satyre.simulation.markov_walker.MarkovWalker(transition_matrix, pm_index, velocity_array, *, n_trials=1000, border=10000.0, max_steps=10000, total_food=1000, food_mode='random', condition='dark')[source]
Bases:
objectSimulate fly locomotion using a Hidden-Markov-Model of prototypical movements derived from experimental data.
The transition-probability matrix drives the selection of successive PMs. Each PM carries thrust, slip, and yaw velocities that determine displacement and body rotation.
- Parameters:
transition_matrix (
ndarray[tuple[Any,...],dtype[floating]]) – Cumulative transition-probability matrix of shape(N, N)whereNis the number of prototypical movements.pm_index (
ndarray[tuple[Any,...],dtype[floating]]) – Row-sorted PM index matrix of shape(N, N). Each row maps cumulative-probability columns back to PM identifiers.velocity_array (
ndarray[tuple[Any,...],dtype[floating]]) – Array of shape(N, 3)holding[thrust, slip, yaw]velocities for each PM (units: mm s⁻¹ / rad s⁻¹).n_trials (
int) – Number of independent simulation trials executed bysimulate_multiple().border (
float) – Half-width of the square toroidal arena (mm).max_steps (
int) – Maximum number of PM steps per trial.total_food (
int) – Number of food items scattered in the arena at the start of each trial.food_mode (
str) – Food-distribution mode —'random'or'clustered'.condition (
str) – Sensory condition —'dark'(tactile body-overlap detection) or'light'(visual detection within a 20 mm radius).
- food_found_total
Number of food items collected in the most recent single trial.
- all_performed_pms
List of PM indices visited during the most recent trial.
- psi_angles
Drift (ψ) angles between body heading and trajectory direction.
Example
>>> import numpy as np >>> from satyre import MarkovWalker >>> trans = np.eye(5, dtype=float) # dummy identity >>> trans = np.cumsum(trans, axis=1) >>> pm_idx = np.tile(np.arange(5), (5, 1)).astype(float) >>> velos = np.random.randn(5, 3) * 0.5 >>> walker = MarkovWalker(trans, pm_idx, velos, ... max_steps=100, n_trials=2) >>> walker.simulate()
- simulate()[source]
Run a single foraging trial.
Resets the agent, scatters food, then steps through PMs until max_steps is reached. Populates
food_found_totalandpsi_angles.- Return type:
- simulate_multiple()[source]
Run n_trials independent trials and collect results.
- Return type:
dict[str,ndarray[tuple[Any,...],dtype[TypeVar(_ScalarT, bound=generic)]]]- Returns:
Dictionary with the following keys (each value is an
ndarrayindexed by trial number). Column count is determined by the longest trial (hyperspace wrapping can add sub-steps); shorter trials are NaN-padded.food_found— shape(n_trials,)step_sizes— shape(n_trials, n_cols)psi_angles— shape(n_trials, n_psi)position_x— shape(n_trials, n_cols)position_y— shape(n_trials, n_cols)head_x,head_y,tail_x,tail_y
LevyWalker
- class satyre.simulation.levy_walker.LevyWalker(cauchy_alpha=1.0, *, n_trials=1000, border=10000.0, mode='cauchy', max_steps=1000, total_food=10000, food_mode='random')[source]
Bases:
objectSimulate Lévy-flight or random-walk foraging in a toroidal arena.
The agent draws step sizes from either a Cauchy-derived heavy-tailed distribution (Lévy flight) or a Gaussian (uniform random walk), chooses a uniformly random direction, and checks for food overlap after each step.
- Parameters:
cauchy_alpha (
float) – Shape parameter for the Cauchy step-size distribution. Higher values produce shorter tails. Ignored when mode is'uniform'.n_trials (
int) – Number of independent simulation trials executed bysimulate_multiple().border (
float) – Half-width of the square toroidal arena (mm).mode (
str) – Step-size distribution —'cauchy'for Lévy flight or'uniform'for Gaussian random walk.max_steps (
int) – Maximum number of steps per trial.total_food (
int) – Number of food items placed at the start of each trial.food_mode (
str) – Food distribution —'random'or'clustered'.
- food_found_total
Items collected in the most recent single trial.
- step_size_arr
Step-size array from the most recent trial.
Example
>>> from satyre import LevyWalker >>> walker = LevyWalker(cauchy_alpha=1.5, mode='cauchy', ... max_steps=500, n_trials=10) >>> walker.simulate() >>> print(walker.food_found_total)
- simulate()[source]
Run a single foraging trial.
Resets the agent, scatters food, steps until max_steps, and populates
food_found_total.- Return type:
- simulate_multiple()[source]
Run n_trials independent trials.
- Returns:
food_found— shape(n_trials,)step_sizes— shape(n_trials, n_cols)
Column count n_cols is determined by the longest trial (hyperspace wrapping can add sub-steps beyond max_steps). Shorter trials are NaN-padded.
- Return type:
dict[str,ndarray[tuple[Any,...],dtype[TypeVar(_ScalarT, bound=generic)]]]