在不否定的情况下找到布尔值乘积和的所有解的算法

Algorithm to find all solutions for a boolean sum of products without negation

提问人:dln385 提问时间:9/6/2021 更新时间:9/6/2021 访问量:90

问:

我正在开发一个益智游戏,每个关卡都可以通过一系列动作来完成。有八个不同的动作标记为 a-h。我开发了一个求解函数,可以传递一个级别 L 和一组可用的移动 S,它将返回该级别是否可以仅使用 S 的移动来求解。

例如,如果我调用,那么函数可能会发现一系列移动解决了难题,因此它返回 .solve(L, {a,b})aaabbaabaTrue

我有兴趣编写一个算法来找到足以解决一个关卡的所有可用动作集。由于有八个不同的动作,因此有 28 = 256 组可能的动作。我可以全部检查,但这似乎相当浪费。求解器相对较慢,因此目标是使用逻辑来减少我需要运行求解器的次数。

如果仅移动 c 就足以求解一个水平(即 ),那么该水平也可以用移动 c 和 d 来解决(其中移动 d 可用但不需要)。同样,如果一个关卡除了 c 之外的每一步都无法求解(即 ),那么除了 c 和 d 之外,该关卡也将在每一步都无法求解。solve(L, {c}) == Truesolve(L, {a,b,d,e,f,g,h}) == False

更一般地说:

  • 如果和 S⊆T,则solve(L, S) == Truesolve(L, T) == True
  • 如果和 T⊆S,则solve(L, S) == Falsesolve(L, T) == False

我相信这意味着该水平可以表示为不否定的产品总和。例如,一个级别可以表示为 。(在这种情况下,该级别可以用集合 {a}、{c,d,e}、{d,e,f} 以及这些集合的任何超集求解。a ∨ c∧d∧e ∨ d∧e∧f

我怀疑一个好的算法可能首先检查只包含一个动作的集合和那些只包含一个动作的集合,以便可以修剪大量的可能性。我试图提出一种递归算法,但我很难将这两种类型的修剪结合起来。

算法 性能 优化 逻辑

评论

0赞 j_random_hacker 9/6/2021
我不认为这两种类型的修剪可以同时实现,因为 AFAICT 任何能够修剪已知-真解的策略都依赖于从不从当前集合中删除移动(仅添加它们)的正确性,而任何启用已知-错误解决方案修剪的策略都依赖于从不向当前集添加移动(仅删除它们)的正确性。哪种策略更好取决于您认为是否需要许多动作,或者几步就足够了。
0赞 kcsquared 9/6/2021
最佳策略很大程度上取决于 'solve' 函数的性能特征:如果 S 的大小增加 1,solve() 的运行时间会翻倍吗?如果 solve() 是恒定时间,而与 S 的大小无关,那么最小解集的典型大小就变得很重要,并且组合修剪策略开始变得可行。
0赞 j_random_hacker 9/6/2021
@kcsquared:我看不出一个能详尽地找到所有最小解的递归策略如何同时使用两种修剪策略——你能进一步解释一下它是如何做到的吗?
0赞 kcsquared 9/6/2021
@j_random_hacker当然;如果我们对解决方案(数量或预期规模)一无所知,那么组合策略就很难评估;您可以使用两者来“预处理”简单的实例。例如,假设 N 很大,求解 (S) 取 2^|S|时间,而最小的解决方案是罕见的和小的。然后,您可以使用随机算法快速消除大面积的解决方案空间。从 S 空开始,当 S 不是解决方案并且小于某个阈值时,向 S 添加一个随机元素并尝试 S。一旦 S 是解决方案,请继续删除元素以获得最小解决方案。
0赞 j_random_hacker 9/6/2021
@kcsquared:这听起来像是找到一些解决方案的好方法,但 OP 希望“找到所有足以解决关卡的可用动作集”。

答:

1赞 dln385 9/6/2021 #1

给定 n 个不同的移动,即使是最好的算法,在最坏的情况下也需要运行求解器非常接近 O(2n 次,这几乎不比蛮力好。

考虑有八个不同动作和一个可以通过四个动作的任意组合来解决的关卡的情况。这些动作集看起来像 {a,b,c,d}、{a,b,c、e} 等。从八个选项中选出 8 个选择 4 = 70 组四个动作。这些集合都不是彼此的子集,因此此级别最简单的 Sum of Products 表达式将包含 70 项。

考虑一个已经提供的算法,即所有 56 组三步棋都无法提供此级别的解决方案。该算法至少仍需要检查所有 70 组四步棋,以验证每组是否足够。

推广这个最坏情况的水平,给定 n 个不同的移动,算法需要运行求解器至少 n 选择 n/2 次。对于较大的 n

2n choose n is approximately equal to 2 to the 2n all over the square root of n pi

因此,没有一种高效的算法在所有情况下都表现良好。正如 j_random_hackerkcsquared 所推测的那样,最佳策略必然取决于水平总体的特征和求解器的算法复杂性。