
Shorelark Evolution Simulation
Overview
Shorelark is a sophisticated evolution simulation that demonstrates how artificial life can emerge through the combination of neural networks and genetic algorithms. Built entirely from scratch in Rust and compiled to WebAssembly, this project showcases birds learning to navigate their environment and find food through evolutionary processes.
This project was developed following Patryk Wychowaniec's comprehensive tutorial series "Learning to Fly," which provides an in-depth exploration of implementing AI concepts from first principles. The simulation features autonomous agents (birds) that evolve their behavior over generations, becoming increasingly efficient at survival tasks.
The project demonstrates the power of combining multiple AI techniques: feedforward neural networks serve as bird brains, genetic algorithms drive evolution, and sophisticated vision systems enable environmental awareness. All components are implemented from mathematical foundations without external AI libraries.
Key Features
Neural Network Engine
- Custom feedforward neural network implementation with configurable layer topology
- ReLU activation functions with weight randomization and propagation
- Comprehensive test coverage with mathematical verification
- Efficient weight serialization for genetic algorithm integration
Genetic Algorithm
- Roulette wheel selection based on fitness scores (food consumption)
- Uniform crossover combining neural network weights from two parents
- Gaussian mutation introducing controlled random variations
- Fitness-based evolution with comprehensive statistics tracking
Vision System
- Sophisticated bird vision with configurable field of view and range
- Multiple photoreceptor cells for detailed environmental perception
- Distance-based energy calculation using trigonometric mathematics
- Parameterized testing framework for vision system verification
Real-time Simulation
- Smooth 60 FPS rendering using HTML5 Canvas API
- Interactive visualization with rotating triangular birds and circular food
- Fast-forward training mode for accelerated evolution
- Real-time statistics tracking with min/max/average fitness scores
WebAssembly Integration
- Seamless Rust-to-web compilation with wasm-bindgen
- Type-safe boundaries between Rust simulation and JavaScript UI
- Optimized performance for real-time execution
- Memory-efficient data structures for large populations
Architecture
Multi-Crate Workspace Structure
lib-neural-network
- Custom feedforward neural network implementation
- Layer and neuron abstractions with configurable topology
- Weight serialization and deserialization for genetic algorithms
- Comprehensive test suite with floating-point precision handling
lib-genetic-algorithm
- Generic genetic algorithm implementation with trait-based design
- Pluggable selection, crossover, and mutation strategies
- Statistics generation with fitness tracking
- Parameterized testing for algorithm verification
lib-simulation
- Core simulation engine with physics and collision detection
- Animal and food entity management
- Eye implementation with trigonometric field-of-view calculations
- Brain integration connecting vision to neural network decision-making
lib-simulation-wasm
- WebAssembly bindings and JavaScript interop layer
- Data conversion between Rust and JavaScript types
- Performance-optimized simulation stepping
- Statistics aggregation and formatting
Technical Implementation
The Shorelark simulation demonstrates advanced systems programming concepts implemented in Rust, showcasing both performance optimization and mathematical precision.
Neural Network Architecture
Birds' brains are implemented as feedforward neural networks with a carefully designed three-layer topology:
// Network topology for bird brains
let brain = nn::Network::random(rng, &[
// Input Layer: Eye cells (vision data)
nn::LayerTopology { neurons: eye.cells() },
// Hidden Layer: Processing layer
nn::LayerTopology { neurons: 2 * eye.cells() },
// Output Layer: Speed and rotation control
nn::LayerTopology { neurons: 2 },
]);
Vision System Mathematics
The eye implementation uses trigonometry to calculate what each bird sees, with sophisticated field-of-view calculations:
// Calculate if food is within field of view
let vec = food.position - bird.position;
let distance = vec.norm();
let angle = na::Rotation2::rotation_between(&na::Vector2::y(), &vec).angle();
let angle = angle - bird.rotation.angle();
let angle = na::wrap(angle, -PI, PI);
// Determine which eye cell sees the food
if angle >= -self.fov_angle / 2.0 && angle <= self.fov_angle / 2.0 {
let cell_index = ((angle + self.fov_angle / 2.0) / self.fov_angle) * self.cells as f32;
let energy = (self.fov_range - distance) / self.fov_range;
cells[cell_index as usize] += energy;
}
Genetic Algorithm Process
Evolution occurs through a sophisticated genetic algorithm with three main phases: selection chooses parents based on fitness, crossover combines neural network weights, and mutation introduces controlled variations.
WebAssembly Compilation
The Rust simulation compiles to WebAssembly using wasm-pack, enabling high-performance execution in web browsers while maintaining type safety across the Rust-JavaScript boundary.
Evolution Process
The simulation follows a structured evolutionary process:
- Initialization: A population of birds is created with randomized neural network weights and random positions in the environment.
- Simulation Phase: Birds navigate the environment for 2500 simulation steps, using their vision to detect food and their neural networks to make movement decisions.
- Fitness Evaluation: Each bird's fitness is measured by the amount of food consumed during the generation.
- Selection: Roulette wheel selection chooses parent birds based on fitness scores, giving higher-performing birds better chances of reproduction.
- Crossover: Uniform crossover combines neural network weights from two parents to create offspring with mixed traits.
- Mutation: Gaussian mutation introduces small random changes to prevent local optima and maintain genetic diversity.
- Population Replacement: The new generation replaces the old one, and the process repeats.
- Statistics Tracking: Each generation's performance is tracked with minimum, maximum, and average fitness scores.
Learning Outcomes
Technical Skills Demonstrated
- Systems Programming: Building complex, multi-component systems in Rust with proper error handling and memory safety
- AI Implementation: Creating neural networks and genetic algorithms from mathematical foundations
- WebAssembly: Compiling Rust to WASM for high-performance web applications
- Mathematical Computing: Implementing trigonometry, linear algebra, and statistical calculations
- Testing Strategies: Developing comprehensive test suites for mathematical and visual systems
- Performance Optimization: Optimizing simulation performance for real-time execution
AI & Machine Learning Concepts
- Neural Network Architecture: Understanding feedforward networks, activation functions, and weight propagation
- Evolutionary Computation: Implementing selection pressure, genetic operators, and fitness landscapes
- Emergent Behavior: Observing complex behaviors arising from simple rules and evolutionary pressure
- Simulation Design: Creating realistic physics and environmental interactions
Tutorial Series Reference
Based on "Learning to Fly" Tutorial Series
This project follows Patryk Wychowaniec's comprehensive 4-part tutorial series:
- Part 1: The Domain - Introduction to neural networks and genetic algorithms
- Part 2: The Neural Network - Building feedforward networks from scratch
- Part 3: The Genetic Algorithm - Implementing selection, crossover, and mutation
- Part 4: The User Interface - WebAssembly integration and visualization
The tutorial provides an excellent foundation for understanding how to implement AI concepts from first principles, with detailed explanations of mathematical concepts and practical Rust programming techniques.
Future Enhancements
Potential Improvements
- Parameter Optimization: Implement automated hyperparameter tuning using grid search or Bayesian optimization
- Complex Environments: Add obstacles, predators, and varying terrain for more challenging evolutionary pressures
- Advanced Genetics: Implement sexual selection, speciation, and more sophisticated genetic operators
- Analytics Dashboard: Create visualization tools for analyzing evolutionary trends and population dynamics
- Multi-objective Evolution: Evolve for multiple fitness criteria simultaneously
- Neural Architecture Evolution: Allow the network topology itself to evolve