部分回溯搜索的通用算法

问题描述

回溯搜索是一种众所周知的解决问题的技术,在寻找有效解决方案时,它会遍历变量分配的所有可能组合。通用算法被抽象为简洁的高阶函数https://en.wikipedia.org/wiki/Backtracking

有些问题需要部分回溯,也就是说,它们混合了不知道不确定性(可以选择,这很重要,如果您弄错了,则必须回溯)和不在乎不确定性(可以选择,这无关紧要,也许重要的是您需要多长时间才能找到解决方案,但并不是正确性其中,您不必回溯。)

例如考虑可以用the DPLL algorithm解决的布尔可满足性问题。如果您尝试使用通用的回溯算法来表示,那么结果不仅会遍历所有2 ^ N个变量赋值(在一般情况下这是可悲的),而且还会重复出现整个N!尝试变量的顺序(完全不必要,效率极低)。

是否存在用于部分回溯的通用算法?一个简洁的高阶函数,它为不知道不关心选择都接受函数参数?

解决方法

如果我对您的理解正确,那么您是在询问树搜索是否破坏对称性。在您给出的特定示例中,变量分配列表的所有排列都是等效的。

对称将是特定于域的。通过急切的短路和回溯来修剪搜索树的更一般的技术也是如此。我使用了一些打破对称性的技术来概括。

一种方法是按规范的顺序搜索问题空间。如果设置变量10的分支仅尝试变量11、12及更高版本,而不尝试变量9、8或7,则它将不会搜索同一解的任何排列。它只会测试排列唯一的解决方案。 (在SAT解算的特定情况下,这可能会排除最佳搜索顺序,尽管您可以随意对变量进行重新排序。)

另一种方法是进行测试,以确保仅通过任何等效类的不同解决方案,理想情况下,可以在搜索树顶部附近对其进行检查。一个典型的例子是在8皇后问题中,检查您首先看到的行中的皇后是在棋盘的左侧还是右侧。她在右边的任何解决方案都是她在左边的其他解决方案的镜像,因此您可以将搜索空间减少一半。 (实际上,在这个问题上,您可以做得更好。)如果只需要测试可满足性,则可以使用一个过滤器,该过滤器仅保证(如果存在)解决方案,至少可以通过一个解决方案。

如果您有足够的内存,则还可以存储一组已经搜索过的分支,然后检查要考虑是否搜索的分支是否等同于该分支中已经存在的分支。对于具有大量对称性的搜索空间,比具有大量对称性唯一的解决方案的空间更实用。