IC3算法中的get_state, get_predecessor, generalize
IC3算法中的get_state, get_predecessor, generalize
在上一篇“IC3算法简析”中出现了几个函数,它们能确保IC3算法的高效实现,分别是:
- get_state()
- get_predecessor()
- generalize()
get_state()
\(get\_state(F[k] \land \neg P)\)函数的直观含义是“计算公式\(F[k]\)所表示的状态集合与\(\neg P\)所表示的坏态集合的交集”。
使用\(get\_state(F[k] \land \neg P)\)之前,应该确保\(F[k] \land \neg P\)是可满足的,也就是说公式\(F[k]\)所表示的状态集合与\(\neg P\)所表示的坏态集合存在交集。
使用一个cube来表示该交集,即有\(c = get\_state(F[k] \land \neg P)\) ,该cube也被称为counterexample
因为\(c\)(cube/公式)表示的集合是\(F[k]\)和\(\neg P\)的交集,因此有\(c\models F[k]\land \neg P\)可满足。只需找到一个\(c\),当\(c\)满足时,\(F[k]\land \neg P\)也满足。
如何获取counterexample \(c\)?
在上面说到,要确保\(F[k] \land \neg P\)是可满足的。
检查公式的满足性,需要调用SAT求解器。
若\(F[k] \land \neg P\)可满足,则\(is\_sat(F[k] \land \neg P)\)返回sat。
同时SAT求解器可以返回一种“该公式可满足情况下每个变量的赋值情况”。
例如: \(is\_sat( x_1\land \neg x_2)\)是可满足的,SAT求解器还可以返回\([ x_1 == True, x_2 == False]\)(公式满足时每个变量的赋值情况,也被称为model )
根据model,构造一个cube: 如果变量\(x_i\)取\(True\),则构造文字(literal)\(x_i\);如果变量\(x_i\)取\(False\),则构造文字(literal)\(\neg x_i\),再将所有构造的文字(literal)进行合取(\(\land\))。
例如,根据上述例子中的model可以构造的\(cube\)为\(x_1\land \neg x_2\)。
同理,对于\(is\_sat(F[k] \land \neg P)\)也可以如此构造一个对应的cube, 把这个得到cube作为\(c\)。
这样的\(c\)包含所有状态变量,因此只能表示一个状态(亦即这种简单方法构造的\(cube\)只是所求交集中的一个)。
但\(get\_state()\)位于while循环中,可以循环地求出交集中的所有状态。
get_predecessor()
在\(rec\_block()\)函数中,如果删除坏态集合\(s\)之后,序列条件4:
不能够成立,即\(is\_sat(F[i-1]\ \land\ \neg s\ \land\ T\ \land\ s')\)可满足。
说明在(\(F[i-1] \land \neg s\))所表示的状态集合中,还有一部分状态\(q\)无法一步迁移到(\(F[i]\ \land\ \neg s\))
这部分状态需要继续调用\(rec\_block()\)函数进行删除(blocking)。
如何获取这一部分状态\(q\)?
简单的办法是:参考上述\(get\_model()\)方法中获取状态集合的做法。
因为\(is\_sat(F[i-1]\ \land\ \neg s\ \land\ T\ \land\ s')\)可满足
则必有公式\(F[i-1]\ \land\ \neg s\)所表示的状态集合中的一个状态\(c\)使得上述公式满足。
因此,可以取\(is\_sat(F[i-1]\ \land\ \neg s\ \land\ T\ \land\ s')\)公式满足的情况下的状态变量的一种赋值情况。
又因为该状态\(c\)位于公式\(F[i-1]\ \land\ \neg s\)所表示的集合中,所以\(c\)只含有公式\(F[i-1]\ \land\ \neg s\)所包含的状态变量。
所以在取得\(is\_sat(F[i-1]\ \land\ \neg s \land\ T\ \land\ s')\)的sat model后,还要去除\(s'\)中的变量,即去除带prime符号的后继变量。
最后得到的\(c\)也只含有一个状态,但\(get\_predecessor()\)位于while循环中,故可以循环地去除\(q\)中的所有状态。
generalize()
inductive clause generalization
\(\neg g=generalize(\neg s,\ i)\)的作用是:计算出一个\(clause\):\(\neg g\)。这个\(\neg g\)中所包含的文字(literal)是\(\neg s\)所包含文字的子集,而且将\(\neg g\)添加到\(F[1],\dots, F[i]\)中之后,新的frame序列仍然能够满足序列条件(4)。
\(generalize\)的作用是将原本只包含很少状态(例如,一个状态)的\(cube\)规约到包含较多状态的\(cube\)(同时满足序列条件),例如上述两个函数中,求得最后的\(c\)之后,可以使用类似于\(generalize\)的过程进行处理。
generalize过程已经有多种版本的实现。
-
Minimal inductive clause (MIC)-based inductive generalization
A. R. Bradley and Z. Manna, “Checking safety by inductive generalization of counterexamples to induction,” in Proc. Int. Conf. Formal Methods Comput.-Aided Design (FMCAD), Austin, TX, USA, 2007, pp. 173–180. -
Iterative inductive generalization algorithm
N. Eén, A. Mishchenko, and R. K. Brayton, “Efficient implementation of property directed reachability,” inProc. Int. Conf. Formal Methods Comput.-Aided Design (FMCAD), Austin, TX, USA, 2011,pp. 125–134. -
Counterexamples to generalization (CTG)-based inductive generalization
Z. Hassan, A. R. Bradley, and F. Somenzi, “Better generalization in IC3,” in Proc. Int. Conf. Formal Methods Comput.-Aided Design (FMCAD), Portland, OR, USA, Oct. 2013, pp. 157–164. -
simple generalization
一种简单的实现如下:
clause generalize(!s, i):
cls = !s
for each l in !s do:
trycls = the clause obtained by deleting l from cls
if is_sat(I=>trycls) and is_sat(F[j-1] & T & trycls => trycls'):
cls = trycls
return cls
可以看到,\(generalize\)算法尝试对\(\neg s\)中的文字(literal)逐个去除
同时确保序列条件能够得到满足。
其中\(is\_sat(I\Longrightarrow trycls)\)是保证序列条件3能够满足。