lean4-htt/tests/lean/run/smartUnfoldingBug.lean
Kim Morrison c3948cba24
feat: upstream definition of Vector from Batteries (#6197)
This PR upstreams the definition of `Vector` from Batteries, along with
the basic functions.
2024-11-24 23:01:32 +00:00

204 lines
6.2 KiB
Text
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import Lean.Elab
open Nat
structure ProvedSkip(n m: Nat) where
result : Nat
lt : m < n → result = m
ge : n ≤ m → result = m + 1
def provedSkip (n m : Nat) : ProvedSkip n m :=
if c : m < n then
⟨m, fun _ => rfl, fun hyp => False.elim (Nat.lt_irrefl m (Nat.lt_of_lt_of_le c hyp))⟩
else
⟨m + 1, fun hyp => absurd hyp c, fun _ => rfl⟩
def skip: Nat → Nat → Nat :=
fun n m => (provedSkip n m).result
theorem skip_below_eq(n m : Nat) : m < n → (skip n m = m) :=
fun hyp => (provedSkip n m).lt hyp
theorem skip_above_eq(n m : Nat) : n ≤ m → (skip n m = m + 1) :=
fun hyp => (provedSkip n m).ge hyp
theorem skip_not_below_eq(n m : Nat) : Not (m < n) → (skip n m = m + 1) :=
fun hyp =>
let lem : n ≤ m :=
match Nat.lt_or_ge m n with
| Or.inl lt => absurd lt hyp
| Or.inr ge => ge
skip_above_eq n m lem
theorem skip_lt: (k j: Nat) → skip k j < j + 2 :=
fun k j =>
if c : j < k then
let eqn := skip_below_eq k j c
by
rw [eqn]
apply Nat.le_step
apply Nat.le_refl
done
else
let eqn := skip_not_below_eq k j c
by
rw [eqn]
apply Nat.le_refl
done
theorem skip_le_succ {n k j : Nat} : j < n → skip k j < n + 1 :=
by
intro hyp
apply Nat.le_trans (skip_lt k j)
apply Nat.succ_lt_succ
exact hyp
def FinSeq (n: Nat) (α : Type) : Type := (k : Nat) → k < n → α
theorem witness_independent{α : Type}{n : Nat}(seq: FinSeq n α) :
(i : Nat)→ (j : Nat) → (iw : i < n) → (jw : j < n) →
(i = j) → seq i iw = seq j jw :=
fun i j iw jw eqn =>
match j, eqn, jw with
| .(i), rfl, ijw =>
rfl
namespace FinSeq
def init {α : Type}{n: Nat}(seq : FinSeq (n + 1) α): FinSeq n α :=
fun k w =>
seq k (Nat.le_step w)
def last{α : Type}{n: Nat}(seq : FinSeq (n + 1) α): α :=
seq n (Nat.le_refl _)
def delete{α : Type}{n: Nat}(k : Nat) (kw : k < (n + 1)) (seq : FinSeq (n + 1) α): FinSeq n α :=
fun j w =>
seq (skip k j) (skip_le_succ w)
end FinSeq
inductive Vector' (α : Type) : Nat → Type where
| nil : Vector' α zero
| cons{n: Nat}(head: α) (tail: Vector' α n) : Vector' α (n + 1)
infixr:66 "+:" => Vector'.cons
open Vector'
def Vector'.coords {α : Type}{n : Nat}(v: Vector' α n) : FinSeq n α :=
fun j jw =>
match n, v, j, jw with
| .(zero), nil, k, lt => nomatch lt
| m + 1, cons head tail, zero, lt => head
| m + 1, cons head tail, j + 1, w => tail.coords j (Nat.le_of_succ_le_succ w)
def seqVecAux {α: Type}{n m l: Nat}: (s : n + m = l) →
(seq1 : FinSeq n α) → (accum : Vector' α m) →
Vector' α l:=
match n with
| zero => fun s => fun _ => fun seq2 =>
by
have ss : l = m := by
rw [← s]
apply Nat.zero_add
done
have sf : Vector' α l = Vector' α m := by
rw [ss]
exact Eq.mpr sf seq2
done
| k + 1 => fun s seq1 seq2 =>
let ss : k + (m + 1) = l :=
by
rw [← s]
rw [(Nat.add_comm m 1)]
rw [(Nat.add_assoc k 1 m)]
done
seqVecAux ss (seq1.init) ((seq1.last) +: seq2)
def FinSeq.vec {α : Type}{n: Nat} : FinSeq n α → Vector' α n :=
fun seq => seqVecAux (Nat.add_zero n) seq Vector'.nil
def Clause(n : Nat) : Type := Vector' (Option Bool) n
def Valuation(n: Nat) : Type := Vector' Bool n
inductive SatAnswer{dom n: Nat}(clauses : Vector' (Clause n) dom) where
| unsat : SatAnswer clauses
| sat : SatAnswer clauses
structure SimpleRestrictionClauses{dom n: Nat}
(clauses: Vector' (Clause (n + 1)) dom) where
codom : Nat
restClauses : Vector' (Clause n) codom
def prependRes{dom n: Nat}(branch: Bool)(focus: Nat)(focusLt : focus < n + 1)
(clauses: Vector' (Clause (n + 1)) dom):
(rd : SimpleRestrictionClauses clauses) →
(head : Clause (n + 1)) →
SimpleRestrictionClauses (head +: clauses) :=
fun rd head =>
if c : head.coords focus focusLt = some branch then
⟨rd.codom, rd.restClauses⟩
else
⟨rd.codom + 1, (FinSeq.vec (FinSeq.delete focus focusLt head.coords)) +: rd.restClauses⟩
def restClauses{dom n: Nat}(branch: Bool)(focus: Nat)(focusLt : focus < n + 1)
(clauses: Vector' (Clause (n + 1)) dom) :
SimpleRestrictionClauses clauses :=
match dom, clauses with
| 0, _ => ⟨0, Vector'.nil⟩
| m + 1, Vector'.cons head clauses =>
prependRes branch focus focusLt clauses
(restClauses branch focus focusLt clauses) head
def answerSAT{n dom : Nat}: (clauses : Vector' (Clause n) dom) → SatAnswer clauses :=
match n with
| zero =>
match dom with
| zero => fun cls => SatAnswer.sat
| l + 1 => fun _ => SatAnswer.unsat
| m + 1 =>
fun clauses =>
let cls := clauses
let bd := zero_lt_succ m
let rd :=
restClauses false zero bd clauses
let subCls := rd.restClauses
let subSol: SatAnswer subCls := answerSAT subCls
match subSol with
| SatAnswer.sat =>
SatAnswer.sat
| SatAnswer.unsat =>
let rd := restClauses true zero bd cls -- replacing cls by clauses fixes this
let subCls := rd.restClauses
let subSol : SatAnswer subCls := answerSAT subCls
match subSol with
| SatAnswer.sat =>
SatAnswer.sat
| SatAnswer.unsat =>
SatAnswer.unsat
open Lean.Meta
open Lean.Elab.Term
syntax (name:= nrmlform)"whnf!" term : term
@[term_elab nrmlform] def normalformImpl : TermElab :=
fun stx expectedType? =>
match stx with
| `(whnf! $s) =>
do
let t ← elabTerm s none
let e ← whnf t
return e
| _ => Lean.Elab.throwIllFormedSyntax
def cls1 : Clause 2 := -- ¬P
(some false) +: (none) +: Vector'.nil
def cls2 : Clause 2 := (some true) +: none +: Vector'.nil -- P
def egStatement := cls1 +: cls2 +: Vector'.nil
def egAnswer : SatAnswer egStatement := answerSAT egStatement
def egAnswerNorm : SatAnswer egStatement := whnf! egAnswer