base/GAP.md
This guide explains how to use the smile.gap package for genetic algorithms in SMILE.
smile.gap provides:
Chromosome<T>: the contract for candidate solutions.LamarckianChromosome<T>: chromosome with optional local-search steps.GeneticAlgorithm<T>: the evolution engine.BitString: built-in binary chromosome implementation.Selection: parent-selection strategies.Crossover: crossover strategies for BitString.Fitness<T>: fitness scoring contract (used by BitString).The framework assumes higher fitness is better.
A chromosome must implement:
fitness(): returns quality score.newInstance(): creates a random chromosome.crossover(T other): creates two children.mutate(): applies mutation.compareTo(...): orders by fitness (ascending for internal sorting).For BitString, fitness is typically provided via Fitness<BitString>:
double score(BitString chromosome)Available selection strategies:
Selection.RouletteWheel()Selection.ScaledRouletteWheel()Selection.Rank()Selection.Tournament(size, probability) (default choice in many scenarios)BitString only)Available crossover types:
Crossover.SINGLE_POINTCrossover.TWO_POINTCrossover.UNIFORMimport smile.gap.*;
public class GapQuickStart {
static class OnesFitness implements Fitness<BitString> {
@Override
public double score(BitString chromosome) {
int sum = 0;
for (byte bit : chromosome.bits()) {
sum += bit;
}
return sum;
}
}
public static void main(String[] args) {
int populationSize = 100;
int chromosomeLength = 64;
BitString[] seeds = new BitString[populationSize];
Fitness<BitString> fitness = new OnesFitness();
for (int i = 0; i < populationSize; i++) {
seeds[i] = new BitString(
chromosomeLength,
fitness,
Crossover.TWO_POINT,
0.9, // crossover rate
0.01 // mutation rate
);
}
GeneticAlgorithm<BitString> ga = new GeneticAlgorithm<>(
seeds,
Selection.Tournament(3, 0.95),
1 // elitism
);
BitString best = ga.evolve(200, chromosomeLength);
System.out.println("Best fitness: " + best.fitness());
System.out.println("Best chromosome: " + best);
}
}
If BitString is not suitable, implement Chromosome<T> directly.
Checklist:
fitness() deterministic for a fixed chromosome state.crossover() returns new child objects.compareTo so better chromosomes compare larger.If your chromosome supports local improvement, implement LamarckianChromosome<T>.
GeneticAlgorithm can apply local search steps during evaluation:
GeneticAlgorithm<MyChromosome> ga = new GeneticAlgorithm<>(seeds);
ga.setLocalSearchSteps(5); // 0 disables local search
MyChromosome best = ga.evolve(500);
elitism must satisfy: 0 <= elitism < population.length.generation in evolve(...) must be greater than 0.setLocalSearchSteps(t) requires t >= 0.BitString requires valid rates in [0, 1].Reasonable defaults to start with:
Tournament(3, 0.95)0.8 - 0.950.005 - 0.021 - 250 - 200 (problem dependent)Tune these based on convergence speed and solution quality.
Use one or both:
evolve(maxGenerations)evolve(maxGenerations, threshold)The second form stops early if the threshold is reached.
GeneticAlgorithm logs per-generation fitness statistics (best and average).
This is useful for tracking convergence and diagnosing stagnation.
crossover() instead of new children.When adding a custom chromosome, test:
crossover() shape and invariants.mutate() behavior under fixed RNG seeds.fitness() consistency/caching behavior.SMILE — © 2010-2026 Haifeng Li. GNU GPL licensed.