|
3 | 3 | This file helps AI coding agents use this library correctly. It covers decision |
4 | 4 | guidance, API reference, gotchas, and copy-paste templates. |
5 | 5 |
|
6 | | -**Read the Gotchas section before writing code.** Gotchas 1, 2, 3, and 7 cause |
| 6 | +**Read the Gotchas section before writing code.** Gotchas 1, 2, and 5 cause |
7 | 7 | compilation or runtime failures that are hard to debug after the fact. |
8 | 8 |
|
9 | 9 | ## Quick Start |
@@ -84,17 +84,18 @@ When implementing `calculate_for_chromosome`, access genes via `chromosome.genes |
84 | 84 | | `BinaryGenotype` | All | `CrossoverUniform` or `CrossoverSinglePoint` | |
85 | 85 | | `ListGenotype<T>` | All | `CrossoverUniform` | |
86 | 86 | | `MultiListGenotype<T>` | All | `CrossoverUniform` | |
87 | | -| `UniqueGenotype<T>` | `CrossoverClone`, `CrossoverRejuvenate` ONLY | `CrossoverClone` | |
88 | | -| `MultiUniqueGenotype<T>` | Point-based + `CrossoverClone`, `CrossoverRejuvenate` (NO gene-based) | `CrossoverSinglePoint` | |
| 87 | +| `UniqueGenotype<T>` | `CrossoverClone`, `CrossoverRejuvenate` ONLY (others are compile errors) | `CrossoverClone` | |
| 88 | +| `MultiUniqueGenotype<T>` | Point-based + `CrossoverClone`, `CrossoverRejuvenate` (gene-based are compile errors) | `CrossoverSinglePoint` | |
89 | 89 | | `RangeGenotype<T>` | All | `CrossoverMultiPoint` | |
90 | 90 | | `MultiRangeGenotype<T>` | All | `CrossoverSingleGene` | |
91 | 91 |
|
92 | | -**WARNING**: `UniqueGenotype` will cause a **runtime panic** with gene-based or |
93 | | -point-based crossovers. Use `CrossoverClone` (clones parents, relies on mutation |
94 | | -for diversity) or `CrossoverRejuvenate` (like Clone but optimized for less memory copying). |
95 | | -`MultiUniqueGenotype` supports point-based crossovers (`CrossoverSinglePoint`, |
96 | | -`CrossoverMultiPoint`) but panics on gene-based ones (`CrossoverUniform`, |
97 | | -`CrossoverSingleGene`, `CrossoverMultiGene`). |
| 92 | +**Compile-time safety**: `UniqueGenotype` does not implement `SupportsGeneCrossover` |
| 93 | +or `SupportsPointCrossover`, so incompatible crossovers are **compile errors**. |
| 94 | +Use `CrossoverClone` (clones parents, relies on mutation for diversity) or |
| 95 | +`CrossoverRejuvenate` (like Clone but optimized for less memory copying). |
| 96 | +`MultiUniqueGenotype` implements `SupportsPointCrossover` only, so gene-based |
| 97 | +crossovers (`CrossoverUniform`, `CrossoverSingleGene`, `CrossoverMultiGene`) are |
| 98 | +compile errors. |
98 | 99 |
|
99 | 100 | ### Which Select? |
100 | 101 |
|
@@ -250,7 +251,7 @@ ExtensionMassDeduplication::new( |
250 | 251 | Required: |
251 | 252 | - `.with_genotype(genotype)` — the search space |
252 | 253 | - `.with_fitness(fitness)` — the evaluation function |
253 | | -- `.with_target_population_size(n)` — number of chromosomes (**defaults to 0, always set this**) |
| 254 | +- `.with_target_population_size(n)` — number of chromosomes (defaults to 100) |
254 | 255 | - `.with_select(select)` — parent selection strategy |
255 | 256 | - `.with_crossover(crossover)` — how parents combine |
256 | 257 | - `.with_mutate(mutate)` — how offspring are varied |
@@ -348,22 +349,20 @@ let (best, _all_runs) = Evolve::builder() |
348 | 349 | HillClimb also supports `.call_repeatedly(n)` and `.call_par_repeatedly(n)`. |
349 | 350 |
|
350 | 351 | Both `.call()` and `.build()` return `Result<_, TryFromEvolveBuilderError>`. |
351 | | -Builder validation catches: missing required fields, incompatible genotype + |
352 | | -crossover combinations, and missing ending conditions. The error message includes |
353 | | -an actionable fix suggestion. |
| 352 | +Builder validation catches: missing required fields and missing ending conditions. |
| 353 | +Incompatible genotype + crossover combinations are caught at compile time via |
| 354 | +trait bounds (`SupportsGeneCrossover`, `SupportsPointCrossover`). The error |
| 355 | +message includes an actionable fix suggestion. |
354 | 356 |
|
355 | 357 | ### Common mistakes |
356 | 358 |
|
357 | 359 | ```rust |
358 | | -// WRONG: UniqueGenotype + CrossoverUniform = RUNTIME PANIC |
| 360 | +// WRONG: UniqueGenotype + CrossoverUniform = COMPILE ERROR |
359 | 361 | // FIX: Use CrossoverClone or CrossoverRejuvenate |
360 | 362 |
|
361 | 363 | // WRONG: No ending condition = COMPILE/BUILD ERROR |
362 | 364 | // FIX: Add .with_max_stale_generations(1000) |
363 | 365 |
|
364 | | -// WRONG: target_population_size not set (defaults to 0) = SILENT FAILURE |
365 | | -// FIX: Add .with_target_population_size(100) |
366 | | - |
367 | 366 | // WRONG: Fitness returns f64 = TYPE ERROR |
368 | 367 | // FIX: Return Some((score / precision) as FitnessValue) |
369 | 368 |
|
@@ -721,13 +720,10 @@ Combine with `max_stale_generations` to trigger phase transitions automatically |
721 | 720 |
|
722 | 721 | ## Gotchas |
723 | 722 |
|
724 | | -1. **UniqueGenotype + standard crossover = runtime panic.** Use `CrossoverClone`. MultiUniqueGenotype supports point-based but not gene-based crossovers. |
725 | | -2. **FitnessValue is isize.** Scale floats manually: `(score / precision) as FitnessValue`. |
726 | | -3. **Ending condition required.** Evolve/HillClimb need at least one of: `target_fitness_score`, `max_stale_generations`, `max_generations`. |
727 | | -4. **Fitness struct must be `Clone + Debug`.** |
728 | | -5. **RangeGenotype requires a type parameter.** Use turbofish: `RangeGenotype::<f64>::builder()`, `RangeGenotype::<i32>::builder()`. |
729 | | -6. **Permutate + RangeGenotype** requires `MutationType::Step`, `StepScaled`, or `Discrete`. |
730 | | -7. **`target_population_size` defaults to 0.** Always set it for Evolve. |
731 | | -8. **Custom Crossover/Mutate/Extension must call `chromosome.reset_metadata(genotype.genes_hashing)`** after modifying genes directly. |
732 | | -9. **Custom Crossover must call `state.population.increment_age()`** on existing chromosomes. |
733 | | -10. **For deterministic tests:** use `.with_rng_seed_from_u64(0)`. Exact results may change between library versions, but deterministic within a version. |
| 723 | +1. **FitnessValue is isize.** Scale floats manually: `(score / precision) as FitnessValue`. |
| 724 | +2. **Ending condition required.** Evolve/HillClimb need at least one of: `target_fitness_score`, `max_stale_generations`, `max_generations`. |
| 725 | +3. **Fitness struct must be `Clone + Debug`.** |
| 726 | +4. **Permutate + RangeGenotype** requires `MutationType::Step`, `StepScaled`, or `Discrete`. |
| 727 | +5. **`target_population_size` defaults to 100.** Override with `.with_target_population_size(n)` if needed. |
| 728 | +6. **Custom Crossover/Mutate/Extension must call `chromosome.reset_metadata(genotype.genes_hashing)`** after modifying genes directly. |
| 729 | +7. **For deterministic tests:** use `.with_rng_seed_from_u64(0)`. Exact results may change between library versions, but deterministic within a version. |
0 commit comments