簡體   English   中英

斷言的前提條件在互感 Dafny 引理中可能不成立

[英]Asserted precondition might not hold in mutual inductive Dafny lemmas

我正在嘗試使用記錄交互的樹來證明 Dafny 中具有副作用的程序的語義,遵循自由單子方法。 因此,語義將產生以下形狀的樹(簡化為僅用於讀取輸入的一條指令)。

datatype Prog<A>
  = Return (pure : A)
  | Get(input : string -> Prog<A>)

主要問題是這些是無限分支的樹,在 Dafny 中使用這些樹需要一些技巧,因為它們對深度沒有限制,盡管每片葉子都可以通過有限的路徑到達。

我現在想做的是將大步語義定義為歸納關系, 請參閱文章《Dafny 中的有根據的函數和極限謂詞:教程》 這是語言的一小部分,只有一個用於閱讀的命令和一個用於命令的順序組合。 關系big_step_bind依次組成兩個交互樹(bind 是組成單子計算的映射的常用術語),而big_step是大步語義關系。 這些關系是歸納和相互定義的。

datatype Com =  GetC | SeqC(Com, Com)

type Store = map<int, string>

least predicate big_step_bind(c : Com, p : Prog<Store>, q : Prog<Store>) {
  match p {
    case Return(s) => big_step(c, s, q)
    case Get(f)    => exists g :: q == Get(g) && forall i :: big_step_bind(c, f(i), g(i))
  }
}

least predicate big_step(c : Com, s : Store, p : Prog<Store>) {
  match c {
    case GetC =>
      p == Get(i => Return(s[0 := i]))
    case SeqC(c1, c2) =>
      exists p1 :: big_step(c1, s, p1) && big_step_bind(c2, p1, p)
  }
}

到目前為止,一切都運作良好。 但是要在生成的交互樹上運行任何函數,我需要知道大步語義只提供有根據的樹,因為 Dafny 不允許通過對Prog進行遞歸定義並抱怨不終止。 因此,我定義了一個謂詞wfTree ,它挑選出所有類型為Prog的有根據的樹,實際上應該是所有這些樹。

least predicate wfTree<A> (p : Prog<A>){
  match p {
    case Return(b) => true
    case Get(g)    => forall x :: wfTree(g(x))
  }
}

問題

現在我想證明大步語義“產生”的所有樹都是有根據的:

least lemma big_step_bind_wf(c : Com, p : Prog<Store>, q : Prog<Store>)
  requires wfTree(p)                                      // (1)
  requires big_step_bind(c, p, q)
  ensures wfTree(q)
{
  match p {
    case Return(s) => big_step_wf(c, s, q);
    case Get(f) =>
      var i ;
      var q' :| big_step_bind(c, f(i), q');
      big_step_bind_wf(c, f(i), q');
  }
}

least lemma big_step_wf(c : Com, s : Store, p : Prog<Store>)
  requires big_step(c, s, p)
  ensures wfTree(p)
{
  match c {
    case GetC => return;
    case SeqC(c1, c2) =>
      var p1 :| big_step(c1, s, p1) && big_step_bind(c2, p1, p);
      big_step_wf(c1, s, p1);                             // (2)
      assert wfTree(p1);                                  // (3)
      big_step_bind_wf(c2, p1, p);                        // (4)
  }
}

同樣,這些引理通過歸納相互證明。 但是,證明的最后一步(4)無法驗證。 達芙妮 說

錯誤:此調用的先決條件可能不成立。

並且指的是(1),這是big_step_bind_wf的前提條件,需要wfTree(p1)保持。 然而,(2) 恰好具有作為后置條件,並且 (3) 處的assert顯示了這一點。

我現在的問題是:為什么 Dafny 不能確定前提條件是否成立? 我是否遺漏了什么或者這是實施的問題? 非常感謝!

我能夠通過將有根據的程序前置條件移動到后置條件(至少是綁定的引理)來驗證。


datatype Program<T> = Result(T) | Get(input: string -> Program<T>)
    
datatype Command = GetInput | Sequence(Command, Command)
    
    
least predicate big_step_bind
   (c: Command,
    p1: Program<string>,
    p2: Program<string>)
{
    match p1 {
      case Result(x) => big_step(c, p2)
      case Get(pr) =>
         exists qr :: p2 == Get(qr)
            && forall i :: big_step_bind(c, pr(i), qr(i))
    }
}
    
least predicate big_step(c: Command, p: Program<string>){
    match c  {
      case GetInput => p == Get(input => Result(input))
      case Sequence(c1, c2) =>
       exists p1 ::  big_step(c1, p1) && big_step_bind(c2, p1, p)
    }
}
    
least predicate wellFoundedProgram(p: Program<string>)
{
   match p {
     case Result(x) => true
     case Get(px) => forall i ::  wellFoundedProgram(px(i))
   }
}
    
    
least lemma wellFoundedGenerationBind(c: Command, p1: Program<string>, p: Program<string>)
   requires big_step_bind(c, p1, p)
   ensures wellFoundedProgram(p1)
   ensures wellFoundedProgram(p)
{
   match p1 {
     case Result(x) => { wellFoundedGeneration(c, p) ;}
     case Get(px) => {
     }
   }
}
    
least lemma wellFoundedGeneration(c: Command, p: Program<string>)
  requires big_step(c, p)
  ensures wellFoundedProgram(p)
{
   match c {
     case GetInput => {}
     case Sequence(c1, c2) => {
        var p1 :| big_step(c1, p1) && big_step_bind(c2, p1, p);
        wellFoundedGenerationBind(c2, p1, p);
     }
   }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM