当前位置:首页 > Rust > 正文

用Rust实现遗传算法(从零开始掌握Rust遗传算法与智能优化)

在人工智能和优化问题中,Rust遗传算法是一种模拟自然选择过程的启发式搜索技术。它广泛应用于函数优化、机器学习超参数调优、路径规划等领域。本教程将带你从零开始,使用Rust编程语言一步步实现一个完整的遗传算法,即使你是编程新手也能轻松上手!

用Rust实现遗传算法(从零开始掌握Rust遗传算法与智能优化) Rust遗传算法 Rust优化算法 遗传算法入门 Rust编程教程 第1张

什么是遗传算法?

遗传算法(Genetic Algorithm, GA)受达尔文进化论启发,通过“适者生存”原则迭代优化解。其核心步骤包括:

  • 初始化种群(Population)
  • 计算个体适应度(Fitness)
  • 选择(Selection)优秀个体
  • 交叉(Crossover)生成新个体
  • 变异(Mutation)引入多样性

我们将用 Rust 实现一个简单目标:寻找一个二进制字符串(如 "110101"),使其十进制值尽可能接近某个目标数(比如 42)。这属于典型的Rust优化算法应用场景。

准备工作

确保你已安装 Rust(推荐使用 rustup)。创建新项目:

cargo new rust_genetic_algorithmcd rust_genetic_algorithm

Step 1:定义基因和个体

每个个体由一串二进制基因组成。我们用 Vec<u8> 表示基因,并为个体实现基本方法。

use rand::Rng;const GENE_LENGTH: usize = 8; // 8位二进制,最大255const TARGET: u32 = 42;#[derive(Clone)]pub struct Individual {    pub genes: Vec<u8>,    pub fitness: f32,}impl Individual {    // 随机生成一个个体    pub fn new_random() -> Self {        let mut rng = rand::thread_rng();        let genes: Vec<u8> = (0..GENE_LENGTH)            .map(|_| rng.gen_range(0..=1))            .collect();        Individual { genes, fitness: 0.0 }    }    // 计算适应度:越接近TARGET,适应度越高    pub fn calculate_fitness(&mut self) {        let value = self.genes            .iter()            .enumerate()            .map(|(i, &bit)| (bit as u32) << (GENE_LENGTH - 1 - i))            .sum::<u32>();        self.fitness = 1.0 / (1.0 + (value as i32 - TARGET as i32).abs() as f32);    }    // 将基因转为字符串便于打印    pub fn to_string(&self) -> String {        self.genes.iter().map(|&b| b.to_string()).collect()    }}

Step 2:实现遗传操作

接下来实现选择、交叉和变异三大操作。

use rand::seq::SliceRandom;pub fn selection(population: &[Individual]) -> Individual {    let mut rng = rand::thread_rng();    // 轮盘赌选择:适应度高的更可能被选中    let total_fitness: f32 = population.iter().map(|ind| ind.fitness).sum();    let mut pick = rng.gen_range(0.0..total_fitness);    for individual in population {        pick -= individual.fitness;        if pick <= 0.0 {            return individual.clone();        }    }    population[0].clone() // fallback}pub fn crossover(parent1: &Individual, parent2: &Individual) -> (Individual, Individual) {    let mut rng = rand::thread_rng();    let crossover_point = rng.gen_range(1..GENE_LENGTH);    let mut child1_genes = parent1.genes[..crossover_point].to_vec();    child1_genes.extend(&parent2.genes[crossover_point..]);    let mut child2_genes = parent2.genes[..crossover_point].to_vec();    child2_genes.extend(&parent1.genes[crossover_point..]);    (        Individual { genes: child1_genes, fitness: 0.0 },        Individual { genes: child2_genes, fitness: 0.0 },    )}pub fn mutate(individual: &mut Individual, mutation_rate: f32) {    let mut rng = rand::thread_rng();    for gene in &mut individual.genes {        if rng.gen_range(0.0..1.0) < mutation_rate {            *gene = 1 - *gene; // 0变1,1变0        }    }}

Step 3:主算法循环

整合所有组件,运行遗传算法直到找到满意解或达到最大代数。

use std::time::Instant;fn main() {    const POPULATION_SIZE: usize = 50;    const MAX_GENERATIONS: usize = 1000;    const MUTATION_RATE: f32 = 0.01;    let mut population: Vec<Individual> = (0..POPULATION_SIZE)        .map(|_| Individual::new_random())        .collect();    let start_time = Instant::now();    for generation in 0..MAX_GENERATIONS {        // 1. 计算所有个体适应度        for individual in &mut population {            individual.calculate_fitness();        }        // 2. 检查是否找到最优解        if let Some(best) = population.iter().max_by(|a, b| a.fitness.partial_cmp(&b.fitness).unwrap()) {            let value = best.genes                .iter()                .enumerate()                .map(|(i, &bit)| (bit as u32) << (GENE_LENGTH - 1 - i))                .sum::<u32>();                        if value == TARGET {                println!("🎉 在第 {} 代找到目标值 {}!基因: {}",                         generation, TARGET, best.to_string());                println!("耗时: {:?}", start_time.elapsed());                return;            }            if generation % 100 == 0 {                println!("第 {} 代: 当前最佳值 = {}, 适应度 = {:.4}",                         generation, value, best.fitness);            }        }        // 3. 生成新一代        let mut new_population = Vec::with_capacity(POPULATION_SIZE);        while new_population.len() < POPULATION_SIZE {            let parent1 = selection(&population);            let parent2 = selection(&population);            let (mut child1, mut child2) = crossover(&parent1, &parent2);            mutate(&mut child1, MUTATION_RATE);            mutate(&mut child2, MUTATION_RATE);            new_population.push(child1);            new_population.push(child2);        }        population = new_population;    }    println!("❌ 未在 {} 代内找到精确解。", MAX_GENERATIONS);}

Step 4:添加依赖并运行

Cargo.toml 中添加随机数库依赖:

[dependencies]rand = "0.8"

然后运行:

cargo run

你将看到类似输出:

第 0 代: 当前最佳值 = 37, 适应度 = 0.1667第 100 代: 当前最佳值 = 42, 适应度 = 1.0000🎉 在第 103 代找到目标值 42!基因: 00101010耗时: 12.345ms

总结

恭喜!你已经成功用 Rust 实现了一个完整的遗传算法入门项目。这个框架可以轻松扩展到更复杂的问题,如旅行商问题(TSP)、神经网络结构搜索等。Rust 的内存安全和高性能特性使其成为实现此类Rust编程教程中高级算法的理想选择。

下一步建议:尝试修改目标函数、调整种群大小或交叉策略,观察对收敛速度的影响。实践是掌握Rust遗传算法的最佳方式!