-
Notifications
You must be signed in to change notification settings - Fork 2
/
Simple.agda
92 lines (72 loc) · 3.03 KB
/
Simple.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
{-# OPTIONS --rewriting #-}
module Examples.Amortized.Simple where
open import Algebra.Cost
costMonoid = ℕ-CostMonoid
open CostMonoid costMonoid using (ℂ)
open import Level using (0ℓ)
open import Calf costMonoid
open import Calf.Data.Product
open import Calf.Data.Bool
open import Calf.Data.Nat as Nat using (ℕ; zero; suc; nat; _+_; _∸_; pred; _*_; _^_; _>_)
open import Calf.Data.Equality as Eq using (_≡_; refl; _≡⁺_; ≡⁺-syntax; _≡⁻_; ≡⁻-syntax; module ≡-Reasoning)
open import Examples.Amortized.Core
postulate
simple : tp⁻
record Simple : Set where
coinductive
field
quit : cmp (F unit)
next : cmp simple
postulate
simple/decode : val (U simple) ≡ Simple
{-# REWRITE simple/decode #-}
quit/step : ∀ {c e} → Simple.quit (step simple c e) ≡ step (F unit) c (Simple.quit e)
next/step : ∀ {c e} → Simple.next (step simple c e) ≡ step simple c (Simple.next e)
{-# REWRITE quit/step next/step #-}
{-# TERMINATING #-}
every : cmp simple
Simple.quit every = ret triv
Simple.next every = step simple 1 every
Φ : val bool → ℂ
Φ false = 1
Φ true = 0
{-# TERMINATING #-}
alternating : cmp (Π bool λ _ → simple)
Simple.quit (alternating b) = step (F unit) (Φ b) (ret triv)
Simple.next (alternating false) = step simple 2 (alternating true)
Simple.next (alternating true ) = alternating false
record _≈_ (s₁ s₂ : cmp simple) : Set where
coinductive
field
quit : Simple.quit s₁ ≡ Simple.quit s₂
next : Simple.next s₁ ≈ Simple.next s₂
postulate
_≈⁻_ : (s₁ s₂ : cmp simple) → tp⁻
≈⁻/decode : {s₁ s₂ : cmp simple} → val (U (s₁ ≈⁻ s₂)) ≡ s₁ ≈ s₂
{-# REWRITE ≈⁻/decode #-}
≈-cong : (c : ℂ) {x y : Simple} → x ≈ y → step simple c x ≈ step simple c y
_≈_.quit (≈-cong c h) = Eq.cong (step (F unit) c) (_≈_.quit h)
_≈_.next (≈-cong c h) = ≈-cong c (_≈_.next h)
{-# TERMINATING #-}
every≈alternating : ∀ b → alternating b ≈ step simple (Φ b) every
_≈_.quit (every≈alternating _) = refl
_≈_.next (every≈alternating false) = ≈-cong 2 (every≈alternating true)
_≈_.next (every≈alternating true ) = every≈alternating false
simple-program : tp⁺
simple-program = nat
{-# TERMINATING #-}
ψ : cmp (Π simple-program λ _ → Π (U simple) λ _ → F unit)
ψ zero s = Simple.quit s
ψ (suc n) s = ψ n (Simple.next s)
_≈'_ : (q₁ q₂ : cmp simple) → tp⁻
s₁ ≈' s₂ = Π simple-program λ p → ψ p s₁ ≡⁻[ F unit ] ψ p s₂
{-# TERMINATING #-}
classic-amortization : {s₁ s₂ : cmp simple} → val (U (s₁ ≈⁻ s₂) ⇔ U (s₁ ≈' s₂))
classic-amortization = forward , backward
where
forward : {s₁ s₂ : cmp simple} → s₁ ≈ s₂ → cmp (s₁ ≈' s₂)
forward h zero = _≈_.quit h
forward h (suc n) = forward (_≈_.next h) n
backward : {s₁ s₂ : cmp simple} → cmp (s₁ ≈' s₂) → s₁ ≈ s₂
_≈_.quit (backward classic) = classic zero
_≈_.next (backward classic) = backward (λ n → classic (suc n))