最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

coq - while_true_nonterm in Lean4 - Stack Overflow

programmeradmin3浏览0评论

I'm trying to implement while_true_nonterm mentioned in .html.

I have implemented imp language as follows:

import Mathlib.Data.Nat.Basic
import Mathlib.Tactic

-- A `state` can be modeled as a function mapping variable names
-- to values (e.g., natural numbers in this tutorial)
def state := String -> ℕ

-- Retrive the value of a variable in the state
def get (st: state) (x : String) : ℕ := st x

-- Update the state with a new value for a variable
def set (st: state) (x : String) (v: ℕ) : state :=
  fun y => if y = x then v else st y

-- Syntax of commands
inductive com: Type
| skip: com                          -- nop
| assign (x : String) (a: ℕ) : com   -- x := a
| seq (c1 c2 : com) : com            -- c1; c2
| if_ (b : Bool) (c1 c2 : com) : com -- if b then c1 else c2
| while (b : Bool) (c : com) : com   -- while b do c

-- inductive definitions in Lean come with an important implicit principle:
-- ** the only ways to construct proofs of the inductive relation are through its constructors.

-- State transition
inductive ceval : com -> state -> state -> Prop
| E_Skip : ∀ (st : state),
    ceval com.skip st st
| E_Assign : ∀ (st : state) (x : String) (n : ℕ),
    ceval (com.assign x n) st (set st x n)
| E_Seq : ∀ (c1 c2 : com) (st st' st'' : state),
    ceval c1 st st' →
    ceval c2 st' st'' →
    ceval (com.seq c1 c2) st st''
| E_IfTrue : ∀ (st st' : state) (b : Bool) (c1 c2 : com),
    b = true → ceval c1 st st' → ceval (com.if_ b c1 c2) st st'
| E_IfFalse : ∀ (st st' : state) (b : Bool) (c1 c2 : com),
    b = false → ceval c2 st st' → ceval (com.if_ b c1 c2) st st'
| E_WhileFalse : ∀ (st : state) (b : Bool) (c : com),
    b = false → ceval (com.while b c) st st
| E_WhileTrue : ∀ (st st' st'' : state) (b : Bool) (c : com),
    b = true → ceval c st st' → ceval (com.while b c) st' st'' → ceval (com.while b c) st st''

Now, I'm trying to prove while_true_nonterm, which states that if the loop condition is always true, then it never terminates.

Here's my current draft:

theorem while_true_nonterm:
  ∀ (b : Bool) (c : com) (st st' : state),
  b = true → ¬(ceval (com.while b c) st st') := by
  intros b c st st' htrue hceval
  cases hceval
  case E_WhileFalse hfalse =>
    rw[hfalse] at htrue
    contradiction
  case E_WhileTrue st'' htrue' hc hw =>

I'm stuck at this point and not sure how to proceed. Any suggestions?

I'm trying to implement while_true_nonterm mentioned in https://softwarefoundations.cis.upenn.edu/current/plf-current/Equiv.html.

I have implemented imp language as follows:

import Mathlib.Data.Nat.Basic
import Mathlib.Tactic

-- A `state` can be modeled as a function mapping variable names
-- to values (e.g., natural numbers in this tutorial)
def state := String -> ℕ

-- Retrive the value of a variable in the state
def get (st: state) (x : String) : ℕ := st x

-- Update the state with a new value for a variable
def set (st: state) (x : String) (v: ℕ) : state :=
  fun y => if y = x then v else st y

-- Syntax of commands
inductive com: Type
| skip: com                          -- nop
| assign (x : String) (a: ℕ) : com   -- x := a
| seq (c1 c2 : com) : com            -- c1; c2
| if_ (b : Bool) (c1 c2 : com) : com -- if b then c1 else c2
| while (b : Bool) (c : com) : com   -- while b do c

-- inductive definitions in Lean come with an important implicit principle:
-- ** the only ways to construct proofs of the inductive relation are through its constructors.

-- State transition
inductive ceval : com -> state -> state -> Prop
| E_Skip : ∀ (st : state),
    ceval com.skip st st
| E_Assign : ∀ (st : state) (x : String) (n : ℕ),
    ceval (com.assign x n) st (set st x n)
| E_Seq : ∀ (c1 c2 : com) (st st' st'' : state),
    ceval c1 st st' →
    ceval c2 st' st'' →
    ceval (com.seq c1 c2) st st''
| E_IfTrue : ∀ (st st' : state) (b : Bool) (c1 c2 : com),
    b = true → ceval c1 st st' → ceval (com.if_ b c1 c2) st st'
| E_IfFalse : ∀ (st st' : state) (b : Bool) (c1 c2 : com),
    b = false → ceval c2 st st' → ceval (com.if_ b c1 c2) st st'
| E_WhileFalse : ∀ (st : state) (b : Bool) (c : com),
    b = false → ceval (com.while b c) st st
| E_WhileTrue : ∀ (st st' st'' : state) (b : Bool) (c : com),
    b = true → ceval c st st' → ceval (com.while b c) st' st'' → ceval (com.while b c) st st''

Now, I'm trying to prove while_true_nonterm, which states that if the loop condition is always true, then it never terminates.

Here's my current draft:

theorem while_true_nonterm:
  ∀ (b : Bool) (c : com) (st st' : state),
  b = true → ¬(ceval (com.while b c) st st') := by
  intros b c st st' htrue hceval
  cases hceval
  case E_WhileFalse hfalse =>
    rw[hfalse] at htrue
    contradiction
  case E_WhileTrue st'' htrue' hc hw =>

I'm stuck at this point and not sure how to proceed. Any suggestions?

Share Improve this question asked Mar 19 at 21:37 KoukyosyumeiKoukyosyumei 52 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 1

Your code is very Rocq-like, so, to start with, here is a version that would be more idiomatic in Lean (mostly using a capitalized case for types, a snake case for constructors, and transforming propositions of the form ∀ b : Bool, b = true → P[b] into P[true]):

def State := String -> Nat

-- Retrive the value of a variable in the state
def get (st: State) (x : String) : Nat := st x

-- Update the state with a new value for a variable
def set (st: State) (x : String) (v: Nat) : State :=
  fun y => if y = x then v else st y

-- Syntax of commands
inductive Command : Type where
| skip                         -- nop
| assign (x : String) (a: Nat)   -- x := a
| seq (c1 c2 : Command)            -- c1; c2
| if_ (b : Bool) (c1 c2 : Command) -- if b then c1 else c2
| while (b : Bool) (c : Command)   -- while b do c

-- inductive definitions in Lean come with an important implicit principle:
-- ** the only ways to construct proofs of the inductive relation are through its constructors.

-- State transition
inductive Eval : Command -> State -> State -> Prop where
| skip (st : State) : Eval .skip st st
| assign (st : State) (x : String) (n : Nat) : Eval (.assign x n) st (set st x n)
| seq (c₁ c₂ : Command) (st₁ st₂ st₃ : State) :
    Eval c₁ st₁ st₂ → Eval c₂ st₂ st₃ → Eval (.seq c₁ c₂) st₁ st₃
| if_true (st₁ st₂ : State) (c₁ c₂ : Command) : Eval c₁ st₁ st₂ → Eval (.if_ true c₁ c₂) st₁ st₂
| if_false (st₁ st₂ : State) (c₁ c₂ : Command) : Eval c₂ st₁ st₂ → Eval (.if_ false c₁ c₂) st₁ st₂
| while_false (st : State) (c : Command) :
    Eval (.while false c) st st
| while_true (st₁ st₂ st₃ : State) (c : Command) :
    Eval c st₁ st₂ → Eval (.while true c) st₂ st₃ → Eval (.while true c) st₁ st₃

Then, the theorem itself can be proven by induction. The informal reasoning is: to show that a while true loop cannot terminate, assume that it can, and, by induction, prove that you can derive a contradiction. By case analysis, there is only one way such a program could evaluate, and that's by first terminating the while true loop, and then performing an evaluation step. But, by induction hypothesis, having a while true loop terminating is absurd. This is actually much more concise in Lean:

theorem while_true_nonterm : ∀ c st₁ st₂, ¬ Eval (.while true c) st₁ st₂ := by
  intros c st₁ st₂ h
  generalize e : Command.while true c = c' at h
  induction h <;> cases e
  next ih =>
    apply ih
    rfl
发布评论

评论列表(0)

  1. 暂无评论