File tree Expand file tree Collapse file tree 5 files changed +46
-10
lines changed
Expand file tree Collapse file tree 5 files changed +46
-10
lines changed Original file line number Diff line number Diff line change @@ -63,7 +63,7 @@ theorem toArray_eq : List.toArray as = xs ↔ as = xs.toList := by
6363
6464/-! ### size -/
6565
66- @[grind →] theorem eq_empty_of_size_eq_zero (h : xs.size = 0 ) : xs = #[] := by
66+ theorem eq_empty_of_size_eq_zero (h : xs.size = 0 ) : xs = #[] := by
6767 cases xs
6868 simp_all
6969
Original file line number Diff line number Diff line change @@ -486,7 +486,7 @@ abbrev toArray_mkVector := @toArray_replicate
486486`Vector.ext` is an extensionality theorem.
487487Vectors `a` and `b` are equal to each other if their elements are equal for each valid index.
488488-/
489- @[ext]
489+ @[ext, grind ext ]
490490protected theorem ext {xs ys : Vector α n} (h : (i : Nat) → (_ : i < n) → xs[i] = ys[i]) : xs = ys := by
491491 apply Vector.toArray_inj.1
492492 apply Array.ext
Original file line number Diff line number Diff line change @@ -82,6 +82,8 @@ end Lean
8282attribute [ext] Prod PProd Sigma PSigma
8383attribute [ext] funext propext Subtype.eq Array.ext
8484
85+ attribute [grind ext] Array.ext
86+
8587@[ext] protected theorem PUnit.ext (x y : PUnit) : x = y := rfl
8688protected theorem Unit.ext (x y : Unit) : x = y := rfl
8789
Original file line number Diff line number Diff line change 1+ set_option grind.warning false
2+
3+ def IsPalindrome (xs : Array Nat) : Prop := xs.reverse = xs
4+
5+ def checkPalin1 (xs : Array Nat) : Bool :=
6+ go 0
7+ where
8+ go (i : Nat) :=
9+ if h : i < xs.size / 2 then
10+ if xs[i] = xs[xs.size - 1 - i] then
11+ go (i + 1 )
12+ else
13+ false
14+ else
15+ true
16+
17+ -- This give the more natural proof that we'd like to give in `tests/run/grind_palindrome2.lean`,
18+ -- but in which `grind` currently fails.
19+
20+ theorem checkPalin1_correct' : checkPalin1 xs = true ↔ IsPalindrome xs := by
21+ unfold checkPalin1
22+ suffices ∀ i, checkPalin1.go xs i = true ↔ ∀ j, i ≤ j → (_ : j < xs.size - i) → xs[j] = xs[xs.size - 1 - j] by
23+ grind [IsPalindrome]
24+ intro i
25+ fun_induction checkPalin1.go
26+ · grind (splits := 14 )
27+ -- fails, but it would be nice to succeed! The key observations are:
28+ -- [ eqc ] True propositions ▼
29+ -- [ prop ] ∀ (a : Nat) (b : a + 1 ≤ xs.toList.length - x), a + 1 ≤ x ∨ xs[ a ] = xs[xs.toList.length - (a + 1)]
30+ -- [ eqc ] False propositions ▼
31+ -- [ prop ] xs[ x ] = xs[xs.toList.length - (x + 1)]
32+ -- Instantiating the `∀` with `a := x`, we can then easily prove `a + 1 ≤ xs.toList.length - x` and
33+ -- prove that it's not the case that `a + 1 ≤ x`, so we get `xs[x] = xs[xs.toList.length - (x + 1)]`,
34+ -- which is false.
35+ · grind
36+ -- The same argument should apply here.
37+ · grind
Original file line number Diff line number Diff line change @@ -14,15 +14,12 @@ where
1414 else
1515 true
1616
17- example (xs : Array Nat) (w : xs.reverse = xs) (j : Nat) (hj : 0 ≤ j) (hj' : j < xs.size / 2 ) :
18- xs[j] = xs[xs.size - 1 - j] := by
19- grind
20-
21- attribute [grind ext] Array.ext -- TODO: should we mark it by default?
22-
23- theorem checkPalin1_correct' : checkPalin1 xs = true ↔ IsPalindrome xs := by
17+ -- This works nicely, but there is some human assistance here:
18+ -- on the right hand side of the `suffices` we've asserted it's enough to check up to `j < xs.size / 2`
19+ -- while the "natural" statement would be all the way to `j < xs.size - i`.
20+ theorem checkPalin1_correct : checkPalin1 xs = true ↔ IsPalindrome xs := by
2421 unfold checkPalin1
2522 suffices ∀ i, checkPalin1.go xs i = true ↔ ∀ j, i ≤ j → (_ : j < xs.size / 2 ) → xs[j] = xs[xs.size - 1 - j] by
2623 grind [IsPalindrome]
2724 intro i
28- fun_induction checkPalin1.go <;> grind
25+ fun_induction checkPalin1.go with grind
You can’t perform that action at this time.
0 commit comments