警告消息 "Selected triggers ..." 是什么意思?
What does the warning message "Selected triggers ..." mean?
我在使用 VS 的 Dafny 插件时收到以下警告消息。谁能解释一下是什么意思?
Selected triggers: {a[i]} (may loop with "a[i + 1]"). Suppressing loops would leave this expression without triggers.
有问题的行是
assert forall i : int :: 0<=i<a.Length-1 ==> a[i] <= a[i+1] ;
此外,由于这只是一条警告消息,我是否可以得出验证成功的结论?
首先,你是对的,如果没有报告其他错误,那么你可以断定验证成功。
警告与 Z3(以及 Dafny)如何通过基于启发式模式的实例化处理量词有关。该消息说 Dafny 已决定 select a[i]
作为此量词 的触发器(模式),尽管 它有一个所谓的 "matching loop" 与 a[i+1]
。 Dafny 决定这样做是因为它觉得别无选择。
请注意,全称量词的模式仅在稍后 使用 量化事实时相关,而不是在证明它时相关。通过在模式确定的具体值上实例化它来使用普遍量化的事实。 (双重地,存在量词的模式仅在 证明 时才相关;通过尝试使用与模式匹配的值作为见证来证明存在量词。)
当使用与模式匹配的值实例化量词时,通用量词上的模式会导致匹配循环导致构造另一个不同的值。对于您的示例,模式 a[i]
表示“任何时候您有一个 a[blah]
形式的表达式在上下文中浮动,尝试通过为 [=13= 插入 blah
来实例化量词]。假设值 a[0]
在上下文中浮动。那么量词将在 i == 0
处实例化以产生基础子句
0 <= i < a.Length - 1 ==> a[0] <= a[1]
这个新子句被添加到上下文中,并包含值 a[1]
,它也与模式匹配。因此求解器可能会再次实例化量词,这将导致将值 a[2]
添加到上下文中。这可能会永远持续下去并降低求解器的性能。
使用像 Dafny 这样的工具的一部分技巧是设计公式以避免匹配循环。此公式的一种解决方法是将其重写为
forall i, j :: 0 <= i <= j < a.Length - 1 ==> a[i] <= a[j]
因为<=
是传递的,所以这在逻辑上等同于前面的公式。但是当模式为 {a[i], a[j]}
时它没有匹配循环(有两个量化变量,因此模式需要扩展以包含它们),因为用特定值实例化它不会创建匹配的新值模式。
此公式的另一个解决方法是
forall i, j :: 0 <= i <= j < a.Length - 1 && j == i+1 ==> a[i] <= a[j]
这个公式在逻辑上也等同于第一个,因为它约束 j
成为 i+1
的同义词。虽然这看起来是一种奇怪的写法,但它也消除了循环。
事实上,现代版本的 Dafny 会透明地将您的原始公式重写到最后一个公式中,以消除循环并避免警告。
我在使用 VS 的 Dafny 插件时收到以下警告消息。谁能解释一下是什么意思?
Selected triggers: {a[i]} (may loop with "a[i + 1]"). Suppressing loops would leave this expression without triggers.
有问题的行是
assert forall i : int :: 0<=i<a.Length-1 ==> a[i] <= a[i+1] ;
此外,由于这只是一条警告消息,我是否可以得出验证成功的结论?
首先,你是对的,如果没有报告其他错误,那么你可以断定验证成功。
警告与 Z3(以及 Dafny)如何通过基于启发式模式的实例化处理量词有关。该消息说 Dafny 已决定 select a[i]
作为此量词 的触发器(模式),尽管 它有一个所谓的 "matching loop" 与 a[i+1]
。 Dafny 决定这样做是因为它觉得别无选择。
请注意,全称量词的模式仅在稍后 使用 量化事实时相关,而不是在证明它时相关。通过在模式确定的具体值上实例化它来使用普遍量化的事实。 (双重地,存在量词的模式仅在 证明 时才相关;通过尝试使用与模式匹配的值作为见证来证明存在量词。)
当使用与模式匹配的值实例化量词时,通用量词上的模式会导致匹配循环导致构造另一个不同的值。对于您的示例,模式 a[i]
表示“任何时候您有一个 a[blah]
形式的表达式在上下文中浮动,尝试通过为 [=13= 插入 blah
来实例化量词]。假设值 a[0]
在上下文中浮动。那么量词将在 i == 0
处实例化以产生基础子句
0 <= i < a.Length - 1 ==> a[0] <= a[1]
这个新子句被添加到上下文中,并包含值 a[1]
,它也与模式匹配。因此求解器可能会再次实例化量词,这将导致将值 a[2]
添加到上下文中。这可能会永远持续下去并降低求解器的性能。
使用像 Dafny 这样的工具的一部分技巧是设计公式以避免匹配循环。此公式的一种解决方法是将其重写为
forall i, j :: 0 <= i <= j < a.Length - 1 ==> a[i] <= a[j]
因为<=
是传递的,所以这在逻辑上等同于前面的公式。但是当模式为 {a[i], a[j]}
时它没有匹配循环(有两个量化变量,因此模式需要扩展以包含它们),因为用特定值实例化它不会创建匹配的新值模式。
此公式的另一个解决方法是
forall i, j :: 0 <= i <= j < a.Length - 1 && j == i+1 ==> a[i] <= a[j]
这个公式在逻辑上也等同于第一个,因为它约束 j
成为 i+1
的同义词。虽然这看起来是一种奇怪的写法,但它也消除了循环。
事实上,现代版本的 Dafny 会透明地将您的原始公式重写到最后一个公式中,以消除循环并避免警告。