从零开始编写SAT求解器(一)
从零开始编写SAT求解器(一)
- 从零开始编写SAT求解器(一)
- 源起
- 背景知识
- SAT问题
- DIMACS文件
- DPLL算法
- 项目架构
从零开始编写SAT求解器(一)
源起
最近在github上看到了非常有名的cryptominisat开源项目。目前的SAT问题自动求解器有在线版的MiniSAT,但是这个需要科学上网。正好最近一直在写Java和python,C++有点生疏,而网上有大神用Haskell实现了简易的SAT求解器,就想用C++写一个自己的SAT求解器。(C++是最棒的语言)
背景知识
SAT问题
SAT问题是布尔可满足性问题(又名命题可满足性问题)的缩写,即给定一个布尔公式,判断是否存在满足它的解释的问题。SAT问题是第一个被证明的NP问题。这里,我把问题简化为:输入一个析取范式(CNF),输出一个布尔值表示它是否是可满足的,若它是可满足的,再输出一个使它为真的解释。
DIMACS文件
DIMACS文件是对于CNF形式的命题公式的一种简单的ASCII表示,它的结构为:
- 开头是几行注释,以字符’c’开头
- 注释行之后,是一个文件头,格式为
p cnf nvars nclauses
,这里nvars是公式中变量的数量,nclauses是命题中子句的数量 - 在文件头之后,每一行代表一个子句。一个子句是一系列空格分隔的非零整数,最后以0结尾。一个正数代表对应的变量(从1到nvars),一个负数代表对应变量的非。
举个例子:
c A simple examplep cnf 3 3-1 2 0-2 3 0-1 -3 0
它代表的公式是
(¬P1∨P2)∧(¬P2∨P3)∧(¬P1∨¬P3)(\neg{P_1}\vee{P_2})\wedge(\neg{P_2}\vee{P_3})\wedge(\neg{P_1}\vee{\neg{P_3}})(¬P1∨P2)∧(¬P2∨P3)∧(¬P1∨¬P3)
DPLL算法
DPLL算法是一个判断命题公式可满足性的算法,本质上是一个深度优先搜索算法。基本思想为:首先假定一个变量的值(真/假),然后检查当前条件下命题公式是否为真,若为真,程序退出,返回可满足以及一个使命题公式为真的解释;若为假,则回溯(可能改变当前变量的假定值,或退到之前的某个变量);若为假且没有变量可以回溯,程序退出,返回该公式是不可满足的。
项目架构
main函数如下:
#include <chrono>#include "common.h"
#include "DimacsParser.h"
#include "DPLL.h"int main(int argc, char **argv) {//argc=2;if (argc < 2) {std::cerr << "error: no input files" << std::endl;return 1;}for (int i = 1; i < argc; i++) {std::string f(argv[i]);//std::string f="tests\\test5.dimacs";std::cout << f << std::endl;formula phi = DimacsParser::parse(f);// timer startauto start = std::chrono::steady_clock::now();DPLL solver(phi);bool sat = solver.check_sat();model m;if (sat) {m = solver.get_model();}auto end = std::chrono::steady_clock::now();// timer endif (sat) {std::cout << " sat" << std::endl;for (const auto &p : m) {std::cout << " " << p.first << " -> " << p.second << std::endl;}} else {std::cout << " unsat" << std::endl;}auto duration = std::chrono::duration_cast<std::chrono::duration<double>>(end - start);std::cout << " time: " << duration.count() << std::endl;}return 0;
}
采用命令行输入,首先判断参数合法性,若合法,读入文件,将文件解析,返回自定义的formula对象。接着调用DPLL方法,返回是否可解;若可解,输出一个可行的解。可行解使用map存储。
那么,接下来的任务就是实现文件解析、DPLL核心算法。
从零开始编写SAT求解器(一)相关推荐
- windows下编译以及运行cryptominisat 求解器(sat求解器)
cryptominisat是由msoos所开发的一款sat求解器,sat的具体问题另外一篇博客里有详细介绍点击打开链接,本篇文章只介绍如何在windows下运行cryptominisat,将自己遇到的 ...
- sat求解器解哈密顿回路
资料:https://ozanerdem.github.io/jekyll/update/2019/11/17/representation-in-sat.html https://modref.gi ...
- 基于DPLL的SAT求解器
SAT问题 什么是SAT问题? SAT问题即命题逻辑公式的可满足性问题(satisfiability problem),是计算机科学与人工智能基本问题,是一个典型的NP完全问题. 对于任一布尔变元x, ...
- Flow Free solver[连线游戏求解器]
Fast automated solver for Flow Free puzzles written in C. 用C语言编写的连线游戏的快速自动求解器. GIF of the final pro ...
- JAX-FLUIDS:可压缩两相流的完全可微高阶计算流体动力学求解器
原文来自微信公众号"编程语言Lab":论文精读 | JAX-FLUIDS:可压缩两相流的完全可微高阶计算流体动力学求解器 搜索关注"编程语言Lab"公众号(HW ...
- 2-2 组合优化问题-常用模型与通用求解器
组合优化问题常用模型 组合优化问题常常难以求解,我们可以把这些转化为目前已经有成熟求解器的模型. 1. 可满足性问题(Satisfiability, SAT) 上一节已经讲过,SAT 是一个 NPC ...
- 开尔文函数 matlab,KELVIN二维/ RS传热求解器
原标题:KELVIN二维/ RS传热求解器 本文由中国科学软件网翻译整理 KELVIN是一款2D/RS热分析工具,使用图形和轮廓,剖面图和箭头图显示温度.热流密度和温度梯度.探索一切省时省时.性价比高 ...
- 强化学习 求解迷宫问题_使用天真强化学习的迷宫求解器
强化学习 求解迷宫问题 This is a short maze solver game I wrote from scratch in python (in under 260 lines) usi ...
- matlab 读取图片后分区域编号_你的第一个有限元求解器——仅十行MATLAB代码
有限元分析话题中有不少讨论有限元求解器的问题,但大都停留在概念层面,未见实际代码.望本文能略起抛砖引玉之作用. 以下代码是基于MATLAB编写. 问题描述 考虑一平面有界区域 ,设其边界为 .我们求解 ...
最新文章
- Linux 的内存管理工具和调优参数
- 使用Android Studio搭建Android集成开发环境
- 重新分区_手机DATA重新分区教程(超详细)
- Docker 安装JDK1.8
- 糟糕!HttpClient 连接池设置引发的一次雪崩!
- 视频格式转换工具使用
- Android RelativeLayout和LinearLayout性能分析
- FileFilter过滤器的原理和使用
- CloudCC:2017年下半年企业移动CRM市场风向窥测
- PHP危险函数被禁止怎么绕过,PHP危险函数(disable_functions)设置
- ajax卡死new formdata(),使用FormData和jQuery上传Ajax大文件无法发布数据
- SQL Sever 数据完整性
- 云更新网吧系统服务器,云更新网吧服务器环境要求
- YOLOX安装及训练
- JAVA串口通信开发
- 数实融合激变时刻,与长期主义同行
- eyebeam电话呼叫软件使用及配置方法
- 剑指Offer——京东实习笔试题汇总
- 以后你们就要给张一鸣还“花呗”了
- 基于Docker-compose搭建Redis高可用集群-哨兵模式(Redis-Sentinel)