Added early stopping to the headless simulation.
Some checks failed
Build Simulation and Test / Run All Tests (push) Failing after 14m52s

This commit is contained in:
Samuel Bargallo 2025-11-11 19:47:02 +00:00
parent b87106f8f3
commit 9b009ef593
4 changed files with 31 additions and 4 deletions

View File

@ -68,6 +68,7 @@ class HeadlessConfig:
# Simulation settings
max_ticks: Optional[int] = None
max_duration: Optional[float] = None # seconds
early_stop: bool = False # Stop when 0 cells remaining
# Output settings
output: OutputConfig = field(default_factory=OutputConfig)

View File

@ -35,7 +35,7 @@
"starting_energy": 500,
"interaction_radius": 50,
"drag_coefficient": 0.02,
"energy_cost_base": 1.5,
"energy_cost_base": 1.4,
"neural_network_complexity_cost": 0.05,
"movement_cost": 0.25,
"food_energy_value": 140,

View File

@ -33,6 +33,7 @@ class HeadlessConfig:
evolution_interval: int = 1000
output_formats: List[str] = None # ['json', 'csv']
real_time: bool = False # Whether to run in real-time or as fast as possible
early_stop: bool = False # Stop when 0 cells remaining
def __post_init__(self):
if self.output_formats is None:
@ -121,14 +122,14 @@ class HeadlessSimulationEngine:
unit=unit,
desc="Simulation",
leave=True, # Keep the bar when done
bar_format='{l_bar}{bar}| {n_fmt}/{total_fmt} [{elapsed}<{remaining}, {rate_fmt}]'
bar_format='{l_bar}{bar}| {n_fmt}/{total_fmt} [{elapsed}<{remaining}, {rate_fmt}] {postfix}'
)
else:
self.progress_bar = tqdm(
unit='ticks',
desc="Simulation",
leave=True,
bar_format='{l_bar}{bar}| {n_fmt} [{elapsed}, {rate_fmt}]'
bar_format='{l_bar}{bar}| {n_fmt} [{elapsed}, {rate_fmt}] {postfix}'
)
def _update_progress_bar(self):
@ -141,6 +142,10 @@ class HeadlessSimulationEngine:
tps = self.simulation_core.state.actual_tps
elapsed = current_time - self.start_time
# Get current cell count
world_state = self.simulation_core.get_world_state()
cell_count = world_state.get('entity_counts', {}).get('cells', 0)
if TQDM_AVAILABLE and self.progress_bar:
# Use tqdm progress bar
if self.config.max_ticks:
@ -149,6 +154,7 @@ class HeadlessSimulationEngine:
self.progress_bar.n = progress
self.progress_bar.set_postfix({
'TPS': f'{tps:.1f}',
'Cells': cell_count,
'Files': self.files_written
})
elif self.config.max_duration:
@ -157,6 +163,7 @@ class HeadlessSimulationEngine:
self.progress_bar.n = int(progress)
self.progress_bar.set_postfix({
'TPS': f'{tps:.1f}',
'Cells': cell_count,
'Files': self.files_written,
'Tick': current_tick
})
@ -165,6 +172,7 @@ class HeadlessSimulationEngine:
self.progress_bar.n = current_tick
self.progress_bar.set_postfix({
'TPS': f'{tps:.1f}',
'Cells': cell_count,
'Files': self.files_written
})
@ -295,6 +303,14 @@ class HeadlessSimulationEngine:
print(f"Reached max duration: {self.config.max_duration} seconds")
return True
# Check early stopping condition (0 cells remaining)
if self.config.early_stop:
world_state = self.simulation_core.get_world_state()
cell_count = world_state.get('entity_counts', {}).get('cells', 0)
if cell_count == 0:
print(f"Early stopping: 0 cells remaining at tick {self.simulation_core.state.total_ticks}")
return True
return False
def _collect_data(self):

View File

@ -81,6 +81,11 @@ def main():
action="store_true",
help="Create sample configuration files and exit"
)
parser.add_argument(
"--early-stop",
action="store_true",
help="Stop simulation when there are 0 cells remaining"
)
args = parser.parse_args()
@ -140,6 +145,10 @@ def main():
headless_config.output.collect_entities = True
headless_config.output.collect_evolution = True
# Set early stopping flag
if args.early_stop:
headless_config.early_stop = True
except Exception as e:
print(f"Error loading configuration: {e}")
sys.exit(1)
@ -157,7 +166,8 @@ def main():
entities_interval=headless_config.output.entities_interval,
evolution_interval=headless_config.output.evolution_interval,
output_formats=headless_config.output.formats,
real_time=headless_config.output.real_time
real_time=headless_config.output.real_time,
early_stop=headless_config.early_stop
)
# Create and run simulation