從零開始編寫SAT求解器(一)

2021-10-09 01:14:23 字數 1551 閱讀 9861

背景知識

sat問題

sat問題是布林可滿足性問題(又名命題可滿足性問題)的縮寫,即給定乙個布林公式,判斷是否存在滿足它的解釋的問題。sat問題是第乙個被證明的np問題。這裡,我把問題簡化為:輸入乙個析取正規化(cnf),輸出乙個布林值表示它是否是可滿足的,若它是可滿足的,再輸出乙個使它為真的解釋。

dimacs檔案是對於cnf形式的命題公式的一種簡單的ascii表示,它的結構為:

開頭是幾行注釋,以字元』c』開頭

注釋行之後,是乙個檔案頭,格式為p cnf nvars nclauses,這裡nvars是公式中變數的數量,nclauses是命題中子句的數量

在檔案頭之後,每一行代表乙個子句。乙個子句是一系列空格分隔的非零整數,最後以0結尾。乙個正數代表對應的變數(從1到nvars),乙個負數代表對應變數的非。

舉個例子:

c a ****** example

p cnf 33-

120-

230-

1-30

它代表的公式是

dpll演算法是乙個判斷命題公式可滿足性的演算法,本質上是乙個深度優先搜尋演算法。基本思想為:首先假定乙個變數的值(真/假),然後檢查當前條件下命題公式是否為真,若為真,程式退出,返回可滿足以及乙個使命題公式為真的解釋;若為假,則回溯(可能改變當前變數的假定值,或退到之前的某個變數);若為假且沒有變數可以回溯,程式退出,返回該公式是不可滿足的。

專案架構

main函式如下:

#include

#include

"common.h"

#include

"dimacsparser.h"

#include

"dpll.h"

intmain

(int argc,

char

**ar**)

for(

int i =

1; i < argc; i++

)auto end = std::chrono::steady_clock::

now();

// timer end

if(sat)

}else

auto duration = std::chrono::duration_cast<:chrono::duration>

double

>>

(end - start)

; std::cout <<

" time: "

<< duration.

count()

<< std::endl;

}return0;

}

採用命令列輸入,首先判斷引數合法性,若合法,讀入檔案,將檔案解析,返回自定義的formula物件。接著呼叫dpll方法,返回是否可解;若可解,輸出乙個可行的解。可行解使用map儲存。

那麼,接下來的任務就是實現檔案解析、dpll核心演算法。

PyTorch從零開始(一)

之前嘗試過tenano,caffe,keras,tensorflow,這幾個我個人最喜歡的還是tensorflow,因為是google出品,技術崇拜,文件很全,並且我看的deepmind的 都是用的tensorflow框架。之前看的目標檢測的 一般用caffe的很多,人臉識別方面也是caffe是主流...

SpringBoot從零開始(一)

上來先看的這篇部落格 idea新建乙個springboot mybatis mysql專案,以及遇到的問題分享。在其中第9步自動生成的過程中,出現了錯誤如下 the server time zone value is unrecognized or represents more than one ...

從零開始學習javascript(一)

從基礎開始吧,加油 表示和處理乙個html或xml文件的常用方法,可以歸類為介面,其實從個人看來也就是個定義格式的標準?層層巢狀的節點樹 由此衍生的各類呼叫方法。dom也是有分類噠,比如xml dom 用於獲取 更改 新增或刪除 xml 元素的標準 和html dom 關於如何獲取 修改 新增或刪除...