Rust凸优化求解器库Clarabel的使用,Clarabel提供高效二次规划(QP)和半定规划(SDP)求解功能
Rust凸优化求解器库Clarabel的使用
简介
Clarabel.rs是一个Rust实现的用于凸优化问题的内点法数值求解器,使用新颖的齐次嵌入技术。Clarabel.rs解决以下形式的优化问题:
$$ \begin{array}{r} \text{minimize} & \frac{1}{2}x^T P x + q^T x\[2ex] \text{subject to} & Ax + s = b \[1ex] & s \in \mathcal{K} \end{array} $$
决策变量为$x \in \mathbb{R}^n$, $s \in \mathbb{R}^m$,数据矩阵为$P=P^\top \succeq 0$, $q \in \mathbb{R}^n$, $A \in \mathbb{R}^{m \times n}$, 和 $b \in \mathbb{R}^m$。凸集$\mathcal{K}$是凸锥的组合。
特性
- 多功能:解决线性规划(LPs)、二次规划(QPs)、二阶锥规划(SOCPs)和半定规划(SDPs),以及具有指数、幂锥和广义幂锥约束的问题
- 二次目标:无需对目标函数进行任何改写即可处理二次目标
- 不可行性检测:使用齐次嵌入技术检测不可行问题
- 开源:代码在Apache 2.0许可下可用
安装
在Cargo项目中添加以下依赖:
[dependencies]
clarabel = "0.11.1"
Python接口安装:
pip install clarabel
示例代码
以下是一个完整的Rust示例,展示如何使用Clarabel解决一个二次规划问题:
use clarabel::algebra::*;
use clarabel::solver::*;
fn main() {
// 定义问题数据
let P = CscMatrix::new(
2, // 行数
2, // 列数
vec![0, 1, 3], // 列指针
vec![0, 1, 0, 1], // 行索引
vec![3., 1., 4.], // 非零值
);
let q = vec![1., 1.];
let A = CscMatrix::new(
3, // 行数
2, // 列数
vec![0, 2, 4], // 列指针
vec![0, 1, 0, 1], // 行索引
vec![1., 1., 1., 1.], // 非零值
);
let b = vec![1., 1., 1.];
let cones = [ZeroConeT(1), NonnegativeConeT(2)];
// 定义求解器
let settings = DefaultSettings::default();
let mut solver = DefaultSolver::new(&P, &q, &A, &b, &cones, settings);
// 求解问题
solver.solve();
// 获取结果
println!("Solution status: {:?}", solver.solution.status);
println!("Solution x: {:?}", solver.solution.x);
println!("Solution z: {:?}", solver.solution.z);
}
完整示例demo
以下是一个更完整的示例,展示如何使用Clarabel解决一个带约束的二次规划问题:
use clarabel::algebra::*;
use clarabel::solver::*;
fn main() {
// 定义二次目标函数: 最小化 3x1² + 2x1x2 + 4x2² + x1 + x2
let P = CscMatrix::new(
2, // 变量数
2, // 变量数
vec![0, 1, 3], // 列指针 (CSC格式)
vec![0, 1, 0, 1], // 行索引
vec![6., 2., 8.], // 值 (注意: 矩阵P需要乘以1/2)
);
let q = vec![1., 1.]; // 线性项
// 定义约束条件:
// 1. x1 + x2 = 1 (等式约束)
// 2. x1 >= 0 (非负约束)
// 3. x2 >= 0 (非负约束)
let A = CscMatrix::new(
3, // 约束数
2, // 变量数
vec![0, 2, 4], // 列指针
vec![0, 1, 0, 1], // 行索引
vec![1., 1., 1., 1.], // 值
);
let b = vec![1., 0., 0.]; // 约束右边值
// 定义锥约束:
// 1. 第一个约束是等式约束 (Zero锥)
// 2. 后两个约束是非负约束 (Nonnegative锥)
let cones = [ZeroConeT(1), NonnegativeConeT(2)];
// 使用默认设置创建求解器
let settings = DefaultSettings::default();
let mut solver = DefaultSolver::new(&P, &q, &A, &b, &cones, settings);
// 求解问题
solver.solve();
// 输出详细结果
println!("=== 求解结果 ===");
println!("状态: {:?}", solver.solution.status);
println!("最优解 x: {:?}", solver.solution.x);
println!("对偶变量 z: {:?}", solver.solution.z);
println!("目标值: {}", solver.solution.obj_val);
println!("求解时间: {}秒", solver.solution.solve_time);
println!("迭代次数: {}", solver.solution.iterations);
// 检查解的状态
match solver.solution.status {
SolverStatus::Solved => {
println!("问题成功求解!");
println!("最优解: x1 = {:.4}, x2 = {:.4}",
solver.solution.x[0],
solver.solution.x[1]);
},
SolverStatus::Infeasible => println!("问题不可行!"),
SolverStatus::MaxIterations => println!("达到最大迭代次数!"),
_ => println!("求解器返回未处理的状态"),
}
}
引用
@misc{Clarabel_2024,
title={Clarabel: An interior-point solver for conic programs with quadratic objectives},
author={Paul J. Goulart and Yuwen Chen},
year={2024},
eprint={2405.12762},
archivePrefix={arXiv},
primaryClass={math.OC}
}
许可证
本项目采用Apache License 2.0许可。
Rust凸优化求解器库Clarabel的使用指南
介绍
Clarabel是一个用纯Rust编写的凸优化求解器库,专门用于解决二次规划(QP)和半定规划(SDP)问题。它提供了高效的求解能力,特别适合需要高性能和内存安全的优化应用场景。
主要特性
- 纯Rust实现,无外部依赖
- 支持二次规划(QP)和半定规划(SDP)
- 内点法求解器
- 数值稳定且高效
- 提供简洁的API接口
安装方法
在Cargo.toml中添加依赖:
[dependencies]
clarabel = "0.5" # 请使用最新版本
基本使用方法
1. 解决二次规划问题(QP)
use clarabel::algebra::*;
use clarabel::solver::*;
fn main() {
// 定义问题数据
let P = CscMatrix::new(
2, // 行数
2, // 列数
vec![0, 1, 3], // 列指针
vec![0, 0, 1], // 行索引
vec![2., 1., 2.], // 值
);
let q = vec![-2., -4.];
// 约束条件 A*x = b
let A = CscMatrix::new(
2, // 行数
2, // 列数
vec![0, 1, 2], // 列指针
vec![0, 1], // 行索引
vec![1., 1.], // 值
);
let b = vec![1., 1.];
// 构建求解器
let settings = DefaultSettings::default();
let mut solver = DefaultSolver::new(&P, &q, &A, &b, settings);
// 求解
solver.solve();
// 获取结果
println!("Solution: {:?}", solver.solution.x);
}
2. 解决半定规划问题(SDP)
use clarabel::algebra::*;
use clarabel::solver::*;
fn main() {
// 定义SDP问题数据
let c = vec![1., 2., 3.];
// 约束矩阵 A_i
let A0 = CscMatrix::new(
2, 2,
vec![0, 1, 2],
vec![0, 1],
vec![1., 1.]
);
let A1 = CscMatrix::new(
2, 2,
vec![0, 1, 2],
vec![0, 1],
vec![1., -1.]
);
let A = vec![A0, A1];
let b = vec![1., 0.5];
// 构建求解器
let settings = DefaultSettings::default();
let mut solver = DefaultSolver::new_sdp(&c, &A, &b, settings);
// 求解
solver.solve();
// 获取结果
println!("SDP Solution: {:?}", solver.solution.x);
}
高级用法
自定义求解器设置
use clarabel::solver::*;
let settings = Settings {
max_iter: 1000, // 最大迭代次数
time_limit: Some(10.0), // 时间限制(秒)
verbose: true, // 显示求解过程
tol_gap_abs: 1e-8, // 绝对间隙容差
tol_gap_rel: 1e-8, // 相对间隙容差
..Default::default() // 其他参数使用默认值
};
处理不等式约束
// 添加不等式约束 Ax <= b
let A_ineq = CscMatrix::new(
1, 2,
vec![0, 1, 2],
vec![0, 1],
vec![1., 1.]
);
let b_ineq = vec![2.];
// 构建求解器时传入不等式约束
let mut solver = DefaultSolver::new_with_ineq(&P, &q, &A, &b, &A_极速, &b_ineq, settings);
完整示例demo
下面是一个完整的二次规划问题示例,展示了如何使用Clarabel解决一个实际的优化问题:
use clarabel::algebra::*;
use clarabel::solver::*;
fn main() {
// 最小化目标函数: 2x² + xy + 2y² - 2x - 4y
// 约束条件: x + y = 1
// 构建二次项矩阵P (2x2)
let P = CscMatrix::new(
2, // 行数
2, // 列数
vec![0, 1, 3], // 列指针
vec![0, 0, 1], // 行索引 (0,0), (0,1), (1,1)
vec![4., 1., 4.], // 值 (注意: 原问题中的2x²需要乘以2)
);
// 构建线性项向量q
let q = vec![-2., -4.];
// 等式约束矩阵A (1x2)
let A = CscMatrix::new(
1, // 行数 (1个等式约束)
2, // 列数
vec![0, 1, 2], // 列指针
vec![0, 0], // 行索引 (0,0), (0,1)
vec![1., 1.], // 值
);
// 等式约束右侧b
let b = vec![1.];
// 自定义求解器设置
let settings = Settings {
max_iter: 100,
time_limit: None,
verbose: true,
tol_gap_abs: 1e-6,
tol_gap_rel: 1e-6,
..Default::default()
};
// 构建并求解问题
let mut solver = DefaultSolver::new(&P, &q, &A, &b, settings);
solver.solve();
// 输出结果
println!("优化状态: {:?}", solver.solution.status);
println!("最优解: x = {:.4}, y = {:.4}",
solver.solution.x[0],
solver.solution.x[1]);
println!("目标函数值: {:.4}", solver.solution.obj_val);
println!("求解时间: {:.2}ms", solver.solution.solve_time * 1000.0);
}
注意事项
- Clarabel使用稀疏矩阵格式(CSC)来表示问题数据,确保数据格式正确
- 对于大规模问题,考虑使用更高效的矩阵构建方法
- 检查求解器返回的状态信息,确保问题已成功解决
- 可以通过调整求解器参数来优化性能
性能建议
- 尽量重用求解器实例以减少内存分配
- 对于重复求解类似问题,考虑热启动
- 使用
rayon
等并行库预处理问题数据可提高性能
Clarabel为Rust生态提供了一个强大而高效的凸优化求解方案,特别适合嵌入到需要高性能和内存安全的应用程序中。