#线性规划 #单纯形 #对偶 #优化 #原问题

ellp

提供原问题和对偶单纯形求解器的线性规划库

4个版本

0.2.0 2022年12月26日
0.1.2 2021年6月26日
0.1.1 2021年6月11日
0.1.0 2021年6月10日

#631 in 数学

MIT 协议

95KB
2.5K SLoC

ellp

Crates.io docs.rs GitHub

提供原问题和对偶单纯形求解器的线性规划库。这两个求解器目前对一组小测试问题有效。这个库是一个 早期工作版本

示例

以下代码展示了如何设置一个线性规划问题,然后使用原问题和对偶单纯形求解器求解。

use ellp::*;

let mut prob = Problem::new();

let x1 = prob
    .add_var(2., Bound::TwoSided(-1., 1.), Some("x1".to_string()))
    .unwrap();

let x2 = prob
    .add_var(10., Bound::Upper(6.), Some("x2".to_string()))
    .unwrap();

let x3 = prob
    .add_var(0., Bound::Lower(0.), Some("x3".to_string()))
    .unwrap();

let x4 = prob
    .add_var(1., Bound::Fixed(0.), Some("x4".to_string()))
    .unwrap();

let x5 = prob
    .add_var(0., Bound::Free, Some("x5".to_string()))
    .unwrap();

prob.add_constraint(vec![(x1, 2.5), (x2, 3.5)], ConstraintOp::Gte, 5.)
    .unwrap();

prob.add_constraint(vec![(x2, 2.5), (x1, 4.5)], ConstraintOp::Lte, 1.)
    .unwrap();

prob.add_constraint(vec![(x3, -1.), (x4, -3.), (x5, -4.)], ConstraintOp::Eq, 2.)
    .unwrap();

println!("{}", prob);

let primal_solver = PrimalSimplexSolver::default();
let dual_solver = DualSimplexSolver::default();

let primal_result = primal_solver.solve(prob.clone()).unwrap();
let dual_result = dual_solver.solve(prob).unwrap();

if let SolverResult::Optimal(sol) = primal_result {
    println!("primal obj: {}", sol.obj());
    println!("primal opt point: {}", sol.x());
} else {
    panic!("should have an optimal point");
}

if let SolverResult::Optimal(sol) = dual_result {
    println!("dual obj: {}", sol.obj());
    println!("dual opt point: {}", sol.x());
} else {
    panic!("should have an optimal point");
}

输出是

minimize
+ 2 x1 + 10 x2 + 1 x4 

subject to
+ 2.5 x1 + 3.5 x2 ≥ 5
+ 2.5 x2 + 4.5 x1 ≤ 1
- 1 x3 - 3 x4 - 4 x5 = 2

with the bounds
-1 ≤ x1 ≤ 1
x2 ≤ 6
x3 ≥ 0
x4 = 0
x5 free

primal obj: 19.157894736842103
primal opt point: 
  ┌                     ┐
  │ -0.9473684210526313 │
  │  2.1052631578947367 │
  │                   0 │
  │                   0 │
  │                -0.5 │
  └                     ┘

dual obj: 19.157894736842103
dual opt point: 
  ┌                     ┐
  │ -0.9473684210526313 │
  │  2.1052631578947367 │
  │                   0 │
  │                   0 │
  │                -0.5 │
  └                     ┘

如果问题不可行或无界,则 solve 将返回 SolverResult::InfeasibleSolverResult::Unbounded,分别表示。

开发优先级

  • 整理代码,添加适当的日志记录
  • 性能改进(LU分解更新,最速下降法)
  • 添加基准测试和测试问题,并说明如何运行它们(以及如何运行所有测试)
  • 切换到稀疏矩阵(可能使其可选)
  • 制作一个可以解决由mps文件给出的问题的二进制文件

其他注意事项

  • https://netlib.org/lp/获取的MPS格式问题
  • 可以使用 cargo test --features benchmarks 运行它们

依赖项

~3.5MB
~75K SLoC