Some checks failed
Build Simulation and Test / Run All Tests (push) Failing after 2m35s
94 lines
3.5 KiB
Python
94 lines
3.5 KiB
Python
from world.base.neural import FlexibleNeuralNetwork
|
|
from config.constants import MAX_VELOCITY, MAX_ROTATIONAL_VELOCITY
|
|
from world.behavioral import BehavioralModel
|
|
|
|
|
|
class CellBrain(BehavioralModel):
|
|
"""
|
|
Enhanced CellBrain using a flexible neural network with input normalization.
|
|
"""
|
|
|
|
def __init__(self, neural_network=None, input_ranges=None):
|
|
super().__init__()
|
|
|
|
# Define input and output keys
|
|
self.input_keys = ['distance', 'angle', 'current_speed', 'current_angular_velocity']
|
|
self.output_keys = ['linear_acceleration', 'angular_acceleration']
|
|
|
|
# Initialize inputs and outputs
|
|
self.inputs = {key: 0.0 for key in self.input_keys}
|
|
self.outputs = {key: 0.0 for key in self.output_keys}
|
|
|
|
# Set input ranges for normalization
|
|
default_ranges = {
|
|
'distance': (0, 50),
|
|
'angle': (-180, 180),
|
|
'current_speed': (-MAX_VELOCITY, MAX_VELOCITY),
|
|
'current_angular_velocity': (-MAX_ROTATIONAL_VELOCITY, MAX_ROTATIONAL_VELOCITY)
|
|
}
|
|
self.input_ranges = input_ranges if input_ranges is not None else default_ranges
|
|
|
|
# Use provided network or create new one
|
|
if neural_network is None:
|
|
self.neural_network = FlexibleNeuralNetwork(
|
|
input_size=len(self.input_keys),
|
|
output_size=len(self.output_keys)
|
|
)
|
|
else:
|
|
self.neural_network = neural_network
|
|
|
|
def _normalize_input(self, key, value):
|
|
min_val, max_val = self.input_ranges.get(key, (0.0, 1.0))
|
|
# Avoid division by zero
|
|
if max_val == min_val:
|
|
return 0.0
|
|
# Normalize to [-1, 1]
|
|
return 2 * (value - min_val) / (max_val - min_val) - 1
|
|
|
|
def tick(self, input_data) -> dict:
|
|
"""
|
|
Process inputs through neural network and produce outputs.
|
|
|
|
:param input_data: Dictionary containing input values
|
|
:return: Dictionary with output values
|
|
"""
|
|
# Update internal input state
|
|
for key in self.input_keys:
|
|
self.inputs[key] = input_data.get(key, 0.0)
|
|
|
|
# Normalize inputs
|
|
input_array = [self._normalize_input(key, self.inputs[key]) for key in self.input_keys]
|
|
|
|
# Process through neural network
|
|
output_array = self.neural_network.forward(input_array)
|
|
|
|
# Map outputs back to dictionary
|
|
self.outputs = {
|
|
key: output_array[i] if i < len(output_array) else 0.0
|
|
for i, key in enumerate(self.output_keys)
|
|
}
|
|
|
|
return self.outputs.copy()
|
|
|
|
def mutate(self, mutation_rate=0.1):
|
|
"""
|
|
Create a mutated copy of this CellBrain.
|
|
|
|
:param mutation_rate: Rate of mutation for the neural network
|
|
:return: New CellBrain with mutated neural network
|
|
"""
|
|
mutated_network = self.neural_network.mutate(mutation_rate)
|
|
return CellBrain(neural_network=mutated_network, input_ranges=self.input_ranges.copy())
|
|
|
|
def get_network_info(self):
|
|
"""Get information about the underlying neural network."""
|
|
return self.neural_network.get_structure_info()
|
|
|
|
def __repr__(self):
|
|
inputs = {key: round(value, 5) for key, value in self.inputs.items()}
|
|
outputs = {key: round(value, 5) for key, value in self.outputs.items()}
|
|
network_info = self.get_network_info()
|
|
|
|
return (f"CellBrain(inputs={inputs}, outputs={outputs}, "
|
|
f"network_layers={network_info['layer_sizes']}, "
|
|
f"connections={network_info['total_connections']})") |