Tldr
主要也只需要阅读 IPASIR 接口,一个 User-Friendly 的接口,通过重写这些接口来更好的调用
CaDiCaL这个求解器
API Overview
求解器的状态
我们假定求解器会返回以下几种状态:
UNKNOWNSOLVINGSATUNSAT
主要给出了九个函数接口:
const char *ipasir_signature (void);void *ipasir_init (void);void ipasir_release (void *solver);void ipasir_set_terminate (void *solver, void *state, int (*terminate) (void *state));
void ipasir_add (void *solver, int lit_or_zero);void ipasir_assume (void *solver, int lit);int ipasir_solve (void *solver);int ipasir_val (void *solver, int lit);int ipasir_failed (void *solver, int lit);Service API
前面四个函数可以视为一组:
ipasir_signature主要是为了说明求解器的名称与版本(需要返回C-style的字符串)ipasir_init来创建一个新的求解器实例并返回一个指针(指向这个实例的指针)ipasir_release用于释放求解器的资源ipasir_set_terminate函数用于设置一个回调函数,以指示是否应中止搜索。- 回调函数的签名为
int terminate(void* state)。如果回调函数返回非零值,则表示应终止搜索。求解器必须在搜索过程中定时调用此函数,并在回调函数返回非零值时立即中止搜索。 - 调用此回调函数时,参数
state的值与ipasir_set_terminate函数第二个参数所接收的值相同。
- 回调函数的签名为
Solving API
后五个函数为另一组,我们的状态转移图如下:

- 调用
ipasir_init后,求解器的状态为UNKNOWN,并准备好接收子句和假设 - 调用
ipasir_solve函数时,求解器的状态转变为SOLVING - 当搜索过程完成时,根据结果的不同,状态会变为
SAT或UNSAT,搜索也可能被中止,此时求解器的状态将变回UNKNOWN
具体而言,五个函数分别做以下事情:
-
ipasir_add用于向当前子句中添加文字,这个函数与读取cnf文件类似,读到0就会将子句存储(默认为子句已结束),由此函数添加的子句不能被删除,需要删除的话可以通过加入一些假设进行子句删除(例如我需要删除子句 ,通过引入一个从没出现过的变量 加入到子句中 ,然后我们加入假设 即可删除这个子句,因为子句直接为真)Example
例如公式为 ,我们的调用链为:
ipasir_add(s, 1),ipasir_add(s, 2),ipasir_add(s, 0),ipasir_add(s, -3),ipasir_add(s, 0) -
ipasir_assume用于添加单元子句假设,所有已添加的假设仅对下一次ipasir_solve调用有效。当ipasir_solve调用结束时,所有假设都会被移除,随后可以指定新的假设集。 -
ipasir_solve用于在由ipasir_assume调用给定的假设条件下,求解通过ipasir_add调用所设定的公式。当被调用时,求解器会转变为SOLVING状态,直至公式求解完成或搜索被中断。- 若找到一个可满足的赋值,该函数将返回值 10,且求解器的状态转变为
SAT。 - 若问题被证明为不可满足,函数将返回值 20,并将状态转变为
UNSAT。 - 如果搜索过程中途被中断,则返回值为 0,同时求解器回到
UNKNOWN状态。
- 若找到一个可满足的赋值,该函数将返回值 10,且求解器的状态转变为
-
ipasir_val当ipasir_solve找到一个可满足的赋值从而使求解器处于SAT状态时,我们可以调用此函数来获取某个变量(或文字)的值。ipasir_val(s, lit)的返回值规则定义为:如果文字lit在该解下为真/被满足,则返回+lit;否则返回-lit。- 如果给定变量(文字)的真值在可满足的部分真值赋值中未被赋值,则返回值可能为零。
-
ipasir_failed若某个公式在特定假设下被判定为UNSAT,了解其中哪些假设实际被用于证明该不可满足性至关重要。所有被使用假设的合取本身已足以证明公式的不可满足性。通过调用ipasir_failed并以相关假设作为参数,即可获取此信息。如果该假设被使用过,函数返回值为 1,否则为 0。
我们允许在 UNSAT 状态下再次调用 ipasir_solve 函数,这是因为这种不可满足性可能是由假设导致的。由于每次调用 ipasir_solve 后,所有假设都会被清除,这意味着求解器的输入已经发生了改变,此时的公式可能是 SAT 的