CNF公式化简:单子句设置true or fause,去除相关子句,结果为两个字句相反就回溯,结果为空就为正解(分支回溯策略)
一、算法思想:
基于树/二叉树的回溯搜索算法,主要使用三种基本处理策略:
1.纯文字规则
首先,在给定的公式中寻找只出现了一次的文字,这样的文字被称为纯文字。
2.单子句规则
如果子句集S中有一个单子句L,那么L一定取真值,于是可以从S中删除所有包含L的子句(包括单子句本身),得到子句集S1,如果它是空集,则S可满足。否则对S1中的每个子句,如果它包含文字¬L,则从该子句中去掉这个文字,这样可得到子句集合S2。S可满足当且仅当S2可满足。单子句传播策略就是反复利用单子句规则化简S的过程。过程中使用集合的并计算来求解。
3.分支策略
按某种策略选取一个文字L.如果L取真值,则根据单子句传播策略,可将S化成S2;若L取假值(即¬L成立)时,S可化成S1.
二、实例分析:
F = {,,, }
1.首先应用单子句规则,将-2设置为真,去除所有包含-2 的子句(即包含-2后为真),化简结果如下:
(tips:子句 12
中的变量2已经被赋值为假,因此我们可以消去子句
1 2
,因为无论变量1取何值,子句 12
都为真)
2.这时子集中不存在单子句,施行分支策略:
1)将3赋值为真
如果变量3赋值为真,那么子句 3 4
就变成了永真子句(因为3为真,所以 3 4
必然为真),我们可以从集合中移除这个子句。剩下的子句是:
此时如果变量1赋值为真,那么 -1
为假,子句 -1 6
的真值取决于变量6。如果变量6为真,那么子句 -1 6
为真;如果变量6为假,那么子句 -1 6
为假,这将导致整个集合不可满足。但是,由于我们不需要具体求解变量6的值,只要知道存在至少一种赋值使得集合为真即可。
即意味我们找到了一个解:
- 变量1为假(false)
- 变量2为假(false)
- 变量3为真(true)
- 变量4可以为真(true)或假(false),因为变量4不在任何子句中
- 变量6可以为真(true)或假(false),因为变量6不在任何子句中
2)将3赋值为假
如果变量3赋值为假,那么子句 3 4
取决于变量4的值。如果变量4为真,那么子句 3 4
为真;如果变量4为假,那么子句 3 4
为假,这将导致整个集合不可满足。但是,我们同样不需要具体求解变量4的值,因为我们在情况1中已经找到了一个解。
交错使用上述三种策略可不断地对公式化简,并最终达到终止状态,其执行过程可表示为一棵二叉搜索树。
三、代码实现(待完善)
思考:
1.数独求解算法如何表示特定数字只出现一次?(单个cell)
每一个cell的数用一个三位数表示,第一位表示行数,第二位表示列数,第三行表示当前cell 数字
-
约束传播(Constraint Propagation):
- 当你分配一个数字到一个特定的单元格时,你可以立即更新与之相关的行、列和3x3子格,以确保该数字不会在那些位置再次出现。
- 例如,如果你在第二行第三列放置了数字3,那么你可以立即更新第二行、第三列以及包含该单元格的3x3子格,确保数字3不会出现在这些位置的任何其他单元格中。
-
单值单元(Single Candidate Cell):
- 如果一个单元格只有一个可能的数字(即只有一个候选数字),那么这个数字必须被放置在这个单元格中。
- 这通常是通过检查行、列和子格来实现的。如果一个单元格是唯一的候选数字,那么这个数字就被放置在这个单元格中。
-
唯一候选数(Unique Candidate Number):
- 如果一个数字在特定的行、列或子格中只能出现在一个特定的单元格中,那么这个数字必须被放置在这个单元格中。
- 这类似于单值单元,但是它关注的是数字而不是单元格。
2. 语义编码向自然编码转换
1-999--->1-729 ijn--->(i-1)*81 + (j-1)*9 + n
解码逐步取模