19次发布

0.9.0 2024年8月20日
0.7.2 2024年7月27日
0.7.0 2023年5月25日
0.6.0 2022年10月14日
0.5.0 2022年7月7日

#131 in 算法

Download history 4/week @ 2024-07-09 120/week @ 2024-07-16 553/week @ 2024-07-23 144/week @ 2024-07-30 469/week @ 2024-08-06 251/week @ 2024-08-13

1,436 每月下载量
用于 genetic_algorithm_meta

MIT/Apache

265KB
5.5K SLoC

genetic-algorithm

Rust的遗传算法实现。灵感来自书籍 Genetic Algorithms in Elixir

该方法的三个主要元素

  • 基因型(搜索空间)
  • 适应度函数(搜索目标)
  • 策略(搜索策略)
    • 进化(进化策略)
    • 排列(适用于小搜索空间,具有100%保证)
    • 爬山法(当搜索空间是凸的,局部最优解少或交叉不可行/效率低时)

术语

  • 种群:一个种群有 population_size 个个体(称为染色体)。
  • 染色体:一个染色体有 genes_size 个基因
  • 基因:基因是染色体中的位置和基因(等位基因)值的组合
  • 等位基因:等位基因是基因的可能值
  • 基因型:包含基因和等位基因,并知道如何高效地生成和变异染色体
  • 适应度:知道如何确定染色体的适应度

文档

docs.rs

快速使用

use genetic_algorithm::strategy::evolve::prelude::*;

// the search space
let genotype = BinaryGenotype::builder() // boolean alleles
    .with_genes_size(100)                // 100 genes per chromosome
    .build()
    .unwrap();

println!("{}", genotype);

// the search goal to optimize towards (maximize or minimize)
#[derive(Clone, Debug)]
pub struct CountTrue;
impl Fitness for CountTrue {
    type Allele = BinaryGenotype; // bool
    fn calculate_for_chromosome(&mut self, chromosome: &Chromosome<Self::Allele>) -> Option<FitnessValue> {
        Some(chromosome.genes.iter().filter(|&value| *value).count() as FitnessValue)
    }
}

// the search strategy
let mut rng = rand::thread_rng();     // a randomness provider implementing Trait rand::Rng
let evolve = Evolve::builder()
    .with_genotype(genotype)
    .with_population_size(100)                     // evolve with 100 chromosomes
    .with_target_fitness_score(100)                // goal is 100 times true in the best chromosome
    .with_fitness(CountTrue)                       // count the number of true values in the chromosomes
    .with_crossover(CrossoverUniform::new(true))   // crossover all individual genes between 2 chromosomes for offspring
    .with_mutate(MutateOnce::new(0.2))             // mutate a single gene with a 20% probability per chromosome
    .with_compete(CompeteElite::new())             // sort the chromosomes by fitness to determine crossover order
    .with_reporter(EvolveReporterSimple::new(100)) // optional builder step, report every 100 generations
    .call(&mut rng);
    .unwrap()

println!("{}", evolve);

示例

使用 cargo run --example [EXAMPLE_BASENAME] --release

测试

使用cargo test运行测试

基准测试

使用 criterion 实现。使用 cargo bench 运行基准测试

性能分析

使用 criterion 和 pprof 实现。

在以下位置找到火焰图:./target/criterion/profile_evolve_binary/profile/flamegraph.svg

使用以下命令运行:cargo run --example profile_evolve_binary --release -- --bench --profile-time 5

待办事项

  • 使持续时间统计返回 Duration,这样我们就可以之后选择 sec/milli/micro。
  • 添加模拟退火策略
  • 添加缩放排列?可以通过网格搜索实现,然后在新尺度内搜索最后一个网格

也许

  • 添加带有和没有重复项的轮盘竞争(带有适应度排序)
  • 为 UniqueGenotype 添加 OrderOne 交叉
  • 为 RangeGenotype 添加 WholeArithmetic 交叉
  • 添加缩放辅助函数
  • 将 SteepestAscent 的 max_stale_generations 默认值设置为 1

问题

  • 排列(以及可能的其他)在 gene_size 0 时崩溃。也许它应该只返回一个空染色体?

依赖项

~4MB
~70K SLoC