Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Merged by Bors] - feat(pfun/recursion): unbounded recursion #3778

Closed
wants to merge 35 commits into from
Closed
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
4e62dd7
feat(pfun/recursion): unbounded recursion
cipher1024 May 27, 2019
a563c7b
remove unused declarations
cipher1024 Aug 14, 2020
69f2fc2
rename Sup and complete_partial_order and apply lint
cipher1024 Aug 15, 2020
a66a5da
generalize sets to complete lattice
cipher1024 Aug 15, 2020
bc48b1d
move fix.lean
cipher1024 Aug 15, 2020
1204e4c
bundle continuous homomorphism
cipher1024 Aug 15, 2020
44a6e23
update `fix`
cipher1024 Aug 20, 2020
692aab7
Merge branch 'master' of https://github.com/leanprover-community/math…
cipher1024 Aug 20, 2020
0539a29
Use bundled morphisms, improve definition of `omega_complete_partial_…
cipher1024 Aug 22, 2020
361f638
apply `#lint` suggestions
cipher1024 Aug 22, 2020
1123d68
reverse changes in `data/stream/basic.lean`
cipher1024 Aug 22, 2020
4400964
fix namespace issue
cipher1024 Aug 23, 2020
3d14433
apply lint advice; rename `nat.up.lt` to `nat.up.gt`
cipher1024 Aug 23, 2020
c7ff867
address comments from reviewers
cipher1024 Aug 23, 2020
9dc308e
add documentation
cipher1024 Aug 25, 2020
fd994e4
squeeze simp
cipher1024 Aug 25, 2020
2503833
use `extends` in type class definition
cipher1024 Aug 25, 2020
c33af31
remove `main_declaration` annotations
cipher1024 Aug 25, 2020
bdb60a5
Merge branch 'master' into unbounded-recursion-basic
cipher1024 Aug 26, 2020
3a141c4
documentation and renaming
cipher1024 Aug 27, 2020
a0dea9f
Apply suggestions from code review
cipher1024 Aug 31, 2020
2a0f750
rename file, add comment
cipher1024 Aug 31, 2020
dd0cc15
add simon as author to data.pfun
digama0 Sep 1, 2020
637f74a
move nat.up to nat.upto
digama0 Sep 1, 2020
8bb1b3b
Update omega_complete_partial_order.lean
cipher1024 Sep 1, 2020
b285353
remove `ite`, add comment
cipher1024 Sep 1, 2020
7f3d788
more docs
digama0 Sep 1, 2020
d8e6d36
more docs
digama0 Sep 1, 2020
5bc749e
Merge remote-tracking branch 'origin/unbounded-recursion-basic' into …
digama0 Sep 1, 2020
68d75f2
tweak docs
digama0 Sep 1, 2020
b0e9b2b
split fix and lawful_fix
digama0 Sep 1, 2020
cbad880
more tweaks
digama0 Sep 1, 2020
a362ed4
fix import
digama0 Sep 1, 2020
5eaae39
Merge branch 'master' of https://github.com/leanprover-community/math…
cipher1024 Sep 2, 2020
8ca492a
bypass omege-cpo instance when looking for preorder instance roption
cipher1024 Sep 2, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
74 changes: 74 additions & 0 deletions src/data/nat/up.lean
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/-
Copyright (c) 2020 Simon Hudon. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Author: Simon Hudon
-/
import data.nat.basic

/-!
# `nat.up`

`nat.up p`, with `p` a predicate on `ℕ`, is a subtype of `ℕ` that contains value
`n` if no value below `n` (excluding `n`) satisfies `p`.

This allows us to prove `>` is well-founded when `∃ i, p i`. This helps implement
searches on `ℕ`, starting at `0` and with an unknown upper-bound.
cipher1024 marked this conversation as resolved.
Show resolved Hide resolved

-/

namespace nat

@[reducible]
def up (p : ℕ → Prop) : Type := { i : ℕ // (∀ j < i, ¬ p j) }

namespace up

variable {p : ℕ → Prop}

protected def lt (p) : up p → up p → Prop := λ x y, x.1 > y.1

instance : has_lt (up p) :=
{ lt := λ x y, x.1 > y.1 }

protected def wf : Exists p → well_founded (up.lt p)
| ⟨x,h⟩ :=
have h : (<) = measure (λ y : nat.up p, x - y.val),
by { ext, dsimp [measure,inv_image],
rw nat.sub_lt_sub_left_iff, refl,
by_contradiction h', revert h,
apply x_1.property _ (lt_of_not_ge h'), },
cast (congr_arg _ h.symm) (measure_wf _)

def zero : nat.up p := ⟨ 0, λ j h, false.elim (nat.not_lt_zero _ h) ⟩

def succ (x : nat.up p) (h : ¬ p x.val) : nat.up p :=
⟨x.val.succ, by { intros j h', rw nat.lt_succ_iff_lt_or_eq at h',
cases h', apply x.property _ h', subst j, apply h } ⟩

section find

variables [decidable_pred p] (h : Exists p)

def find_aux : nat.up p → nat.up p :=
well_founded.fix (up.wf h) $ λ x f,
if h : p x.val then x
else f (x.succ h) $ nat.lt_succ_self _

def find : ℕ := (find_aux h up.zero).val

lemma p_find : p (find h) :=
let P := (λ x : nat.up p, p (find_aux h x).val) in
suffices ∀ x, P x, from this _,
assume x,
well_founded.induction (nat.up.wf h) _ $ λ y ih,
by { dsimp [P], rw [find_aux,well_founded.fix_eq],
by_cases h' : (p y); simp *,
apply ih, apply nat.lt_succ_self, }

lemma find_least_solution (i : ℕ) (h' : i < find h) : ¬ p i :=
subtype.property (find_aux h nat.up.zero) _ h'

end find

end up
end nat
57 changes: 57 additions & 0 deletions src/data/pfun.lean
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ theorem dom_iff_mem : ∀ {o : roption α}, o.dom ↔ ∃y, y ∈ o
theorem get_mem {o : roption α} (h) : get o h ∈ o := ⟨_, rfl⟩

/-- `roption` extensionality -/
@[ext]
theorem ext {o p : roption α} (H : ∀ a, a ∈ o ↔ a ∈ p) : o = p :=
ext' ⟨λ h, ((H _).1 ⟨h, rfl⟩).fst,
λ h, ((H _).2 ⟨h, rfl⟩).fst⟩ $
Expand Down Expand Up @@ -94,6 +95,16 @@ begin
{ rintro ⟨x, rfl⟩, apply some_ne_none }
end

lemma eq_none_or_eq_some (o : roption α) : o = none ∨ ∃ x, o = some x :=
begin
classical,
by_cases h : o.dom,
{ rw dom_iff_mem at h, right,
apply exists_imp_exists _ h,
simp [eq_some_iff] },
{ rw eq_none_iff', exact or.inl h },
end

@[simp] lemma some_inj {a b : α} : roption.some a = some b ↔ a = b :=
function.injective.eq_iff (λ a b h, congr_fun (eq_of_heq (roption.mk.inj h).2) trivial)

Expand Down Expand Up @@ -172,6 +183,26 @@ by haveI := classical.dec; exact
⟨λ o, to_option o, of_option, λ o, of_to_option o,
λ o, eq.trans (by dsimp; congr) (to_of_option o)⟩

instance : order_bot (roption α) :=
{ le := λ x y, ∀ i, i ∈ x → i ∈ y,
le_refl := λ x y, id,
le_trans := λ x y z f g i, g _ ∘ f _,
le_antisymm := λ x y f g, roption.ext $ λ z, ⟨f _, g _⟩,
bot := none,
bot_le := by { introv x, rintro ⟨⟨_⟩,_⟩, } }

lemma le_total_of_le_of_le {x y : roption α} (z : roption α) (hx : x ≤ z) (hy : y ≤ z) :
x ≤ y ∨ y ≤ x :=
begin
rcases roption.eq_none_or_eq_some x with h | ⟨b, h₀⟩,
{ rw h, left, apply order_bot.bot_le _ },
right, intros b' h₁,
rw roption.eq_some_iff at h₀,
replace hx := hx _ h₀, replace hy := hy _ h₁,
replace hx := roption.mem_unique hx hy, subst hx,
exact h₀
end

/-- `assert p f` is a bind-like operation which appends an additional condition
`p` to the domain and uses `f` to produce the value. -/
def assert (p : Prop) (f : p → roption α) : roption α :=
Expand Down Expand Up @@ -210,6 +241,23 @@ theorem mem_assert {p : Prop} {f : p → roption α}
⟨match a with _, ⟨h, rfl⟩ := ⟨_, ⟨_, rfl⟩⟩ end,
λ ⟨a, h⟩, mem_assert _ h⟩

lemma assert_pos {p : Prop} {f : p → roption α} (h : p) :
assert p f = f h :=
begin
dsimp [assert],
cases h' : f h, simp [h',h],
cipher1024 marked this conversation as resolved.
Show resolved Hide resolved
apply function.hfunext,
{ simp only [h,h',exists_prop_of_true] },
{ cc }
end

lemma assert_neg {p : Prop} {f : p → roption α} (h : ¬ p) :
assert p f = none :=
begin
dsimp [assert,none], congr, simp [h],
cipher1024 marked this conversation as resolved.
Show resolved Hide resolved
apply function.hfunext, simp [h], cc,
end

theorem mem_bind {f : roption α} {g : α → roption β} :
∀ {a b}, a ∈ f → b ∈ g a → b ∈ f.bind g
| _ _ ⟨h, rfl⟩ ⟨h₂, rfl⟩ := ⟨⟨h, h₂⟩, rfl⟩
Expand Down Expand Up @@ -273,6 +321,15 @@ by rw [bind_some_eq_map]; simp [map_id']
@[simp] theorem bind_eq_bind {α β} (f : roption α) (g : α → roption β) :
f >>= g = f.bind g := rfl

lemma bind_le {α} (x : roption α) (f : α → roption β) (y : roption β) :
x >>= f ≤ y ↔ (∀ a, a ∈ x → f a ≤ y) :=
begin
split; intro h,
{ intros a h' b, replace h := h b, simp at h, apply h _ h' },
{ intros b h', simp at h', rcases h' with ⟨a,h₀,h₁⟩,
cipher1024 marked this conversation as resolved.
Show resolved Hide resolved
apply h _ h₀ _ h₁ },
end

instance : monad_fail roption :=
{ fail := λ_ _, none, ..roption.monad }

Expand Down