Skip to content

Commit e8bafc8

Browse files
authored
4 (#228)
This PR solves problem 4.
1 parent 499ef31 commit e8bafc8

File tree

2 files changed

+146
-9
lines changed

2 files changed

+146
-9
lines changed

HumanEvalLean/HumanEval115.lean

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -60,13 +60,19 @@ theorem Vector.sum_eq_zero {xs : Vector Nat n} : xs.sum = 0 ↔ ∀ (i : Nat) (h
6060
rw [← Vector.sum_toList, List.sum_eq_zero]
6161
grind
6262

63-
theorem List.sum_eq_foldl {xs : List Nat} :
63+
theorem List.sum_eq_foldl [Zero α] [Add α]
64+
[Associative (α := α) (· + ·)][Commutative (α := α) (· + ·)]
65+
[LawfulLeftIdentity (· + ·) (0 : α)]
66+
{xs : List α} :
6467
xs.sum = xs.foldl (init := 0) (· + ·) := by
65-
rw [← List.reverse_reverse (as := xs)]
66-
generalize xs.reverse = xs
67-
induction xs <;> grind
68-
69-
theorem Array.sum_eq_foldl {xs : Array Nat} :
68+
conv => lhs; rw [← List.reverse_reverse (as := xs)]
69+
rw [List.sum_reverse, List.sum_eq_foldr, List.foldr_reverse]
70+
simp only [Commutative.comm]
71+
72+
theorem Array.sum_eq_foldl [Zero α] [Add α]
73+
[Associative (α := α) (· + ·)][Commutative (α := α) (· + ·)]
74+
[LawfulLeftIdentity (· + ·) (0 : α)]
75+
{xs : Array α} :
7076
xs.sum = xs.foldl (init := 0) (· + ·) := by
7177
rw [← Array.toArray_toList (xs := xs)]
7278
grind [List.sum_eq_foldl]

HumanEvalLean/HumanEval4.lean

Lines changed: 134 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,136 @@
1-
def mean_absolute_deviation : Unit :=
2-
()
1+
module
2+
3+
import Std
4+
open Std
5+
6+
/-! ## Missing API -/
7+
8+
theorem List.sum_eq_foldl [Zero α] [Add α]
9+
[Associative (α := α) (· + ·)][Commutative (α := α) (· + ·)]
10+
[LawfulLeftIdentity (· + ·) (0 : α)]
11+
{xs : List α} :
12+
xs.sum = xs.foldl (init := 0) (· + ·) := by
13+
conv => lhs; rw [← List.reverse_reverse (as := xs)]
14+
rw [List.sum_reverse, List.sum_eq_foldr, List.foldr_reverse]
15+
simp only [Commutative.comm]
16+
17+
def Std.Iter.sum [Add β] [Zero β] [Iterator α Id β] [IteratorLoop α Id Id]
18+
(it : Iter (α := α) β) : β :=
19+
it.fold (init := 0) (· + ·)
20+
21+
theorem Std.Iter.sum_toList [Add β] [Zero β]
22+
[Associative (α := β) (· + ·)] [Commutative (α := β) (· + ·)]
23+
[LawfulLeftIdentity (· + ·) (0 : β)]
24+
[Iterator α Id β] [IteratorLoop α Id Id]
25+
[LawfulIteratorLoop α Id Id] [Iterators.Finite α Id] {it : Iter (α := α) β} :
26+
it.toList.sum = it.sum := by
27+
simp only [Iter.sum, ← Iter.foldl_toList, List.sum_eq_foldl]
28+
29+
theorem Array.size_singleton {x : α} :
30+
#[x].size = 1 := by
31+
simp
32+
33+
@[simp, grind =]
34+
theorem Array.sum_singleton [Add α] [Zero α] [LawfulRightIdentity (· + ·) (0 : α)] {x : α} :
35+
#[x].sum = x := by
36+
simp [Array.sum_eq_foldr, LawfulRightIdentity.right_id x]
37+
38+
-- Library defect: remove the `LeftIdentity` parameter from Array.sum_append
39+
40+
@[simp, grind =]
41+
theorem Array.sum_push [Add α] [Zero α]
42+
[Associative (α := α) (· + ·)]
43+
[LawfulIdentity (· + ·) (0 : α)]
44+
{xs : Array α} {x : α} :
45+
(xs.push x).sum = xs.sum + x := by
46+
simp [Array.sum_eq_foldr, LawfulRightIdentity.right_id, LawfulLeftIdentity.left_id,
47+
← Array.foldr_assoc]
48+
49+
def Rat.abs (x : Rat) :=
50+
if 0 ≤ x then x else - x
51+
52+
theorem Rat.abs_nonneg {x : Rat} :
53+
0 ≤ x.abs := by
54+
simp only [Rat.abs]
55+
grind
56+
57+
theorem Rat.abs_of_nonneg {x : Rat} (h : 0 ≤ x) :
58+
x.abs = x := by
59+
grind [Rat.abs]
60+
61+
theorem Rat.abs_of_nonpos {x : Rat} (h : x ≤ 0) :
62+
x.abs = - x := by
63+
grind [Rat.abs]
64+
65+
theorem Rat.abs_sub_comm {x y : Rat} :
66+
(x - y).abs = (y - x).abs := by
67+
grind [Rat.abs]
68+
69+
instance Rat.instAssociativeHAdd : Associative (α := Rat) (· + ·) := ⟨Rat.add_assoc⟩
70+
instance Rat.instCommutativeHAdd : Commutative (α := Rat) (· + ·) := ⟨Rat.add_comm⟩
71+
instance : Std.LawfulIdentity (· + ·) (0 : Rat) where
72+
left_id := Rat.zero_add
73+
right_id := Rat.add_zero
74+
75+
/-! ## Implementation -/
76+
77+
def mean (xs : Array Rat) : Rat :=
78+
xs.sum / xs.size
79+
80+
def meanAbsoluteDeviation (xs : Array Rat) : Rat :=
81+
let mean := mean xs
82+
(xs.iter
83+
|>.map (fun x => (x - mean).abs)
84+
|>.sum) / xs.size
85+
86+
/-! ## Tests -/
87+
88+
example : meanAbsoluteDeviation #[(1 : Rat), 2, 3] = (2 : Rat) / 3 := by native_decide
89+
example : meanAbsoluteDeviation #[(1 : Rat), 2, 3, 4] = 1 := by native_decide
90+
example : meanAbsoluteDeviation #[(1 : Rat), 2, 3, 4, 5] = (6 : Rat) / 5 := by native_decide
91+
92+
/-!
93+
## Verification
94+
95+
In order to verify the implementation, we point to library lemmas verifying `Array.sum`, `Rat.abs`,
96+
`Array.size` and `Array.map`. Then we show that `mean` is actually the quotient of `sum` and `size`
97+
and that `meanAbsoluteDeviation` computes the mean of absolute deviations from the mean,
98+
expressed using said four library functions.
99+
-/
100+
101+
section API
102+
103+
variable {x : Rat} {xs ys : Array Rat} {f : Rat → β}
104+
105+
example : (#[] : Array Rat).sum = 0 := Array.sum_empty
106+
example : (#[x]).sum = x := Array.sum_singleton
107+
example : (xs.push x).sum = xs.sum + x := Array.sum_push
108+
example : (xs ++ ys).sum = xs.sum + ys.sum := Array.sum_append
109+
110+
example (h : 0 ≤ x) : x.abs = x := Rat.abs_of_nonneg h
111+
example (h : x ≤ 0) : x.abs = - x := Rat.abs_of_nonpos h
112+
example : 0 ≤ x.abs := Rat.abs_nonneg
113+
114+
example : (#[] : Array Rat).size = 0 := Array.size_empty
115+
example : (#[x]).size = 1 := Array.size_singleton
116+
example : (xs.push x).size = xs.size + 1 := Array.size_push _
117+
example : (xs ++ ys).size = xs.size + ys.size := Array.size_append
118+
119+
example : (#[] : Array Rat).map f = #[] := Array.map_empty
120+
example : #[x].map f = #[f x] := Array.map_singleton
121+
example : (xs.push x).map f = (xs.map f).push (f x) := Array.map_push
122+
example : (xs ++ ys).map f = xs.map f ++ ys.map f := Array.map_append
123+
124+
end API
125+
126+
theorem mean_spec {xs : Array Rat} :
127+
mean xs = xs.sum / xs.size := by
128+
simp [mean]
129+
130+
theorem meanAbsoluteDeviation_spec {xs : Array Rat} :
131+
meanAbsoluteDeviation xs =
132+
mean (xs.map (fun x => (x - mean xs).abs)) := by
133+
simp [meanAbsoluteDeviation, mean, ← Iter.sum_toList, ← Array.sum_toList]
3134

4135
/-!
5136
## Prompt
@@ -43,4 +174,4 @@ def check(candidate):
43174
assert abs(candidate([1.0, 2.0, 3.0, 4.0, 5.0]) - 6.0/5.0) < 1e-6
44175
45176
```
46-
-/
177+
-/

0 commit comments

Comments
 (0)