https://github.com/squeakycheese75/evo-kit
A lightweight, type-safe genetic algorithm toolkit for Go.
https://github.com/squeakycheese75/evo-kit
evolutionary-algorithm generics genetic-algorithm go golang heuristics optimization search
Last synced: 18 days ago
JSON representation
A lightweight, type-safe genetic algorithm toolkit for Go.
- Host: GitHub
- URL: https://github.com/squeakycheese75/evo-kit
- Owner: squeakycheese75
- License: mit
- Created: 2026-06-02T11:40:34.000Z (27 days ago)
- Default Branch: main
- Last Pushed: 2026-06-04T10:01:47.000Z (25 days ago)
- Last Synced: 2026-06-04T10:05:07.966Z (25 days ago)
- Topics: evolutionary-algorithm, generics, genetic-algorithm, go, golang, heuristics, optimization, search
- Language: Go
- Homepage:
- Size: 16.6 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# evo-kit
A lightweight, type-safe genetic algorithm toolkit for Go.
Evolve solutions to optimization problems using Go generics.
## Why?
Many optimization problems can be expressed as:
- Generate a candidate solution
- Score how good it is
- Mutate and combine candidates
- Repeat until a good solution is found
evo-kit handles the evolutionary loop so you can focus on the problem itself.
## Features
- Generic candidate types using Go generics
- Tournament and roulette-wheel selection
- Maximization and minimization support
- Elitism
- Parallel fitness evaluation with configurable workers
- Island model evolution
- Configurable migration between islands
- Optional parallel island execution
- Target score stopping
- Stagnation-based stopping
- Generation statistics and history tracking
- Extensible architecture for custom evolutionary operators
## Installation
```bash
go get github.com/squeakycheese75/evo-kit
```
## Quick Example
```go
result, err := ga.Run(ga.Config[string]{
PopulationSize: 100,
Generations: 500,
MutationRate: 0.1,
CrossoverRate: 0.7,
EliteCount: 2,
Generate: func(rng *rand.Rand) string {
return randomString(rng, len(target))
},
Fitness: func(candidate string) float64 {
return score(candidate, target)
},
Mutate: mutate,
Crossover: crossover,
})
if err != nil {
log.Fatal(err)
}
fmt.Printf("best=%q score=%.0f\n",
result.Best,
result.BestScore,
)
```
Example output:
```text
best="hello world" score=11
```
## Island Evolution
```go
cfg := ga.Config[Solution]{
PopulationSize: 100,
Generations: 500,
Islands: &ga.IslandConfig{
Count: 4,
MigrationInterval: 25,
MigrationCount: 2,
Parallel: true,
},
Generate: generate,
Fitness: fitness,
Mutate: mutate,
Crossover: crossover,
}
result, err := ga.Run(cfg)
```
## Included Examples
| Example | Description |
|----------|-------------|
| string_match | Evolve a string until it matches a target |
| string_match_islands | Evolve a string using island-model evolution |
| knapsack | Maximize value within a weight constraint |
| query_plan | Optimize execution order and parallelism |
Run an example:
```bash
go run ./examples/query_plan
```
Example output:
```text
gen=0 cost=9522.53
gen=31 cost=7645.53
best cost: 7645.53
improvement: 19.71%
stop reason: stagnated
```
Run the island example:
```bash
go run ./examples/string_match_islands
```
## Configuration
```go
cfg := ga.Config[Candidate]{
PopulationSize: 200,
Generations: 500,
MutationRate: 0.1,
CrossoverRate: 0.7,
EliteCount: 2,
Direction: ga.Minimize,
MaxStagnation: 50,
Workers: runtime.NumCPU(),
}
```
## Parallel Fitness Evaluation
Fitness evaluation can be parallelised with `Workers`.
```go
cfg := ga.Config[Candidate]{
PopulationSize: 500,
Generations: 200,
Workers: runtime.NumCPU(),
Generate: generate,
Fitness: expensiveFitness,
Mutate: mutate,
Crossover: crossover,
}
```
A value of `0` or `1` scores candidates sequentially.
When `Workers > 1`, the fitness function must be safe to call concurrently.
Typical scaling for expensive fitness functions:
| Workers | Time |
|----------|------|
| 1 | 1.18s |
| 2 | 590ms |
| 4 | 296ms |
| 8 | 154ms |
## When should I use a genetic algorithm?
Genetic algorithms work well when:
- Exhaustive search is too expensive
- The search space is large
- An approximate solution is acceptable
- The fitness function is easy to evaluate
Examples include scheduling, routing, portfolio optimization, query planning, game AI, and parameter tuning.