具体化和半具体化谓词

reified and half-reified predicates

最近我注意到 FlatZinc 的某些最新版本支持 半具体化谓词 :

Half-reified predicates essentially represent constraints that are implied by a Boolean variable rather than being equivalent to one.

source: docs

问:

share/minizinc/的内容,发现在std里面只有nosets.mzn使用了_imp谓词,所以我的印象是还没有强制要求支持 _imp 谓词。 问:这是正确的吗?

查看文档,我发现了这个:

Solver libraries should therefore provide reified versions of constraints whenever possible. The library contains files fzn__reif.mzn for this purpose.

source: docs

如果我解释正确,则不需要支持 _reif 谓词,因为它们已经在 share/minizinc 中重新定义(尽管它可能对性能有益)。 问:这是正确的吗?

最常见的谓词(调用)R(...) 用作实际约束:constraint R(...)。处理表达式 R(...) 时的问题是现在是否可以将其直接提供给求解器,或者它是否具有需要评估的重新定义。

如果在更复杂的表达式 B \/ R(...) 中使用谓词,那么我们不能只给求解器调用 R(...),因为我们不想强制执行 R(...)。相反,我们想知道 R(...) 描述的关系是否成立。这就是我们所说的具体化。

因此,必须有一个 R_reif(..., r) 强制 r <-> R(...) 的谓词。本质上这给出了 R(...) 的真值。同样,当编译器得到表达式 R_reif(...,r) 时,它会查看是否可以直接将其提供给求解器,或者是否有可用的重新定义。如果这两个都不可用,那么编译器将尝试从 R(...) 的重新定义生成一个重新定义。如果这也失败,那么编译器将停止编译。

如果我们回顾一下我们的示例 B \/ R(...),那么您可能会注意到使用 r <-> R(...) 超出了必要的范围。如果 R(...) 为假,那么我们仍然需要 Btrue,如果 Bfalse 我们仍然要强制 R(...);但是,我们知道没有什么会迫使 R(...) 变成 false。我们说 R(...) 是在积极的背景下。在这种情况下,这意味着 r -> R(...) 就足够了。这被称为 half-reification.

在 MiniZinc 中可以引入一个 R_imp(..., r) 谓词来提供一个单独的半具体化谓词。这又可以是直接传递给求解器或重新定义的东西。如果编译器必须具体化表达式 R(...) 并发现它处于正上下文中,那么它将首先尝试查看是否可以找到 R_imp(..., r),否则回退到 R_reif(..., r) .请注意,如果生成重定义,则调用的上下文向内传播,并且半具体化仍然可以在重定义中发生。

直接总结并回答您的问题:

  • 所有全局谓词都可以具体化。 _reif 的重新定义可以显式定义,也可以通过重新定义的生成来生成。
  • None 的全局变量是半具体化的。这不是必需的,因为在生成具体化的重新定义时仍然可以触发半具体化,并且目前没有已知的显式半具体化定义表现更好的情况。
  • 目前没有需要求解器支持的半具体化谓词。但是请注意,求解器(包括 FlatZinc 内置函数)可以将任何 _reif 谓词实现为 _imp
  • 不需要支持任何全局_reif谓词;然而,在 FlatZinc 内置函数中有几个必需的 _reif 谓词 do 需要支持。如果求解器没有重新定义或实现这些谓词,那么求解器将无法支持生成的 FlatZinc。