зеркало из
https://github.com/docxology/cognitive.git
synced 2025-10-29 12:16:04 +02:00
164 строки
5.3 KiB
Python
164 строки
5.3 KiB
Python
"""
|
|
Main entry point for the ant colony simulation.
|
|
"""
|
|
|
|
import argparse
|
|
import yaml
|
|
import numpy as np
|
|
from visualization.renderer import SimulationRenderer
|
|
from agents.nestmate import Nestmate, Position
|
|
from dataclasses import dataclass
|
|
from typing import List
|
|
|
|
@dataclass
|
|
class FoodSource:
|
|
"""Represents a food source in the environment."""
|
|
position: Position
|
|
size: float
|
|
value: float
|
|
remaining: float
|
|
|
|
@dataclass
|
|
class Obstacle:
|
|
"""Represents an obstacle in the environment."""
|
|
position: Position
|
|
size: float
|
|
|
|
class Simulation:
|
|
"""Main simulation class."""
|
|
|
|
def __init__(self, config_path: str):
|
|
"""Initialize simulation with configuration."""
|
|
with open(config_path, 'r') as f:
|
|
self.config = yaml.safe_load(f)
|
|
|
|
# Set random seed
|
|
np.random.seed(self.config['simulation']['random_seed'])
|
|
|
|
# Initialize environment
|
|
self.env_size = self.config['environment']['size']
|
|
self.nest_location = self.config['environment']['nest_location']
|
|
|
|
# Initialize agents
|
|
self.agents = self._create_agents()
|
|
|
|
# Initialize resources
|
|
self.food_sources = self._create_food_sources()
|
|
self.obstacles = self._create_obstacles()
|
|
|
|
# Initialize pheromone grids
|
|
self.pheromones = {
|
|
'food': np.zeros(self.env_size),
|
|
'home': np.zeros(self.env_size)
|
|
}
|
|
|
|
# Setup visualization if enabled
|
|
if self.config['visualization']['enabled']:
|
|
self.renderer = SimulationRenderer(self.config)
|
|
else:
|
|
self.renderer = None
|
|
|
|
def _create_agents(self) -> List[Nestmate]:
|
|
"""Create initial population of agents."""
|
|
agents = []
|
|
for _ in range(self.config['colony']['initial_population']):
|
|
# Start agents near nest
|
|
x = self.nest_location[0] + np.random.normal(0, 2)
|
|
y = self.nest_location[1] + np.random.normal(0, 2)
|
|
theta = np.random.uniform(0, 2 * np.pi)
|
|
|
|
agent = Nestmate(self.config['agent'])
|
|
agent.position = Position(x, y, theta)
|
|
agents.append(agent)
|
|
|
|
return agents
|
|
|
|
def _create_food_sources(self) -> List[FoodSource]:
|
|
"""Create initial food sources."""
|
|
sources = []
|
|
for _ in range(self.config['environment']['food_sources']['count']):
|
|
x = np.random.uniform(0, self.env_size[0])
|
|
y = np.random.uniform(0, self.env_size[1])
|
|
size = np.random.uniform(*self.config['environment']['food_sources']['size_range'])
|
|
value = np.random.uniform(*self.config['environment']['food_sources']['value_range'])
|
|
|
|
source = FoodSource(
|
|
position=Position(x, y, 0),
|
|
size=size,
|
|
value=value,
|
|
remaining=value
|
|
)
|
|
sources.append(source)
|
|
|
|
return sources
|
|
|
|
def _create_obstacles(self) -> List[Obstacle]:
|
|
"""Create initial obstacles."""
|
|
obstacles = []
|
|
for _ in range(self.config['environment']['obstacles']['count']):
|
|
x = np.random.uniform(0, self.env_size[0])
|
|
y = np.random.uniform(0, self.env_size[1])
|
|
size = np.random.uniform(*self.config['environment']['obstacles']['size_range'])
|
|
|
|
obstacle = Obstacle(
|
|
position=Position(x, y, 0),
|
|
size=size
|
|
)
|
|
obstacles.append(obstacle)
|
|
|
|
return obstacles
|
|
|
|
def update(self) -> None:
|
|
"""Update simulation state for one timestep."""
|
|
dt = self.config['simulation']['timestep']
|
|
|
|
# Update agents
|
|
world_state = {
|
|
'agents': self.agents,
|
|
'resources': self.food_sources,
|
|
'obstacles': self.obstacles,
|
|
'pheromones': self.pheromones
|
|
}
|
|
|
|
for agent in self.agents:
|
|
agent.update(dt, world_state)
|
|
|
|
# Update pheromones
|
|
decay = self.config['environment']['pheromone_decay']
|
|
self.pheromones['food'] *= decay
|
|
self.pheromones['home'] *= decay
|
|
|
|
# Update visualization
|
|
if self.renderer and self.config['visualization']['enabled']:
|
|
self.renderer.update(world_state)
|
|
|
|
def run(self) -> None:
|
|
"""Run the simulation."""
|
|
max_steps = self.config['simulation']['max_steps']
|
|
|
|
try:
|
|
for step in range(max_steps):
|
|
self.update()
|
|
|
|
if step % 100 == 0:
|
|
print(f"Step {step}/{max_steps}")
|
|
|
|
except KeyboardInterrupt:
|
|
print("\nSimulation interrupted by user")
|
|
|
|
finally:
|
|
if self.renderer:
|
|
self.renderer.show()
|
|
|
|
def main():
|
|
"""Main entry point."""
|
|
parser = argparse.ArgumentParser(description="Ant Colony Simulation")
|
|
parser.add_argument('--config', type=str, required=True,
|
|
help='Path to configuration file')
|
|
args = parser.parse_args()
|
|
|
|
simulation = Simulation(args.config)
|
|
simulation.run()
|
|
|
|
if __name__ == '__main__':
|
|
main() |