-
Notifications
You must be signed in to change notification settings - Fork 246
/
Copy pathWellFounded.agda
265 lines (194 loc) · 9.38 KB
/
WellFounded.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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
------------------------------------------------------------------------
-- The Agda standard library
--
-- Well-founded induction
------------------------------------------------------------------------
{-# OPTIONS --cubical-compatible --safe #-}
module Induction.WellFounded where
open import Data.Product.Base using (Σ; _,_; proj₁; proj₂)
open import Function.Base using (_∘_; flip; _on_)
open import Induction
open import Level using (Level; _⊔_)
open import Relation.Binary.Core using (Rel)
open import Relation.Binary.Definitions
using (Symmetric; Asymmetric; Irreflexive; _Respects₂_;
_Respectsʳ_; _Respects_)
open import Relation.Binary.PropositionalEquality.Core using (_≡_; refl)
open import Relation.Binary.Consequences using (asym⇒irr)
open import Relation.Unary
open import Relation.Nullary.Negation.Core using (¬_)
private
variable
a b ℓ ℓ₁ ℓ₂ r : Level
A : Set a
B : Set b
------------------------------------------------------------------------
-- Definitions
-- When using well-founded recursion you can recurse arbitrarily, as
-- long as the arguments become smaller, and "smaller" is
-- well-founded.
WfRec : Rel A r → ∀ {ℓ} → RecStruct A ℓ _
WfRec _<_ P x = ∀ {y} → y < x → P y
-- The accessibility predicate: x is accessible if everything which is
-- smaller than x is also accessible (inductively).
data Acc {A : Set a} (_<_ : Rel A ℓ) (x : A) : Set (a ⊔ ℓ) where
acc : (rs : WfRec _<_ (Acc _<_) x) → Acc _<_ x
-- The accessibility predicate encodes what it means to be
-- well-founded; if all elements are accessible, then _<_ is
-- well-founded.
WellFounded : Rel A ℓ → Set _
WellFounded _<_ = ∀ x → Acc _<_ x
------------------------------------------------------------------------
-- Basic properties
acc-inverse : ∀ {_<_ : Rel A ℓ} {x : A} (q : Acc _<_ x) →
WfRec _<_ (Acc _<_) x
acc-inverse (acc rs) y<x = rs y<x
module _ {_≈_ : Rel A ℓ₁} {_<_ : Rel A ℓ₂} where
Acc-resp-flip-≈ : _<_ Respectsʳ (flip _≈_) → (Acc _<_) Respects _≈_
Acc-resp-flip-≈ respʳ x≈y (acc rec) = acc λ z<y → rec (respʳ x≈y z<y)
Acc-resp-≈ : Symmetric _≈_ → _<_ Respectsʳ _≈_ → (Acc _<_) Respects _≈_
Acc-resp-≈ sym respʳ x≈y wf = Acc-resp-flip-≈ (respʳ ∘ sym) x≈y wf
------------------------------------------------------------------------
-- Well-founded induction for the subset of accessible elements:
module Some {_<_ : Rel A r} {ℓ} where
wfRecBuilder : SubsetRecursorBuilder (Acc _<_) (WfRec _<_ {ℓ = ℓ})
wfRecBuilder P f x (acc rs) = λ y<x → f _ (wfRecBuilder P f _ (rs y<x))
wfRec : SubsetRecursor (Acc _<_) (WfRec _<_)
wfRec = subsetBuild wfRecBuilder
unfold-wfRec : (P : Pred A ℓ) (f : WfRec _<_ P ⊆′ P) {x : A} (q : Acc _<_ x) →
wfRec P f x q ≡ f x λ y<x → wfRec P f _ (acc-inverse q y<x)
unfold-wfRec P f (acc rs) = refl
------------------------------------------------------------------------
-- Well-founded induction for all elements, assuming they are all
-- accessible:
module All {_<_ : Rel A r} (wf : WellFounded _<_) ℓ where
wfRecBuilder : RecursorBuilder (WfRec _<_ {ℓ = ℓ})
wfRecBuilder P f x = Some.wfRecBuilder P f x (wf x)
wfRec : Recursor (WfRec _<_)
wfRec = build wfRecBuilder
wfRec-builder = wfRecBuilder
module FixPoint
{_<_ : Rel A r} (wf : WellFounded _<_)
(P : Pred A ℓ) (f : WfRec _<_ P ⊆′ P)
(f-ext : (x : A) {IH IH′ : WfRec _<_ P x} →
(∀ {y} y<x → IH {y} y<x ≡ IH′ y<x) →
f x IH ≡ f x IH′)
where
some-wfrec-Irrelevant : Pred A _
some-wfrec-Irrelevant x = ∀ q q′ → Some.wfRec P f x q ≡ Some.wfRec P f x q′
some-wfRec-irrelevant : ∀ x → some-wfrec-Irrelevant x
some-wfRec-irrelevant = All.wfRec wf _ some-wfrec-Irrelevant
λ { x IH (acc rs) (acc rs′) → f-ext x λ y<x → IH y<x (rs y<x) (rs′ y<x) }
open All wf ℓ
wfRecBuilder-wfRec : ∀ {x y} y<x → wfRecBuilder P f x y<x ≡ wfRec P f y
wfRecBuilder-wfRec {x} {y} y<x with acc rs ← wf x
= some-wfRec-irrelevant y (rs y<x) (wf y)
unfold-wfRec : ∀ {x} → wfRec P f x ≡ f x λ _ → wfRec P f _
unfold-wfRec {x} = f-ext x wfRecBuilder-wfRec
------------------------------------------------------------------------
-- Well-founded relations are asymmetric and irreflexive.
module _ {_<_ : Rel A r} where
acc⇒asym : ∀ {x y} → Acc _<_ x → x < y → ¬ (y < x)
acc⇒asym {x} hx =
Some.wfRec (λ x → ∀ {y} → x < y → ¬ (y < x)) (λ _ hx x<y y<x → hx y<x y<x x<y) _ hx
wf⇒asym : WellFounded _<_ → Asymmetric _<_
wf⇒asym wf = acc⇒asym (wf _)
wf⇒irrefl : {_≈_ : Rel A ℓ} → _<_ Respects₂ _≈_ →
Symmetric _≈_ → WellFounded _<_ → Irreflexive _≈_ _<_
wf⇒irrefl r s wf = asym⇒irr r s (wf⇒asym wf)
------------------------------------------------------------------------
-- It might be useful to establish proofs of Acc or Well-founded using
-- combinators such as the ones below (see, for instance,
-- "Constructing Recursion Operators in Intuitionistic Type Theory" by
-- Lawrence C Paulson).
module Subrelation {_<₁_ : Rel A ℓ₁} {_<₂_ : Rel A ℓ₂}
(<₁⇒<₂ : ∀ {x y} → x <₁ y → x <₂ y) where
accessible : Acc _<₂_ ⊆ Acc _<₁_
accessible (acc rs) = acc λ y<x → accessible (rs (<₁⇒<₂ y<x))
wellFounded : WellFounded _<₂_ → WellFounded _<₁_
wellFounded wf = λ x → accessible (wf x)
-- DEPRECATED in v1.4.
-- Please use proofs in `Relation.Binary.Construct.On` instead.
module InverseImage {_<_ : Rel B ℓ} (f : A → B) where
accessible : ∀ {x} → Acc _<_ (f x) → Acc (_<_ on f) x
accessible (acc rs) = acc λ fy<fx → accessible (rs fy<fx)
wellFounded : WellFounded _<_ → WellFounded (_<_ on f)
wellFounded wf = λ x → accessible (wf (f x))
well-founded = wellFounded
{-# WARNING_ON_USAGE accessible
"Warning: accessible was deprecated in v1.4.
\ \Please use accessible from `Relation.Binary.Construct.On` instead."
#-}
{-# WARNING_ON_USAGE wellFounded
"Warning: wellFounded was deprecated in v1.4.
\ \Please use wellFounded from `Relation.Binary.Construct.On` instead."
#-}
-- DEPRECATED in v1.5.
-- Please use `TransClosure` from `Relation.Binary.Construct.Closure.Transitive` instead.
module TransitiveClosure {A : Set a} (_<_ : Rel A ℓ) where
infix 4 _<⁺_
data _<⁺_ : Rel A (a ⊔ ℓ) where
[_] : ∀ {x y} (x<y : x < y) → x <⁺ y
trans : ∀ {x y z} (x<y : x <⁺ y) (y<z : y <⁺ z) → x <⁺ z
downwardsClosed : ∀ {x y} → Acc _<⁺_ y → x <⁺ y → Acc _<⁺_ x
downwardsClosed (acc rs) x<y = acc λ z<x → rs (trans z<x x<y)
mutual
accessible : ∀ {x} → Acc _<_ x → Acc _<⁺_ x
accessible acc-x = acc (accessible′ acc-x)
accessible′ : ∀ {x} → Acc _<_ x → WfRec _<⁺_ (Acc _<⁺_) x
accessible′ (acc rs) [ y<x ] = accessible (rs y<x)
accessible′ acc-x (trans y<z z<x) =
downwardsClosed (accessible′ acc-x z<x) y<z
wellFounded : WellFounded _<_ → WellFounded _<⁺_
wellFounded wf = λ x → accessible (wf x)
{-# WARNING_ON_USAGE _<⁺_
"Warning: _<⁺_ was deprecated in v1.5.
\ \Please use TransClosure from Relation.Binary.Construct.Closure.Transitive instead."
#-}
-- DEPRECATED in v1.3.
-- Please use `×-Lex` from `Data.Product.Relation.Binary.Lex.Strict` instead.
module Lexicographic {A : Set a} {B : A → Set b}
(RelA : Rel A ℓ₁)
(RelB : ∀ x → Rel (B x) ℓ₂) where
infix 4 _<_
data _<_ : Rel (Σ A B) (a ⊔ b ⊔ ℓ₁ ⊔ ℓ₂) where
left : ∀ {x₁ y₁ x₂ y₂} (x₁<x₂ : RelA x₁ x₂) → (x₁ , y₁) < (x₂ , y₂)
right : ∀ {x y₁ y₂} (y₁<y₂ : RelB x y₁ y₂) → (x , y₁) < (x , y₂)
mutual
accessible : ∀ {x y} →
Acc RelA x → (∀ {x} → WellFounded (RelB x)) →
Acc _<_ (x , y)
accessible accA wfB = acc (accessible′ accA (wfB _) wfB)
accessible′ :
∀ {x y} →
Acc RelA x → Acc (RelB x) y → (∀ {x} → WellFounded (RelB x)) →
WfRec _<_ (Acc _<_) (x , y)
accessible′ (acc rsA) _ wfB (left x′<x) = accessible (rsA x′<x) wfB
accessible′ accA (acc rsB) wfB (right y′<y) =
acc (accessible′ accA (rsB y′<y) wfB)
wellFounded : WellFounded RelA → (∀ {x} → WellFounded (RelB x)) →
WellFounded _<_
wellFounded wfA wfB p = accessible (wfA (proj₁ p)) wfB
well-founded = wellFounded
{-# WARNING_ON_USAGE _<_
"Warning: _<_ was deprecated in v1.3.
\ \Please use `×-Lex` from `Data.Product.Relation.Binary.Lex.Strict` instead."
#-}
{-# WARNING_ON_USAGE accessible
"Warning: accessible was deprecated in v1.3."
#-}
{-# WARNING_ON_USAGE accessible′
"Warning: accessible′ was deprecated in v1.3."
#-}
{-# WARNING_ON_USAGE wellFounded
"Warning: wellFounded was deprecated in v1.3.
\ \Please use `×-wellFounded` from `Data.Product.Relation.Binary.Lex.Strict` instead."
#-}
------------------------------------------------------------------------
-- DEPRECATED NAMES
------------------------------------------------------------------------
-- Please use the new names as continuing support for the old names is
-- not guaranteed.
-- Version 1.0
module Inverse-image = InverseImage
module Transitive-closure = TransitiveClosure