改进dpll算法的性能 我在C++中实现了 dPLL 算法,如:

改进dpll算法的性能 我在C++中实现了 dPLL 算法,如:,c++,algorithm,recursion,sat-solvers,dpll,C++,Algorithm,Recursion,Sat Solvers,Dpll,但是有一个糟糕的表现。在此步骤中: return DPLL(Φ ∧ l) or DPLL(Φ ∧ not(l)); 目前,我试图避免创建Φ的副本,而是将l或not(l)添加到Φ的唯一副本中,并在/ifDPLL()返回false时删除它们。这似乎破坏了给出错误结果的算法(不可满足,即使集合是可满足的) 关于如何避免此步骤中的显式复制有何建议?一种不太简单的DPLL方法通过在单元传播和纯文字赋值步骤中记录变量赋值和对子句所做的更改,然后撤消更改(回溯),从而避免复制公式当生成空子句时。因此,当变量

但是有一个糟糕的表现。在此步骤中:

return DPLL(Φ ∧ l) or DPLL(Φ ∧ not(l));
目前,我试图避免创建
Φ
的副本,而是将
l
not(l)
添加到
Φ
的唯一副本中,并在/if
DPLL()
返回
false时删除它们。这似乎破坏了给出错误结果的算法(
不可满足
,即使集合是可满足的


关于如何避免此步骤中的显式复制有何建议?

一种不太简单的DPLL方法通过在单元传播和纯文字赋值步骤中记录变量赋值和对子句所做的更改,然后撤消更改(回溯),从而避免复制公式当生成空子句时。因此,当变量x被赋值为true时,您会将所有包含正文本x的子句标记为非活动(并在满足后忽略它们),并从包含它的所有子句中删除-x。记录哪些子句中有-x,以便以后可以回溯。同时记录出于相同原因标记为不活动的条款

另一种方法是跟踪每个未满足子句中未分配变量的数量。记录数字减少的时间,以便以后可以回溯。如果计数达到1,则执行单元传播;如果计数达到0,且所有文本都为false,则执行回溯


我在上面写了“不那么天真”,因为还有更好的方法。现代DPLL类型SAT解算器使用一种称为“两个关注的文本”的惰性子句更新方案,其优点是不需要从子句中删除文本,因此在发现错误的赋值时不需要恢复它们。变量赋值仍然需要记录和回溯,但不必更新子句相关结构,这使得两个关注的文本比任何其他已知的SAT解算器回溯方案都要快。你肯定会在课堂上了解到这一点。< / P>如果你想帮助你的话,你的C++代码怎么写?”艾略夫:这很可能会在我的第一次谷歌搜索中把代码发给我的同学,这样我可能会遇到麻烦。除此之外,我更希望有算法方面的东西,我可以自己动手实现。标记非活动听起来很有趣,但我想我还需要区分不同的调用级别,因为这是一个递归算法。顺便问一下,你还记得天真算法的可行性吗?我的方法很难在大约1分钟内解决100个变量和300多个长度为3的子句的问题,这合理吗?这种性能与我的预期一致,但在同一SAT实例上,性能可能会因变量赋值顺序和其他因素而大不相同。
return DPLL(Φ ∧ l) or DPLL(Φ ∧ not(l));