Written during my sophomore year, this library was an exploration into Evolutionary Algorithms applied to Reinforcement Learning tasks (specifically Atari games).
Concept
While standard Cartesian Genetic Programming (CGP) relies heavily on mutation, this project attempted to hybridize CGP with NEAT (NeuroEvolution of Augmenting Topologies) concepts to protect topological innovation through speciation.
The goal was to evolve graph-based programs that could learn control policies without gradient-based optimization.
Technical Highlights
- Graph-based Crossover: Implemented custom crossover operators like
subgraph_crossoverandaligned_node_crossoverto handle the destructive nature of mating graph structures. - Speciation: Adapted NEAT’s compatibility distance metric to CGP graphs to maintain population diversity and prevent premature convergence.
- Active Gene Tracking: Differentiated between “active” nodes (those contributing to output) and “junk DNA,” optimizing the mutation logic to focus on phenotypic changes.
Retrospective (2025)
Looking back, this codebase captures a transitional moment where I was moving from scripting to library design.
- The Ambition: Attempting to merge NEAT’s speciation dynamics with CGP’s grid-based topology was theoretically distinct and arguably ahead of my software engineering skills at the time.
- The “Legacy” Code: The project relies on the now-deprecated Julia v0.6 and uses
eval(parse(...))patterns for configuration (a significant performance anti-pattern in modern Julia). - The Lesson: It taught me the difficulty of designing genetic operators that respect topological constraints, a lesson that informs my current understanding of optimization in structured spaces.
