This PR sets up the new integrated test/bench suite. It then migrates all benchmarks and some related tests to the new suite. There's also some documentation and some linting. For now, a lot of the old tests are left alone so this PR doesn't become even larger than it already is. Eventually, all tests should be migrated to the new suite though so there isn't a confusing mix of two systems.
421 lines
8.5 KiB
Text
421 lines
8.5 KiB
Text
namespace Ex1
|
||
|
||
variable (P : Nat → Prop)
|
||
|
||
def ackermann : (Nat × Nat) → Nat
|
||
| (0, m) => m + 1
|
||
| (n+1, 0) => ackermann (n, 1)
|
||
| (n+1, m+1) => ackermann (n, ackermann (n + 1, m))
|
||
termination_by p => p
|
||
|
||
/--
|
||
error: Failed: `fail` tactic was invoked
|
||
case case1
|
||
P : Nat → Prop
|
||
m✝ : Nat
|
||
⊢ P (m✝ + 1)
|
||
|
||
case case2
|
||
P : Nat → Prop
|
||
n✝ : Nat
|
||
ih1✝ : P (ackermann (n✝, 1))
|
||
⊢ P (ackermann (n✝, 1))
|
||
|
||
case case3
|
||
P : Nat → Prop
|
||
n✝ m✝ : Nat
|
||
ih2✝ : P (ackermann (n✝ + 1, m✝))
|
||
ih1✝ : P (ackermann (n✝, ackermann (n✝ + 1, m✝)))
|
||
⊢ P (ackermann (n✝, ackermann (n✝ + 1, m✝)))
|
||
-/
|
||
#guard_msgs in
|
||
example : P (ackermann p) := by
|
||
fun_induction ackermann p
|
||
fail
|
||
|
||
/--
|
||
error: Failed: `fail` tactic was invoked
|
||
case case1
|
||
P : Nat → Prop
|
||
m✝ : Nat
|
||
⊢ P (m✝ + 1)
|
||
|
||
case case2
|
||
P : Nat → Prop
|
||
n✝ : Nat
|
||
⊢ P (ackermann (n✝, 1))
|
||
|
||
case case3
|
||
P : Nat → Prop
|
||
n✝ m✝ : Nat
|
||
⊢ P (ackermann (n✝, ackermann (n✝ + 1, m✝)))
|
||
-/
|
||
#guard_msgs in
|
||
example : P (ackermann p) := by
|
||
fun_cases ackermann p
|
||
fail
|
||
|
||
/--
|
||
error: unsolved goals
|
||
case case1
|
||
P : Nat → Prop
|
||
n m m✝ : Nat
|
||
⊢ P (m✝ + 1)
|
||
|
||
case case2
|
||
P : Nat → Prop
|
||
n m n✝ : Nat
|
||
ih1✝ : P (ackermann (n✝, 1))
|
||
⊢ P (ackermann (n✝, 1))
|
||
|
||
case case3
|
||
P : Nat → Prop
|
||
n m n✝ m✝ : Nat
|
||
ih2✝ : P (ackermann (n✝ + 1, m✝))
|
||
ih1✝ : P (ackermann (n✝, ackermann (n✝ + 1, m✝)))
|
||
⊢ P (ackermann (n✝, ackermann (n✝ + 1, m✝)))
|
||
-/
|
||
#guard_msgs in
|
||
example : P (ackermann (n, m)) := by
|
||
fun_induction ackermann (n, m)
|
||
|
||
/--
|
||
error: unsolved goals
|
||
case case1
|
||
P : Nat → Prop
|
||
n m m✝ : Nat
|
||
⊢ P (m✝ + 1)
|
||
|
||
case case2
|
||
P : Nat → Prop
|
||
n m n✝ : Nat
|
||
⊢ P (ackermann (n✝, 1))
|
||
|
||
case case3
|
||
P : Nat → Prop
|
||
n m n✝ m✝ : Nat
|
||
⊢ P (ackermann (n✝, ackermann (n✝ + 1, m✝)))
|
||
-/
|
||
#guard_msgs in
|
||
example : P (ackermann (n, m)) := by
|
||
fun_cases ackermann (n, m)
|
||
|
||
-- Testing Generalization:
|
||
|
||
/--
|
||
error: unsolved goals
|
||
case case1
|
||
P : Nat → Prop
|
||
n m m✝ : Nat
|
||
⊢ P (ackermann (n, m))
|
||
|
||
case case2
|
||
P : Nat → Prop
|
||
n m n✝ : Nat
|
||
⊢ P (ackermann (n, m))
|
||
|
||
case case3
|
||
P : Nat → Prop
|
||
n m n✝ m✝ : Nat
|
||
⊢ P (ackermann (n, m))
|
||
-/
|
||
#guard_msgs in
|
||
example : P (ackermann (n, m)) := by
|
||
fun_cases ackermann (n+n, m)
|
||
|
||
end Ex1
|
||
|
||
namespace Ex2
|
||
|
||
variable (P : Nat → Prop)
|
||
|
||
def ackermann : Nat → Nat → Nat
|
||
| 0, m => m + 1
|
||
| n+1, 0 => ackermann n 1
|
||
| n+1, m+1 => ackermann n (ackermann (n + 1) m)
|
||
termination_by n m => (n, m)
|
||
|
||
/--
|
||
error: unsolved goals
|
||
case case1
|
||
P : Nat → Prop
|
||
m✝ : Nat
|
||
⊢ P (m✝ + 1)
|
||
|
||
case case2
|
||
P : Nat → Prop
|
||
n✝ : Nat
|
||
ih1✝ : P (ackermann n✝ 1)
|
||
⊢ P (ackermann n✝ 1)
|
||
|
||
case case3
|
||
P : Nat → Prop
|
||
n✝ m✝ : Nat
|
||
ih2✝ : P (ackermann (n✝ + 1) m✝)
|
||
ih1✝ : P (ackermann n✝ (ackermann (n✝ + 1) m✝))
|
||
⊢ P (ackermann n✝ (ackermann (n✝ + 1) m✝))
|
||
-/
|
||
#guard_msgs in
|
||
example : P (ackermann n m) := by
|
||
fun_induction ackermann n m
|
||
|
||
/--
|
||
error: Expected fully applied application of `ackermann` with 2 arguments, but found 1 arguments
|
||
-/
|
||
#guard_msgs in
|
||
example : P (ackermann n m) := by
|
||
fun_induction ackermann n
|
||
|
||
end Ex2
|
||
|
||
namespace Ex3
|
||
|
||
variable (P : List α → Prop)
|
||
|
||
def ackermann {α} (inc : List α) : List α → List α → List α
|
||
| [], ms => ms ++ inc
|
||
| _::ns, [] => ackermann inc ns inc
|
||
| n::ns, _::ms => ackermann inc ns (ackermann inc (n::ns) ms)
|
||
termination_by ns ms => (ns, ms)
|
||
|
||
/--
|
||
error: unsolved goals
|
||
case case1
|
||
α : Type u_1
|
||
P : List α → Prop
|
||
inc ms✝ : List α
|
||
⊢ P (ms✝ ++ inc)
|
||
|
||
case case2
|
||
α : Type u_1
|
||
P : List α → Prop
|
||
inc : List α
|
||
head✝ : α
|
||
ns✝ : List α
|
||
ih1✝ : P (ackermann inc ns✝ inc)
|
||
⊢ P (ackermann inc ns✝ inc)
|
||
|
||
case case3
|
||
α : Type u_1
|
||
P : List α → Prop
|
||
inc : List α
|
||
n✝ : α
|
||
ns✝ : List α
|
||
head✝ : α
|
||
ms✝ : List α
|
||
ih2✝ : P (ackermann inc (n✝ :: ns✝) ms✝)
|
||
ih1✝ : P (ackermann inc ns✝ (ackermann inc (n✝ :: ns✝) ms✝))
|
||
⊢ P (ackermann inc ns✝ (ackermann inc (n✝ :: ns✝) ms✝))
|
||
-/
|
||
#guard_msgs in
|
||
example : P (ackermann inc n m) := by
|
||
fun_induction ackermann inc n m
|
||
|
||
/--
|
||
error: Expected fully applied application of `ackermann` with 4 arguments, but found 3 arguments
|
||
-/
|
||
#guard_msgs in
|
||
example : P (ackermann inc n m) := by
|
||
fun_induction ackermann inc n
|
||
|
||
/--
|
||
error: Expected fully applied application of `ackermann` with 4 arguments, but found 2 arguments
|
||
-/
|
||
#guard_msgs in
|
||
example : P (ackermann inc n m) := by
|
||
fun_induction ackermann inc
|
||
|
||
end Ex3
|
||
|
||
namespace Structural
|
||
|
||
variable (P : Nat → Prop)
|
||
|
||
def fib : Nat → Nat
|
||
| 0 => 0
|
||
| 1 => 1
|
||
| n+2 => fib n + fib (n+1)
|
||
termination_by structural x => x
|
||
|
||
/--
|
||
error: Failed: `fail` tactic was invoked
|
||
case case1
|
||
P : Nat → Prop
|
||
⊢ P 0
|
||
|
||
case case2
|
||
P : Nat → Prop
|
||
⊢ P 1
|
||
|
||
case case3
|
||
P : Nat → Prop
|
||
n✝ : Nat
|
||
ih2✝ : P (fib n✝)
|
||
ih1✝ : P (fib (n✝ + 1))
|
||
⊢ P (fib n✝ + fib (n✝ + 1))
|
||
-/
|
||
#guard_msgs in
|
||
example : P (fib n) := by
|
||
fun_induction fib n
|
||
fail
|
||
|
||
example : n ≤ fib (n + 2) := by
|
||
fun_induction fib n
|
||
case case1 => simp [fib]
|
||
case case2 => simp [fib]
|
||
case case3 n ih1 ih2 => simp_all [fib]; omega
|
||
|
||
example : n ≤ fib (n + 2) := by
|
||
fun_induction fib n with
|
||
| case1 | case2 => simp [fib]
|
||
| case3 => simp_all [fib]; omega
|
||
|
||
|
||
end Structural
|
||
|
||
namespace StructuralWithOmittedParam
|
||
|
||
variable (P : Nat → Prop)
|
||
|
||
variable (inc : Nat)
|
||
def fib : Nat → Nat
|
||
| 0 => 0
|
||
| 1 => inc
|
||
| n+2 => fib n + fib (n+1)
|
||
termination_by structural x => x
|
||
|
||
/--
|
||
info: StructuralWithOmittedParam.fib.induct (motive : Nat → Prop) (case1 : motive 0) (case2 : motive 1)
|
||
(case3 : ∀ (n : Nat), motive n → motive (n + 1) → motive n.succ.succ) (a✝ : Nat) : motive a✝
|
||
-/
|
||
#guard_msgs in
|
||
#check fib.induct -- NB: No inc showing up
|
||
|
||
/--
|
||
error: Failed: `fail` tactic was invoked
|
||
case case1
|
||
P : Nat → Prop
|
||
inc : Nat
|
||
⊢ P (fib 2 0)
|
||
|
||
case case2
|
||
P : Nat → Prop
|
||
inc : Nat
|
||
⊢ P (fib 2 1)
|
||
|
||
case case3
|
||
P : Nat → Prop
|
||
inc n✝ : Nat
|
||
ih2✝ : P (fib 2 n✝)
|
||
ih1✝ : P (fib 2 (n✝ + 1))
|
||
⊢ P (fib 2 n✝.succ.succ)
|
||
-/
|
||
#guard_msgs in
|
||
example : P (fib 2 n) := by
|
||
fun_induction fib 3 n
|
||
fail
|
||
|
||
/--
|
||
error: Failed: `fail` tactic was invoked
|
||
case case1
|
||
P : Nat → Prop
|
||
inc : Nat
|
||
⊢ P 0
|
||
|
||
case case2
|
||
P : Nat → Prop
|
||
inc : Nat
|
||
⊢ P 2
|
||
|
||
case case3
|
||
P : Nat → Prop
|
||
inc n✝ : Nat
|
||
ih2✝ : P (fib 2 n✝)
|
||
ih1✝ : P (fib 2 (n✝ + 1))
|
||
⊢ P (fib 2 n✝ + fib 2 (n✝ + 1))
|
||
-/
|
||
#guard_msgs in
|
||
example : P (fib 2 n) := by
|
||
fun_induction fib _ n
|
||
fail
|
||
|
||
end StructuralWithOmittedParam
|
||
|
||
namespace StructuralIndices
|
||
|
||
-- Testing recursion on an indexed data type
|
||
inductive Finn : Nat → Type where
|
||
| fzero : {n : Nat} → Finn n
|
||
| fsucc : {n : Nat} → Finn n → Finn (n+1)
|
||
|
||
def Finn.min (x : Bool) {n : Nat} (m : Nat) : Finn n → (f : Finn n) → Finn n
|
||
| fzero, _ => fzero
|
||
| _, fzero => fzero
|
||
| fsucc i, fsucc j => fsucc (Finn.min (not x) (m + 1) i j)
|
||
termination_by structural i => i
|
||
|
||
def Finn.min' (x : Bool) {n : Nat} (m : Nat) : Finn n → (f : Finn n) → Finn n
|
||
| fzero, _ => fzero
|
||
| _, fzero => fzero
|
||
| fsucc i, fsucc j => fsucc (Finn.min' (not x) (m + 1) i j)
|
||
termination_by structural _ j => j
|
||
|
||
def Finn.min'' (x : Bool) {n : Nat} (m : Nat) : Finn n → (f : Finn n) → Finn n
|
||
| fzero, _ => fzero
|
||
| _, fzero => fzero
|
||
| fsucc i, fsucc j => fsucc (Finn.min'' (not x) (m + 1) i j)
|
||
termination_by structural n
|
||
|
||
def Finn.le : Finn n → Finn n → Bool
|
||
| fzero, _ => true
|
||
| _, fzero => false
|
||
| fsucc i, fsucc j => Finn.le i j
|
||
|
||
theorem Finn.min_le_right₀ : (Finn.min x m i j).le j := by
|
||
induction x, m, i, j using @Finn.min.induct <;> simp_all [Finn.min, Finn.le]
|
||
|
||
theorem Finn.min_le_right : (Finn.min x m i j).le j := by
|
||
fun_induction Finn.min x m i j <;> simp_all [Finn.min, Finn.le]
|
||
|
||
theorem Finn.min_le_right' : (Finn.min' x m i j).le j := by
|
||
fun_induction Finn.min' x m i j <;> simp_all [Finn.min', Finn.le]
|
||
|
||
theorem Finn.min_le_right'' : (Finn.min'' x m i j).le j := by
|
||
fun_induction Finn.min'' x m i j <;> simp_all [Finn.min'', Finn.le]
|
||
|
||
end StructuralIndices
|
||
|
||
namespace Nonrec
|
||
|
||
def foo := 1
|
||
|
||
/-- error: No functional induction theorem for `foo`, or function is mutually recursive -/
|
||
#guard_msgs in
|
||
example : True := by
|
||
fun_induction foo
|
||
|
||
|
||
end Nonrec
|
||
|
||
namespace Mutual
|
||
|
||
inductive Tree (α : Type u) : Type u where
|
||
| node : α → (Bool → List (Tree α)) → Tree α
|
||
|
||
-- Recursion over nested inductive
|
||
|
||
mutual
|
||
def Tree.size : Tree α → Nat
|
||
| .node _ tsf => 1 + size_aux (tsf true) + size_aux (tsf false)
|
||
termination_by structural t => t
|
||
def Tree.size_aux : List (Tree α) → Nat
|
||
| [] => 0
|
||
| t :: ts => size t + size_aux ts
|
||
end
|
||
|
||
/-- error: No functional induction theorem for `Tree.size`, or function is mutually recursive -/
|
||
#guard_msgs in
|
||
example (t : Tree α) : True := by
|
||
fun_induction Tree.size t
|
||
|
||
end Mutual
|