4 个版本 (重大变更)

0.4.0 2024年8月15日
0.3.3 2024年8月12日
0.2.3 2024年8月10日
0.1.0 2024年8月10日

#216算法

Download history 413/week @ 2024-08-09

413 每月下载量

GPL-3.0-only

1MB
11K SLoC

Rust 7.5K SLoC // 0.1% comments C 3.5K SLoC // 0.2% comments

Optirustic

Package Documentation

Optirustic 是一个用 Rust 编写的框架,它提供了解决多目标问题的算法和分析工具,使用多目标进化算法(MOEAs)。它允许您

  • 定义具有自定义目标函数的最小化和最大化问题;
  • 定义约束和无约束变量(实数、整数、布尔值或选择);
  • 使用多线程评估具有许多个体的种群中的目标和约束;
  • 将种群历史导出为 JSON 格式,并从文件中恢复其进化;

目前,它包括 NSGA2NSGA3 算法。

API 文档可在 docs.rs 上找到。展示此库功能的示例可在此存储库的示例文件夹中找到。

安装 Optirustic

Optirustic 可在 crates.io 上找到。推荐的方法是在您的 Cargo.toml 中添加一行

[dependencies]
optirustic = "*"

示例

问题定义

在这个例子中,我们将使用 NSGA2 算法解决 Schaffer 的问题。该问题旨在最小化以下 2 个目标

  • f1(x) = x2
  • f2(x) = (x - 2)2

该问题有 1 个变量(x),范围在 -10001000 之间。可选解预期位于 [0; 2] 范围内。

问题实现

问题通过使用 SCHProblem 结构体实现。当算法运行时,它首先为问题变量(在本例中为 x)生成一组潜在解。然后,它在此库公开的 Evaluator 特性中计算目标(f1(x) 和 f2(x))。

#[derive(Debug)]
pub struct SCHProblem;

impl SCHProblem {
    /// Create the problem for the optimisation.
    pub fn create() -> Result<Problem, OError> {
        // define the objectives
        let objectives = vec![
            Objective::new("x^2", ObjectiveDirection::Minimise),
            Objective::new("(x-2)^2", ObjectiveDirection::Minimise),
        ];
        // define the variable
        let variables = vec![VariableType::Real(BoundedNumber::new(
            "x", -1000.0, 1000.0,
        )?)];
        // the problem has no constraints
        let constraints = None;

        let e = Box::new(SCHProblem);
        Problem::new(objectives, variables, constraints, e)
    }

    /// The first objective function
    pub fn f1(x: f64) -> f64 {
        x.powi(2)
    }

    /// The second objective function
    pub fn f2(x: f64) -> f64 {
        (x - 2.0).powi(2)
    }
}

// Implement the function to evaluate the objectives and constraints. The `evaluate`
// function below receives the individuals which contain the variables/solutions `x` 
// proposed by the algorithm. The function must return the evaluated objectives and
// constraints in the `EvaluationResult` struct.
impl Evaluator for SCHProblem {
    fn evaluate(&self, i: &Individual) -> Result<EvaluationResult, Box<dyn Error>> {
        let x = i.get_variable_value("x")?.as_real()?;
        let mut objectives = HashMap::new();
        objectives.insert("x^2".to_string(), SCHProblem::f1(x));
        objectives.insert("(x-2)^2".to_string(), SCHProblem::f2(x));
        Ok(EvaluationResult {
            constraints: None,
            objectives,
        })
    }
}

设置和运行遗传算法

以下代码设置了具有 NSGA2 算法,包含 100 个个体,并在达到 250 代种群时停止。

...

fn main() -> Result<(), Box<dyn Error>> {
    // Setup the NSGA2 algorithm
    let args = NSGA2Arg {
        // use 100 individuals and stop the algorithm at 250 generations
        number_of_individuals: 100,
        stopping_condition: StoppingConditionType::MaxGeneration(MaxGeneration(250)),
        // use default options for the SBX and PM operators
        crossover_operator_options: None,
        mutation_operator_options: None,
        // no need to evaluate the objective in parallel
        parallel: Some(false),
        // do not export intermediate solutions
        export_history: None,
        resume_from_file: None,
        // to reproduce results
        seed: Some(10),
    };
    let mut algo = NSGA2::new(problem, args)?;

    // run the algorithm
    algo.run()?;

    // Export serialised results at last generation
    algo.save_to_json(&PathBuf::from("."), Some("SCH_2obj"))?;

    Ok(())
}

完整的示例代码可在该存储库的 示例文件夹 中找到,并可以使用以下命令运行:

cargo run --example nsga2_sch --release

这是算法导出的序列化数据: SCH_2obj_NSGA2_gen250.json,以下是绘制的解

Results

依赖项

~7–12MB
~232K SLoC