-
Notifications
You must be signed in to change notification settings - Fork 354
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: port Logic.Hydra #2290
Closed
Closed
Changes from 11 commits
Commits
Show all changes
12 commits
Select commit
Hold shift + click to select a range
a82d304
feat: port Logic.Hydra
urkud 105421c
Initial file copy from mathport
urkud 33052cc
automated fixes
urkud ece766b
Snapshot
urkud 7b0aea6
Fix
urkud e6be053
Merge branch 'master' into port/Logic.Hydra
int-y1 911f24a
zero -> empty
int-y1 7812e9b
fix red
int-y1 92111bf
docs
int-y1 bac593b
code style
int-y1 f189944
add link to issue
kim-em 32de69f
restore apply_fun proofs
ChrisHughes24 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,160 @@ | ||
/- | ||
Copyright (c) 2022 Junyan Xu. All rights reserved. | ||
Released under Apache 2.0 license as described in the file LICENSE. | ||
Authors: Junyan Xu | ||
|
||
! This file was ported from Lean 3 source module logic.hydra | ||
! leanprover-community/mathlib commit 48085f140e684306f9e7da907cd5932056d1aded | ||
! Please do not edit these lines, except to modify the commit id | ||
! if you have ported upstream changes. | ||
-/ | ||
import Mathlib.Data.Finsupp.Lex | ||
import Mathlib.Data.Finsupp.Multiset | ||
import Mathlib.Order.GameAdd | ||
|
||
/-! | ||
# Termination of a hydra game | ||
|
||
This file deals with the following version of the hydra game: each head of the hydra is | ||
labelled by an element in a type `α`, and when you cut off one head with label `a`, it | ||
grows back an arbitrary but finite number of heads, all labelled by elements smaller than | ||
`a` with respect to a well-founded relation `r` on `α`. We show that no matter how (in | ||
what order) you choose cut off the heads, the game always terminates, i.e. all heads will | ||
eventually be cut off (but of course it can last arbitrarily long, i.e. takes an | ||
arbitrary finite number of steps). | ||
|
||
This result is stated as the well-foundedness of the `CutExpand` relation defined in | ||
this file: we model the heads of the hydra as a multiset of elements of `α`, and the | ||
valid "moves" of the game are modelled by the relation `CutExpand r` on `Multiset α`: | ||
`CutExpand r s' s` is true iff `s'` is obtained by removing one head `a ∈ s` and | ||
adding back an arbitrary multiset `t` of heads such that all `a' ∈ t` satisfy `r a' a`. | ||
|
||
We follow the proof by Peter LeFanu Lumsdaine at https://mathoverflow.net/a/229084/3332. | ||
|
||
TODO: formalize the relations corresponding to more powerful (e.g. Kirby–Paris and Buchholz) | ||
hydras, and prove their well-foundedness. | ||
-/ | ||
|
||
|
||
namespace Relation | ||
|
||
open Multiset Prod | ||
|
||
variable {α : Type _} | ||
|
||
/-- The relation that specifies valid moves in our hydra game. `CutExpand r s' s` | ||
means that `s'` is obtained by removing one head `a ∈ s` and adding back an arbitrary | ||
multiset `t` of heads such that all `a' ∈ t` satisfy `r a' a`. | ||
|
||
This is most directly translated into `s' = s.erase a + t`, but `Multiset.erase` requires | ||
`DecidableEq α`, so we use the equivalent condition `s' + {a} = s + t` instead, which | ||
is also easier to verify for explicit multisets `s'`, `s` and `t`. | ||
|
||
We also don't include the condition `a ∈ s` because `s' + {a} = s + t` already | ||
guarantees `a ∈ s + t`, and if `r` is irreflexive then `a ∉ t`, which is the | ||
case when `r` is well-founded, the case we are primarily interested in. | ||
|
||
The lemma `Relation.cutExpand_iff` below converts between this convenient definition | ||
and the direct translation when `r` is irreflexive. -/ | ||
def CutExpand (r : α → α → Prop) (s' s : Multiset α) : Prop := | ||
∃ (t : Multiset α) (a : α), (∀ a' ∈ t, r a' a) ∧ s' + {a} = s + t | ||
#align relation.cut_expand Relation.CutExpand | ||
|
||
variable {r : α → α → Prop} | ||
|
||
theorem cutExpand_le_invImage_lex [IsIrrefl α r] : | ||
CutExpand r ≤ InvImage (Finsupp.Lex (rᶜ ⊓ (· ≠ ·)) (· < ·)) toFinsupp := by | ||
rintro s t ⟨u, a, hr, he⟩ | ||
replace hr := fun a' ↦ mt (hr a') | ||
classical | ||
refine ⟨a, fun b h ↦ ?_, ?_⟩ <;> simp_rw [toFinsupp_apply] | ||
· replace he := congr_arg (count b) he -- porting note: was apply_fun count b at he | ||
simpa only [count_add, count_singleton, if_neg h.2, add_zero, count_eq_zero.2 (hr b h.1)] | ||
using he | ||
· replace he := congr_arg (count a) he -- porting note: was apply_fun count a at he | ||
simp only [count_add, count_singleton_self, count_eq_zero.2 (hr _ (irrefl_of r a)), | ||
add_zero] at he | ||
exact he ▸ Nat.lt_succ_self _ | ||
#align relation.cut_expand_le_inv_image_lex Relation.cutExpand_le_invImage_lex | ||
|
||
theorem cutExpand_singleton {s x} (h : ∀ x' ∈ s, r x' x) : CutExpand r s {x} := | ||
⟨s, x, h, add_comm s _⟩ | ||
#align relation.cut_expand_singleton Relation.cutExpand_singleton | ||
|
||
theorem cutExpand_singleton_singleton {x' x} (h : r x' x) : CutExpand r {x'} {x} := | ||
cutExpand_singleton fun a h ↦ by rwa [mem_singleton.1 h] | ||
#align relation.cut_expand_singleton_singleton Relation.cutExpand_singleton_singleton | ||
|
||
theorem cutExpand_add_left {t u} (s) : CutExpand r (s + t) (s + u) ↔ CutExpand r t u := | ||
exists₂_congr fun _ _ ↦ and_congr Iff.rfl <| by rw [add_assoc, add_assoc, add_left_cancel_iff] | ||
#align relation.cut_expand_add_left Relation.cutExpand_add_left | ||
|
||
theorem cutExpand_iff [DecidableEq α] [IsIrrefl α r] {s' s : Multiset α} : | ||
CutExpand r s' s ↔ | ||
∃ (t : Multiset α) (a : α), (∀ a' ∈ t, r a' a) ∧ a ∈ s ∧ s' = s.erase a + t := by | ||
simp_rw [CutExpand, add_singleton_eq_iff] | ||
refine' exists₂_congr fun t a ↦ ⟨_, _⟩ | ||
· rintro ⟨ht, ha, rfl⟩ | ||
obtain h | h := mem_add.1 ha | ||
exacts [⟨ht, h, erase_add_left_pos t h⟩, (@irrefl α r _ a (ht a h)).elim] | ||
· rintro ⟨ht, h, rfl⟩ | ||
exact ⟨ht, mem_add.2 (Or.inl h), (erase_add_left_pos t h).symm⟩ | ||
#align relation.cut_expand_iff Relation.cutExpand_iff | ||
|
||
theorem not_cutExpand_zero [IsIrrefl α r] (s) : ¬CutExpand r s 0 := by | ||
classical | ||
rw [cutExpand_iff] | ||
rintro ⟨_, _, _, ⟨⟩, _⟩ | ||
#align relation.not_cut_expand_zero Relation.not_cutExpand_zero | ||
|
||
/-- For any relation `r` on `α`, multiset addition `Multiset α × Multiset α → Multiset α` is a | ||
fibration between the game sum of `CutExpand r` with itself and `CutExpand r` itself. -/ | ||
theorem cutExpand_fibration (r : α → α → Prop) : | ||
Fibration (GameAdd (CutExpand r) (CutExpand r)) (CutExpand r) fun s ↦ s.1 + s.2 := by | ||
rintro ⟨s₁, s₂⟩ s ⟨t, a, hr, he⟩; dsimp at he ⊢ | ||
classical | ||
-- Porting note: Originally `obtain ⟨ha, rfl⟩` | ||
-- This is https://github.com/leanprover/std4/issues/62 | ||
obtain ⟨ha, hb⟩ := add_singleton_eq_iff.1 he | ||
kim-em marked this conversation as resolved.
Show resolved
Hide resolved
|
||
rw [hb] | ||
rw [add_assoc, mem_add] at ha | ||
obtain h | h := ha | ||
· refine' ⟨(s₁.erase a + t, s₂), GameAdd.fst ⟨t, a, hr, _⟩, _⟩ | ||
· rw [add_comm, ← add_assoc, singleton_add, cons_erase h] | ||
· rw [add_assoc s₁, erase_add_left_pos _ h, add_right_comm, add_assoc] | ||
· refine' ⟨(s₁, (s₂ + t).erase a), GameAdd.snd ⟨t, a, hr, _⟩, _⟩ | ||
· rw [add_comm, singleton_add, cons_erase h] | ||
· rw [add_assoc, erase_add_right_pos _ h] | ||
#align relation.cut_expand_fibration Relation.cutExpand_fibration | ||
|
||
/-- A multiset is accessible under `CutExpand` if all its singleton subsets are, | ||
assuming `r` is irreflexive. -/ | ||
theorem acc_of_singleton [IsIrrefl α r] {s : Multiset α} (hs : ∀ a ∈ s, Acc (CutExpand r) {a}) : | ||
Acc (CutExpand r) s := by | ||
induction s using Multiset.induction | ||
case empty => exact Acc.intro 0 fun s h ↦ (not_cutExpand_zero s h).elim | ||
case cons a s ihs => | ||
rw [← s.singleton_add a] | ||
rw [forall_mem_cons] at hs | ||
exact (hs.1.prod_gameAdd <| ihs fun a ha ↦ hs.2 a ha).of_fibration _ (cutExpand_fibration r) | ||
#align relation.acc_of_singleton Relation.acc_of_singleton | ||
|
||
/-- A singleton `{a}` is accessible under `CutExpand r` if `a` is accessible under `r`, | ||
assuming `r` is irreflexive. -/ | ||
theorem _root_.Acc.cutExpand [IsIrrefl α r] {a : α} (hacc : Acc r a) : Acc (CutExpand r) {a} := by | ||
induction' hacc with a h ih | ||
refine' Acc.intro _ fun s ↦ _ | ||
classical | ||
simp only [cutExpand_iff, mem_singleton] | ||
rintro ⟨t, a, hr, rfl, rfl⟩ | ||
refine' acc_of_singleton fun a' ↦ _ | ||
rw [erase_singleton, zero_add] | ||
exact ih a' ∘ hr a' | ||
#align acc.cut_expand Acc.cutExpand | ||
|
||
/-- `CutExpand r` is well-founded when `r` is. -/ | ||
theorem _root_.WellFounded.cutExpand (hr : WellFounded r) : WellFounded (CutExpand r) := | ||
⟨have := hr.isIrrefl; fun _ ↦ acc_of_singleton fun a _ ↦ (hr.apply a).cutExpand⟩ | ||
#align well_founded.cut_expand WellFounded.cutExpand | ||
|
||
end Relation |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In fact,
apply_fun
has been improved in the meantime, and works here. (Also a few lines below.)