Daniel Ari Friedman ca645167d2 In Stream
2025-02-07 13:49:44 -08:00

120 строки
3.6 KiB
Python

"""
Main simulation runner for the Path Network.
Orchestrates the interaction between the network of agents and environmental dynamics.
"""
import numpy as np
from typing import Dict, List, Optional, Tuple
from dataclasses import dataclass
from ..core.network import PathNetwork, NetworkConfig
from ..core.dynamics import EnvironmentalDynamics, DynamicsConfig
from ..utils.visualization import NetworkVisualizer
@dataclass
class SimulationConfig:
"""Configuration for the simulation."""
network_config: NetworkConfig
dynamics_config: DynamicsConfig
num_steps: int = 1000
save_interval: int = 10
visualization_interval: int = 50
class SimulationRunner:
"""
Main simulation runner that coordinates the network of agents
and environmental dynamics.
"""
def __init__(
self,
config: SimulationConfig,
visualizer: Optional[NetworkVisualizer] = None
):
self.config = config
self.network = PathNetwork(config.network_config)
self.dynamics = EnvironmentalDynamics(config.dynamics_config)
self.visualizer = visualizer
self.current_step = 0
self.history: List[Dict] = []
def step(self) -> Dict:
"""
Perform one step of the simulation.
Returns:
Dict containing the current state of the simulation
"""
# Get current water level
water_level = self.dynamics.step()
# Update network
agent_heights = self.network.step(water_level)
# Record state
state = {
'step': self.current_step,
'water_level': water_level,
'agent_heights': agent_heights
}
if self.current_step % self.config.save_interval == 0:
self.history.append(state)
# Visualize if needed
if (
self.visualizer is not None and
self.current_step % self.config.visualization_interval == 0
):
self.visualizer.update(self.network, water_level)
self.current_step += 1
return state
def run(self, num_steps: Optional[int] = None) -> List[Dict]:
"""
Run the simulation for a specified number of steps.
Args:
num_steps: Number of steps to run (default: config.num_steps)
Returns:
List of recorded states
"""
steps_to_run = num_steps or self.config.num_steps
for _ in range(steps_to_run):
self.step()
return self.history
def add_perturbation(
self,
magnitude: float,
duration: float,
decay: float = 1.0
) -> None:
"""Add a perturbation to the environmental dynamics."""
self.dynamics.add_perturbation(magnitude, duration, decay)
def get_network_state(self) -> Tuple[Dict[int, float], float]:
"""
Get the current state of the network and environment.
Returns:
Tuple of agent heights and current water level
"""
_, heights = self.network.get_network_state()
water_level = self.dynamics.history[-1] if self.dynamics.history else 0.0
return heights, water_level
def get_history(self) -> List[Dict]:
"""Get the simulation history."""
return self.history.copy()
def reset(self) -> None:
"""Reset the simulation to initial state."""
self.current_step = 0
self.history.clear()
self.dynamics.reset()
# Note: Network is not reset as it maintains its learned structure