-
Notifications
You must be signed in to change notification settings - Fork 2
/
Exp2.agda
122 lines (100 loc) · 4.26 KB
/
Exp2.agda
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
{-# OPTIONS --rewriting #-}
module Examples.Exp2 where
open import Algebra.Cost
parCostMonoid = ℕ²-ParCostMonoid
open ParCostMonoid parCostMonoid
open import Calf costMonoid
open import Calf.Parallel parCostMonoid
open import Calf.Data.Bool
open import Calf.Data.Nat
open import Calf.Data.IsBounded costMonoid
open import Calf.Data.BigO costMonoid
open import Relation.Binary.PropositionalEquality as Eq using (_≡_; refl; _≢_; module ≡-Reasoning)
open import Data.Nat as Nat using (_+_; pred; _*_; _^_; _⊔_)
import Data.Nat.Properties as N
open import Data.Nat.PredExp2
open import Data.Empty
open import Function using (_∘_)
Correct : cmp (Π nat λ _ → F nat) → Set
Correct exp₂ = (n : ℕ) → ◯ (exp₂ n ≡ ret (2 ^ n))
module Slow where
exp₂ : cmp (Π nat λ _ → F nat)
exp₂ zero = ret (suc zero)
exp₂ (suc n) =
bind (F nat) (exp₂ n ∥ exp₂ n) λ (r₁ , r₂) →
step (F nat) (1 , 1) (ret (r₁ + r₂))
exp₂/bound : cmp (Π nat λ _ → F nat)
exp₂/bound n = step (F nat) (pred[2^ n ] , n) (ret (2 ^ n))
exp₂/is-bounded : ∀ n → exp₂ n ≤⁻[ F nat ] exp₂/bound n
exp₂/is-bounded zero = ≤⁻-refl
exp₂/is-bounded (suc n) =
let open ≤⁻-Reasoning (F nat) in
begin
(bind (F nat) (exp₂ n ∥ exp₂ n) λ (r₁ , r₂) →
step (F nat) (1 , 1) (ret (r₁ + r₂)))
≲⟨
≤⁻-mono₂ (λ e₁ e₂ → bind (F nat) (e₁ ∥ e₂) λ (r₁ , r₂) → step (F nat) (1 , 1) (ret (r₁ + r₂)))
(exp₂/is-bounded n)
(exp₂/is-bounded n)
⟩
(bind (F nat) ((step (F nat) (pred[2^ n ] , n) (ret (2 ^ n))) ∥ (step (F nat) (pred[2^ n ] , n) (ret (2 ^ n)))) λ (r₁ , r₂) →
step (F nat) (1 , 1) (ret (r₁ + r₂)))
≡⟨⟩
step (F nat) (pred[2^ n ] + pred[2^ n ] + 1 , n ⊔ n + 1) (ret (2 ^ n + 2 ^ n))
≡⟨
Eq.cong₂ (step (F nat))
(Eq.cong₂ _,_
(Eq.trans (N.+-comm _ 1) (pred[2^suc[n]] n))
(Eq.trans (N.+-comm _ 1) (Eq.cong (1 +_) (N.⊔-idem n))))
(Eq.cong ret (lemma/2^suc n))
⟩
step (F nat) (pred[2^ suc n ] , suc n) (ret (2 ^ suc n))
∎
exp₂/correct : Correct exp₂
exp₂/correct n u = Eq.trans (≤⁻-ext-≡ u (exp₂/is-bounded n)) (step/ext (F nat) (ret (2 ^ n)) (pred[2^ n ] , n) u)
exp₂/asymptotic : given nat measured-via (λ n → n) , exp₂ ∈𝓞(λ n → 2 ^ n , n)
exp₂/asymptotic =
f[n]≤g[n]via λ n →
≤⁻-mono (λ e → bind (F _) e (λ _ → ret triv))
(≤⁻-trans (exp₂/is-bounded n) (step-monoˡ-≤⁻ (ret (2 ^ n)) (N.pred[n]≤n {2 ^ n} , N.≤-refl {n})))
module Fast where
exp₂ : cmp (Π nat λ _ → F nat)
exp₂ zero = ret (suc zero)
exp₂ (suc n) =
bind (F nat) (exp₂ n) λ r →
step (F nat) (1 , 1) (ret (r + r))
exp₂/bound : cmp (Π nat λ _ → F nat)
exp₂/bound n = step (F nat) (n , n) (ret (2 ^ n))
exp₂/is-bounded : ∀ n → exp₂ n ≤⁻[ F nat ] exp₂/bound n
exp₂/is-bounded zero = ≤⁻-refl
exp₂/is-bounded (suc n) =
let open ≤⁻-Reasoning (F nat) in
begin
(bind (F nat) (exp₂ n) λ r →
step (F nat) (1 , 1) (ret (r + r)))
≲⟨ ≤⁻-mono (λ e → bind (F nat) e λ r → step (F nat) (1 , 1) (ret (r + r))) (exp₂/is-bounded n) ⟩
(bind (F nat) (step (F nat) (n , n) (ret (2 ^ n))) λ r →
step (F nat) (1 , 1) (ret (r + r)))
≡⟨⟩
step (F nat) (n + 1 , n + 1) (ret (2 ^ n + 2 ^ n))
≡⟨
Eq.cong₂ (step (F nat))
(Eq.cong₂ _,_ (N.+-comm _ 1) (N.+-comm _ 1))
(Eq.cong ret (lemma/2^suc n))
⟩
step (F nat) (suc n , suc n) (ret (2 ^ suc n))
∎
exp₂/correct : Correct exp₂
exp₂/correct n u = Eq.trans (≤⁻-ext-≡ u (exp₂/is-bounded n)) (step/ext (F nat) (ret (2 ^ n)) (n , n) u)
exp₂/asymptotic : given nat measured-via (λ n → n) , exp₂ ∈𝓞(λ n → n , n)
exp₂/asymptotic = f[n]≤g[n]via (≤⁻-mono (λ e → bind (F _) e _) ∘ exp₂/is-bounded)
slow≡fast : ◯ (Slow.exp₂ ≡ Fast.exp₂)
slow≡fast u = funext λ n →
begin
Slow.exp₂ n
≡⟨ Slow.exp₂/correct n u ⟩
ret (2 ^ n)
≡˘⟨ Fast.exp₂/correct n u ⟩
Fast.exp₂ n
∎
where open ≡-Reasoning