Rust线性规划求解库minilp的使用,minilp提供轻量级高效的线性编程与优化解决方案

Rust线性规划求解库minilp的使用,minilp提供轻量级高效的线性编程与优化解决方案

minilp是一个快速的线性规划求解库。线性规划是一种在满足线性等式和不等式约束条件下,寻找一组连续变量的线性函数最小值(或最大值)的技术。

特性

  • 纯Rust实现
  • 能够解决具有数十万变量和约束的问题
  • 增量式:可以向现有解决方案添加约束而无需从头开始求解
  • 问题可以通过API定义或从MPS文件解析

警告:这是一个早期阶段的项目。尽管该库已经相当强大和快速,但在处理一些更复杂的问题时可能会出现循环、精度丢失或panic的情况。请报告错误并贡献代码!

示例

基本用法:

use minilp::{Problem, OptimizationDirection, ComparisonOp};

// 最大化目标函数 x + 2 * y,其中变量 x >= 0 且 0 <= y <= 3
let mut problem = Problem::new(OptimizationDirection::Maximize);
let x = problem.add_var(1.0, (0.0, f64::INFINITY));
let y = problem.add_var(2.0, (0.0, 3.0));

// 约束条件:x + y <= 4 且 2 * x + y >= 2
problem.add_constraint(&[(x, 1.0), (y, 1.0)], ComparisonOp::Le, 4.0);
problem.add_constraint(&[(x, 2.0), (y, 1.0)], ComparisonOp::Ge, 2.0);

// 最优值为7,在x=1和y=3时取得
let solution = problem.solve().unwrap();
assert_eq!(solution.objective(), 7.0);
assert_eq!(solution[x], 1.0);
assert_eq!(solution[y], 3.0);

完整示例

下面是一个更完整的示例,展示如何使用minilp解决一个简单的生产计划问题:

use minilp::{Problem, OptimizationDirection, ComparisonOp};

fn main() {
    // 创建一个最大化问题
    let mut problem = Problem::new(OptimizationDirection::Maximize);
    
    // 添加变量:产品A和产品B的生产数量
    // 产品A每单位利润3元,产品B每单位利润5元
    // 生产数量必须非负
    let product_a = problem.add_var(3.0, (0.0, f64::INFINITY));  // 利润系数3.0
    let product_b = problem.add_var(5.0, (0.0, f64::INFINITY));  // 利润系数5.0
    
    // 添加约束条件:
    // 1. 机器时间约束:生产1单位A需要1小时,1单位B需要2小时,总可用时间100小时
    problem.add_constraint(
        &[(product_a, 1.0), (product_b, 2.0)], 
        ComparisonOp::Le, 
        100.0
    );
    
    // 2. 原材料约束:生产1单位A需要4kg原料,1单位B需要3kg原料,总原料可用量240kg
    problem.add_constraint(
        &[(product_a, 4.0), (product_b, 3.0)],
        ComparisonOp::Le,
        240.0
    );
    
    // 3. 市场需求约束:产品B的产量不超过60单位
    problem.add_constraint(
        &[(product_b, 1.0)],
        ComparisonOp::Le,
        60.0
    );
    
    // 求解问题
    let solution = problem.solve().unwrap();
    
    // 输出结果
    println!("最大利润: {:.2}元", solution.objective());
    println!("产品A最优产量: {:.2}单位", solution[product_a]);
    println!("产品B最优产量: {:.2}单位", solution[product_b]);
}

安装

在项目目录中运行以下Cargo命令:

cargo add minilp

或者在Cargo.toml中添加以下行:

minilp = "0.2.2"

许可证

该项目采用Apache License, Version 2.0许可证。


1 回复

Rust线性规划求解库minilp使用指南

简介

minilp是一个轻量级、高效的Rust线性规划求解库,用于解决线性优化问题。它提供了简单直观的API来定义和求解线性规划问题,特别适合需要嵌入到Rust应用程序中的优化场景。

主要特性

  • 支持最大化或最小化线性目标函数
  • 支持等式和不等式约束
  • 纯Rust实现,无外部依赖
  • 轻量级且高效
  • 支持变量边界约束

安装

在Cargo.toml中添加依赖:

[dependencies]
minilp = "0.3"

基本使用方法

1. 创建优化问题

use minilp::{Problem, OptimizationDirection};

// 创建最大化问题
let mut problem = Problem::new(OptimizationDirection::Maximize);

2. 添加变量

// 添加变量并返回变量索引
let x1 = problem.add_var(10.0, (0.0, f64::INFINITY)); // 系数10.0,范围>=0
let x2 = problem.add_var(6.0, (0.0, f64::INFINITY));  // 系数6.0,范围>=0

3. 添加约束

// 添加约束: x1 + x2 <= 5.0
problem.add_constraint(&[(x1, 1.0), (x2, 1.0)], minilp::ComparisonOp::Le, 5.0);

// 添加约束: 5x1 + 2x2 <= 20.0
problem.add_constraint(&[(x1, 5.0), (x2, 2.0)], minilp::ComparisonOp::Le, 20.0);

4. 求解问题

// 求解问题
let solution = problem.solve().unwrap();

// 获取结果
println!("Objective value: {}", solution.objective());
println!("x1 = {}", solution[x1]);
println!("x2 = {}", solution[x2]);

完整示例

下面是一个完整的线性规划问题求解示例:

use minilp::{Problem, OptimizationDirection, ComparisonOp};

fn main() {
    // 创建最大化问题
    let mut problem = Problem::new(OptimizationDirection::Maximize);
    
    // 添加变量
    let x1 = problem.add_var(10.0, (0.0, f64::INFINITY)); // 利润系数10,x1 >= 0
    let x2 = problem.add_var(6.0, (0.0, f64::INFINITY));  // 利润系数6,x2 >= 0
    
    // 添加约束
    // 约束1: x1 + x2 <= 5 (资源限制)
    problem.add_constraint(&[(x1, 1.0), (x2, 1.0)], ComparisonOp::Le, 5.0);
    
    // 约束2: 5x1 + 2x2 <= 20 (资源限制)
    problem.add_constraint(&[(x1, 5.0), (x2, 2.0)], ComparisonOp::Le, 20.0);
    
    // 求解问题
    match problem.solve() {
        Ok(solution) => {
            println!("最优解:");
            println!("目标函数值: {}", solution.objective());
            println!("x1 = {}", solution[x1]);
            println!("x2 = {}", solution[x2]);
        }
        Err(e) => println!("求解失败: {:?}", e),
    }
}

高级用法

混合整数规划

minilp也支持整数变量:

use minilp::{Problem, OptimizationDirection, VariableType};

let mut problem = Problem::new(OptimizationDirection::Maximize);

// 添加整数变量
let x1 = problem.add_var_with_type(3.0, (0.0, f64::INFINITY), VariableType::Integer);
let x2 = problem.add_var_with_type(2.0, (0.0, f64::INFINITY), VariableType::Integer);

// 添加约束
problem.add_constraint(&[(x1, 1.0), (x2, 1.0)], ComparisonOp::Le, 4.0);

let solution = problem.solve().unwrap();
println!("x1 = {} (整数)", solution[x1]);
println!("x2 = {} (整数)", solution[x2]);

等式约束

// 添加等式约束 x1 + x2 = 3
problem.add_constraint(&[(x1, 1.0), (x2, 1.0)], ComparisonOp::Eq, 3.0);

性能提示

  1. 对于大型问题,预先分配足够的容量可以提高性能:

    let mut problem = Problem::with_capacity(OptimizationDirection::Maximize, 1000, 100);
    // 1000个变量,100个约束的预估容量
    
  2. 尽可能重用Problem实例以减少内存分配

  3. 对于整数规划问题,解算时间可能随问题规模指数增长

限制

  • minilp适用于中小规模问题
  • 对于大型或复杂问题,可能需要更专业的求解器
  • 整数规划能力有限

minilp是Rust生态中一个简单易用的线性规划解决方案,特别适合需要轻量级、无外部依赖的优化场景。

完整示例DEMO

以下是一个更完整的示例,演示如何使用minilp解决生产计划优化问题:

use minilp::{Problem, OptimizationDirection, ComparisonOp, VariableType};

fn main() {
    // 问题描述:
    // 公司生产两种产品A和B,利润分别为每单位50元和60元
    // 生产约束:
    // 1. 原材料限制:2A + 3B <= 100
    // 2. 人工限制:4A + 2B <= 120
    // 3. 产品B的生产量必须为整数
    
    // 创建最大化利润问题
    let mut problem = Problem::new(OptimizationDirection::Maximize);
    
    // 添加变量
    let a = problem.add_var(50.0, (0.0, f64::INFINITY)); // 产品A,利润50,数量>=0
    let b = problem.add_var_with_type(60.0, (0.0, f64::INFINITY), VariableType::Integer); // 产品B,利润60,整数数量>=0
    
    // 添加约束
    // 原材料约束:2A + 3B <= 100
    problem.add_constraint(&[(a, 2.0), (b, 3.0)], ComparisonOp::Le, 100.0);
    
    // 人工约束:4A + 2B <= 120
    problem.add_constraint(&[(a, 4.0), (b, 2.0)], ComparisonOp::Le, 120.0);
    
    // 求解问题
    match problem.solve() {
        Ok(solution) => {
            println!("=== 最优生产计划 ===");
            println!("最大利润: {:.2}元", solution.objective());
            println!("产品A产量: {:.2}单位", solution[a]);
            println!("产品B产量: {}单位", solution[b]); // 整数
            
            // 计算资源使用情况
            println!("\n=== 资源使用情况 ===");
            println!("原材料使用量: {:.2}/100", 2.0 * solution[a] + 3.0 * solution[b]);
            println!("人工使用量: {:.2}/120", 4.0 * solution[a] + 2.0 * solution[b]);
        }
        Err(e) => println!("求解失败: {:?}", e),
    }
}

这个示例演示了:

  1. 如何定义混合整数规划问题(产品B必须为整数)
  2. 如何添加多个约束条件
  3. 如何解读和使用求解结果
  4. 如何基于结果进行额外计算(资源使用情况)
回到顶部