具体化和半具体化谓词
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
问:
- 所有 全局谓词 现在都有
_reif
版本了吗?
- 是否所有 全局谓词 也有
_imp
版本?
看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(...)
为假,那么我们仍然需要 B
为 true
,如果 B
为 false
我们仍然要强制 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。
最近我注意到 FlatZinc
的某些最新版本支持 半具体化谓词 :
Half-reified predicates essentially represent constraints that are implied by a Boolean variable rather than being equivalent to one.
source: docs
问:
- 所有 全局谓词 现在都有
_reif
版本了吗? - 是否所有 全局谓词 也有
_imp
版本?
看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(...)
为假,那么我们仍然需要 B
为 true
,如果 B
为 false
我们仍然要强制 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。