c – 改进dpll算法的性能
发布时间:2020-12-16 07:01:50 所属栏目:百科 来源:网络整理
导读:我在C中实现DPLL算法,如 wikipedia所述: function DPLL(Φ) if Φ is a consistent set of literals then return true; if Φ contains an empty clause then return false; for every unit clause l in Φ Φ ← unit-propagate(l,Φ); for every literal
我在C中实现DPLL算法,如
wikipedia所述:
function DPLL(Φ) if Φ is a consistent set of literals then return true; if Φ contains an empty clause then return false; for every unit clause l in Φ Φ ← unit-propagate(l,Φ); for every literal l that occurs pure in Φ Φ ← pure-literal-assign(l,Φ); l ← choose-literal(Φ); return DPLL(Φ ∧ l) or DPLL(Φ ∧ not(l)); 但表现糟糕.在这一步: return DPLL(Φ ∧ l) or DPLL(Φ ∧ not(l)); 目前我正在努力避免创建Φ的副本,而是将l或不是(l)添加到Φ的唯一副本中,并在/当DPLL()返回false时将其删除.这似乎打破了算法给出错误的结果(UNSATISFIABLE,即使该集合是SATISFIABLE). 有关如何在此步骤中避免显式副本的任何建议? 解决方法
DPLL的一种不那么天真的方法避免了通过记录变量赋值和单位传播和纯文字赋值步骤中对子句所做的更改来复制公式,然后在生成空子句时撤消更改(回溯).因此,当变量x被赋值为true时,您将所有包含x的正文字的子句标记为非活动状态(之后忽略它们,因为它们已满足)并从包含它的所有子句中删除-x.记录哪些子句中包含-x,以便稍后可以回溯.同样记录您标记为非活动的条款.
另一种方法是跟踪每个未满足条款中未分配变量的数量.记录数字何时减少,以便您可以稍后回溯.如果计数达到1,则进行单位传播,如果数字达到0并且所有文字都为假,则进行回溯. 我上面写的“不太天真”,因为还有更好的方法.现代DPLL类型SAT求解器使用称为“两个监视文字”的惰性子句更新方案,其优点是不需要从子句中删除文字,因此在找到错误的赋值时不需要恢复它们.变量赋值仍然必须被记录和回溯,但不必更新与子句相关的结构使得两个观察文字比任何其他已知的SAT求解器回溯方案更快.毫无疑问,您将在课堂上了解这一点. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |