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
63
63
64
64
/-! ### size -/
65
65
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
67
67
cases xs
68
68
simp_all
69
69
Original file line number Diff line number Diff line change @@ -486,7 +486,7 @@ abbrev toArray_mkVector := @toArray_replicate
486
486
`Vector.ext` is an extensionality theorem.
487
487
Vectors `a` and `b` are equal to each other if their elements are equal for each valid index.
488
488
-/
489
- @[ext]
489
+ @[ext, grind ext ]
490
490
protected theorem ext {xs ys : Vector α n} (h : (i : Nat) → (_ : i < n) → xs[i] = ys[i]) : xs = ys := by
491
491
apply Vector.toArray_inj.1
492
492
apply Array.ext
Original file line number Diff line number Diff line change @@ -82,6 +82,8 @@ end Lean
82
82
attribute [ext] Prod PProd Sigma PSigma
83
83
attribute [ext] funext propext Subtype.eq Array.ext
84
84
85
+ attribute [grind ext] Array.ext
86
+
85
87
@[ext] protected theorem PUnit.ext (x y : PUnit) : x = y := rfl
86
88
protected theorem Unit.ext (x y : Unit) : x = y := rfl
87
89
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
14
14
else
15
15
true
16
16
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
24
21
unfold checkPalin1
25
22
suffices ∀ i, checkPalin1.go xs i = true ↔ ∀ j, i ≤ j → (_ : j < xs.size / 2 ) → xs[j] = xs[xs.size - 1 - j] by
26
23
grind [IsPalindrome]
27
24
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