Rust SAT求解器库varisat-dimacs的使用,支持DIMACS格式的CNF公式解析与求解
Varisat - DIMACS
DIMACS CNF解析器和写入器,用于Varisat SAT求解器。
此crate的功能由主Varisat crate重新导出。
许可证
Varisat源代码根据以下任一许可证授权:
- Apache License, Version 2.0
- MIT license
根据您的选择。
贡献
除非您明确声明,否则任何有意提交给Varisat的贡献,如Apache-2.0许可证中所定义,应按照上述双重许可,没有任何附加条款或条件。
元数据
pkg:cargo/varisat-dimacs@0.2.2
大约5年前
2018版本
MIT OR Apache-2.0
9.65 KiB
安装
在您的项目目录中运行以下Cargo命令:
cargo add varisat-dimacs
或在您的Cargo.toml中添加以下行:
varisat-dimacs = “0.2.2”
主页
文档
仓库
所有者
Jannis Harder
完整示例demo:
use varisat_dimacs::{DimacsParser, DimacsWriter};
use std::io::{Cursor, Read, Write};
fn main() -> Result<(), Box<dyn std::error::Error>> {
// DIMACS CNF格式示例
let cnf_input = r"
p cnf 3 2
1 -2 3 0
-1 2 0
";
// 解析DIMACS CNF公式
let mut parser = DimacsParser::new(Cursor::new(cnf_input));
let cnf_formula = parser.parse()?;
println!("解析的CNF公式: {:?}", cnf_formula);
// 将CNF公式写回DIMACS格式
let mut output = Vec::new();
let mut writer = DimacsWriter::new(&mut output);
writer.write_cnf(&cnf_formula)?;
let output_str = String::from_utf8(output)?;
println!("生成的DIMACS输出:\n{}", output_str);
Ok(())
}
use varisat::{solver::Solver, dimacs::DimacsParser};
use std::io::Cursor;
fn main() -> Result<(), Box<dyn std::error::Error>> {
// 创建SAT求解器
let mut solver = Solver::new();
// DIMACS CNF公式
let cnf_input = r"
p cnf 3 3
1 2 3 0
-1 -2 0
-2 -3 0
";
// 解析并添加公式到求解器
let mut parser = DimacsParser::new(Cursor::new(cnf_input));
solver.add_formula(&parser.parse()?);
// 求解SAT问题
match solver.solve() {
Ok(true) => {
println!("公式可满足");
if let Some(model) = solver.model() {
println!("满足赋值: {:?}", model);
}
}
Ok(false) => {
println!("公式不可满足");
}
Err(e) => {
eprintln!("求解错误: {}", e);
}
}
Ok(())
}
use varisat_dimacs::DimacsParser;
use std::fs::File;
use std::io::BufReader;
fn main() -> Result<(), Box<dyn std::error::Error>> {
// 从文件读取DIMACS CNF
let file = File::open("example.cnf")?;
let reader = BufReader::new(file);
let mut parser = DimacsParser::new(reader);
let cnf_formula = parser.parse()?;
println!("变量数量: {}", cnf_formula.var_count());
println!("子句数量: {}", cnf_formula.len());
// 处理每个子句
for (i, clause) in cnf_formula.iter().enumerate() {
println!("子句 {}: {:?}", i + 1, clause);
}
Ok(())
}
1 回复
Rust SAT求解器库:varisat-dimacs 使用指南
概述
varisat-dimacs 是一个基于 Rust 的 SAT 求解器库,专门用于解析和求解 DIMACS 格式的 CNF(合取范式)公式。该库提供了高效的解析器和求解器实现,适用于需要布尔可满足性求解的应用场景。
核心功能
- DIMACS CNF 格式解析
- 高效的 SAT 求解算法
- 可配置的求解选项
- 结果验证与模型输出
安装方法
在 Cargo.toml 中添加依赖:
[dependencies]
varisat-dimacs = "0.3"
基本用法
1. 解析 DIMACS CNF 文件
use varisat_dimacs::DimacsParser;
use std::fs::File;
use std::io::BufReader;
fn parse_cnf_file() -> Result<(), Box<dyn std::error::Error>> {
let file = File::open("example.cnf")?;
let reader = BufReader::new(file);
let cnf = DimacsParser::parse(reader)?;
println!("解析成功,包含 {} 个子句", cnf.num_clauses());
Ok(())
}
2. 求解 CNF 公式
use varisat_dimacs::{DimacsParser, Solver};
use std::io::Cursor;
fn solve_cnf() -> Result<(), Box<dyn std::error::Error>> {
// 示例 CNF 公式:(x1 ∨ ¬x2) ∧ (x2 ∨ x3)
let cnf_input = "p cnf 3 2\n1 -2 0\n2 3 0";
let cnf = DimacsParser::parse(Cursor::new(cnf_input))?;
let mut solver = Solver::new();
// 添加所有子句到求解器
for clause in cnf.clauses() {
solver.add_clause(clause.iter().copied());
}
// 求解
match solver.solve() {
Some(true) => {
println!("公式可满足");
if let Some(model) = solver.model() {
println!("解模型: {:?}", model);
}
}
Some(false) => println!("公式不可满足"),
None => println!("求解超时"),
}
Ok(())
}
3. 从字符串解析并求解
use varisat_dimacs::{DimacsParser, Solver};
fn solve_from_string() {
let cnf_content = r#"
p cnf 4 3
1 -2 3 0
-1 2 4 0
-3 -4 0
"#;
let cnf = DimacsParser::parse(cnf_content.as_bytes()).unwrap();
let mut solver = Solver::new();
solver.add_formula(&cnf);
if let Some(true) = solver.solve() {
println!("找到解: {:?}", solver.model().unwrap());
}
}
高级配置
设置求解器选项
use varisat_dimacs::Solver;
use varisat::config::SolverConfig;
fn configure_solver() {
let config = SolverConfig::default()
.time_limit(std::time::Duration::from_secs(10))
.conflict_budget(1000);
let mut solver = Solver::with_config(config);
// ... 添加公式并求解
}
错误处理
use varisat_dimacs::DimacsParser;
use std::io::ErrorKind;
fn handle_parsing_errors() -> Result<(), Box<dyn std::error::Error>> {
let invalid_cnf = "invalid cnf content";
match DimacsParser::parse(invalid_cnf.as_bytes()) {
Ok(cnf) => {
// 处理成功解析
println!("成功解析 CNF");
}
Err(e) => {
eprintln!("解析错误: {}", e);
// 处理特定错误类型
}
}
Ok(())
}
性能提示
- 对于大型 CNF 文件,建议使用文件流式解析
- 可以调整求解器配置以获得更好的性能
- 考虑使用增量求解模式处理相关公式序列
示例 CNF 格式
p cnf 3 2
1 -2 0
2 3 0
其中:
p cnf
表示 CNF 问题格式3
表示变量数量2
表示子句数量- 每行以
0
结束表示一个子句 - 数字表示变量(负号表示否定)
这个库为处理 SAT 问题提供了完整的解决方案,从解析到求解都包含在内。
完整示例代码
// 完整示例:演示 varisat-dimacs 库的完整使用流程
use varisat_dimacs::{DimacsParser, Solver};
use varisat::config::SolverConfig;
use std::fs::File;
use std::io::{BufReader, Cursor, Write};
use std::time::Duration;
fn main() -> Result<(), Box<dyn std::error::Error>> {
// 示例1:从文件解析 CNF
println!("=== 示例1:从文件解析 CNF ===");
if let Ok(file) = File::open("example.cnf") {
let reader = BufReader::new(file);
match DimacsParser::parse(reader) {
Ok(cnf) => {
println!("成功解析文件,包含 {} 个子句", cnf.num_clauses());
}
Err(e) => {
eprintln!("文件解析错误: {}", e);
}
}
} else {
println!("未找到 example.cnf 文件,跳过文件解析示例");
}
// 示例2:从字符串解析并求解
println!("\n=== 示例2:从字符串解析并求解 ===");
let cnf_content = r#"
p cnf 4 3
1 -2 3 0
-1 2 4 0
-3 -4 0
"#;
let cnf = DimacsParser::parse(cnf_content.as_bytes())?;
let mut solver = Solver::new();
solver.add_formula(&cnf);
match solver.solve() {
Some(true) => {
println!("公式可满足");
if let Some(model) = solver.model() {
println!("解模型: {:?}", model);
}
}
Some(false) => println!("公式不可满足"),
None => println!("求解超时"),
}
// 示例3:使用配置的求解器
println!("\n=== 示例3:使用配置的求解器 ===");
let config = SolverConfig::default()
.time_limit(Duration::from_secs(5))
.conflict_budget(5000);
let mut configured_solver = Solver::with_config(config);
// 创建另一个测试公式
let test_formula = "p cnf 3 2\n1 -2 0\n2 3 0";
let test_cnf = DimacsParser::parse(Cursor::new(test_formula))?;
configured_solver.add_formula(&test_cnf);
match configured_solver.solve() {
Some(true) => println!("配置求解器:公式可满足"),
Some(false) => println!("配置求解器:公式不可满足"),
None => println!("配置求解器:求解超时"),
}
// 示例4:错误处理演示
println!("\n=== 示例4:错误处理演示 ===");
let invalid_cnf = "invalid cnf content";
match DimacsParser::parse(invalid_cnf.as_bytes()) {
Ok(_) => println!("意外成功解析"),
Err(e) => println!("正确捕获解析错误: {}", e),
}
Ok(())
}
// 辅助函数:创建示例 CNF 文件
fn create_example_cnf() -> Result<(), Box<dyn std::error::Error>> {
let mut file = File::create("example.cnf")?;
file.write_all(b"p cnf 3 2\n1 -2 0\n2 3 0")?;
println!("已创建示例 CNF 文件: example.cnf");
Ok(())
}
// 运行前可调用此函数创建测试文件
// create_example_cnf().unwrap();
这个完整示例演示了 varisat-dimacs 库的主要功能:
- 从文件解析 CNF 公式
- 从字符串内容解析并求解
- 使用自定义配置的求解器
- 错误处理的最佳实践
- 包含创建测试文件的辅助函数
要运行此示例,请确保在 Cargo.toml 中添加了正确的依赖,并根据需要创建测试文件。