You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Dafny中无重复元素序列相关性质的证明问题及解法

问题描述

假设有一个元素互不相同的序列s,将该性质定义为如下谓词:

predicate all_element_different(s: seq<int>)
{
  forall i,j :: 0 <= i < j < |s| ==> s[i] != s[j]
}

该性质也有等价表述:

forall i,j :: 0 <= i < |s| && 0 <= j < |s| && i != j ==> s[i] != s[j]

为此编写引理以证明两种表述等价:

lemma different_properties(s: seq<int>)
  requires all_element_different(s)
  ensures forall i,j :: 0 <= i < |s| && 0 <= j < |s| && i != j ==> s[i] != s[j]
{
}

接下来,因需求需对序列做生成式排序(不修改原序列),定义插入排序函数如下:

function insertionSort(s: seq<int>): (r: seq<int>)
  ensures multiset(s) == multiset(r)
  ensures sorted(r)
  ensures forall x :: x in s ==> x in r
  ensures |s| == |r|

调用该函数后得到新序列r,满足以下断言:

var r := insertionSort(s);
assert multiset(s) == multiset(r);
assert |s| == |r|;
//assert sorted(r); This property is not used here
assert forall x :: x in s ==> x in r;
assert all_element_different(s);

显然all_element_different(r)应当成立,但无法直接证明,因此提取出如下待证引理:

lemma sequence_properties(s: seq<int>, r: seq<int>)
  requires multiset(s) == multiset(r)
  requires |s| == |r|
  requires all_element_different(s)
  ensures all_element_different(r)
{
}

基于多重集等价性的证明方法

通过建立序列元素唯一性与多重集元素计数为1的等价关系,用矛盾法完成证明。

首先定义核心等价引理:

lemma equivalence(s: seq<int>)
  ensures UniqueElements(s) <==> forall k :: k in multiset(s) ==> multiset(s)[k] == 1

以下是完整证明实现:

1. 利用等价性推导目标引理

lemma UniqueMultiSet(s: seq<int>, r: seq<int>)
  requires UniqueElements(s)
  requires |s| == |r|
  requires multiset(s) == multiset(r)
  ensures UniqueElements(r)
{
  equivalence(s);
  equivalence(r);
}

2. 元素唯一推导出多重集计数为1

lemma unique_elements_imply_multiplicity_equals_1(s: seq<int>)
  requires UniqueElements(s)
  ensures forall k :: k in multiset(s) ==> multiset(s)[k] == 1
{
  var ms := multiset(s);
  if !(forall k :: k in ms ==> ms[k] == 1)
  {
    var k :| k in ms && ms[k] > 1;
    var i :| 0 < i < |s|;
    var left := s[..i];
    var right := s[i..];
    assert s == left+right;
    // assert multiset(s) == multiset(left) + multiset(right);
    // assert multiset(s)[k] == multiset(left)[k] + multiset(right)[k];
    if k in left && k in right
    {
      assert !UniqueElements(s);
    } else if k in left && k !in right
    {
      unique_elements_imply_multiplicity_equals_1(left);
    } else if k !in left && k in right
    {
      unique_elements_imply_multiplicity_equals_1(right);
    }else
    {
      assert k !in multiset(s);
    }
  }
}

3. 多重集计数为1推导出元素唯一

lemma multiplicity_equals_1_imply_unique_elements(s: seq<int>)
  requires forall k :: k in multiset(s) ==> multiset(s)[k] == 1
  ensures UniqueElements(s)
{
  if(!UniqueElements(s))
  {
    var i, j, k :| 0 <= i < j < |s| && s[i] == s[j] == k;
    var left := s[..i+1];
    var right := s[i+1..];
    assert s == left + right;
    assert j >= i+1;
    assert k in left && k in right;
    assert multiset(s)[k] >= 2;
  }
}

4. 完成等价性证明

lemma equivalence(s: seq<int>)
  ensures UniqueElements(s) <==> forall k :: k in multiset(s) ==> multiset(s)[k] == 1
{
  if(UniqueElements(s))
  {
    unique_elements_imply_multiplicity_equals_1(s);
  }
  if(forall k :: k in multiset(s) ==> multiset(s)[k] == 1)
  {
    multiplicity_equals_1_imply_unique_elements(s);
  }
}

内容的提问来源于stack exchange,提问作者MogicFrog

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 12:24:55