#遗传算法 #个体 #随机 #种群 #问题 #进化 #交叉

rusty_genes

一个用于实现和执行具有可定制模型的进化算法的库

4 个版本

0.1.3 2023年5月22日
0.1.2 2023年5月21日
0.1.1 2023年5月17日
0.1.0 2023年5月16日

1026算法

Download history 5/week @ 2024-03-31

每月 51 次下载

MIT 许可证

150KB
2K SLoC

rusty_genes

rusty_genes 是一个 Rust 库,旨在简化进化算法的实现和实验,特别是针对基于排列的问题。此库不适用于简单的即插即用,而是提供一系列可定制和组装的模块,以匹配您特定问题的需求。它鼓励用户积极参与算法的构建,以促进灵活性和可扩展性。

rusty_genes 的一个关键特性是支持通过实现一些核心方法来创建自定义算法。这种可扩展性允许用户尝试新的进化策略和技术,推动遗传算法的可能性的边界。

rusty_genes 通过独立的模块提供进化算法的基本组件,允许高度定制。这些组件包括各种选择策略、交叉策略和变异策略,以及定义进化模型和个体的结构。

该库仅支持最大化问题。如果您的用例涉及最小化,您需要通过调整适应度函数或问题表示将其转换为最大化问题。

特性

该库目前实现了两种进化算法

  • 标准遗传算法 (GA)
  • 自适应遗传算法:该算法根据计算出的多样性值动态调整交叉和变异率。这通过交叉操作在多样性高时促进现有多样性的利用,并在多样性低时通过引入和维持更多的多样性来鼓励探索。

rusty_genes 支持以下选择策略

  • 锦标赛选择
  • 轮盘赌选择
  • 玻尔兹曼选择
  • 排名选择
  • 线性选择
  • 精英选择

它还提供各种交叉策略

  • 广义分区交叉 2 (GPX2)
  • 顺序构造交叉 (SCX)
  • 边缘重组交叉 (ERX)
  • 部分映射交叉 (PMX)
  • 订单交叉(OX)
  • 循环交叉(CX)
  • 单点交叉(SPX)

RustyGenes支持以下变异策略:

  • 交换变异
  • 洗牌变异
  • 倒置变异
  • 插入变异
  • 重复变异

用法

以下是如何使用库解决OneMax问题的示例

use rusty_genes::*;
use rand::{distributions::Standard, prelude::*};

/// Represents an individual in the OneMax problem.
///
/// The `genome` is a binary string represented as a vector of booleans. Each boolean
/// represents a bit, and the fitness of an individual is the ratio of 'true' bits to
/// the total number of bits in this binary string.
#[derive(Debug, Clone, PartialEq)]
pub struct OneMax {
    genome: Vec<bool>,
    fitness: f64,
}

impl OneMax {
    // Returns the binary string of the individual.
    pub fn genome(&self) -> &[bool] {
        &self.genome
    }
}

/// Conversion from a `Vec<bool>` to a `OneMax` individual.
///
/// This allows a binary string to be directly converted into an individual.
impl From<Vec<bool>> for OneMax {
    fn from(genome: Vec<bool>) -> Self {
        Self {
            genome,
            fitness: 0.0,
        }
    }
}

/// Implements the method required by the [`Individual`] trait for the OneMax problem.
impl Individual for OneMax {
    /// Returns the fitness of the individual.
    fn fitness(&self) -> f64 {
        self.fitness
    }
}

/// Allows the creation of a new random individual for the OneMax problem.
impl RandomIndividual<usize> for OneMax {
    /// Generates a new random individual for the OneMax problem.
    ///
    /// The `length` parameter determines the length of the binary string (i.e., the genome),
    /// and the `rng` parameter is a random number generator used to generate the binary string.
    fn new_random<R: Rng>(length: &usize, rng: &mut R) -> Self {
        let bits = rng.sample_iter(Standard);
        let genome = Vec::from_iter(bits.take(*length));
        Self::from(genome)
    }
}

/// The evolutionary model for the OneMax problem.
///
/// This struct provides methods for crossover, mutation, and evaluation operations specific
/// to the OneMax problem.
#[derive(Debug, Default)]
pub struct OneMaxEvolutionModel;

/// Implements the methods required by the [`EvolutionModel`] trait for the OneMax problem.
impl EvolutionModel for OneMaxEvolutionModel {
    type Individual = OneMax;
    type Rng = SmallRng;

    /// Creates a new random number generator from entropy.
    fn rng() -> Self::Rng {
        SmallRng::from_entropy()
    }

    /// Performs a single point crossover on the parents' genomes to create a new individual.
    fn crossover(
        &self,
        parent1: &Self::Individual,
        parent2: &Self::Individual,
        rng: &mut Self::Rng,
    ) -> Self::Individual {
        CrossoverStrategy::SinglePoint
            .crossover(&parent1.genome, &parent2.genome, rng)
            .into()
    }

    /// Mutates the individual's genome by using the duplicate mutation strategy.
    fn mutate(&self, individual: &mut Self::Individual, rng: &mut Self::Rng) {
        MutationStrategy::Duplicate.mutate(&mut individual.genome, rng);
    }

    /// Evaluates the individual's fitness by calculating the ratio of `true` bits to the total
    /// number of bits in its genome.
    fn evaluate(&self, individual: &mut Self::Individual) {
        let one_bits = individual.genome.iter().filter(|&&one| one).count();
        let total_bits = individual.genome.len();
        individual.fitness = one_bits as f64 / total_bits as f64;
    }
}

// Create an instance of the evolutionary model.
let one_max = OneMaxEvolutionModel;

// Use the Genetic Algorithm to solve the problem.
let ga = GeneticAlgorithm::build_evolution(one_max);

// Use default parameters of the Genetic Algorithm.
let ga_params = GeneticAlgorithmParameters::default();

// Run the algorithm until the fitness of the fittest individual is close to 1 or
// the number of generations exceeds 100.
let solution = ga.run(&ONE_MAX_LENGTH, &ga_params, |population| {
    population.fittest().fitness() < 0.999999 && population.generation() <= 100
});

// Verify that the solution is correct.
assert!(solution.genome().iter().all(|&one| one == true));

致谢

该项目是合作努力的结果。OpenAI的AI,ChatGPT-4,在文档和实现方面都提供了帮助。

许可证

RustyGenes遵循MIT许可证

该项目处于早期阶段,欢迎贡献。请随时提出问题或提交pull请求。

免责声明

这是初始版本,随着项目的演变可能会发生变化。请自行承担使用风险。

依赖项

~4.5MB
~43K SLoC