set_theory.game.nim
⟷
Mathlib.SetTheory.Game.Nim
The following section lists changes to this file in mathlib3 and mathlib4 that occured after the initial port. Most recent changes are shown first. Hovering over a commit will show all commits associated with the same mathlib3 commit.
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(last sync)
mathlib commit https://github.com/leanprover-community/mathlib/commit/65a1391a0106c9204fe45bc73a039f056558cb83
@@ -512,20 +512,20 @@ theorem SetTheory.PGame.grundyValue_nim_add_nim (n m : ℕ) :
| rw [hn _ hk]
| rw [hm _ hk]
refine' fun h => hk.ne _
- rw [Ordinal.nat_cast_inj] at h
+ rw [Ordinal.natCast_inj] at h
first
| rwa [Nat.xor_left_inj] at h
| rwa [Nat.xor_right_inj] at h
-- Every other smaller Grundy value can be reached by left moves.
· -- If `u < nat.lxor m n`, then either `nat.lxor u n < m` or `nat.lxor u m < n`.
obtain ⟨u, rfl⟩ := Ordinal.lt_omega.1 (hu.trans (Ordinal.nat_lt_omega _))
- replace hu := Ordinal.nat_cast_lt.1 hu
+ replace hu := Ordinal.natCast_lt.1 hu
cases' Nat.lt_xor_cases hu with h h
-- In the first case, reducing the `m` pile to `nat.lxor u n` gives the desired Grundy value.
- · refine' ⟨to_left_moves_add (Sum.inl <| to_left_moves_nim ⟨_, Ordinal.nat_cast_lt.2 h⟩), _⟩
+ · refine' ⟨to_left_moves_add (Sum.inl <| to_left_moves_nim ⟨_, Ordinal.natCast_lt.2 h⟩), _⟩
simp [Nat.xor_cancel_right, hn _ h]
-- In the second case, reducing the `n` pile to `nat.lxor u m` gives the desired Grundy value.
- · refine' ⟨to_left_moves_add (Sum.inr <| to_left_moves_nim ⟨_, Ordinal.nat_cast_lt.2 h⟩), _⟩
+ · refine' ⟨to_left_moves_add (Sum.inr <| to_left_moves_nim ⟨_, Ordinal.natCast_lt.2 h⟩), _⟩
have : n.lxor (u.lxor n) = u; rw [Nat.xor_comm u, Nat.xor_cancel_left]
simpa [hm _ h] using this
#align pgame.grundy_value_nim_add_nim SetTheory.PGame.grundyValue_nim_add_nim
mathlib commit https://github.com/leanprover-community/mathlib/commit/65a1391a0106c9204fe45bc73a039f056558cb83
@@ -523,7 +523,7 @@ theorem SetTheory.PGame.grundyValue_nim_add_nim (n m : ℕ) :
cases' Nat.lt_xor_cases hu with h h
-- In the first case, reducing the `m` pile to `nat.lxor u n` gives the desired Grundy value.
· refine' ⟨to_left_moves_add (Sum.inl <| to_left_moves_nim ⟨_, Ordinal.nat_cast_lt.2 h⟩), _⟩
- simp [Nat.lxor_cancel_right, hn _ h]
+ simp [Nat.xor_cancel_right, hn _ h]
-- In the second case, reducing the `n` pile to `nat.lxor u m` gives the desired Grundy value.
· refine' ⟨to_left_moves_add (Sum.inr <| to_left_moves_nim ⟨_, Ordinal.nat_cast_lt.2 h⟩), _⟩
have : n.lxor (u.lxor n) = u; rw [Nat.xor_comm u, Nat.xor_cancel_left]
mathlib commit https://github.com/leanprover-community/mathlib/commit/65a1391a0106c9204fe45bc73a039f056558cb83
@@ -315,7 +315,7 @@ theorem SetTheory.PGame.nim_fuzzy_zero_of_ne_zero {o : Ordinal} (ho : o ≠ 0) :
SetTheory.PGame.nim o ‖ 0 :=
by
rw [impartial.fuzzy_zero_iff_lf, nim_def, lf_zero_le]
- rw [← Ordinal.pos_iff_ne_zero] at ho
+ rw [← Ordinal.pos_iff_ne_zero] at ho
exact ⟨(Ordinal.principalSegOut ho).top, by simp⟩
#align pgame.nim_fuzzy_zero_of_ne_zero SetTheory.PGame.nim_fuzzy_zero_of_ne_zero
-/
@@ -387,9 +387,9 @@ theorem SetTheory.PGame.equiv_nim_grundyValue :
apply (fuzzy_congr_left (add_congr_left (equiv_nim_grundy_value (G.move_left i₁)).symm)).1
rw [nim_add_fuzzy_zero_iff]
intro heq
- rw [eq_comm, grundy_value_eq_mex_left G] at heq
+ rw [eq_comm, grundy_value_eq_mex_left G] at heq
have h := Ordinal.ne_mex _
- rw [HEq] at h
+ rw [HEq] at h
exact (h i₁).irrefl
· intro i₂
rw [add_move_left_inr, ← impartial.exists_left_move_equiv_iff_fuzzy_zero]
@@ -507,15 +507,15 @@ theorem SetTheory.PGame.grundyValue_nim_add_nim (n m : ℕ) :
obtain ⟨k, rfl⟩ := Ordinal.lt_omega.1 (hk.trans (Ordinal.nat_lt_omega _))
simp only [add_move_left_inl, add_move_left_inr, move_left_nim', Equiv.symm_apply_apply]
-- The inequality follows from injectivity.
- rw [nat_cast_lt] at hk
+ rw [nat_cast_lt] at hk
first
| rw [hn _ hk]
| rw [hm _ hk]
refine' fun h => hk.ne _
- rw [Ordinal.nat_cast_inj] at h
+ rw [Ordinal.nat_cast_inj] at h
first
- | rwa [Nat.xor_left_inj] at h
- | rwa [Nat.xor_right_inj] at h
+ | rwa [Nat.xor_left_inj] at h
+ | rwa [Nat.xor_right_inj] at h
-- Every other smaller Grundy value can be reached by left moves.
· -- If `u < nat.lxor m n`, then either `nat.lxor u n < m` or `nat.lxor u m < n`.
obtain ⟨u, rfl⟩ := Ordinal.lt_omega.1 (hu.trans (Ordinal.nat_lt_omega _))
mathlib commit https://github.com/leanprover-community/mathlib/commit/b1abe23ae96fef89ad30d9f4362c307f72a55010
@@ -491,7 +491,7 @@ xor. -/
@[simp]
theorem SetTheory.PGame.grundyValue_nim_add_nim (n m : ℕ) :
SetTheory.PGame.grundyValue (SetTheory.PGame.nim.{u} n + SetTheory.PGame.nim.{u} m) =
- Nat.lxor' n m :=
+ Nat.xor n m :=
by
-- We do strong induction on both variables.
induction' n using Nat.strong_induction_on with n hn generalizing m
@@ -514,26 +514,26 @@ theorem SetTheory.PGame.grundyValue_nim_add_nim (n m : ℕ) :
refine' fun h => hk.ne _
rw [Ordinal.nat_cast_inj] at h
first
- | rwa [Nat.lxor'_left_inj] at h
- | rwa [Nat.lxor'_right_inj] at h
+ | rwa [Nat.xor_left_inj] at h
+ | rwa [Nat.xor_right_inj] at h
-- Every other smaller Grundy value can be reached by left moves.
· -- If `u < nat.lxor m n`, then either `nat.lxor u n < m` or `nat.lxor u m < n`.
obtain ⟨u, rfl⟩ := Ordinal.lt_omega.1 (hu.trans (Ordinal.nat_lt_omega _))
replace hu := Ordinal.nat_cast_lt.1 hu
- cases' Nat.lt_lxor'_cases hu with h h
+ cases' Nat.lt_xor_cases hu with h h
-- In the first case, reducing the `m` pile to `nat.lxor u n` gives the desired Grundy value.
· refine' ⟨to_left_moves_add (Sum.inl <| to_left_moves_nim ⟨_, Ordinal.nat_cast_lt.2 h⟩), _⟩
simp [Nat.lxor_cancel_right, hn _ h]
-- In the second case, reducing the `n` pile to `nat.lxor u m` gives the desired Grundy value.
· refine' ⟨to_left_moves_add (Sum.inr <| to_left_moves_nim ⟨_, Ordinal.nat_cast_lt.2 h⟩), _⟩
- have : n.lxor (u.lxor n) = u; rw [Nat.lxor'_comm u, Nat.lxor'_cancel_left]
+ have : n.lxor (u.lxor n) = u; rw [Nat.xor_comm u, Nat.xor_cancel_left]
simpa [hm _ h] using this
#align pgame.grundy_value_nim_add_nim SetTheory.PGame.grundyValue_nim_add_nim
-/
#print SetTheory.PGame.nim_add_nim_equiv /-
theorem SetTheory.PGame.nim_add_nim_equiv {n m : ℕ} :
- SetTheory.PGame.nim n + SetTheory.PGame.nim m ≈ SetTheory.PGame.nim (Nat.lxor' n m) := by
+ SetTheory.PGame.nim n + SetTheory.PGame.nim m ≈ SetTheory.PGame.nim (Nat.xor n m) := by
rw [← grundy_value_eq_iff_equiv_nim, grundy_value_nim_add_nim]
#align pgame.nim_add_nim_equiv SetTheory.PGame.nim_add_nim_equiv
-/
@@ -541,9 +541,9 @@ theorem SetTheory.PGame.nim_add_nim_equiv {n m : ℕ} :
#print SetTheory.PGame.grundyValue_add /-
theorem SetTheory.PGame.grundyValue_add (G H : SetTheory.PGame) [G.Impartial] [H.Impartial]
{n m : ℕ} (hG : SetTheory.PGame.grundyValue G = n) (hH : SetTheory.PGame.grundyValue H = m) :
- SetTheory.PGame.grundyValue (G + H) = Nat.lxor' n m :=
+ SetTheory.PGame.grundyValue (G + H) = Nat.xor n m :=
by
- rw [← nim_grundy_value (Nat.lxor' n m), grundy_value_eq_iff_equiv]
+ rw [← nim_grundy_value (Nat.xor n m), grundy_value_eq_iff_equiv]
refine' Equiv.trans _ nim_add_nim_equiv
convert add_congr (equiv_nim_grundy_value G) (equiv_nim_grundy_value H) <;> simp only [hG, hH]
#align pgame.grundy_value_add SetTheory.PGame.grundyValue_add
mathlib commit https://github.com/leanprover-community/mathlib/commit/ce64cd319bb6b3e82f31c2d38e79080d377be451
@@ -3,9 +3,9 @@ Copyright (c) 2020 Fox Thomson. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Fox Thomson, Markus Himmel
-/
-import Mathbin.Data.Nat.Bitwise
-import Mathbin.SetTheory.Game.Birthday
-import Mathbin.SetTheory.Game.Impartial
+import Data.Nat.Bitwise
+import SetTheory.Game.Birthday
+import SetTheory.Game.Impartial
#align_import set_theory.game.nim from "leanprover-community/mathlib"@"d0b1936853671209a866fa35b9e54949c81116e2"
mathlib commit https://github.com/leanprover-community/mathlib/commit/442a83d738cb208d3600056c489be16900ba701d
@@ -38,223 +38,249 @@ noncomputable section
universe u
-open scoped PGame
+open scoped SetTheory.PGame
-namespace PGame
+namespace SetTheory.PGame
-#print PGame.nim /-
+#print SetTheory.PGame.nim /-
-- Uses `noncomputable!` to avoid `rec_fn_macro only allowed in meta definitions` VM error
/-- The definition of single-heap nim, which can be viewed as a pile of stones where each player can
take a positive number of stones from it on their turn. -/
-noncomputable def nim : Ordinal.{u} → PGame.{u}
+noncomputable def SetTheory.PGame.nim : Ordinal.{u} → SetTheory.PGame.{u}
| o₁ =>
let f o₂ :=
have : Ordinal.typein o₁.out.R o₂ < o₁ := Ordinal.typein_lt_self o₂
nim (Ordinal.typein o₁.out.R o₂)
⟨o₁.out.α, o₁.out.α, f, f⟩
-#align pgame.nim PGame.nim
+#align pgame.nim SetTheory.PGame.nim
-/
open Ordinal
-#print PGame.nim_def /-
-theorem nim_def (o : Ordinal) :
- nim o =
- PGame.mk o.out.α o.out.α (fun o₂ => nim (Ordinal.typein (· < ·) o₂)) fun o₂ =>
- nim (Ordinal.typein (· < ·) o₂) :=
+#print SetTheory.PGame.nim_def /-
+theorem SetTheory.PGame.nim_def (o : Ordinal) :
+ SetTheory.PGame.nim o =
+ SetTheory.PGame.mk o.out.α o.out.α (fun o₂ => SetTheory.PGame.nim (Ordinal.typein (· < ·) o₂))
+ fun o₂ => SetTheory.PGame.nim (Ordinal.typein (· < ·) o₂) :=
by rw [nim]; rfl
-#align pgame.nim_def PGame.nim_def
+#align pgame.nim_def SetTheory.PGame.nim_def
-/
-#print PGame.leftMoves_nim /-
-theorem leftMoves_nim (o : Ordinal) : (nim o).LeftMoves = o.out.α := by rw [nim_def]; rfl
-#align pgame.left_moves_nim PGame.leftMoves_nim
+#print SetTheory.PGame.leftMoves_nim /-
+theorem SetTheory.PGame.leftMoves_nim (o : Ordinal) : (SetTheory.PGame.nim o).LeftMoves = o.out.α :=
+ by rw [nim_def]; rfl
+#align pgame.left_moves_nim SetTheory.PGame.leftMoves_nim
-/
-#print PGame.rightMoves_nim /-
-theorem rightMoves_nim (o : Ordinal) : (nim o).RightMoves = o.out.α := by rw [nim_def]; rfl
-#align pgame.right_moves_nim PGame.rightMoves_nim
+#print SetTheory.PGame.rightMoves_nim /-
+theorem SetTheory.PGame.rightMoves_nim (o : Ordinal) :
+ (SetTheory.PGame.nim o).RightMoves = o.out.α := by rw [nim_def]; rfl
+#align pgame.right_moves_nim SetTheory.PGame.rightMoves_nim
-/
-#print PGame.moveLeft_nim_hEq /-
-theorem moveLeft_nim_hEq (o : Ordinal) :
- HEq (nim o).moveLeft fun i : o.out.α => nim (typein (· < ·) i) := by rw [nim_def]; rfl
-#align pgame.move_left_nim_heq PGame.moveLeft_nim_hEq
+#print SetTheory.PGame.moveLeft_nim_hEq /-
+theorem SetTheory.PGame.moveLeft_nim_hEq (o : Ordinal) :
+ HEq (SetTheory.PGame.nim o).moveLeft fun i : o.out.α =>
+ SetTheory.PGame.nim (typein (· < ·) i) :=
+ by rw [nim_def]; rfl
+#align pgame.move_left_nim_heq SetTheory.PGame.moveLeft_nim_hEq
-/
-#print PGame.moveRight_nim_hEq /-
-theorem moveRight_nim_hEq (o : Ordinal) :
- HEq (nim o).moveRight fun i : o.out.α => nim (typein (· < ·) i) := by rw [nim_def]; rfl
-#align pgame.move_right_nim_heq PGame.moveRight_nim_hEq
+#print SetTheory.PGame.moveRight_nim_hEq /-
+theorem SetTheory.PGame.moveRight_nim_hEq (o : Ordinal) :
+ HEq (SetTheory.PGame.nim o).moveRight fun i : o.out.α =>
+ SetTheory.PGame.nim (typein (· < ·) i) :=
+ by rw [nim_def]; rfl
+#align pgame.move_right_nim_heq SetTheory.PGame.moveRight_nim_hEq
-/
-#print PGame.toLeftMovesNim /-
+#print SetTheory.PGame.toLeftMovesNim /-
/-- Turns an ordinal less than `o` into a left move for `nim o` and viceversa. -/
-noncomputable def toLeftMovesNim {o : Ordinal} : Set.Iio o ≃ (nim o).LeftMoves :=
- (enumIsoOut o).toEquiv.trans (Equiv.cast (leftMoves_nim o).symm)
-#align pgame.to_left_moves_nim PGame.toLeftMovesNim
+noncomputable def SetTheory.PGame.toLeftMovesNim {o : Ordinal} :
+ Set.Iio o ≃ (SetTheory.PGame.nim o).LeftMoves :=
+ (enumIsoOut o).toEquiv.trans (Equiv.cast (SetTheory.PGame.leftMoves_nim o).symm)
+#align pgame.to_left_moves_nim SetTheory.PGame.toLeftMovesNim
-/
-#print PGame.toRightMovesNim /-
+#print SetTheory.PGame.toRightMovesNim /-
/-- Turns an ordinal less than `o` into a right move for `nim o` and viceversa. -/
-noncomputable def toRightMovesNim {o : Ordinal} : Set.Iio o ≃ (nim o).RightMoves :=
- (enumIsoOut o).toEquiv.trans (Equiv.cast (rightMoves_nim o).symm)
-#align pgame.to_right_moves_nim PGame.toRightMovesNim
+noncomputable def SetTheory.PGame.toRightMovesNim {o : Ordinal} :
+ Set.Iio o ≃ (SetTheory.PGame.nim o).RightMoves :=
+ (enumIsoOut o).toEquiv.trans (Equiv.cast (SetTheory.PGame.rightMoves_nim o).symm)
+#align pgame.to_right_moves_nim SetTheory.PGame.toRightMovesNim
-/
-#print PGame.toLeftMovesNim_symm_lt /-
+#print SetTheory.PGame.toLeftMovesNim_symm_lt /-
@[simp]
-theorem toLeftMovesNim_symm_lt {o : Ordinal} (i : (nim o).LeftMoves) :
- ↑(toLeftMovesNim.symm i) < o :=
- (toLeftMovesNim.symm i).Prop
-#align pgame.to_left_moves_nim_symm_lt PGame.toLeftMovesNim_symm_lt
+theorem SetTheory.PGame.toLeftMovesNim_symm_lt {o : Ordinal}
+ (i : (SetTheory.PGame.nim o).LeftMoves) : ↑(SetTheory.PGame.toLeftMovesNim.symm i) < o :=
+ (SetTheory.PGame.toLeftMovesNim.symm i).Prop
+#align pgame.to_left_moves_nim_symm_lt SetTheory.PGame.toLeftMovesNim_symm_lt
-/
-#print PGame.toRightMovesNim_symm_lt /-
+#print SetTheory.PGame.toRightMovesNim_symm_lt /-
@[simp]
-theorem toRightMovesNim_symm_lt {o : Ordinal} (i : (nim o).RightMoves) :
- ↑(toRightMovesNim.symm i) < o :=
- (toRightMovesNim.symm i).Prop
-#align pgame.to_right_moves_nim_symm_lt PGame.toRightMovesNim_symm_lt
+theorem SetTheory.PGame.toRightMovesNim_symm_lt {o : Ordinal}
+ (i : (SetTheory.PGame.nim o).RightMoves) : ↑(SetTheory.PGame.toRightMovesNim.symm i) < o :=
+ (SetTheory.PGame.toRightMovesNim.symm i).Prop
+#align pgame.to_right_moves_nim_symm_lt SetTheory.PGame.toRightMovesNim_symm_lt
-/
-#print PGame.moveLeft_nim' /-
+#print SetTheory.PGame.moveLeft_nim' /-
@[simp]
-theorem moveLeft_nim' {o : Ordinal.{u}} (i) :
- (nim o).moveLeft i = nim (toLeftMovesNim.symm i).val :=
- (congr_heq (moveLeft_nim_hEq o).symm (cast_hEq _ i)).symm
-#align pgame.move_left_nim' PGame.moveLeft_nim'
+theorem SetTheory.PGame.moveLeft_nim' {o : Ordinal.{u}} (i) :
+ (SetTheory.PGame.nim o).moveLeft i =
+ SetTheory.PGame.nim (SetTheory.PGame.toLeftMovesNim.symm i).val :=
+ (congr_heq (SetTheory.PGame.moveLeft_nim_hEq o).symm (cast_hEq _ i)).symm
+#align pgame.move_left_nim' SetTheory.PGame.moveLeft_nim'
-/
-#print PGame.moveLeft_nim /-
-theorem moveLeft_nim {o : Ordinal} (i) : (nim o).moveLeft (toLeftMovesNim i) = nim i := by simp
-#align pgame.move_left_nim PGame.moveLeft_nim
+#print SetTheory.PGame.moveLeft_nim /-
+theorem SetTheory.PGame.moveLeft_nim {o : Ordinal} (i) :
+ (SetTheory.PGame.nim o).moveLeft (SetTheory.PGame.toLeftMovesNim i) = SetTheory.PGame.nim i :=
+ by simp
+#align pgame.move_left_nim SetTheory.PGame.moveLeft_nim
-/
-#print PGame.moveRight_nim' /-
+#print SetTheory.PGame.moveRight_nim' /-
@[simp]
-theorem moveRight_nim' {o : Ordinal} (i) : (nim o).moveRight i = nim (toRightMovesNim.symm i).val :=
- (congr_heq (moveRight_nim_hEq o).symm (cast_hEq _ i)).symm
-#align pgame.move_right_nim' PGame.moveRight_nim'
+theorem SetTheory.PGame.moveRight_nim' {o : Ordinal} (i) :
+ (SetTheory.PGame.nim o).moveRight i =
+ SetTheory.PGame.nim (SetTheory.PGame.toRightMovesNim.symm i).val :=
+ (congr_heq (SetTheory.PGame.moveRight_nim_hEq o).symm (cast_hEq _ i)).symm
+#align pgame.move_right_nim' SetTheory.PGame.moveRight_nim'
-/
-#print PGame.moveRight_nim /-
-theorem moveRight_nim {o : Ordinal} (i) : (nim o).moveRight (toRightMovesNim i) = nim i := by simp
-#align pgame.move_right_nim PGame.moveRight_nim
+#print SetTheory.PGame.moveRight_nim /-
+theorem SetTheory.PGame.moveRight_nim {o : Ordinal} (i) :
+ (SetTheory.PGame.nim o).moveRight (SetTheory.PGame.toRightMovesNim i) = SetTheory.PGame.nim i :=
+ by simp
+#align pgame.move_right_nim SetTheory.PGame.moveRight_nim
-/
-#print PGame.leftMovesNimRecOn /-
+#print SetTheory.PGame.leftMovesNimRecOn /-
/-- A recursion principle for left moves of a nim game. -/
@[elab_as_elim]
-def leftMovesNimRecOn {o : Ordinal} {P : (nim o).LeftMoves → Sort _} (i : (nim o).LeftMoves)
- (H : ∀ a < o, P <| toLeftMovesNim ⟨a, H⟩) : P i := by
+def SetTheory.PGame.leftMovesNimRecOn {o : Ordinal} {P : (SetTheory.PGame.nim o).LeftMoves → Sort _}
+ (i : (SetTheory.PGame.nim o).LeftMoves)
+ (H : ∀ a < o, P <| SetTheory.PGame.toLeftMovesNim ⟨a, H⟩) : P i := by
rw [← to_left_moves_nim.apply_symm_apply i]; apply H
-#align pgame.left_moves_nim_rec_on PGame.leftMovesNimRecOn
+#align pgame.left_moves_nim_rec_on SetTheory.PGame.leftMovesNimRecOn
-/
-#print PGame.rightMovesNimRecOn /-
+#print SetTheory.PGame.rightMovesNimRecOn /-
/-- A recursion principle for right moves of a nim game. -/
@[elab_as_elim]
-def rightMovesNimRecOn {o : Ordinal} {P : (nim o).RightMoves → Sort _} (i : (nim o).RightMoves)
- (H : ∀ a < o, P <| toRightMovesNim ⟨a, H⟩) : P i := by
+def SetTheory.PGame.rightMovesNimRecOn {o : Ordinal}
+ {P : (SetTheory.PGame.nim o).RightMoves → Sort _} (i : (SetTheory.PGame.nim o).RightMoves)
+ (H : ∀ a < o, P <| SetTheory.PGame.toRightMovesNim ⟨a, H⟩) : P i := by
rw [← to_right_moves_nim.apply_symm_apply i]; apply H
-#align pgame.right_moves_nim_rec_on PGame.rightMovesNimRecOn
+#align pgame.right_moves_nim_rec_on SetTheory.PGame.rightMovesNimRecOn
-/
-#print PGame.isEmpty_nim_zero_leftMoves /-
-instance isEmpty_nim_zero_leftMoves : IsEmpty (nim 0).LeftMoves := by rw [nim_def];
- exact Ordinal.isEmpty_out_zero
-#align pgame.is_empty_nim_zero_left_moves PGame.isEmpty_nim_zero_leftMoves
+#print SetTheory.PGame.isEmpty_nim_zero_leftMoves /-
+instance SetTheory.PGame.isEmpty_nim_zero_leftMoves : IsEmpty (SetTheory.PGame.nim 0).LeftMoves :=
+ by rw [nim_def]; exact Ordinal.isEmpty_out_zero
+#align pgame.is_empty_nim_zero_left_moves SetTheory.PGame.isEmpty_nim_zero_leftMoves
-/
-#print PGame.isEmpty_nim_zero_rightMoves /-
-instance isEmpty_nim_zero_rightMoves : IsEmpty (nim 0).RightMoves := by rw [nim_def];
- exact Ordinal.isEmpty_out_zero
-#align pgame.is_empty_nim_zero_right_moves PGame.isEmpty_nim_zero_rightMoves
+#print SetTheory.PGame.isEmpty_nim_zero_rightMoves /-
+instance SetTheory.PGame.isEmpty_nim_zero_rightMoves : IsEmpty (SetTheory.PGame.nim 0).RightMoves :=
+ by rw [nim_def]; exact Ordinal.isEmpty_out_zero
+#align pgame.is_empty_nim_zero_right_moves SetTheory.PGame.isEmpty_nim_zero_rightMoves
-/
-#print PGame.nimZeroRelabelling /-
+#print SetTheory.PGame.nimZeroRelabelling /-
/-- `nim 0` has exactly the same moves as `0`. -/
-def nimZeroRelabelling : nim 0 ≡r 0 :=
- Relabelling.isEmpty _
-#align pgame.nim_zero_relabelling PGame.nimZeroRelabelling
+def SetTheory.PGame.nimZeroRelabelling : SetTheory.PGame.nim 0 ≡r 0 :=
+ SetTheory.PGame.Relabelling.isEmpty _
+#align pgame.nim_zero_relabelling SetTheory.PGame.nimZeroRelabelling
-/
-#print PGame.nim_zero_equiv /-
-theorem nim_zero_equiv : nim 0 ≈ 0 :=
- Equiv.isEmpty _
-#align pgame.nim_zero_equiv PGame.nim_zero_equiv
+#print SetTheory.PGame.nim_zero_equiv /-
+theorem SetTheory.PGame.nim_zero_equiv : SetTheory.PGame.nim 0 ≈ 0 :=
+ SetTheory.PGame.Equiv.isEmpty _
+#align pgame.nim_zero_equiv SetTheory.PGame.nim_zero_equiv
-/
-#print PGame.uniqueNimOneLeftMoves /-
-noncomputable instance uniqueNimOneLeftMoves : Unique (nim 1).LeftMoves :=
- (Equiv.cast <| leftMoves_nim 1).unique
-#align pgame.unique_nim_one_left_moves PGame.uniqueNimOneLeftMoves
+#print SetTheory.PGame.uniqueNimOneLeftMoves /-
+noncomputable instance SetTheory.PGame.uniqueNimOneLeftMoves :
+ Unique (SetTheory.PGame.nim 1).LeftMoves :=
+ (Equiv.cast <| SetTheory.PGame.leftMoves_nim 1).unique
+#align pgame.unique_nim_one_left_moves SetTheory.PGame.uniqueNimOneLeftMoves
-/
-#print PGame.uniqueNimOneRightMoves /-
-noncomputable instance uniqueNimOneRightMoves : Unique (nim 1).RightMoves :=
- (Equiv.cast <| rightMoves_nim 1).unique
-#align pgame.unique_nim_one_right_moves PGame.uniqueNimOneRightMoves
+#print SetTheory.PGame.uniqueNimOneRightMoves /-
+noncomputable instance SetTheory.PGame.uniqueNimOneRightMoves :
+ Unique (SetTheory.PGame.nim 1).RightMoves :=
+ (Equiv.cast <| SetTheory.PGame.rightMoves_nim 1).unique
+#align pgame.unique_nim_one_right_moves SetTheory.PGame.uniqueNimOneRightMoves
-/
-#print PGame.default_nim_one_leftMoves_eq /-
+#print SetTheory.PGame.default_nim_one_leftMoves_eq /-
@[simp]
-theorem default_nim_one_leftMoves_eq :
- (default : (nim 1).LeftMoves) = @toLeftMovesNim 1 ⟨0, zero_lt_one⟩ :=
+theorem SetTheory.PGame.default_nim_one_leftMoves_eq :
+ (default : (SetTheory.PGame.nim 1).LeftMoves) =
+ @SetTheory.PGame.toLeftMovesNim 1 ⟨0, zero_lt_one⟩ :=
rfl
-#align pgame.default_nim_one_left_moves_eq PGame.default_nim_one_leftMoves_eq
+#align pgame.default_nim_one_left_moves_eq SetTheory.PGame.default_nim_one_leftMoves_eq
-/
-#print PGame.default_nim_one_rightMoves_eq /-
+#print SetTheory.PGame.default_nim_one_rightMoves_eq /-
@[simp]
-theorem default_nim_one_rightMoves_eq :
- (default : (nim 1).RightMoves) = @toRightMovesNim 1 ⟨0, zero_lt_one⟩ :=
+theorem SetTheory.PGame.default_nim_one_rightMoves_eq :
+ (default : (SetTheory.PGame.nim 1).RightMoves) =
+ @SetTheory.PGame.toRightMovesNim 1 ⟨0, zero_lt_one⟩ :=
rfl
-#align pgame.default_nim_one_right_moves_eq PGame.default_nim_one_rightMoves_eq
+#align pgame.default_nim_one_right_moves_eq SetTheory.PGame.default_nim_one_rightMoves_eq
-/
-#print PGame.toLeftMovesNim_one_symm /-
+#print SetTheory.PGame.toLeftMovesNim_one_symm /-
@[simp]
-theorem toLeftMovesNim_one_symm (i) : (@toLeftMovesNim 1).symm i = ⟨0, zero_lt_one⟩ := by simp
-#align pgame.to_left_moves_nim_one_symm PGame.toLeftMovesNim_one_symm
+theorem SetTheory.PGame.toLeftMovesNim_one_symm (i) :
+ (@SetTheory.PGame.toLeftMovesNim 1).symm i = ⟨0, zero_lt_one⟩ := by simp
+#align pgame.to_left_moves_nim_one_symm SetTheory.PGame.toLeftMovesNim_one_symm
-/
-#print PGame.toRightMovesNim_one_symm /-
+#print SetTheory.PGame.toRightMovesNim_one_symm /-
@[simp]
-theorem toRightMovesNim_one_symm (i) : (@toRightMovesNim 1).symm i = ⟨0, zero_lt_one⟩ := by simp
-#align pgame.to_right_moves_nim_one_symm PGame.toRightMovesNim_one_symm
+theorem SetTheory.PGame.toRightMovesNim_one_symm (i) :
+ (@SetTheory.PGame.toRightMovesNim 1).symm i = ⟨0, zero_lt_one⟩ := by simp
+#align pgame.to_right_moves_nim_one_symm SetTheory.PGame.toRightMovesNim_one_symm
-/
-#print PGame.nim_one_moveLeft /-
-theorem nim_one_moveLeft (x) : (nim 1).moveLeft x = nim 0 := by simp
-#align pgame.nim_one_move_left PGame.nim_one_moveLeft
+#print SetTheory.PGame.nim_one_moveLeft /-
+theorem SetTheory.PGame.nim_one_moveLeft (x) :
+ (SetTheory.PGame.nim 1).moveLeft x = SetTheory.PGame.nim 0 := by simp
+#align pgame.nim_one_move_left SetTheory.PGame.nim_one_moveLeft
-/
-#print PGame.nim_one_moveRight /-
-theorem nim_one_moveRight (x) : (nim 1).moveRight x = nim 0 := by simp
-#align pgame.nim_one_move_right PGame.nim_one_moveRight
+#print SetTheory.PGame.nim_one_moveRight /-
+theorem SetTheory.PGame.nim_one_moveRight (x) :
+ (SetTheory.PGame.nim 1).moveRight x = SetTheory.PGame.nim 0 := by simp
+#align pgame.nim_one_move_right SetTheory.PGame.nim_one_moveRight
-/
-#print PGame.nimOneRelabelling /-
+#print SetTheory.PGame.nimOneRelabelling /-
/-- `nim 1` has exactly the same moves as `star`. -/
-def nimOneRelabelling : nim 1 ≡r star := by
+def SetTheory.PGame.nimOneRelabelling : SetTheory.PGame.nim 1 ≡r SetTheory.PGame.star :=
+ by
rw [nim_def]
refine' ⟨_, _, fun i => _, fun j => _⟩
any_goals dsimp; apply Equiv.equivOfUnique
all_goals simp; exact nim_zero_relabelling
-#align pgame.nim_one_relabelling PGame.nimOneRelabelling
+#align pgame.nim_one_relabelling SetTheory.PGame.nimOneRelabelling
-/
-#print PGame.nim_one_equiv /-
-theorem nim_one_equiv : nim 1 ≈ star :=
- nimOneRelabelling.Equiv
-#align pgame.nim_one_equiv PGame.nim_one_equiv
+#print SetTheory.PGame.nim_one_equiv /-
+theorem SetTheory.PGame.nim_one_equiv : SetTheory.PGame.nim 1 ≈ SetTheory.PGame.star :=
+ SetTheory.PGame.nimOneRelabelling.Equiv
+#align pgame.nim_one_equiv SetTheory.PGame.nim_one_equiv
-/
-#print PGame.nim_birthday /-
+#print SetTheory.PGame.nim_birthday /-
@[simp]
-theorem nim_birthday (o : Ordinal) : (nim o).birthday = o :=
+theorem SetTheory.PGame.nim_birthday (o : Ordinal) : (SetTheory.PGame.nim o).birthday = o :=
by
induction' o using Ordinal.induction with o IH
rw [nim_def, birthday_def]
@@ -262,39 +288,42 @@ theorem nim_birthday (o : Ordinal) : (nim o).birthday = o :=
rw [max_eq_right le_rfl]
convert lsub_typein o
exact funext fun i => IH _ (typein_lt_self i)
-#align pgame.nim_birthday PGame.nim_birthday
+#align pgame.nim_birthday SetTheory.PGame.nim_birthday
-/
-#print PGame.neg_nim /-
+#print SetTheory.PGame.neg_nim /-
@[simp]
-theorem neg_nim (o : Ordinal) : -nim o = nim o :=
+theorem SetTheory.PGame.neg_nim (o : Ordinal) : -SetTheory.PGame.nim o = SetTheory.PGame.nim o :=
by
induction' o using Ordinal.induction with o IH
rw [nim_def]; dsimp <;> congr <;> funext i <;> exact IH _ (Ordinal.typein_lt_self i)
-#align pgame.neg_nim PGame.neg_nim
+#align pgame.neg_nim SetTheory.PGame.neg_nim
-/
-#print PGame.nim_impartial /-
-instance nim_impartial (o : Ordinal) : Impartial (nim o) :=
+#print SetTheory.PGame.nim_impartial /-
+instance SetTheory.PGame.nim_impartial (o : Ordinal) :
+ SetTheory.PGame.Impartial (SetTheory.PGame.nim o) :=
by
induction' o using Ordinal.induction with o IH
rw [impartial_def, neg_nim]
refine' ⟨equiv_rfl, fun i => _, fun i => _⟩ <;> simpa using IH _ (typein_lt_self _)
-#align pgame.nim_impartial PGame.nim_impartial
+#align pgame.nim_impartial SetTheory.PGame.nim_impartial
-/
-#print PGame.nim_fuzzy_zero_of_ne_zero /-
-theorem nim_fuzzy_zero_of_ne_zero {o : Ordinal} (ho : o ≠ 0) : nim o ‖ 0 :=
+#print SetTheory.PGame.nim_fuzzy_zero_of_ne_zero /-
+theorem SetTheory.PGame.nim_fuzzy_zero_of_ne_zero {o : Ordinal} (ho : o ≠ 0) :
+ SetTheory.PGame.nim o ‖ 0 :=
by
rw [impartial.fuzzy_zero_iff_lf, nim_def, lf_zero_le]
rw [← Ordinal.pos_iff_ne_zero] at ho
exact ⟨(Ordinal.principalSegOut ho).top, by simp⟩
-#align pgame.nim_fuzzy_zero_of_ne_zero PGame.nim_fuzzy_zero_of_ne_zero
+#align pgame.nim_fuzzy_zero_of_ne_zero SetTheory.PGame.nim_fuzzy_zero_of_ne_zero
-/
-#print PGame.nim_add_equiv_zero_iff /-
+#print SetTheory.PGame.nim_add_equiv_zero_iff /-
@[simp]
-theorem nim_add_equiv_zero_iff (o₁ o₂ : Ordinal) : (nim o₁ + nim o₂ ≈ 0) ↔ o₁ = o₂ :=
+theorem SetTheory.PGame.nim_add_equiv_zero_iff (o₁ o₂ : Ordinal) :
+ (SetTheory.PGame.nim o₁ + SetTheory.PGame.nim o₂ ≈ 0) ↔ o₁ = o₂ :=
by
constructor
· refine' not_imp_not.1 fun hne : _ ≠ _ => (impartial.not_equiv_zero_iff _).2 _
@@ -306,42 +335,48 @@ theorem nim_add_equiv_zero_iff (o₁ o₂ : Ordinal) : (nim o₁ + nim o₂ ≈
· simpa using (impartial.add_self (nim o₁)).2
· rintro rfl
exact impartial.add_self (nim o₁)
-#align pgame.nim_add_equiv_zero_iff PGame.nim_add_equiv_zero_iff
+#align pgame.nim_add_equiv_zero_iff SetTheory.PGame.nim_add_equiv_zero_iff
-/
-#print PGame.nim_add_fuzzy_zero_iff /-
+#print SetTheory.PGame.nim_add_fuzzy_zero_iff /-
@[simp]
-theorem nim_add_fuzzy_zero_iff {o₁ o₂ : Ordinal} : nim o₁ + nim o₂ ‖ 0 ↔ o₁ ≠ o₂ := by
+theorem SetTheory.PGame.nim_add_fuzzy_zero_iff {o₁ o₂ : Ordinal} :
+ SetTheory.PGame.nim o₁ + SetTheory.PGame.nim o₂ ‖ 0 ↔ o₁ ≠ o₂ := by
rw [iff_not_comm, impartial.not_fuzzy_zero_iff, nim_add_equiv_zero_iff]
-#align pgame.nim_add_fuzzy_zero_iff PGame.nim_add_fuzzy_zero_iff
+#align pgame.nim_add_fuzzy_zero_iff SetTheory.PGame.nim_add_fuzzy_zero_iff
-/
-#print PGame.nim_equiv_iff_eq /-
+#print SetTheory.PGame.nim_equiv_iff_eq /-
@[simp]
-theorem nim_equiv_iff_eq {o₁ o₂ : Ordinal} : (nim o₁ ≈ nim o₂) ↔ o₁ = o₂ := by
+theorem SetTheory.PGame.nim_equiv_iff_eq {o₁ o₂ : Ordinal} :
+ (SetTheory.PGame.nim o₁ ≈ SetTheory.PGame.nim o₂) ↔ o₁ = o₂ := by
rw [impartial.equiv_iff_add_equiv_zero, nim_add_equiv_zero_iff]
-#align pgame.nim_equiv_iff_eq PGame.nim_equiv_iff_eq
+#align pgame.nim_equiv_iff_eq SetTheory.PGame.nim_equiv_iff_eq
-/
-#print PGame.grundyValue /-
+#print SetTheory.PGame.grundyValue /-
/-- The Grundy value of an impartial game, the ordinal which corresponds to the game of nim that the
game is equivalent to -/
-noncomputable def grundyValue : ∀ G : PGame.{u}, Ordinal.{u}
+noncomputable def SetTheory.PGame.grundyValue : ∀ G : SetTheory.PGame.{u}, Ordinal.{u}
| G => Ordinal.mex.{u, u} fun i => grundy_value (G.moveLeft i)
decreasing_by pgame_wf_tac
-#align pgame.grundy_value PGame.grundyValue
+#align pgame.grundy_value SetTheory.PGame.grundyValue
-/
-#print PGame.grundyValue_eq_mex_left /-
-theorem grundyValue_eq_mex_left (G : PGame) :
- grundyValue G = Ordinal.mex.{u, u} fun i => grundyValue (G.moveLeft i) := by rw [grundy_value]
-#align pgame.grundy_value_eq_mex_left PGame.grundyValue_eq_mex_left
+#print SetTheory.PGame.grundyValue_eq_mex_left /-
+theorem SetTheory.PGame.grundyValue_eq_mex_left (G : SetTheory.PGame) :
+ SetTheory.PGame.grundyValue G =
+ Ordinal.mex.{u, u} fun i => SetTheory.PGame.grundyValue (G.moveLeft i) :=
+ by rw [grundy_value]
+#align pgame.grundy_value_eq_mex_left SetTheory.PGame.grundyValue_eq_mex_left
-/
-#print PGame.equiv_nim_grundyValue /-
+#print SetTheory.PGame.equiv_nim_grundyValue /-
/-- The Sprague-Grundy theorem which states that every impartial game is equivalent to a game of
nim, namely the game of nim corresponding to the games Grundy value -/
-theorem equiv_nim_grundyValue : ∀ (G : PGame.{u}) [G.Impartial], G ≈ nim (grundyValue G)
+theorem SetTheory.PGame.equiv_nim_grundyValue :
+ ∀ (G : SetTheory.PGame.{u}) [G.Impartial],
+ G ≈ SetTheory.PGame.nim (SetTheory.PGame.grundyValue G)
| G => by
intro hG
rw [impartial.equiv_iff_add_equiv_zero, ← impartial.forall_left_moves_fuzzy_iff_equiv_zero]
@@ -377,62 +412,67 @@ theorem equiv_nim_grundyValue : ∀ (G : PGame.{u}) [G.Impartial], G ≈ nim (gr
apply (add_congr_left (equiv_nim_grundy_value (G.move_left i))).trans
simpa only [hi] using impartial.add_self (nim (grundy_value (G.move_left i)))
decreasing_by pgame_wf_tac
-#align pgame.equiv_nim_grundy_value PGame.equiv_nim_grundyValue
+#align pgame.equiv_nim_grundy_value SetTheory.PGame.equiv_nim_grundyValue
-/
-#print PGame.grundyValue_eq_iff_equiv_nim /-
-theorem grundyValue_eq_iff_equiv_nim {G : PGame} [G.Impartial] {o : Ordinal} :
- grundyValue G = o ↔ (G ≈ nim o) :=
+#print SetTheory.PGame.grundyValue_eq_iff_equiv_nim /-
+theorem SetTheory.PGame.grundyValue_eq_iff_equiv_nim {G : SetTheory.PGame} [G.Impartial]
+ {o : Ordinal} : SetTheory.PGame.grundyValue G = o ↔ (G ≈ SetTheory.PGame.nim o) :=
⟨by rintro rfl; exact equiv_nim_grundy_value G, by intro h; rw [← nim_equiv_iff_eq];
exact (equiv_nim_grundy_value G).symm.trans h⟩
-#align pgame.grundy_value_eq_iff_equiv_nim PGame.grundyValue_eq_iff_equiv_nim
+#align pgame.grundy_value_eq_iff_equiv_nim SetTheory.PGame.grundyValue_eq_iff_equiv_nim
-/
-#print PGame.nim_grundyValue /-
+#print SetTheory.PGame.nim_grundyValue /-
@[simp]
-theorem nim_grundyValue (o : Ordinal.{u}) : grundyValue (nim o) = o :=
- grundyValue_eq_iff_equiv_nim.2 PGame.equiv_rfl
-#align pgame.nim_grundy_value PGame.nim_grundyValue
+theorem SetTheory.PGame.nim_grundyValue (o : Ordinal.{u}) :
+ SetTheory.PGame.grundyValue (SetTheory.PGame.nim o) = o :=
+ SetTheory.PGame.grundyValue_eq_iff_equiv_nim.2 SetTheory.PGame.equiv_rfl
+#align pgame.nim_grundy_value SetTheory.PGame.nim_grundyValue
-/
-#print PGame.grundyValue_eq_iff_equiv /-
-theorem grundyValue_eq_iff_equiv (G H : PGame) [G.Impartial] [H.Impartial] :
- grundyValue G = grundyValue H ↔ (G ≈ H) :=
- grundyValue_eq_iff_equiv_nim.trans (equiv_congr_left.1 (equiv_nim_grundyValue H) _).symm
-#align pgame.grundy_value_eq_iff_equiv PGame.grundyValue_eq_iff_equiv
+#print SetTheory.PGame.grundyValue_eq_iff_equiv /-
+theorem SetTheory.PGame.grundyValue_eq_iff_equiv (G H : SetTheory.PGame) [G.Impartial]
+ [H.Impartial] : SetTheory.PGame.grundyValue G = SetTheory.PGame.grundyValue H ↔ (G ≈ H) :=
+ SetTheory.PGame.grundyValue_eq_iff_equiv_nim.trans
+ (SetTheory.PGame.equiv_congr_left.1 (SetTheory.PGame.equiv_nim_grundyValue H) _).symm
+#align pgame.grundy_value_eq_iff_equiv SetTheory.PGame.grundyValue_eq_iff_equiv
-/
-#print PGame.grundyValue_zero /-
+#print SetTheory.PGame.grundyValue_zero /-
@[simp]
-theorem grundyValue_zero : grundyValue 0 = 0 :=
- grundyValue_eq_iff_equiv_nim.2 nim_zero_equiv.symm
-#align pgame.grundy_value_zero PGame.grundyValue_zero
+theorem SetTheory.PGame.grundyValue_zero : SetTheory.PGame.grundyValue 0 = 0 :=
+ SetTheory.PGame.grundyValue_eq_iff_equiv_nim.2 SetTheory.PGame.nim_zero_equiv.symm
+#align pgame.grundy_value_zero SetTheory.PGame.grundyValue_zero
-/
-#print PGame.grundyValue_iff_equiv_zero /-
-theorem grundyValue_iff_equiv_zero (G : PGame) [G.Impartial] : grundyValue G = 0 ↔ (G ≈ 0) := by
+#print SetTheory.PGame.grundyValue_iff_equiv_zero /-
+theorem SetTheory.PGame.grundyValue_iff_equiv_zero (G : SetTheory.PGame) [G.Impartial] :
+ SetTheory.PGame.grundyValue G = 0 ↔ (G ≈ 0) := by
rw [← grundy_value_eq_iff_equiv, grundy_value_zero]
-#align pgame.grundy_value_iff_equiv_zero PGame.grundyValue_iff_equiv_zero
+#align pgame.grundy_value_iff_equiv_zero SetTheory.PGame.grundyValue_iff_equiv_zero
-/
-#print PGame.grundyValue_star /-
+#print SetTheory.PGame.grundyValue_star /-
@[simp]
-theorem grundyValue_star : grundyValue star = 1 :=
- grundyValue_eq_iff_equiv_nim.2 nim_one_equiv.symm
-#align pgame.grundy_value_star PGame.grundyValue_star
+theorem SetTheory.PGame.grundyValue_star : SetTheory.PGame.grundyValue SetTheory.PGame.star = 1 :=
+ SetTheory.PGame.grundyValue_eq_iff_equiv_nim.2 SetTheory.PGame.nim_one_equiv.symm
+#align pgame.grundy_value_star SetTheory.PGame.grundyValue_star
-/
-#print PGame.grundyValue_neg /-
+#print SetTheory.PGame.grundyValue_neg /-
@[simp]
-theorem grundyValue_neg (G : PGame) [G.Impartial] : grundyValue (-G) = grundyValue G := by
+theorem SetTheory.PGame.grundyValue_neg (G : SetTheory.PGame) [G.Impartial] :
+ SetTheory.PGame.grundyValue (-G) = SetTheory.PGame.grundyValue G := by
rw [grundy_value_eq_iff_equiv_nim, neg_equiv_iff, neg_nim, ← grundy_value_eq_iff_equiv_nim]
-#align pgame.grundy_value_neg PGame.grundyValue_neg
+#align pgame.grundy_value_neg SetTheory.PGame.grundyValue_neg
-/
-#print PGame.grundyValue_eq_mex_right /-
-theorem grundyValue_eq_mex_right :
- ∀ (G : PGame) [G.Impartial],
- grundyValue G = Ordinal.mex.{u, u} fun i => grundyValue (G.moveRight i)
+#print SetTheory.PGame.grundyValue_eq_mex_right /-
+theorem SetTheory.PGame.grundyValue_eq_mex_right :
+ ∀ (G : SetTheory.PGame) [G.Impartial],
+ SetTheory.PGame.grundyValue G =
+ Ordinal.mex.{u, u} fun i => SetTheory.PGame.grundyValue (G.moveRight i)
| ⟨l, r, L, R⟩ => by
intro H
rw [← grundy_value_neg, grundy_value_eq_mex_left]
@@ -440,16 +480,18 @@ theorem grundyValue_eq_mex_right :
ext i
haveI : (R i).Impartial := @impartial.move_right_impartial ⟨l, r, L, R⟩ _ i
apply grundy_value_neg
-#align pgame.grundy_value_eq_mex_right PGame.grundyValue_eq_mex_right
+#align pgame.grundy_value_eq_mex_right SetTheory.PGame.grundyValue_eq_mex_right
-/
-#print PGame.grundyValue_nim_add_nim /-
+#print SetTheory.PGame.grundyValue_nim_add_nim /-
-- Todo: this actually generalizes to all ordinals, by defining `ordinal.lxor` as the pairwise
-- `nat.lxor` of base `ω` Cantor normal forms.
/-- The Grundy value of the sum of two nim games with natural numbers of piles equals their bitwise
xor. -/
@[simp]
-theorem grundyValue_nim_add_nim (n m : ℕ) : grundyValue (nim.{u} n + nim.{u} m) = Nat.lxor' n m :=
+theorem SetTheory.PGame.grundyValue_nim_add_nim (n m : ℕ) :
+ SetTheory.PGame.grundyValue (SetTheory.PGame.nim.{u} n + SetTheory.PGame.nim.{u} m) =
+ Nat.lxor' n m :=
by
-- We do strong induction on both variables.
induction' n using Nat.strong_induction_on with n hn generalizing m
@@ -486,24 +528,26 @@ theorem grundyValue_nim_add_nim (n m : ℕ) : grundyValue (nim.{u} n + nim.{u} m
· refine' ⟨to_left_moves_add (Sum.inr <| to_left_moves_nim ⟨_, Ordinal.nat_cast_lt.2 h⟩), _⟩
have : n.lxor (u.lxor n) = u; rw [Nat.lxor'_comm u, Nat.lxor'_cancel_left]
simpa [hm _ h] using this
-#align pgame.grundy_value_nim_add_nim PGame.grundyValue_nim_add_nim
+#align pgame.grundy_value_nim_add_nim SetTheory.PGame.grundyValue_nim_add_nim
-/
-#print PGame.nim_add_nim_equiv /-
-theorem nim_add_nim_equiv {n m : ℕ} : nim n + nim m ≈ nim (Nat.lxor' n m) := by
+#print SetTheory.PGame.nim_add_nim_equiv /-
+theorem SetTheory.PGame.nim_add_nim_equiv {n m : ℕ} :
+ SetTheory.PGame.nim n + SetTheory.PGame.nim m ≈ SetTheory.PGame.nim (Nat.lxor' n m) := by
rw [← grundy_value_eq_iff_equiv_nim, grundy_value_nim_add_nim]
-#align pgame.nim_add_nim_equiv PGame.nim_add_nim_equiv
+#align pgame.nim_add_nim_equiv SetTheory.PGame.nim_add_nim_equiv
-/
-#print PGame.grundyValue_add /-
-theorem grundyValue_add (G H : PGame) [G.Impartial] [H.Impartial] {n m : ℕ} (hG : grundyValue G = n)
- (hH : grundyValue H = m) : grundyValue (G + H) = Nat.lxor' n m :=
+#print SetTheory.PGame.grundyValue_add /-
+theorem SetTheory.PGame.grundyValue_add (G H : SetTheory.PGame) [G.Impartial] [H.Impartial]
+ {n m : ℕ} (hG : SetTheory.PGame.grundyValue G = n) (hH : SetTheory.PGame.grundyValue H = m) :
+ SetTheory.PGame.grundyValue (G + H) = Nat.lxor' n m :=
by
rw [← nim_grundy_value (Nat.lxor' n m), grundy_value_eq_iff_equiv]
refine' Equiv.trans _ nim_add_nim_equiv
convert add_congr (equiv_nim_grundy_value G) (equiv_nim_grundy_value H) <;> simp only [hG, hH]
-#align pgame.grundy_value_add PGame.grundyValue_add
+#align pgame.grundy_value_add SetTheory.PGame.grundyValue_add
-/
-end PGame
+end SetTheory.PGame
mathlib commit https://github.com/leanprover-community/mathlib/commit/8ea5598db6caeddde6cb734aa179cc2408dbd345
@@ -2,16 +2,13 @@
Copyright (c) 2020 Fox Thomson. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Fox Thomson, Markus Himmel
-
-! This file was ported from Lean 3 source module set_theory.game.nim
-! leanprover-community/mathlib commit d0b1936853671209a866fa35b9e54949c81116e2
-! Please do not edit these lines, except to modify the commit id
-! if you have ported upstream changes.
-/
import Mathbin.Data.Nat.Bitwise
import Mathbin.SetTheory.Game.Birthday
import Mathbin.SetTheory.Game.Impartial
+#align_import set_theory.game.nim from "leanprover-community/mathlib"@"d0b1936853671209a866fa35b9e54949c81116e2"
+
/-!
# Nim and the Sprague-Grundy theorem
mathlib commit https://github.com/leanprover-community/mathlib/commit/728ef9dbb281241906f25cbeb30f90d83e0bb451
@@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE.
Authors: Fox Thomson, Markus Himmel
! This file was ported from Lean 3 source module set_theory.game.nim
-! leanprover-community/mathlib commit 92ca63f0fb391a9ca5f22d2409a6080e786d99f7
+! leanprover-community/mathlib commit d0b1936853671209a866fa35b9e54949c81116e2
! Please do not edit these lines, except to modify the commit id
! if you have ported upstream changes.
-/
@@ -15,6 +15,9 @@ import Mathbin.SetTheory.Game.Impartial
/-!
# Nim and the Sprague-Grundy theorem
+> THIS FILE IS SYNCHRONIZED WITH MATHLIB4.
+> Any changes to this file require a corresponding PR to mathlib4.
+
This file contains the definition for nim for any ordinal `o`. In the game of `nim o₁` both players
may move to `nim o₂` for any `o₂ < o₁`.
We also define a Grundy value for an impartial game `G` and prove the Sprague-Grundy theorem, that
mathlib commit https://github.com/leanprover-community/mathlib/commit/8b981918a93bc45a8600de608cde7944a80d92b9
@@ -42,6 +42,7 @@ open scoped PGame
namespace PGame
+#print PGame.nim /-
-- Uses `noncomputable!` to avoid `rec_fn_macro only allowed in meta definitions` VM error
/-- The definition of single-heap nim, which can be viewed as a pile of stones where each player can
take a positive number of stones from it on their turn. -/
@@ -52,134 +53,190 @@ noncomputable def nim : Ordinal.{u} → PGame.{u}
nim (Ordinal.typein o₁.out.R o₂)
⟨o₁.out.α, o₁.out.α, f, f⟩
#align pgame.nim PGame.nim
+-/
open Ordinal
+#print PGame.nim_def /-
theorem nim_def (o : Ordinal) :
nim o =
PGame.mk o.out.α o.out.α (fun o₂ => nim (Ordinal.typein (· < ·) o₂)) fun o₂ =>
nim (Ordinal.typein (· < ·) o₂) :=
by rw [nim]; rfl
#align pgame.nim_def PGame.nim_def
+-/
+#print PGame.leftMoves_nim /-
theorem leftMoves_nim (o : Ordinal) : (nim o).LeftMoves = o.out.α := by rw [nim_def]; rfl
#align pgame.left_moves_nim PGame.leftMoves_nim
+-/
+#print PGame.rightMoves_nim /-
theorem rightMoves_nim (o : Ordinal) : (nim o).RightMoves = o.out.α := by rw [nim_def]; rfl
#align pgame.right_moves_nim PGame.rightMoves_nim
+-/
+#print PGame.moveLeft_nim_hEq /-
theorem moveLeft_nim_hEq (o : Ordinal) :
HEq (nim o).moveLeft fun i : o.out.α => nim (typein (· < ·) i) := by rw [nim_def]; rfl
#align pgame.move_left_nim_heq PGame.moveLeft_nim_hEq
+-/
+#print PGame.moveRight_nim_hEq /-
theorem moveRight_nim_hEq (o : Ordinal) :
HEq (nim o).moveRight fun i : o.out.α => nim (typein (· < ·) i) := by rw [nim_def]; rfl
#align pgame.move_right_nim_heq PGame.moveRight_nim_hEq
+-/
+#print PGame.toLeftMovesNim /-
/-- Turns an ordinal less than `o` into a left move for `nim o` and viceversa. -/
noncomputable def toLeftMovesNim {o : Ordinal} : Set.Iio o ≃ (nim o).LeftMoves :=
(enumIsoOut o).toEquiv.trans (Equiv.cast (leftMoves_nim o).symm)
#align pgame.to_left_moves_nim PGame.toLeftMovesNim
+-/
+#print PGame.toRightMovesNim /-
/-- Turns an ordinal less than `o` into a right move for `nim o` and viceversa. -/
noncomputable def toRightMovesNim {o : Ordinal} : Set.Iio o ≃ (nim o).RightMoves :=
(enumIsoOut o).toEquiv.trans (Equiv.cast (rightMoves_nim o).symm)
#align pgame.to_right_moves_nim PGame.toRightMovesNim
+-/
+#print PGame.toLeftMovesNim_symm_lt /-
@[simp]
theorem toLeftMovesNim_symm_lt {o : Ordinal} (i : (nim o).LeftMoves) :
↑(toLeftMovesNim.symm i) < o :=
(toLeftMovesNim.symm i).Prop
#align pgame.to_left_moves_nim_symm_lt PGame.toLeftMovesNim_symm_lt
+-/
+#print PGame.toRightMovesNim_symm_lt /-
@[simp]
theorem toRightMovesNim_symm_lt {o : Ordinal} (i : (nim o).RightMoves) :
↑(toRightMovesNim.symm i) < o :=
(toRightMovesNim.symm i).Prop
#align pgame.to_right_moves_nim_symm_lt PGame.toRightMovesNim_symm_lt
+-/
+#print PGame.moveLeft_nim' /-
@[simp]
theorem moveLeft_nim' {o : Ordinal.{u}} (i) :
(nim o).moveLeft i = nim (toLeftMovesNim.symm i).val :=
(congr_heq (moveLeft_nim_hEq o).symm (cast_hEq _ i)).symm
#align pgame.move_left_nim' PGame.moveLeft_nim'
+-/
+#print PGame.moveLeft_nim /-
theorem moveLeft_nim {o : Ordinal} (i) : (nim o).moveLeft (toLeftMovesNim i) = nim i := by simp
#align pgame.move_left_nim PGame.moveLeft_nim
+-/
+#print PGame.moveRight_nim' /-
@[simp]
theorem moveRight_nim' {o : Ordinal} (i) : (nim o).moveRight i = nim (toRightMovesNim.symm i).val :=
(congr_heq (moveRight_nim_hEq o).symm (cast_hEq _ i)).symm
#align pgame.move_right_nim' PGame.moveRight_nim'
+-/
+#print PGame.moveRight_nim /-
theorem moveRight_nim {o : Ordinal} (i) : (nim o).moveRight (toRightMovesNim i) = nim i := by simp
#align pgame.move_right_nim PGame.moveRight_nim
+-/
+#print PGame.leftMovesNimRecOn /-
/-- A recursion principle for left moves of a nim game. -/
@[elab_as_elim]
def leftMovesNimRecOn {o : Ordinal} {P : (nim o).LeftMoves → Sort _} (i : (nim o).LeftMoves)
(H : ∀ a < o, P <| toLeftMovesNim ⟨a, H⟩) : P i := by
rw [← to_left_moves_nim.apply_symm_apply i]; apply H
#align pgame.left_moves_nim_rec_on PGame.leftMovesNimRecOn
+-/
+#print PGame.rightMovesNimRecOn /-
/-- A recursion principle for right moves of a nim game. -/
@[elab_as_elim]
def rightMovesNimRecOn {o : Ordinal} {P : (nim o).RightMoves → Sort _} (i : (nim o).RightMoves)
(H : ∀ a < o, P <| toRightMovesNim ⟨a, H⟩) : P i := by
rw [← to_right_moves_nim.apply_symm_apply i]; apply H
#align pgame.right_moves_nim_rec_on PGame.rightMovesNimRecOn
+-/
+#print PGame.isEmpty_nim_zero_leftMoves /-
instance isEmpty_nim_zero_leftMoves : IsEmpty (nim 0).LeftMoves := by rw [nim_def];
exact Ordinal.isEmpty_out_zero
#align pgame.is_empty_nim_zero_left_moves PGame.isEmpty_nim_zero_leftMoves
+-/
+#print PGame.isEmpty_nim_zero_rightMoves /-
instance isEmpty_nim_zero_rightMoves : IsEmpty (nim 0).RightMoves := by rw [nim_def];
exact Ordinal.isEmpty_out_zero
#align pgame.is_empty_nim_zero_right_moves PGame.isEmpty_nim_zero_rightMoves
+-/
+#print PGame.nimZeroRelabelling /-
/-- `nim 0` has exactly the same moves as `0`. -/
def nimZeroRelabelling : nim 0 ≡r 0 :=
Relabelling.isEmpty _
#align pgame.nim_zero_relabelling PGame.nimZeroRelabelling
+-/
+#print PGame.nim_zero_equiv /-
theorem nim_zero_equiv : nim 0 ≈ 0 :=
Equiv.isEmpty _
#align pgame.nim_zero_equiv PGame.nim_zero_equiv
+-/
+#print PGame.uniqueNimOneLeftMoves /-
noncomputable instance uniqueNimOneLeftMoves : Unique (nim 1).LeftMoves :=
(Equiv.cast <| leftMoves_nim 1).unique
#align pgame.unique_nim_one_left_moves PGame.uniqueNimOneLeftMoves
+-/
+#print PGame.uniqueNimOneRightMoves /-
noncomputable instance uniqueNimOneRightMoves : Unique (nim 1).RightMoves :=
(Equiv.cast <| rightMoves_nim 1).unique
#align pgame.unique_nim_one_right_moves PGame.uniqueNimOneRightMoves
+-/
+#print PGame.default_nim_one_leftMoves_eq /-
@[simp]
theorem default_nim_one_leftMoves_eq :
(default : (nim 1).LeftMoves) = @toLeftMovesNim 1 ⟨0, zero_lt_one⟩ :=
rfl
#align pgame.default_nim_one_left_moves_eq PGame.default_nim_one_leftMoves_eq
+-/
+#print PGame.default_nim_one_rightMoves_eq /-
@[simp]
theorem default_nim_one_rightMoves_eq :
(default : (nim 1).RightMoves) = @toRightMovesNim 1 ⟨0, zero_lt_one⟩ :=
rfl
#align pgame.default_nim_one_right_moves_eq PGame.default_nim_one_rightMoves_eq
+-/
+#print PGame.toLeftMovesNim_one_symm /-
@[simp]
theorem toLeftMovesNim_one_symm (i) : (@toLeftMovesNim 1).symm i = ⟨0, zero_lt_one⟩ := by simp
#align pgame.to_left_moves_nim_one_symm PGame.toLeftMovesNim_one_symm
+-/
+#print PGame.toRightMovesNim_one_symm /-
@[simp]
theorem toRightMovesNim_one_symm (i) : (@toRightMovesNim 1).symm i = ⟨0, zero_lt_one⟩ := by simp
#align pgame.to_right_moves_nim_one_symm PGame.toRightMovesNim_one_symm
+-/
+#print PGame.nim_one_moveLeft /-
theorem nim_one_moveLeft (x) : (nim 1).moveLeft x = nim 0 := by simp
#align pgame.nim_one_move_left PGame.nim_one_moveLeft
+-/
+#print PGame.nim_one_moveRight /-
theorem nim_one_moveRight (x) : (nim 1).moveRight x = nim 0 := by simp
#align pgame.nim_one_move_right PGame.nim_one_moveRight
+-/
+#print PGame.nimOneRelabelling /-
/-- `nim 1` has exactly the same moves as `star`. -/
def nimOneRelabelling : nim 1 ≡r star := by
rw [nim_def]
@@ -187,11 +244,15 @@ def nimOneRelabelling : nim 1 ≡r star := by
any_goals dsimp; apply Equiv.equivOfUnique
all_goals simp; exact nim_zero_relabelling
#align pgame.nim_one_relabelling PGame.nimOneRelabelling
+-/
+#print PGame.nim_one_equiv /-
theorem nim_one_equiv : nim 1 ≈ star :=
nimOneRelabelling.Equiv
#align pgame.nim_one_equiv PGame.nim_one_equiv
+-/
+#print PGame.nim_birthday /-
@[simp]
theorem nim_birthday (o : Ordinal) : (nim o).birthday = o :=
by
@@ -202,28 +263,36 @@ theorem nim_birthday (o : Ordinal) : (nim o).birthday = o :=
convert lsub_typein o
exact funext fun i => IH _ (typein_lt_self i)
#align pgame.nim_birthday PGame.nim_birthday
+-/
+#print PGame.neg_nim /-
@[simp]
theorem neg_nim (o : Ordinal) : -nim o = nim o :=
by
induction' o using Ordinal.induction with o IH
rw [nim_def]; dsimp <;> congr <;> funext i <;> exact IH _ (Ordinal.typein_lt_self i)
#align pgame.neg_nim PGame.neg_nim
+-/
+#print PGame.nim_impartial /-
instance nim_impartial (o : Ordinal) : Impartial (nim o) :=
by
induction' o using Ordinal.induction with o IH
rw [impartial_def, neg_nim]
refine' ⟨equiv_rfl, fun i => _, fun i => _⟩ <;> simpa using IH _ (typein_lt_self _)
#align pgame.nim_impartial PGame.nim_impartial
+-/
+#print PGame.nim_fuzzy_zero_of_ne_zero /-
theorem nim_fuzzy_zero_of_ne_zero {o : Ordinal} (ho : o ≠ 0) : nim o ‖ 0 :=
by
rw [impartial.fuzzy_zero_iff_lf, nim_def, lf_zero_le]
rw [← Ordinal.pos_iff_ne_zero] at ho
exact ⟨(Ordinal.principalSegOut ho).top, by simp⟩
#align pgame.nim_fuzzy_zero_of_ne_zero PGame.nim_fuzzy_zero_of_ne_zero
+-/
+#print PGame.nim_add_equiv_zero_iff /-
@[simp]
theorem nim_add_equiv_zero_iff (o₁ o₂ : Ordinal) : (nim o₁ + nim o₂ ≈ 0) ↔ o₁ = o₂ :=
by
@@ -238,28 +307,38 @@ theorem nim_add_equiv_zero_iff (o₁ o₂ : Ordinal) : (nim o₁ + nim o₂ ≈
· rintro rfl
exact impartial.add_self (nim o₁)
#align pgame.nim_add_equiv_zero_iff PGame.nim_add_equiv_zero_iff
+-/
+#print PGame.nim_add_fuzzy_zero_iff /-
@[simp]
theorem nim_add_fuzzy_zero_iff {o₁ o₂ : Ordinal} : nim o₁ + nim o₂ ‖ 0 ↔ o₁ ≠ o₂ := by
rw [iff_not_comm, impartial.not_fuzzy_zero_iff, nim_add_equiv_zero_iff]
#align pgame.nim_add_fuzzy_zero_iff PGame.nim_add_fuzzy_zero_iff
+-/
+#print PGame.nim_equiv_iff_eq /-
@[simp]
theorem nim_equiv_iff_eq {o₁ o₂ : Ordinal} : (nim o₁ ≈ nim o₂) ↔ o₁ = o₂ := by
rw [impartial.equiv_iff_add_equiv_zero, nim_add_equiv_zero_iff]
#align pgame.nim_equiv_iff_eq PGame.nim_equiv_iff_eq
+-/
+#print PGame.grundyValue /-
/-- The Grundy value of an impartial game, the ordinal which corresponds to the game of nim that the
game is equivalent to -/
noncomputable def grundyValue : ∀ G : PGame.{u}, Ordinal.{u}
| G => Ordinal.mex.{u, u} fun i => grundy_value (G.moveLeft i)
decreasing_by pgame_wf_tac
#align pgame.grundy_value PGame.grundyValue
+-/
+#print PGame.grundyValue_eq_mex_left /-
theorem grundyValue_eq_mex_left (G : PGame) :
grundyValue G = Ordinal.mex.{u, u} fun i => grundyValue (G.moveLeft i) := by rw [grundy_value]
#align pgame.grundy_value_eq_mex_left PGame.grundyValue_eq_mex_left
+-/
+#print PGame.equiv_nim_grundyValue /-
/-- The Sprague-Grundy theorem which states that every impartial game is equivalent to a game of
nim, namely the game of nim corresponding to the games Grundy value -/
theorem equiv_nim_grundyValue : ∀ (G : PGame.{u}) [G.Impartial], G ≈ nim (grundyValue G)
@@ -299,42 +378,58 @@ theorem equiv_nim_grundyValue : ∀ (G : PGame.{u}) [G.Impartial], G ≈ nim (gr
simpa only [hi] using impartial.add_self (nim (grundy_value (G.move_left i)))
decreasing_by pgame_wf_tac
#align pgame.equiv_nim_grundy_value PGame.equiv_nim_grundyValue
+-/
+#print PGame.grundyValue_eq_iff_equiv_nim /-
theorem grundyValue_eq_iff_equiv_nim {G : PGame} [G.Impartial] {o : Ordinal} :
grundyValue G = o ↔ (G ≈ nim o) :=
⟨by rintro rfl; exact equiv_nim_grundy_value G, by intro h; rw [← nim_equiv_iff_eq];
exact (equiv_nim_grundy_value G).symm.trans h⟩
#align pgame.grundy_value_eq_iff_equiv_nim PGame.grundyValue_eq_iff_equiv_nim
+-/
+#print PGame.nim_grundyValue /-
@[simp]
theorem nim_grundyValue (o : Ordinal.{u}) : grundyValue (nim o) = o :=
grundyValue_eq_iff_equiv_nim.2 PGame.equiv_rfl
#align pgame.nim_grundy_value PGame.nim_grundyValue
+-/
+#print PGame.grundyValue_eq_iff_equiv /-
theorem grundyValue_eq_iff_equiv (G H : PGame) [G.Impartial] [H.Impartial] :
grundyValue G = grundyValue H ↔ (G ≈ H) :=
grundyValue_eq_iff_equiv_nim.trans (equiv_congr_left.1 (equiv_nim_grundyValue H) _).symm
#align pgame.grundy_value_eq_iff_equiv PGame.grundyValue_eq_iff_equiv
+-/
+#print PGame.grundyValue_zero /-
@[simp]
theorem grundyValue_zero : grundyValue 0 = 0 :=
grundyValue_eq_iff_equiv_nim.2 nim_zero_equiv.symm
#align pgame.grundy_value_zero PGame.grundyValue_zero
+-/
+#print PGame.grundyValue_iff_equiv_zero /-
theorem grundyValue_iff_equiv_zero (G : PGame) [G.Impartial] : grundyValue G = 0 ↔ (G ≈ 0) := by
rw [← grundy_value_eq_iff_equiv, grundy_value_zero]
#align pgame.grundy_value_iff_equiv_zero PGame.grundyValue_iff_equiv_zero
+-/
+#print PGame.grundyValue_star /-
@[simp]
theorem grundyValue_star : grundyValue star = 1 :=
grundyValue_eq_iff_equiv_nim.2 nim_one_equiv.symm
#align pgame.grundy_value_star PGame.grundyValue_star
+-/
+#print PGame.grundyValue_neg /-
@[simp]
theorem grundyValue_neg (G : PGame) [G.Impartial] : grundyValue (-G) = grundyValue G := by
rw [grundy_value_eq_iff_equiv_nim, neg_equiv_iff, neg_nim, ← grundy_value_eq_iff_equiv_nim]
#align pgame.grundy_value_neg PGame.grundyValue_neg
+-/
+#print PGame.grundyValue_eq_mex_right /-
theorem grundyValue_eq_mex_right :
∀ (G : PGame) [G.Impartial],
grundyValue G = Ordinal.mex.{u, u} fun i => grundyValue (G.moveRight i)
@@ -346,7 +441,9 @@ theorem grundyValue_eq_mex_right :
haveI : (R i).Impartial := @impartial.move_right_impartial ⟨l, r, L, R⟩ _ i
apply grundy_value_neg
#align pgame.grundy_value_eq_mex_right PGame.grundyValue_eq_mex_right
+-/
+#print PGame.grundyValue_nim_add_nim /-
-- Todo: this actually generalizes to all ordinals, by defining `ordinal.lxor` as the pairwise
-- `nat.lxor` of base `ω` Cantor normal forms.
/-- The Grundy value of the sum of two nim games with natural numbers of piles equals their bitwise
@@ -390,11 +487,15 @@ theorem grundyValue_nim_add_nim (n m : ℕ) : grundyValue (nim.{u} n + nim.{u} m
have : n.lxor (u.lxor n) = u; rw [Nat.lxor'_comm u, Nat.lxor'_cancel_left]
simpa [hm _ h] using this
#align pgame.grundy_value_nim_add_nim PGame.grundyValue_nim_add_nim
+-/
+#print PGame.nim_add_nim_equiv /-
theorem nim_add_nim_equiv {n m : ℕ} : nim n + nim m ≈ nim (Nat.lxor' n m) := by
rw [← grundy_value_eq_iff_equiv_nim, grundy_value_nim_add_nim]
#align pgame.nim_add_nim_equiv PGame.nim_add_nim_equiv
+-/
+#print PGame.grundyValue_add /-
theorem grundyValue_add (G H : PGame) [G.Impartial] [H.Impartial] {n m : ℕ} (hG : grundyValue G = n)
(hH : grundyValue H = m) : grundyValue (G + H) = Nat.lxor' n m :=
by
@@ -402,6 +503,7 @@ theorem grundyValue_add (G H : PGame) [G.Impartial] [H.Impartial] {n m : ℕ} (h
refine' Equiv.trans _ nim_add_nim_equiv
convert add_congr (equiv_nim_grundy_value G) (equiv_nim_grundy_value H) <;> simp only [hG, hH]
#align pgame.grundy_value_add PGame.grundyValue_add
+-/
end PGame
mathlib commit https://github.com/leanprover-community/mathlib/commit/cca40788df1b8755d5baf17ab2f27dacc2e17acb
@@ -220,7 +220,7 @@ instance nim_impartial (o : Ordinal) : Impartial (nim o) :=
theorem nim_fuzzy_zero_of_ne_zero {o : Ordinal} (ho : o ≠ 0) : nim o ‖ 0 :=
by
rw [impartial.fuzzy_zero_iff_lf, nim_def, lf_zero_le]
- rw [← Ordinal.pos_iff_ne_zero] at ho
+ rw [← Ordinal.pos_iff_ne_zero] at ho
exact ⟨(Ordinal.principalSegOut ho).top, by simp⟩
#align pgame.nim_fuzzy_zero_of_ne_zero PGame.nim_fuzzy_zero_of_ne_zero
@@ -252,7 +252,8 @@ theorem nim_equiv_iff_eq {o₁ o₂ : Ordinal} : (nim o₁ ≈ nim o₂) ↔ o
/-- The Grundy value of an impartial game, the ordinal which corresponds to the game of nim that the
game is equivalent to -/
noncomputable def grundyValue : ∀ G : PGame.{u}, Ordinal.{u}
- | G => Ordinal.mex.{u, u} fun i => grundy_value (G.moveLeft i)decreasing_by pgame_wf_tac
+ | G => Ordinal.mex.{u, u} fun i => grundy_value (G.moveLeft i)
+decreasing_by pgame_wf_tac
#align pgame.grundy_value PGame.grundyValue
theorem grundyValue_eq_mex_left (G : PGame) :
@@ -272,9 +273,9 @@ theorem equiv_nim_grundyValue : ∀ (G : PGame.{u}) [G.Impartial], G ≈ nim (gr
apply (fuzzy_congr_left (add_congr_left (equiv_nim_grundy_value (G.move_left i₁)).symm)).1
rw [nim_add_fuzzy_zero_iff]
intro heq
- rw [eq_comm, grundy_value_eq_mex_left G] at heq
+ rw [eq_comm, grundy_value_eq_mex_left G] at heq
have h := Ordinal.ne_mex _
- rw [HEq] at h
+ rw [HEq] at h
exact (h i₁).irrefl
· intro i₂
rw [add_move_left_inr, ← impartial.exists_left_move_equiv_iff_fuzzy_zero]
@@ -295,8 +296,8 @@ theorem equiv_nim_grundyValue : ∀ (G : PGame.{u}) [G.Impartial], G ≈ nim (gr
use to_left_moves_add (Sum.inl i)
rw [add_move_left_inl, move_left_mk]
apply (add_congr_left (equiv_nim_grundy_value (G.move_left i))).trans
- simpa only [hi] using impartial.add_self (nim (grundy_value (G.move_left i)))decreasing_by
- pgame_wf_tac
+ simpa only [hi] using impartial.add_self (nim (grundy_value (G.move_left i)))
+decreasing_by pgame_wf_tac
#align pgame.equiv_nim_grundy_value PGame.equiv_nim_grundyValue
theorem grundyValue_eq_iff_equiv_nim {G : PGame} [G.Impartial] {o : Ordinal} :
@@ -367,11 +368,15 @@ theorem grundyValue_nim_add_nim (n m : ℕ) : grundyValue (nim.{u} n + nim.{u} m
obtain ⟨k, rfl⟩ := Ordinal.lt_omega.1 (hk.trans (Ordinal.nat_lt_omega _))
simp only [add_move_left_inl, add_move_left_inr, move_left_nim', Equiv.symm_apply_apply]
-- The inequality follows from injectivity.
- rw [nat_cast_lt] at hk
- first |rw [hn _ hk]|rw [hm _ hk]
+ rw [nat_cast_lt] at hk
+ first
+ | rw [hn _ hk]
+ | rw [hm _ hk]
refine' fun h => hk.ne _
- rw [Ordinal.nat_cast_inj] at h
- first |rwa [Nat.lxor'_left_inj] at h|rwa [Nat.lxor'_right_inj] at h
+ rw [Ordinal.nat_cast_inj] at h
+ first
+ | rwa [Nat.lxor'_left_inj] at h
+ | rwa [Nat.lxor'_right_inj] at h
-- Every other smaller Grundy value can be reached by left moves.
· -- If `u < nat.lxor m n`, then either `nat.lxor u n < m` or `nat.lxor u m < n`.
obtain ⟨u, rfl⟩ := Ordinal.lt_omega.1 (hu.trans (Ordinal.nat_lt_omega _))
mathlib commit https://github.com/leanprover-community/mathlib/commit/917c3c072e487b3cccdbfeff17e75b40e45f66cb
@@ -38,7 +38,7 @@ noncomputable section
universe u
-open PGame
+open scoped PGame
namespace PGame
mathlib commit https://github.com/leanprover-community/mathlib/commit/917c3c072e487b3cccdbfeff17e75b40e45f66cb
@@ -59,35 +59,21 @@ theorem nim_def (o : Ordinal) :
nim o =
PGame.mk o.out.α o.out.α (fun o₂ => nim (Ordinal.typein (· < ·) o₂)) fun o₂ =>
nim (Ordinal.typein (· < ·) o₂) :=
- by
- rw [nim]
- rfl
+ by rw [nim]; rfl
#align pgame.nim_def PGame.nim_def
-theorem leftMoves_nim (o : Ordinal) : (nim o).LeftMoves = o.out.α :=
- by
- rw [nim_def]
- rfl
+theorem leftMoves_nim (o : Ordinal) : (nim o).LeftMoves = o.out.α := by rw [nim_def]; rfl
#align pgame.left_moves_nim PGame.leftMoves_nim
-theorem rightMoves_nim (o : Ordinal) : (nim o).RightMoves = o.out.α :=
- by
- rw [nim_def]
- rfl
+theorem rightMoves_nim (o : Ordinal) : (nim o).RightMoves = o.out.α := by rw [nim_def]; rfl
#align pgame.right_moves_nim PGame.rightMoves_nim
theorem moveLeft_nim_hEq (o : Ordinal) :
- HEq (nim o).moveLeft fun i : o.out.α => nim (typein (· < ·) i) :=
- by
- rw [nim_def]
- rfl
+ HEq (nim o).moveLeft fun i : o.out.α => nim (typein (· < ·) i) := by rw [nim_def]; rfl
#align pgame.move_left_nim_heq PGame.moveLeft_nim_hEq
theorem moveRight_nim_hEq (o : Ordinal) :
- HEq (nim o).moveRight fun i : o.out.α => nim (typein (· < ·) i) :=
- by
- rw [nim_def]
- rfl
+ HEq (nim o).moveRight fun i : o.out.α => nim (typein (· < ·) i) := by rw [nim_def]; rfl
#align pgame.move_right_nim_heq PGame.moveRight_nim_hEq
/-- Turns an ordinal less than `o` into a left move for `nim o` and viceversa. -/
@@ -132,30 +118,22 @@ theorem moveRight_nim {o : Ordinal} (i) : (nim o).moveRight (toRightMovesNim i)
/-- A recursion principle for left moves of a nim game. -/
@[elab_as_elim]
def leftMovesNimRecOn {o : Ordinal} {P : (nim o).LeftMoves → Sort _} (i : (nim o).LeftMoves)
- (H : ∀ a < o, P <| toLeftMovesNim ⟨a, H⟩) : P i :=
- by
- rw [← to_left_moves_nim.apply_symm_apply i]
- apply H
+ (H : ∀ a < o, P <| toLeftMovesNim ⟨a, H⟩) : P i := by
+ rw [← to_left_moves_nim.apply_symm_apply i]; apply H
#align pgame.left_moves_nim_rec_on PGame.leftMovesNimRecOn
/-- A recursion principle for right moves of a nim game. -/
@[elab_as_elim]
def rightMovesNimRecOn {o : Ordinal} {P : (nim o).RightMoves → Sort _} (i : (nim o).RightMoves)
- (H : ∀ a < o, P <| toRightMovesNim ⟨a, H⟩) : P i :=
- by
- rw [← to_right_moves_nim.apply_symm_apply i]
- apply H
+ (H : ∀ a < o, P <| toRightMovesNim ⟨a, H⟩) : P i := by
+ rw [← to_right_moves_nim.apply_symm_apply i]; apply H
#align pgame.right_moves_nim_rec_on PGame.rightMovesNimRecOn
-instance isEmpty_nim_zero_leftMoves : IsEmpty (nim 0).LeftMoves :=
- by
- rw [nim_def]
+instance isEmpty_nim_zero_leftMoves : IsEmpty (nim 0).LeftMoves := by rw [nim_def];
exact Ordinal.isEmpty_out_zero
#align pgame.is_empty_nim_zero_left_moves PGame.isEmpty_nim_zero_leftMoves
-instance isEmpty_nim_zero_rightMoves : IsEmpty (nim 0).RightMoves :=
- by
- rw [nim_def]
+instance isEmpty_nim_zero_rightMoves : IsEmpty (nim 0).RightMoves := by rw [nim_def];
exact Ordinal.isEmpty_out_zero
#align pgame.is_empty_nim_zero_right_moves PGame.isEmpty_nim_zero_rightMoves
@@ -323,11 +301,7 @@ theorem equiv_nim_grundyValue : ∀ (G : PGame.{u}) [G.Impartial], G ≈ nim (gr
theorem grundyValue_eq_iff_equiv_nim {G : PGame} [G.Impartial] {o : Ordinal} :
grundyValue G = o ↔ (G ≈ nim o) :=
- ⟨by
- rintro rfl
- exact equiv_nim_grundy_value G, by
- intro h
- rw [← nim_equiv_iff_eq]
+ ⟨by rintro rfl; exact equiv_nim_grundy_value G, by intro h; rw [← nim_equiv_iff_eq];
exact (equiv_nim_grundy_value G).symm.trans h⟩
#align pgame.grundy_value_eq_iff_equiv_nim PGame.grundyValue_eq_iff_equiv_nim
@@ -408,8 +382,7 @@ theorem grundyValue_nim_add_nim (n m : ℕ) : grundyValue (nim.{u} n + nim.{u} m
simp [Nat.lxor_cancel_right, hn _ h]
-- In the second case, reducing the `n` pile to `nat.lxor u m` gives the desired Grundy value.
· refine' ⟨to_left_moves_add (Sum.inr <| to_left_moves_nim ⟨_, Ordinal.nat_cast_lt.2 h⟩), _⟩
- have : n.lxor (u.lxor n) = u
- rw [Nat.lxor'_comm u, Nat.lxor'_cancel_left]
+ have : n.lxor (u.lxor n) = u; rw [Nat.lxor'_comm u, Nat.lxor'_cancel_left]
simpa [hm _ h] using this
#align pgame.grundy_value_nim_add_nim PGame.grundyValue_nim_add_nim
mathlib commit https://github.com/leanprover-community/mathlib/commit/95a87616d63b3cb49d3fe678d416fbe9c4217bf4
@@ -38,96 +38,96 @@ noncomputable section
universe u
-open Pgame
+open PGame
-namespace Pgame
+namespace PGame
-- Uses `noncomputable!` to avoid `rec_fn_macro only allowed in meta definitions` VM error
/-- The definition of single-heap nim, which can be viewed as a pile of stones where each player can
take a positive number of stones from it on their turn. -/
-noncomputable def nim : Ordinal.{u} → Pgame.{u}
+noncomputable def nim : Ordinal.{u} → PGame.{u}
| o₁ =>
let f o₂ :=
have : Ordinal.typein o₁.out.R o₂ < o₁ := Ordinal.typein_lt_self o₂
nim (Ordinal.typein o₁.out.R o₂)
⟨o₁.out.α, o₁.out.α, f, f⟩
-#align pgame.nim Pgame.nim
+#align pgame.nim PGame.nim
open Ordinal
theorem nim_def (o : Ordinal) :
nim o =
- Pgame.mk o.out.α o.out.α (fun o₂ => nim (Ordinal.typein (· < ·) o₂)) fun o₂ =>
+ PGame.mk o.out.α o.out.α (fun o₂ => nim (Ordinal.typein (· < ·) o₂)) fun o₂ =>
nim (Ordinal.typein (· < ·) o₂) :=
by
rw [nim]
rfl
-#align pgame.nim_def Pgame.nim_def
+#align pgame.nim_def PGame.nim_def
theorem leftMoves_nim (o : Ordinal) : (nim o).LeftMoves = o.out.α :=
by
rw [nim_def]
rfl
-#align pgame.left_moves_nim Pgame.leftMoves_nim
+#align pgame.left_moves_nim PGame.leftMoves_nim
theorem rightMoves_nim (o : Ordinal) : (nim o).RightMoves = o.out.α :=
by
rw [nim_def]
rfl
-#align pgame.right_moves_nim Pgame.rightMoves_nim
+#align pgame.right_moves_nim PGame.rightMoves_nim
theorem moveLeft_nim_hEq (o : Ordinal) :
HEq (nim o).moveLeft fun i : o.out.α => nim (typein (· < ·) i) :=
by
rw [nim_def]
rfl
-#align pgame.move_left_nim_heq Pgame.moveLeft_nim_hEq
+#align pgame.move_left_nim_heq PGame.moveLeft_nim_hEq
theorem moveRight_nim_hEq (o : Ordinal) :
HEq (nim o).moveRight fun i : o.out.α => nim (typein (· < ·) i) :=
by
rw [nim_def]
rfl
-#align pgame.move_right_nim_heq Pgame.moveRight_nim_hEq
+#align pgame.move_right_nim_heq PGame.moveRight_nim_hEq
/-- Turns an ordinal less than `o` into a left move for `nim o` and viceversa. -/
noncomputable def toLeftMovesNim {o : Ordinal} : Set.Iio o ≃ (nim o).LeftMoves :=
(enumIsoOut o).toEquiv.trans (Equiv.cast (leftMoves_nim o).symm)
-#align pgame.to_left_moves_nim Pgame.toLeftMovesNim
+#align pgame.to_left_moves_nim PGame.toLeftMovesNim
/-- Turns an ordinal less than `o` into a right move for `nim o` and viceversa. -/
noncomputable def toRightMovesNim {o : Ordinal} : Set.Iio o ≃ (nim o).RightMoves :=
(enumIsoOut o).toEquiv.trans (Equiv.cast (rightMoves_nim o).symm)
-#align pgame.to_right_moves_nim Pgame.toRightMovesNim
+#align pgame.to_right_moves_nim PGame.toRightMovesNim
@[simp]
theorem toLeftMovesNim_symm_lt {o : Ordinal} (i : (nim o).LeftMoves) :
↑(toLeftMovesNim.symm i) < o :=
(toLeftMovesNim.symm i).Prop
-#align pgame.to_left_moves_nim_symm_lt Pgame.toLeftMovesNim_symm_lt
+#align pgame.to_left_moves_nim_symm_lt PGame.toLeftMovesNim_symm_lt
@[simp]
theorem toRightMovesNim_symm_lt {o : Ordinal} (i : (nim o).RightMoves) :
↑(toRightMovesNim.symm i) < o :=
(toRightMovesNim.symm i).Prop
-#align pgame.to_right_moves_nim_symm_lt Pgame.toRightMovesNim_symm_lt
+#align pgame.to_right_moves_nim_symm_lt PGame.toRightMovesNim_symm_lt
@[simp]
theorem moveLeft_nim' {o : Ordinal.{u}} (i) :
(nim o).moveLeft i = nim (toLeftMovesNim.symm i).val :=
(congr_heq (moveLeft_nim_hEq o).symm (cast_hEq _ i)).symm
-#align pgame.move_left_nim' Pgame.moveLeft_nim'
+#align pgame.move_left_nim' PGame.moveLeft_nim'
theorem moveLeft_nim {o : Ordinal} (i) : (nim o).moveLeft (toLeftMovesNim i) = nim i := by simp
-#align pgame.move_left_nim Pgame.moveLeft_nim
+#align pgame.move_left_nim PGame.moveLeft_nim
@[simp]
theorem moveRight_nim' {o : Ordinal} (i) : (nim o).moveRight i = nim (toRightMovesNim.symm i).val :=
(congr_heq (moveRight_nim_hEq o).symm (cast_hEq _ i)).symm
-#align pgame.move_right_nim' Pgame.moveRight_nim'
+#align pgame.move_right_nim' PGame.moveRight_nim'
theorem moveRight_nim {o : Ordinal} (i) : (nim o).moveRight (toRightMovesNim i) = nim i := by simp
-#align pgame.move_right_nim Pgame.moveRight_nim
+#align pgame.move_right_nim PGame.moveRight_nim
/-- A recursion principle for left moves of a nim game. -/
@[elab_as_elim]
@@ -136,7 +136,7 @@ def leftMovesNimRecOn {o : Ordinal} {P : (nim o).LeftMoves → Sort _} (i : (nim
by
rw [← to_left_moves_nim.apply_symm_apply i]
apply H
-#align pgame.left_moves_nim_rec_on Pgame.leftMovesNimRecOn
+#align pgame.left_moves_nim_rec_on PGame.leftMovesNimRecOn
/-- A recursion principle for right moves of a nim game. -/
@[elab_as_elim]
@@ -145,62 +145,62 @@ def rightMovesNimRecOn {o : Ordinal} {P : (nim o).RightMoves → Sort _} (i : (n
by
rw [← to_right_moves_nim.apply_symm_apply i]
apply H
-#align pgame.right_moves_nim_rec_on Pgame.rightMovesNimRecOn
+#align pgame.right_moves_nim_rec_on PGame.rightMovesNimRecOn
instance isEmpty_nim_zero_leftMoves : IsEmpty (nim 0).LeftMoves :=
by
rw [nim_def]
exact Ordinal.isEmpty_out_zero
-#align pgame.is_empty_nim_zero_left_moves Pgame.isEmpty_nim_zero_leftMoves
+#align pgame.is_empty_nim_zero_left_moves PGame.isEmpty_nim_zero_leftMoves
instance isEmpty_nim_zero_rightMoves : IsEmpty (nim 0).RightMoves :=
by
rw [nim_def]
exact Ordinal.isEmpty_out_zero
-#align pgame.is_empty_nim_zero_right_moves Pgame.isEmpty_nim_zero_rightMoves
+#align pgame.is_empty_nim_zero_right_moves PGame.isEmpty_nim_zero_rightMoves
/-- `nim 0` has exactly the same moves as `0`. -/
def nimZeroRelabelling : nim 0 ≡r 0 :=
Relabelling.isEmpty _
-#align pgame.nim_zero_relabelling Pgame.nimZeroRelabelling
+#align pgame.nim_zero_relabelling PGame.nimZeroRelabelling
theorem nim_zero_equiv : nim 0 ≈ 0 :=
Equiv.isEmpty _
-#align pgame.nim_zero_equiv Pgame.nim_zero_equiv
+#align pgame.nim_zero_equiv PGame.nim_zero_equiv
noncomputable instance uniqueNimOneLeftMoves : Unique (nim 1).LeftMoves :=
(Equiv.cast <| leftMoves_nim 1).unique
-#align pgame.unique_nim_one_left_moves Pgame.uniqueNimOneLeftMoves
+#align pgame.unique_nim_one_left_moves PGame.uniqueNimOneLeftMoves
noncomputable instance uniqueNimOneRightMoves : Unique (nim 1).RightMoves :=
(Equiv.cast <| rightMoves_nim 1).unique
-#align pgame.unique_nim_one_right_moves Pgame.uniqueNimOneRightMoves
+#align pgame.unique_nim_one_right_moves PGame.uniqueNimOneRightMoves
@[simp]
theorem default_nim_one_leftMoves_eq :
(default : (nim 1).LeftMoves) = @toLeftMovesNim 1 ⟨0, zero_lt_one⟩ :=
rfl
-#align pgame.default_nim_one_left_moves_eq Pgame.default_nim_one_leftMoves_eq
+#align pgame.default_nim_one_left_moves_eq PGame.default_nim_one_leftMoves_eq
@[simp]
theorem default_nim_one_rightMoves_eq :
(default : (nim 1).RightMoves) = @toRightMovesNim 1 ⟨0, zero_lt_one⟩ :=
rfl
-#align pgame.default_nim_one_right_moves_eq Pgame.default_nim_one_rightMoves_eq
+#align pgame.default_nim_one_right_moves_eq PGame.default_nim_one_rightMoves_eq
@[simp]
theorem toLeftMovesNim_one_symm (i) : (@toLeftMovesNim 1).symm i = ⟨0, zero_lt_one⟩ := by simp
-#align pgame.to_left_moves_nim_one_symm Pgame.toLeftMovesNim_one_symm
+#align pgame.to_left_moves_nim_one_symm PGame.toLeftMovesNim_one_symm
@[simp]
theorem toRightMovesNim_one_symm (i) : (@toRightMovesNim 1).symm i = ⟨0, zero_lt_one⟩ := by simp
-#align pgame.to_right_moves_nim_one_symm Pgame.toRightMovesNim_one_symm
+#align pgame.to_right_moves_nim_one_symm PGame.toRightMovesNim_one_symm
theorem nim_one_moveLeft (x) : (nim 1).moveLeft x = nim 0 := by simp
-#align pgame.nim_one_move_left Pgame.nim_one_moveLeft
+#align pgame.nim_one_move_left PGame.nim_one_moveLeft
theorem nim_one_moveRight (x) : (nim 1).moveRight x = nim 0 := by simp
-#align pgame.nim_one_move_right Pgame.nim_one_moveRight
+#align pgame.nim_one_move_right PGame.nim_one_moveRight
/-- `nim 1` has exactly the same moves as `star`. -/
def nimOneRelabelling : nim 1 ≡r star := by
@@ -208,11 +208,11 @@ def nimOneRelabelling : nim 1 ≡r star := by
refine' ⟨_, _, fun i => _, fun j => _⟩
any_goals dsimp; apply Equiv.equivOfUnique
all_goals simp; exact nim_zero_relabelling
-#align pgame.nim_one_relabelling Pgame.nimOneRelabelling
+#align pgame.nim_one_relabelling PGame.nimOneRelabelling
theorem nim_one_equiv : nim 1 ≈ star :=
nimOneRelabelling.Equiv
-#align pgame.nim_one_equiv Pgame.nim_one_equiv
+#align pgame.nim_one_equiv PGame.nim_one_equiv
@[simp]
theorem nim_birthday (o : Ordinal) : (nim o).birthday = o :=
@@ -223,28 +223,28 @@ theorem nim_birthday (o : Ordinal) : (nim o).birthday = o :=
rw [max_eq_right le_rfl]
convert lsub_typein o
exact funext fun i => IH _ (typein_lt_self i)
-#align pgame.nim_birthday Pgame.nim_birthday
+#align pgame.nim_birthday PGame.nim_birthday
@[simp]
theorem neg_nim (o : Ordinal) : -nim o = nim o :=
by
induction' o using Ordinal.induction with o IH
rw [nim_def]; dsimp <;> congr <;> funext i <;> exact IH _ (Ordinal.typein_lt_self i)
-#align pgame.neg_nim Pgame.neg_nim
+#align pgame.neg_nim PGame.neg_nim
instance nim_impartial (o : Ordinal) : Impartial (nim o) :=
by
induction' o using Ordinal.induction with o IH
rw [impartial_def, neg_nim]
refine' ⟨equiv_rfl, fun i => _, fun i => _⟩ <;> simpa using IH _ (typein_lt_self _)
-#align pgame.nim_impartial Pgame.nim_impartial
+#align pgame.nim_impartial PGame.nim_impartial
theorem nim_fuzzy_zero_of_ne_zero {o : Ordinal} (ho : o ≠ 0) : nim o ‖ 0 :=
by
rw [impartial.fuzzy_zero_iff_lf, nim_def, lf_zero_le]
rw [← Ordinal.pos_iff_ne_zero] at ho
exact ⟨(Ordinal.principalSegOut ho).top, by simp⟩
-#align pgame.nim_fuzzy_zero_of_ne_zero Pgame.nim_fuzzy_zero_of_ne_zero
+#align pgame.nim_fuzzy_zero_of_ne_zero PGame.nim_fuzzy_zero_of_ne_zero
@[simp]
theorem nim_add_equiv_zero_iff (o₁ o₂ : Ordinal) : (nim o₁ + nim o₂ ≈ 0) ↔ o₁ = o₂ :=
@@ -259,31 +259,31 @@ theorem nim_add_equiv_zero_iff (o₁ o₂ : Ordinal) : (nim o₁ + nim o₂ ≈
· simpa using (impartial.add_self (nim o₁)).2
· rintro rfl
exact impartial.add_self (nim o₁)
-#align pgame.nim_add_equiv_zero_iff Pgame.nim_add_equiv_zero_iff
+#align pgame.nim_add_equiv_zero_iff PGame.nim_add_equiv_zero_iff
@[simp]
theorem nim_add_fuzzy_zero_iff {o₁ o₂ : Ordinal} : nim o₁ + nim o₂ ‖ 0 ↔ o₁ ≠ o₂ := by
rw [iff_not_comm, impartial.not_fuzzy_zero_iff, nim_add_equiv_zero_iff]
-#align pgame.nim_add_fuzzy_zero_iff Pgame.nim_add_fuzzy_zero_iff
+#align pgame.nim_add_fuzzy_zero_iff PGame.nim_add_fuzzy_zero_iff
@[simp]
theorem nim_equiv_iff_eq {o₁ o₂ : Ordinal} : (nim o₁ ≈ nim o₂) ↔ o₁ = o₂ := by
rw [impartial.equiv_iff_add_equiv_zero, nim_add_equiv_zero_iff]
-#align pgame.nim_equiv_iff_eq Pgame.nim_equiv_iff_eq
+#align pgame.nim_equiv_iff_eq PGame.nim_equiv_iff_eq
/-- The Grundy value of an impartial game, the ordinal which corresponds to the game of nim that the
game is equivalent to -/
-noncomputable def grundyValue : ∀ G : Pgame.{u}, Ordinal.{u}
+noncomputable def grundyValue : ∀ G : PGame.{u}, Ordinal.{u}
| G => Ordinal.mex.{u, u} fun i => grundy_value (G.moveLeft i)decreasing_by pgame_wf_tac
-#align pgame.grundy_value Pgame.grundyValue
+#align pgame.grundy_value PGame.grundyValue
-theorem grundyValue_eq_mex_left (G : Pgame) :
+theorem grundyValue_eq_mex_left (G : PGame) :
grundyValue G = Ordinal.mex.{u, u} fun i => grundyValue (G.moveLeft i) := by rw [grundy_value]
-#align pgame.grundy_value_eq_mex_left Pgame.grundyValue_eq_mex_left
+#align pgame.grundy_value_eq_mex_left PGame.grundyValue_eq_mex_left
/-- The Sprague-Grundy theorem which states that every impartial game is equivalent to a game of
nim, namely the game of nim corresponding to the games Grundy value -/
-theorem equiv_nim_grundyValue : ∀ (G : Pgame.{u}) [G.Impartial], G ≈ nim (grundyValue G)
+theorem equiv_nim_grundyValue : ∀ (G : PGame.{u}) [G.Impartial], G ≈ nim (grundyValue G)
| G => by
intro hG
rw [impartial.equiv_iff_add_equiv_zero, ← impartial.forall_left_moves_fuzzy_iff_equiv_zero]
@@ -319,9 +319,9 @@ theorem equiv_nim_grundyValue : ∀ (G : Pgame.{u}) [G.Impartial], G ≈ nim (gr
apply (add_congr_left (equiv_nim_grundy_value (G.move_left i))).trans
simpa only [hi] using impartial.add_self (nim (grundy_value (G.move_left i)))decreasing_by
pgame_wf_tac
-#align pgame.equiv_nim_grundy_value Pgame.equiv_nim_grundyValue
+#align pgame.equiv_nim_grundy_value PGame.equiv_nim_grundyValue
-theorem grundyValue_eq_iff_equiv_nim {G : Pgame} [G.Impartial] {o : Ordinal} :
+theorem grundyValue_eq_iff_equiv_nim {G : PGame} [G.Impartial] {o : Ordinal} :
grundyValue G = o ↔ (G ≈ nim o) :=
⟨by
rintro rfl
@@ -329,39 +329,39 @@ theorem grundyValue_eq_iff_equiv_nim {G : Pgame} [G.Impartial] {o : Ordinal} :
intro h
rw [← nim_equiv_iff_eq]
exact (equiv_nim_grundy_value G).symm.trans h⟩
-#align pgame.grundy_value_eq_iff_equiv_nim Pgame.grundyValue_eq_iff_equiv_nim
+#align pgame.grundy_value_eq_iff_equiv_nim PGame.grundyValue_eq_iff_equiv_nim
@[simp]
theorem nim_grundyValue (o : Ordinal.{u}) : grundyValue (nim o) = o :=
- grundyValue_eq_iff_equiv_nim.2 Pgame.equiv_rfl
-#align pgame.nim_grundy_value Pgame.nim_grundyValue
+ grundyValue_eq_iff_equiv_nim.2 PGame.equiv_rfl
+#align pgame.nim_grundy_value PGame.nim_grundyValue
-theorem grundyValue_eq_iff_equiv (G H : Pgame) [G.Impartial] [H.Impartial] :
+theorem grundyValue_eq_iff_equiv (G H : PGame) [G.Impartial] [H.Impartial] :
grundyValue G = grundyValue H ↔ (G ≈ H) :=
grundyValue_eq_iff_equiv_nim.trans (equiv_congr_left.1 (equiv_nim_grundyValue H) _).symm
-#align pgame.grundy_value_eq_iff_equiv Pgame.grundyValue_eq_iff_equiv
+#align pgame.grundy_value_eq_iff_equiv PGame.grundyValue_eq_iff_equiv
@[simp]
theorem grundyValue_zero : grundyValue 0 = 0 :=
grundyValue_eq_iff_equiv_nim.2 nim_zero_equiv.symm
-#align pgame.grundy_value_zero Pgame.grundyValue_zero
+#align pgame.grundy_value_zero PGame.grundyValue_zero
-theorem grundyValue_iff_equiv_zero (G : Pgame) [G.Impartial] : grundyValue G = 0 ↔ (G ≈ 0) := by
+theorem grundyValue_iff_equiv_zero (G : PGame) [G.Impartial] : grundyValue G = 0 ↔ (G ≈ 0) := by
rw [← grundy_value_eq_iff_equiv, grundy_value_zero]
-#align pgame.grundy_value_iff_equiv_zero Pgame.grundyValue_iff_equiv_zero
+#align pgame.grundy_value_iff_equiv_zero PGame.grundyValue_iff_equiv_zero
@[simp]
theorem grundyValue_star : grundyValue star = 1 :=
grundyValue_eq_iff_equiv_nim.2 nim_one_equiv.symm
-#align pgame.grundy_value_star Pgame.grundyValue_star
+#align pgame.grundy_value_star PGame.grundyValue_star
@[simp]
-theorem grundyValue_neg (G : Pgame) [G.Impartial] : grundyValue (-G) = grundyValue G := by
+theorem grundyValue_neg (G : PGame) [G.Impartial] : grundyValue (-G) = grundyValue G := by
rw [grundy_value_eq_iff_equiv_nim, neg_equiv_iff, neg_nim, ← grundy_value_eq_iff_equiv_nim]
-#align pgame.grundy_value_neg Pgame.grundyValue_neg
+#align pgame.grundy_value_neg PGame.grundyValue_neg
theorem grundyValue_eq_mex_right :
- ∀ (G : Pgame) [G.Impartial],
+ ∀ (G : PGame) [G.Impartial],
grundyValue G = Ordinal.mex.{u, u} fun i => grundyValue (G.moveRight i)
| ⟨l, r, L, R⟩ => by
intro H
@@ -370,7 +370,7 @@ theorem grundyValue_eq_mex_right :
ext i
haveI : (R i).Impartial := @impartial.move_right_impartial ⟨l, r, L, R⟩ _ i
apply grundy_value_neg
-#align pgame.grundy_value_eq_mex_right Pgame.grundyValue_eq_mex_right
+#align pgame.grundy_value_eq_mex_right PGame.grundyValue_eq_mex_right
-- Todo: this actually generalizes to all ordinals, by defining `ordinal.lxor` as the pairwise
-- `nat.lxor` of base `ω` Cantor normal forms.
@@ -411,19 +411,19 @@ theorem grundyValue_nim_add_nim (n m : ℕ) : grundyValue (nim.{u} n + nim.{u} m
have : n.lxor (u.lxor n) = u
rw [Nat.lxor'_comm u, Nat.lxor'_cancel_left]
simpa [hm _ h] using this
-#align pgame.grundy_value_nim_add_nim Pgame.grundyValue_nim_add_nim
+#align pgame.grundy_value_nim_add_nim PGame.grundyValue_nim_add_nim
theorem nim_add_nim_equiv {n m : ℕ} : nim n + nim m ≈ nim (Nat.lxor' n m) := by
rw [← grundy_value_eq_iff_equiv_nim, grundy_value_nim_add_nim]
-#align pgame.nim_add_nim_equiv Pgame.nim_add_nim_equiv
+#align pgame.nim_add_nim_equiv PGame.nim_add_nim_equiv
-theorem grundyValue_add (G H : Pgame) [G.Impartial] [H.Impartial] {n m : ℕ} (hG : grundyValue G = n)
+theorem grundyValue_add (G H : PGame) [G.Impartial] [H.Impartial] {n m : ℕ} (hG : grundyValue G = n)
(hH : grundyValue H = m) : grundyValue (G + H) = Nat.lxor' n m :=
by
rw [← nim_grundy_value (Nat.lxor' n m), grundy_value_eq_iff_equiv]
refine' Equiv.trans _ nim_add_nim_equiv
convert add_congr (equiv_nim_grundy_value G) (equiv_nim_grundy_value H) <;> simp only [hG, hH]
-#align pgame.grundy_value_add Pgame.grundyValue_add
+#align pgame.grundy_value_add PGame.grundyValue_add
-end Pgame
+end PGame
mathlib commit https://github.com/leanprover-community/mathlib/commit/e3fb84046afd187b710170887195d50bada934ee
@@ -311,7 +311,7 @@ theorem equiv_nim_grundyValue : ∀ (G : Pgame.{u}) [G.Impartial], G ≈ nim (gr
rw [grundy_value_eq_mex_left]
intro i₂
have hnotin : _ ∉ _ := fun hin =>
- (le_not_le_of_lt (Ordinal.typein_lt_self i₂)).2 (cinfₛ_le' hin)
+ (le_not_le_of_lt (Ordinal.typein_lt_self i₂)).2 (csInf_le' hin)
simpa using hnotin
cases' h' with i hi
use to_left_moves_add (Sum.inl i)
mathlib commit https://github.com/leanprover-community/mathlib/commit/bd9851ca476957ea4549eb19b40e7b5ade9428cc
nat_cast
/int_cast
/rat_cast
to natCast
/intCast
/ratCast
(#11486)
Now that I am defining NNRat.cast
, I want a definitive answer to this naming issue. Plenty of lemmas in mathlib already use natCast
/intCast
/ratCast
over nat_cast
/int_cast
/rat_cast
, and this matches with the general expectation that underscore-separated name parts correspond to a single declaration.
@@ -375,25 +375,25 @@ theorem grundyValue_nim_add_nim (n m : ℕ) :
obtain ⟨k, rfl⟩ := Ordinal.lt_omega.1 (hk.trans (Ordinal.nat_lt_omega _))
simp only [add_moveLeft_inl, add_moveLeft_inr, moveLeft_nim', Equiv.symm_apply_apply]
-- The inequality follows from injectivity.
- rw [nat_cast_lt] at hk
+ rw [natCast_lt] at hk
first
| rw [hn _ hk]
| rw [hm _ hk]
refine' fun h => hk.ne _
- rw [Ordinal.nat_cast_inj] at h
+ rw [Ordinal.natCast_inj] at h
first
| rwa [Nat.xor_left_inj] at h
| rwa [Nat.xor_right_inj] at h
-- Every other smaller Grundy value can be reached by left moves.
· -- If `u < m ^^^ n`, then either `u ^^^ n < m` or `u ^^^ m < n`.
obtain ⟨u, rfl⟩ := Ordinal.lt_omega.1 (hu.trans (Ordinal.nat_lt_omega _))
- replace hu := Ordinal.nat_cast_lt.1 hu
+ replace hu := Ordinal.natCast_lt.1 hu
cases' Nat.lt_xor_cases hu with h h
-- In the first case, reducing the `m` pile to `u ^^^ n` gives the desired Grundy value.
- · refine' ⟨toLeftMovesAdd (Sum.inl <| toLeftMovesNim ⟨_, Ordinal.nat_cast_lt.2 h⟩), _⟩
+ · refine' ⟨toLeftMovesAdd (Sum.inl <| toLeftMovesNim ⟨_, Ordinal.natCast_lt.2 h⟩), _⟩
simp [Nat.xor_cancel_right, hn _ h]
-- In the second case, reducing the `n` pile to `u ^^^ m` gives the desired Grundy value.
- · refine' ⟨toLeftMovesAdd (Sum.inr <| toLeftMovesNim ⟨_, Ordinal.nat_cast_lt.2 h⟩), _⟩
+ · refine' ⟨toLeftMovesAdd (Sum.inr <| toLeftMovesNim ⟨_, Ordinal.natCast_lt.2 h⟩), _⟩
have : n ^^^ (u ^^^ n) = u := by rw [Nat.xor_comm u, Nat.xor_cancel_left]
simpa [hm _ h] using this
#align pgame.grundy_value_nim_add_nim SetTheory.PGame.grundyValue_nim_add_nim
Nat.xor_comm
(#11506)
as it conflicts with xor_comm
in the root namespace. Also protect Nat.xor_assoc
in case someone adds xor_assoc
.
@@ -391,7 +391,7 @@ theorem grundyValue_nim_add_nim (n m : ℕ) :
cases' Nat.lt_xor_cases hu with h h
-- In the first case, reducing the `m` pile to `u ^^^ n` gives the desired Grundy value.
· refine' ⟨toLeftMovesAdd (Sum.inl <| toLeftMovesNim ⟨_, Ordinal.nat_cast_lt.2 h⟩), _⟩
- simp [Nat.lxor_cancel_right, hn _ h]
+ simp [Nat.xor_cancel_right, hn _ h]
-- In the second case, reducing the `n` pile to `u ^^^ m` gives the desired Grundy value.
· refine' ⟨toLeftMovesAdd (Sum.inr <| toLeftMovesNim ⟨_, Ordinal.nat_cast_lt.2 h⟩), _⟩
have : n ^^^ (u ^^^ n) = u := by rw [Nat.xor_comm u, Nat.xor_cancel_left]
The termination checker has been getting more capable, and many of the termination_by
or decreasing_by
clauses in Mathlib are no longer needed.
(Note that termination_by?
will show the automatically derived termination expression, so no information is being lost by removing these.)
Co-authored-by: Scott Morrison <scott.morrison@gmail.com>
@@ -261,7 +261,6 @@ theorem nim_equiv_iff_eq {o₁ o₂ : Ordinal} : (nim o₁ ≈ nim o₂) ↔ o
noncomputable def grundyValue : PGame.{u} → Ordinal.{u}
| G => Ordinal.mex.{u, u} fun i => grundyValue (G.moveLeft i)
termination_by G => G
-decreasing_by pgame_wf_tac
#align pgame.grundy_value SetTheory.PGame.grundyValue
theorem grundyValue_eq_mex_left (G : PGame) :
have
, replace
and suffices
(#10640)
No changes to tactic file, it's just boring fixes throughout the library.
This follows on from #6964.
Co-authored-by: sgouezel <sebastien.gouezel@univ-rennes1.fr> Co-authored-by: Eric Wieser <wieser.eric@gmail.com>
@@ -395,7 +395,7 @@ theorem grundyValue_nim_add_nim (n m : ℕ) :
simp [Nat.lxor_cancel_right, hn _ h]
-- In the second case, reducing the `n` pile to `u ^^^ m` gives the desired Grundy value.
· refine' ⟨toLeftMovesAdd (Sum.inr <| toLeftMovesNim ⟨_, Ordinal.nat_cast_lt.2 h⟩), _⟩
- have : n ^^^ (u ^^^ n) = u; rw [Nat.xor_comm u, Nat.xor_cancel_left]
+ have : n ^^^ (u ^^^ n) = u := by rw [Nat.xor_comm u, Nat.xor_cancel_left]
simpa [hm _ h] using this
#align pgame.grundy_value_nim_add_nim SetTheory.PGame.grundyValue_nim_add_nim
Co-authored-by: Scott Morrison <scott.morrison@gmail.com> Co-authored-by: Eric Wieser <wieser.eric@gmail.com> Co-authored-by: Joachim Breitner <mail@joachim-breitner.de>
@@ -51,7 +51,7 @@ noncomputable def nim : Ordinal.{u} → PGame.{u}
have _ : Ordinal.typein o₁.out.r o₂ < o₁ := Ordinal.typein_lt_self o₂
nim (Ordinal.typein o₁.out.r o₂)
⟨o₁.out.α, o₁.out.α, f, f⟩
-termination_by nim o => o
+termination_by o => o
#align pgame.nim SetTheory.PGame.nim
open Ordinal
@@ -260,7 +260,7 @@ theorem nim_equiv_iff_eq {o₁ o₂ : Ordinal} : (nim o₁ ≈ nim o₂) ↔ o
game is equivalent to -/
noncomputable def grundyValue : PGame.{u} → Ordinal.{u}
| G => Ordinal.mex.{u, u} fun i => grundyValue (G.moveLeft i)
-termination_by grundyValue G => G
+termination_by G => G
decreasing_by pgame_wf_tac
#align pgame.grundy_value SetTheory.PGame.grundyValue
@@ -305,8 +305,8 @@ theorem equiv_nim_grundyValue : ∀ (G : PGame.{u}) [G.Impartial], G ≈ nim (gr
rw [add_moveLeft_inl, moveLeft_mk]
apply Equiv.trans (add_congr_left (equiv_nim_grundyValue (G.moveLeft i)))
simpa only [hi] using Impartial.add_self (nim (grundyValue (G.moveLeft i)))
-termination_by equiv_nim_grundyValue G _ => G
-decreasing_by pgame_wf_tac
+termination_by G => G
+decreasing_by all_goals pgame_wf_tac
#align pgame.equiv_nim_grundy_value SetTheory.PGame.equiv_nim_grundyValue
theorem grundyValue_eq_iff_equiv_nim {G : PGame} [G.Impartial] {o : Ordinal} :
@@ -258,7 +258,7 @@ theorem nim_equiv_iff_eq {o₁ o₂ : Ordinal} : (nim o₁ ≈ nim o₂) ↔ o
/-- The Grundy value of an impartial game, the ordinal which corresponds to the game of nim that the
game is equivalent to -/
-noncomputable def grundyValue : ∀ _ : PGame.{u}, Ordinal.{u}
+noncomputable def grundyValue : PGame.{u} → Ordinal.{u}
| G => Ordinal.mex.{u, u} fun i => grundyValue (G.moveLeft i)
termination_by grundyValue G => G
decreasing_by pgame_wf_tac
attribute [simp] ... in
-> attribute [local simp] ... in
(#7678)
Mathlib.Logic.Unique contains the line attribute [simp] eq_iff_true_of_subsingleton in ...
:
Despite what the in
part may imply, this adds the lemma to the simp set "globally", including for downstream files; it is likely that attribute [local simp] eq_iff_true_of_subsingleton in ...
was meant instead (or maybe scoped simp
, but I think "scoped" refers to the current namespace). Indeed, the relevant lemma is not marked with @[simp]
for possible slowness: https://github.com/leanprover/std4/blob/846e9e1d6bb534774d1acd2dc430e70987da3c18/Std/Logic.lean#L749. Adding it to the simp set causes the example at https://leanprover.zulipchat.com/#narrow/stream/287929-mathlib4/topic/Regression.20in.20simp to slow down.
This PR changes this and fixes the relevant downstream simp
s. There was also one ocurrence of attribute [simp] FullSubcategory.comp_def FullSubcategory.id_def in
in Mathlib.CategoryTheory.Monoidal.Subcategory but that was much easier to fix.
@@ -174,12 +174,14 @@ theorem default_nim_one_rightMoves_eq :
@[simp]
theorem toLeftMovesNim_one_symm (i) :
- (@toLeftMovesNim 1).symm i = ⟨0, Set.mem_Iio.mpr zero_lt_one⟩ := by simp
+ (@toLeftMovesNim 1).symm i = ⟨0, Set.mem_Iio.mpr zero_lt_one⟩ := by
+ simp [eq_iff_true_of_subsingleton]
#align pgame.to_left_moves_nim_one_symm SetTheory.PGame.toLeftMovesNim_one_symm
@[simp]
theorem toRightMovesNim_one_symm (i) :
- (@toRightMovesNim 1).symm i = ⟨0, Set.mem_Iio.mpr zero_lt_one⟩ := by simp
+ (@toRightMovesNim 1).symm i = ⟨0, Set.mem_Iio.mpr zero_lt_one⟩ := by
+ simp [eq_iff_true_of_subsingleton]
#align pgame.to_right_moves_nim_one_symm SetTheory.PGame.toRightMovesNim_one_symm
theorem nim_one_moveLeft (x) : (nim 1).moveLeft x = nim 0 := by simp
Nat.land
, Nat.lor
, and Nat.xor
(#7759)
This didn't exist in Lean 3.
@@ -359,17 +359,17 @@ theorem grundyValue_eq_mex_right :
xor. -/
@[simp]
theorem grundyValue_nim_add_nim (n m : ℕ) :
- grundyValue (nim.{u} n + nim.{u} m) = Nat.xor n m := by
+ grundyValue (nim.{u} n + nim.{u} m) = n ^^^ m := by
-- We do strong induction on both variables.
induction' n using Nat.strong_induction_on with n hn generalizing m
induction' m using Nat.strong_induction_on with m hm
rw [grundyValue_eq_mex_left]
refine (Ordinal.mex_le_of_ne.{u, u} fun i => ?_).antisymm
(Ordinal.le_mex_of_forall fun ou hu => ?_)
- -- The Grundy value `Nat.xor n m` can't be reached by left moves.
+ -- The Grundy value `n ^^^ m` can't be reached by left moves.
· apply leftMoves_add_cases i <;>
- · -- A left move leaves us with a Grundy value of `Nat.xor k m` for `k < n`, or
- -- `Nat.xor n k` for `k < m`.
+ · -- A left move leaves us with a Grundy value of `k ^^^ m` for `k < n`, or
+ -- `n ^^^ k` for `k < m`.
refine' fun a => leftMovesNimRecOn a fun ok hk => _
obtain ⟨k, rfl⟩ := Ordinal.lt_omega.1 (hk.trans (Ordinal.nat_lt_omega _))
simp only [add_moveLeft_inl, add_moveLeft_inr, moveLeft_nim', Equiv.symm_apply_apply]
@@ -384,26 +384,26 @@ theorem grundyValue_nim_add_nim (n m : ℕ) :
| rwa [Nat.xor_left_inj] at h
| rwa [Nat.xor_right_inj] at h
-- Every other smaller Grundy value can be reached by left moves.
- · -- If `u < Nat.xor m n`, then either `Nat.xor u n < m` or `Nat.xor u m < n`.
+ · -- If `u < m ^^^ n`, then either `u ^^^ n < m` or `u ^^^ m < n`.
obtain ⟨u, rfl⟩ := Ordinal.lt_omega.1 (hu.trans (Ordinal.nat_lt_omega _))
replace hu := Ordinal.nat_cast_lt.1 hu
cases' Nat.lt_xor_cases hu with h h
- -- In the first case, reducing the `m` pile to `Nat.xor u n` gives the desired Grundy value.
+ -- In the first case, reducing the `m` pile to `u ^^^ n` gives the desired Grundy value.
· refine' ⟨toLeftMovesAdd (Sum.inl <| toLeftMovesNim ⟨_, Ordinal.nat_cast_lt.2 h⟩), _⟩
simp [Nat.lxor_cancel_right, hn _ h]
- -- In the second case, reducing the `n` pile to `Nat.xor u m` gives the desired Grundy value.
+ -- In the second case, reducing the `n` pile to `u ^^^ m` gives the desired Grundy value.
· refine' ⟨toLeftMovesAdd (Sum.inr <| toLeftMovesNim ⟨_, Ordinal.nat_cast_lt.2 h⟩), _⟩
- have : n.xor (u.xor n) = u; rw [Nat.xor_comm u, Nat.xor_cancel_left]
+ have : n ^^^ (u ^^^ n) = u; rw [Nat.xor_comm u, Nat.xor_cancel_left]
simpa [hm _ h] using this
#align pgame.grundy_value_nim_add_nim SetTheory.PGame.grundyValue_nim_add_nim
-theorem nim_add_nim_equiv {n m : ℕ} : nim n + nim m ≈ nim (Nat.xor n m) := by
+theorem nim_add_nim_equiv {n m : ℕ} : nim n + nim m ≈ nim (n ^^^ m) := by
rw [← grundyValue_eq_iff_equiv_nim, grundyValue_nim_add_nim]
#align pgame.nim_add_nim_equiv SetTheory.PGame.nim_add_nim_equiv
theorem grundyValue_add (G H : PGame) [G.Impartial] [H.Impartial] {n m : ℕ} (hG : grundyValue G = n)
- (hH : grundyValue H = m) : grundyValue (G + H) = Nat.xor n m := by
- rw [← nim_grundyValue (Nat.xor n m), grundyValue_eq_iff_equiv]
+ (hH : grundyValue H = m) : grundyValue (G + H) = n ^^^ m := by
+ rw [← nim_grundyValue (n ^^^ m), grundyValue_eq_iff_equiv]
refine' Equiv.trans _ nim_add_nim_equiv
convert add_congr (equiv_nim_grundyValue G) (equiv_nim_grundyValue H) <;> simp only [hG, hH]
#align pgame.grundy_value_add SetTheory.PGame.grundyValue_add
Nat.bitwise'
(#7451)
Building upon the proof that Nat.bitwise
and Nat.bitwise'
are equal (from #7410), this PR completely removes bitwise'
and changes all uses to bitwise
instead.
In particular, land'/lor'/lxor'
are replaced with the bitwise
-based equivalent operations in core, which have overriden optimized implementations in the compiler.
Co-authored-by: Eric Wieser <wieser.eric@gmail.com> Co-authored-by: Alex Keizer <alex@keizer.dev> Co-authored-by: Chris Hughes <chrishughes24@gmail.com>
@@ -354,22 +354,22 @@ theorem grundyValue_eq_mex_right :
#align pgame.grundy_value_eq_mex_right SetTheory.PGame.grundyValue_eq_mex_right
-- Todo: this actually generalizes to all ordinals, by defining `Ordinal.lxor` as the pairwise
--- `Nat.lxor'` of base `ω` Cantor normal forms.
+-- `Nat.xor` of base `ω` Cantor normal forms.
/-- The Grundy value of the sum of two nim games with natural numbers of piles equals their bitwise
xor. -/
@[simp]
theorem grundyValue_nim_add_nim (n m : ℕ) :
- grundyValue (nim.{u} n + nim.{u} m) = Nat.lxor' n m := by
+ grundyValue (nim.{u} n + nim.{u} m) = Nat.xor n m := by
-- We do strong induction on both variables.
induction' n using Nat.strong_induction_on with n hn generalizing m
induction' m using Nat.strong_induction_on with m hm
rw [grundyValue_eq_mex_left]
refine (Ordinal.mex_le_of_ne.{u, u} fun i => ?_).antisymm
(Ordinal.le_mex_of_forall fun ou hu => ?_)
- -- The Grundy value `Nat.lxor' n m` can't be reached by left moves.
+ -- The Grundy value `Nat.xor n m` can't be reached by left moves.
· apply leftMoves_add_cases i <;>
- · -- A left move leaves us with a Grundy value of `Nat.lxor' k m` for `k < n`, or
- -- `Nat.lxor' n k` for `k < m`.
+ · -- A left move leaves us with a Grundy value of `Nat.xor k m` for `k < n`, or
+ -- `Nat.xor n k` for `k < m`.
refine' fun a => leftMovesNimRecOn a fun ok hk => _
obtain ⟨k, rfl⟩ := Ordinal.lt_omega.1 (hk.trans (Ordinal.nat_lt_omega _))
simp only [add_moveLeft_inl, add_moveLeft_inr, moveLeft_nim', Equiv.symm_apply_apply]
@@ -381,29 +381,29 @@ theorem grundyValue_nim_add_nim (n m : ℕ) :
refine' fun h => hk.ne _
rw [Ordinal.nat_cast_inj] at h
first
- | rwa [Nat.lxor'_left_inj] at h
- | rwa [Nat.lxor'_right_inj] at h
+ | rwa [Nat.xor_left_inj] at h
+ | rwa [Nat.xor_right_inj] at h
-- Every other smaller Grundy value can be reached by left moves.
- · -- If `u < Nat.lxor' m n`, then either `Nat.lxor' u n < m` or `Nat.lxor' u m < n`.
+ · -- If `u < Nat.xor m n`, then either `Nat.xor u n < m` or `Nat.xor u m < n`.
obtain ⟨u, rfl⟩ := Ordinal.lt_omega.1 (hu.trans (Ordinal.nat_lt_omega _))
replace hu := Ordinal.nat_cast_lt.1 hu
- cases' Nat.lt_lxor'_cases hu with h h
- -- In the first case, reducing the `m` pile to `Nat.lxor' u n` gives the desired Grundy value.
+ cases' Nat.lt_xor_cases hu with h h
+ -- In the first case, reducing the `m` pile to `Nat.xor u n` gives the desired Grundy value.
· refine' ⟨toLeftMovesAdd (Sum.inl <| toLeftMovesNim ⟨_, Ordinal.nat_cast_lt.2 h⟩), _⟩
simp [Nat.lxor_cancel_right, hn _ h]
- -- In the second case, reducing the `n` pile to `Nat.lxor' u m` gives the desired Grundy value.
+ -- In the second case, reducing the `n` pile to `Nat.xor u m` gives the desired Grundy value.
· refine' ⟨toLeftMovesAdd (Sum.inr <| toLeftMovesNim ⟨_, Ordinal.nat_cast_lt.2 h⟩), _⟩
- have : n.lxor' (u.lxor' n) = u; rw [Nat.lxor'_comm u, Nat.lxor'_cancel_left]
+ have : n.xor (u.xor n) = u; rw [Nat.xor_comm u, Nat.xor_cancel_left]
simpa [hm _ h] using this
#align pgame.grundy_value_nim_add_nim SetTheory.PGame.grundyValue_nim_add_nim
-theorem nim_add_nim_equiv {n m : ℕ} : nim n + nim m ≈ nim (Nat.lxor' n m) := by
+theorem nim_add_nim_equiv {n m : ℕ} : nim n + nim m ≈ nim (Nat.xor n m) := by
rw [← grundyValue_eq_iff_equiv_nim, grundyValue_nim_add_nim]
#align pgame.nim_add_nim_equiv SetTheory.PGame.nim_add_nim_equiv
theorem grundyValue_add (G H : PGame) [G.Impartial] [H.Impartial] {n m : ℕ} (hG : grundyValue G = n)
- (hH : grundyValue H = m) : grundyValue (G + H) = Nat.lxor' n m := by
- rw [← nim_grundyValue (Nat.lxor' n m), grundyValue_eq_iff_equiv]
+ (hH : grundyValue H = m) : grundyValue (G + H) = Nat.xor n m := by
+ rw [← nim_grundyValue (Nat.xor n m), grundyValue_eq_iff_equiv]
refine' Equiv.trans _ nim_add_nim_equiv
convert add_congr (equiv_nim_grundyValue G) (equiv_nim_grundyValue H) <;> simp only [hG, hH]
#align pgame.grundy_value_add SetTheory.PGame.grundyValue_add
Game
to SetTheory.Game
(#6365)
move Game
and PGame
into namespace SetTheory
as _root_.Game
might collide with other definitions (e.g. in projects depending on mathlib)
@@ -23,8 +23,9 @@ where `n` and `m` are natural numbers, then `G + H` has the Grundy value `n xor
The pen-and-paper definition of nim defines the possible moves of `nim o` to be `Set.Iio o`.
However, this definition does not work for us because it would make the type of nim
-`ordinal.{u} → pgame.{u + 1}`, which would make it impossible for us to state the Sprague-Grundy
-theorem, since that requires the type of `nim` to be `ordinal.{u} → pgame.{u}`. For this reason, we
+`Ordinal.{u} → SetTheory.PGame.{u + 1}`, which would make it impossible for us to state the
+Sprague-Grundy theorem, since that requires the type of `nim` to be
+`Ordinal.{u} → SetTheory.PGame.{u}`. For this reason, we
instead use `o.out.α` for the possible moves. You can use `to_left_moves_nim` and
`to_right_moves_nim` to convert an ordinal less than `o` into a left or right move of `nim o`, and
vice versa.
@@ -35,6 +36,8 @@ noncomputable section
universe u
+namespace SetTheory
+
open scoped PGame
namespace PGame
@@ -49,7 +52,7 @@ noncomputable def nim : Ordinal.{u} → PGame.{u}
nim (Ordinal.typein o₁.out.r o₂)
⟨o₁.out.α, o₁.out.α, f, f⟩
termination_by nim o => o
-#align pgame.nim PGame.nim
+#align pgame.nim SetTheory.PGame.nim
open Ordinal
@@ -59,131 +62,131 @@ theorem nim_def (o : Ordinal) :
PGame.mk o.out.α o.out.α (fun o₂ => nim (Ordinal.typein (· < ·) o₂)) fun o₂ =>
nim (Ordinal.typein (· < ·) o₂) := by
rw [nim]; rfl
-#align pgame.nim_def PGame.nim_def
+#align pgame.nim_def SetTheory.PGame.nim_def
theorem leftMoves_nim (o : Ordinal) : (nim o).LeftMoves = o.out.α := by rw [nim_def]; rfl
-#align pgame.left_moves_nim PGame.leftMoves_nim
+#align pgame.left_moves_nim SetTheory.PGame.leftMoves_nim
theorem rightMoves_nim (o : Ordinal) : (nim o).RightMoves = o.out.α := by rw [nim_def]; rfl
-#align pgame.right_moves_nim PGame.rightMoves_nim
+#align pgame.right_moves_nim SetTheory.PGame.rightMoves_nim
theorem moveLeft_nim_hEq (o : Ordinal) :
have : IsWellOrder (Quotient.out o).α (· < ·) := inferInstance
HEq (nim o).moveLeft fun i : o.out.α => nim (typein (· < ·) i) := by rw [nim_def]; rfl
-#align pgame.move_left_nim_heq PGame.moveLeft_nim_hEq
+#align pgame.move_left_nim_heq SetTheory.PGame.moveLeft_nim_hEq
theorem moveRight_nim_hEq (o : Ordinal) :
have : IsWellOrder (Quotient.out o).α (· < ·) := inferInstance
HEq (nim o).moveRight fun i : o.out.α => nim (typein (· < ·) i) := by rw [nim_def]; rfl
-#align pgame.move_right_nim_heq PGame.moveRight_nim_hEq
+#align pgame.move_right_nim_heq SetTheory.PGame.moveRight_nim_hEq
/-- Turns an ordinal less than `o` into a left move for `nim o` and viceversa. -/
noncomputable def toLeftMovesNim {o : Ordinal} : Set.Iio o ≃ (nim o).LeftMoves :=
(enumIsoOut o).toEquiv.trans (Equiv.cast (leftMoves_nim o).symm)
-#align pgame.to_left_moves_nim PGame.toLeftMovesNim
+#align pgame.to_left_moves_nim SetTheory.PGame.toLeftMovesNim
/-- Turns an ordinal less than `o` into a right move for `nim o` and viceversa. -/
noncomputable def toRightMovesNim {o : Ordinal} : Set.Iio o ≃ (nim o).RightMoves :=
(enumIsoOut o).toEquiv.trans (Equiv.cast (rightMoves_nim o).symm)
-#align pgame.to_right_moves_nim PGame.toRightMovesNim
+#align pgame.to_right_moves_nim SetTheory.PGame.toRightMovesNim
@[simp]
theorem toLeftMovesNim_symm_lt {o : Ordinal} (i : (nim o).LeftMoves) :
↑(toLeftMovesNim.symm i) < o :=
(toLeftMovesNim.symm i).prop
-#align pgame.to_left_moves_nim_symm_lt PGame.toLeftMovesNim_symm_lt
+#align pgame.to_left_moves_nim_symm_lt SetTheory.PGame.toLeftMovesNim_symm_lt
@[simp]
theorem toRightMovesNim_symm_lt {o : Ordinal} (i : (nim o).RightMoves) :
↑(toRightMovesNim.symm i) < o :=
(toRightMovesNim.symm i).prop
-#align pgame.to_right_moves_nim_symm_lt PGame.toRightMovesNim_symm_lt
+#align pgame.to_right_moves_nim_symm_lt SetTheory.PGame.toRightMovesNim_symm_lt
@[simp]
theorem moveLeft_nim' {o : Ordinal.{u}} (i) :
(nim o).moveLeft i = nim (toLeftMovesNim.symm i).val :=
(congr_heq (moveLeft_nim_hEq o).symm (cast_heq _ i)).symm
-#align pgame.move_left_nim' PGame.moveLeft_nim'
+#align pgame.move_left_nim' SetTheory.PGame.moveLeft_nim'
theorem moveLeft_nim {o : Ordinal} (i) : (nim o).moveLeft (toLeftMovesNim i) = nim i := by simp
-#align pgame.move_left_nim PGame.moveLeft_nim
+#align pgame.move_left_nim SetTheory.PGame.moveLeft_nim
@[simp]
theorem moveRight_nim' {o : Ordinal} (i) : (nim o).moveRight i = nim (toRightMovesNim.symm i).val :=
(congr_heq (moveRight_nim_hEq o).symm (cast_heq _ i)).symm
-#align pgame.move_right_nim' PGame.moveRight_nim'
+#align pgame.move_right_nim' SetTheory.PGame.moveRight_nim'
theorem moveRight_nim {o : Ordinal} (i) : (nim o).moveRight (toRightMovesNim i) = nim i := by simp
-#align pgame.move_right_nim PGame.moveRight_nim
+#align pgame.move_right_nim SetTheory.PGame.moveRight_nim
/-- A recursion principle for left moves of a nim game. -/
@[elab_as_elim]
def leftMovesNimRecOn {o : Ordinal} {P : (nim o).LeftMoves → Sort*} (i : (nim o).LeftMoves)
(H : ∀ a (H : a < o), P <| toLeftMovesNim ⟨a, H⟩) : P i := by
rw [← toLeftMovesNim.apply_symm_apply i]; apply H
-#align pgame.left_moves_nim_rec_on PGame.leftMovesNimRecOn
+#align pgame.left_moves_nim_rec_on SetTheory.PGame.leftMovesNimRecOn
/-- A recursion principle for right moves of a nim game. -/
@[elab_as_elim]
def rightMovesNimRecOn {o : Ordinal} {P : (nim o).RightMoves → Sort*} (i : (nim o).RightMoves)
(H : ∀ a (H : a < o), P <| toRightMovesNim ⟨a, H⟩) : P i := by
rw [← toRightMovesNim.apply_symm_apply i]; apply H
-#align pgame.right_moves_nim_rec_on PGame.rightMovesNimRecOn
+#align pgame.right_moves_nim_rec_on SetTheory.PGame.rightMovesNimRecOn
instance isEmpty_nim_zero_leftMoves : IsEmpty (nim 0).LeftMoves := by
rw [nim_def]
exact Ordinal.isEmpty_out_zero
-#align pgame.is_empty_nim_zero_left_moves PGame.isEmpty_nim_zero_leftMoves
+#align pgame.is_empty_nim_zero_left_moves SetTheory.PGame.isEmpty_nim_zero_leftMoves
instance isEmpty_nim_zero_rightMoves : IsEmpty (nim 0).RightMoves := by
rw [nim_def]
exact Ordinal.isEmpty_out_zero
-#align pgame.is_empty_nim_zero_right_moves PGame.isEmpty_nim_zero_rightMoves
+#align pgame.is_empty_nim_zero_right_moves SetTheory.PGame.isEmpty_nim_zero_rightMoves
/-- `nim 0` has exactly the same moves as `0`. -/
def nimZeroRelabelling : nim 0 ≡r 0 :=
Relabelling.isEmpty _
-#align pgame.nim_zero_relabelling PGame.nimZeroRelabelling
+#align pgame.nim_zero_relabelling SetTheory.PGame.nimZeroRelabelling
theorem nim_zero_equiv : nim 0 ≈ 0 :=
Equiv.isEmpty _
-#align pgame.nim_zero_equiv PGame.nim_zero_equiv
+#align pgame.nim_zero_equiv SetTheory.PGame.nim_zero_equiv
noncomputable instance uniqueNimOneLeftMoves : Unique (nim 1).LeftMoves :=
(Equiv.cast <| leftMoves_nim 1).unique
-#align pgame.unique_nim_one_left_moves PGame.uniqueNimOneLeftMoves
+#align pgame.unique_nim_one_left_moves SetTheory.PGame.uniqueNimOneLeftMoves
noncomputable instance uniqueNimOneRightMoves : Unique (nim 1).RightMoves :=
(Equiv.cast <| rightMoves_nim 1).unique
-#align pgame.unique_nim_one_right_moves PGame.uniqueNimOneRightMoves
+#align pgame.unique_nim_one_right_moves SetTheory.PGame.uniqueNimOneRightMoves
@[simp]
theorem default_nim_one_leftMoves_eq :
(default : (nim 1).LeftMoves) = @toLeftMovesNim 1 ⟨0, Set.mem_Iio.mpr zero_lt_one⟩ :=
rfl
-#align pgame.default_nim_one_left_moves_eq PGame.default_nim_one_leftMoves_eq
+#align pgame.default_nim_one_left_moves_eq SetTheory.PGame.default_nim_one_leftMoves_eq
@[simp]
theorem default_nim_one_rightMoves_eq :
(default : (nim 1).RightMoves) = @toRightMovesNim 1 ⟨0, Set.mem_Iio.mpr zero_lt_one⟩ :=
rfl
-#align pgame.default_nim_one_right_moves_eq PGame.default_nim_one_rightMoves_eq
+#align pgame.default_nim_one_right_moves_eq SetTheory.PGame.default_nim_one_rightMoves_eq
@[simp]
theorem toLeftMovesNim_one_symm (i) :
(@toLeftMovesNim 1).symm i = ⟨0, Set.mem_Iio.mpr zero_lt_one⟩ := by simp
-#align pgame.to_left_moves_nim_one_symm PGame.toLeftMovesNim_one_symm
+#align pgame.to_left_moves_nim_one_symm SetTheory.PGame.toLeftMovesNim_one_symm
@[simp]
theorem toRightMovesNim_one_symm (i) :
(@toRightMovesNim 1).symm i = ⟨0, Set.mem_Iio.mpr zero_lt_one⟩ := by simp
-#align pgame.to_right_moves_nim_one_symm PGame.toRightMovesNim_one_symm
+#align pgame.to_right_moves_nim_one_symm SetTheory.PGame.toRightMovesNim_one_symm
theorem nim_one_moveLeft (x) : (nim 1).moveLeft x = nim 0 := by simp
-#align pgame.nim_one_move_left PGame.nim_one_moveLeft
+#align pgame.nim_one_move_left SetTheory.PGame.nim_one_moveLeft
theorem nim_one_moveRight (x) : (nim 1).moveRight x = nim 0 := by simp
-#align pgame.nim_one_move_right PGame.nim_one_moveRight
+#align pgame.nim_one_move_right SetTheory.PGame.nim_one_moveRight
/-- `nim 1` has exactly the same moves as `star`. -/
def nimOneRelabelling : nim 1 ≡r star := by
@@ -191,11 +194,11 @@ def nimOneRelabelling : nim 1 ≡r star := by
refine' ⟨_, _, fun i => _, fun j => _⟩
any_goals dsimp; apply Equiv.equivOfUnique
all_goals simp; exact nimZeroRelabelling
-#align pgame.nim_one_relabelling PGame.nimOneRelabelling
+#align pgame.nim_one_relabelling SetTheory.PGame.nimOneRelabelling
theorem nim_one_equiv : nim 1 ≈ star :=
nimOneRelabelling.equiv
-#align pgame.nim_one_equiv PGame.nim_one_equiv
+#align pgame.nim_one_equiv SetTheory.PGame.nim_one_equiv
@[simp]
theorem nim_birthday (o : Ordinal) : (nim o).birthday = o := by
@@ -205,25 +208,25 @@ theorem nim_birthday (o : Ordinal) : (nim o).birthday = o := by
rw [max_eq_right le_rfl]
convert lsub_typein o with i
exact IH _ (typein_lt_self i)
-#align pgame.nim_birthday PGame.nim_birthday
+#align pgame.nim_birthday SetTheory.PGame.nim_birthday
@[simp]
theorem neg_nim (o : Ordinal) : -nim o = nim o := by
induction' o using Ordinal.induction with o IH
rw [nim_def]; dsimp; congr <;> funext i <;> exact IH _ (Ordinal.typein_lt_self i)
-#align pgame.neg_nim PGame.neg_nim
+#align pgame.neg_nim SetTheory.PGame.neg_nim
instance nim_impartial (o : Ordinal) : Impartial (nim o) := by
induction' o using Ordinal.induction with o IH
rw [impartial_def, neg_nim]
refine' ⟨equiv_rfl, fun i => _, fun i => _⟩ <;> simpa using IH _ (typein_lt_self _)
-#align pgame.nim_impartial PGame.nim_impartial
+#align pgame.nim_impartial SetTheory.PGame.nim_impartial
theorem nim_fuzzy_zero_of_ne_zero {o : Ordinal} (ho : o ≠ 0) : nim o ‖ 0 := by
rw [Impartial.fuzzy_zero_iff_lf, nim_def, lf_zero_le]
rw [← Ordinal.pos_iff_ne_zero] at ho
exact ⟨(Ordinal.principalSegOut ho).top, by simp⟩
-#align pgame.nim_fuzzy_zero_of_ne_zero PGame.nim_fuzzy_zero_of_ne_zero
+#align pgame.nim_fuzzy_zero_of_ne_zero SetTheory.PGame.nim_fuzzy_zero_of_ne_zero
@[simp]
theorem nim_add_equiv_zero_iff (o₁ o₂ : Ordinal) : (nim o₁ + nim o₂ ≈ 0) ↔ o₁ = o₂ := by
@@ -239,17 +242,17 @@ theorem nim_add_equiv_zero_iff (o₁ o₂ : Ordinal) : (nim o₁ + nim o₂ ≈
using (Impartial.add_self (nim o₁)).2
· rintro rfl
exact Impartial.add_self (nim o₁)
-#align pgame.nim_add_equiv_zero_iff PGame.nim_add_equiv_zero_iff
+#align pgame.nim_add_equiv_zero_iff SetTheory.PGame.nim_add_equiv_zero_iff
@[simp]
theorem nim_add_fuzzy_zero_iff {o₁ o₂ : Ordinal} : nim o₁ + nim o₂ ‖ 0 ↔ o₁ ≠ o₂ := by
rw [iff_not_comm, Impartial.not_fuzzy_zero_iff, nim_add_equiv_zero_iff]
-#align pgame.nim_add_fuzzy_zero_iff PGame.nim_add_fuzzy_zero_iff
+#align pgame.nim_add_fuzzy_zero_iff SetTheory.PGame.nim_add_fuzzy_zero_iff
@[simp]
theorem nim_equiv_iff_eq {o₁ o₂ : Ordinal} : (nim o₁ ≈ nim o₂) ↔ o₁ = o₂ := by
rw [Impartial.equiv_iff_add_equiv_zero, nim_add_equiv_zero_iff]
-#align pgame.nim_equiv_iff_eq PGame.nim_equiv_iff_eq
+#align pgame.nim_equiv_iff_eq SetTheory.PGame.nim_equiv_iff_eq
/-- The Grundy value of an impartial game, the ordinal which corresponds to the game of nim that the
game is equivalent to -/
@@ -257,11 +260,11 @@ noncomputable def grundyValue : ∀ _ : PGame.{u}, Ordinal.{u}
| G => Ordinal.mex.{u, u} fun i => grundyValue (G.moveLeft i)
termination_by grundyValue G => G
decreasing_by pgame_wf_tac
-#align pgame.grundy_value PGame.grundyValue
+#align pgame.grundy_value SetTheory.PGame.grundyValue
theorem grundyValue_eq_mex_left (G : PGame) :
grundyValue G = Ordinal.mex.{u, u} fun i => grundyValue (G.moveLeft i) := by rw [grundyValue]
-#align pgame.grundy_value_eq_mex_left PGame.grundyValue_eq_mex_left
+#align pgame.grundy_value_eq_mex_left SetTheory.PGame.grundyValue_eq_mex_left
/-- The Sprague-Grundy theorem which states that every impartial game is equivalent to a game of
nim, namely the game of nim corresponding to the games Grundy value -/
@@ -302,42 +305,42 @@ theorem equiv_nim_grundyValue : ∀ (G : PGame.{u}) [G.Impartial], G ≈ nim (gr
simpa only [hi] using Impartial.add_self (nim (grundyValue (G.moveLeft i)))
termination_by equiv_nim_grundyValue G _ => G
decreasing_by pgame_wf_tac
-#align pgame.equiv_nim_grundy_value PGame.equiv_nim_grundyValue
+#align pgame.equiv_nim_grundy_value SetTheory.PGame.equiv_nim_grundyValue
theorem grundyValue_eq_iff_equiv_nim {G : PGame} [G.Impartial] {o : Ordinal} :
grundyValue G = o ↔ (G ≈ nim o) :=
⟨by rintro rfl; exact equiv_nim_grundyValue G,
by intro h; rw [← nim_equiv_iff_eq]; exact Equiv.trans (Equiv.symm (equiv_nim_grundyValue G)) h⟩
-#align pgame.grundy_value_eq_iff_equiv_nim PGame.grundyValue_eq_iff_equiv_nim
+#align pgame.grundy_value_eq_iff_equiv_nim SetTheory.PGame.grundyValue_eq_iff_equiv_nim
@[simp]
theorem nim_grundyValue (o : Ordinal.{u}) : grundyValue (nim o) = o :=
grundyValue_eq_iff_equiv_nim.2 PGame.equiv_rfl
-#align pgame.nim_grundy_value PGame.nim_grundyValue
+#align pgame.nim_grundy_value SetTheory.PGame.nim_grundyValue
theorem grundyValue_eq_iff_equiv (G H : PGame) [G.Impartial] [H.Impartial] :
grundyValue G = grundyValue H ↔ (G ≈ H) :=
grundyValue_eq_iff_equiv_nim.trans (equiv_congr_left.1 (equiv_nim_grundyValue H) _).symm
-#align pgame.grundy_value_eq_iff_equiv PGame.grundyValue_eq_iff_equiv
+#align pgame.grundy_value_eq_iff_equiv SetTheory.PGame.grundyValue_eq_iff_equiv
@[simp]
theorem grundyValue_zero : grundyValue 0 = 0 :=
grundyValue_eq_iff_equiv_nim.2 (Equiv.symm nim_zero_equiv)
-#align pgame.grundy_value_zero PGame.grundyValue_zero
+#align pgame.grundy_value_zero SetTheory.PGame.grundyValue_zero
theorem grundyValue_iff_equiv_zero (G : PGame) [G.Impartial] : grundyValue G = 0 ↔ (G ≈ 0) := by
rw [← grundyValue_eq_iff_equiv, grundyValue_zero]
-#align pgame.grundy_value_iff_equiv_zero PGame.grundyValue_iff_equiv_zero
+#align pgame.grundy_value_iff_equiv_zero SetTheory.PGame.grundyValue_iff_equiv_zero
@[simp]
theorem grundyValue_star : grundyValue star = 1 :=
grundyValue_eq_iff_equiv_nim.2 (Equiv.symm nim_one_equiv)
-#align pgame.grundy_value_star PGame.grundyValue_star
+#align pgame.grundy_value_star SetTheory.PGame.grundyValue_star
@[simp]
theorem grundyValue_neg (G : PGame) [G.Impartial] : grundyValue (-G) = grundyValue G := by
rw [grundyValue_eq_iff_equiv_nim, neg_equiv_iff, neg_nim, ← grundyValue_eq_iff_equiv_nim]
-#align pgame.grundy_value_neg PGame.grundyValue_neg
+#align pgame.grundy_value_neg SetTheory.PGame.grundyValue_neg
theorem grundyValue_eq_mex_right :
∀ (G : PGame) [G.Impartial],
@@ -348,7 +351,7 @@ theorem grundyValue_eq_mex_right :
ext i
haveI : (R i).Impartial := @Impartial.moveRight_impartial ⟨l, r, L, R⟩ _ i
apply grundyValue_neg
-#align pgame.grundy_value_eq_mex_right PGame.grundyValue_eq_mex_right
+#align pgame.grundy_value_eq_mex_right SetTheory.PGame.grundyValue_eq_mex_right
-- Todo: this actually generalizes to all ordinals, by defining `Ordinal.lxor` as the pairwise
-- `Nat.lxor'` of base `ω` Cantor normal forms.
@@ -392,17 +395,17 @@ theorem grundyValue_nim_add_nim (n m : ℕ) :
· refine' ⟨toLeftMovesAdd (Sum.inr <| toLeftMovesNim ⟨_, Ordinal.nat_cast_lt.2 h⟩), _⟩
have : n.lxor' (u.lxor' n) = u; rw [Nat.lxor'_comm u, Nat.lxor'_cancel_left]
simpa [hm _ h] using this
-#align pgame.grundy_value_nim_add_nim PGame.grundyValue_nim_add_nim
+#align pgame.grundy_value_nim_add_nim SetTheory.PGame.grundyValue_nim_add_nim
theorem nim_add_nim_equiv {n m : ℕ} : nim n + nim m ≈ nim (Nat.lxor' n m) := by
rw [← grundyValue_eq_iff_equiv_nim, grundyValue_nim_add_nim]
-#align pgame.nim_add_nim_equiv PGame.nim_add_nim_equiv
+#align pgame.nim_add_nim_equiv SetTheory.PGame.nim_add_nim_equiv
theorem grundyValue_add (G H : PGame) [G.Impartial] [H.Impartial] {n m : ℕ} (hG : grundyValue G = n)
(hH : grundyValue H = m) : grundyValue (G + H) = Nat.lxor' n m := by
rw [← nim_grundyValue (Nat.lxor' n m), grundyValue_eq_iff_equiv]
refine' Equiv.trans _ nim_add_nim_equiv
convert add_congr (equiv_nim_grundyValue G) (equiv_nim_grundyValue H) <;> simp only [hG, hH]
-#align pgame.grundy_value_add PGame.grundyValue_add
+#align pgame.grundy_value_add SetTheory.PGame.grundyValue_add
end PGame
Type _
and Sort _
(#6499)
We remove all possible occurences of Type _
and Sort _
in favor of Type*
and Sort*
.
This has nice performance benefits.
@@ -118,14 +118,14 @@ theorem moveRight_nim {o : Ordinal} (i) : (nim o).moveRight (toRightMovesNim i)
/-- A recursion principle for left moves of a nim game. -/
@[elab_as_elim]
-def leftMovesNimRecOn {o : Ordinal} {P : (nim o).LeftMoves → Sort _} (i : (nim o).LeftMoves)
+def leftMovesNimRecOn {o : Ordinal} {P : (nim o).LeftMoves → Sort*} (i : (nim o).LeftMoves)
(H : ∀ a (H : a < o), P <| toLeftMovesNim ⟨a, H⟩) : P i := by
rw [← toLeftMovesNim.apply_symm_apply i]; apply H
#align pgame.left_moves_nim_rec_on PGame.leftMovesNimRecOn
/-- A recursion principle for right moves of a nim game. -/
@[elab_as_elim]
-def rightMovesNimRecOn {o : Ordinal} {P : (nim o).RightMoves → Sort _} (i : (nim o).RightMoves)
+def rightMovesNimRecOn {o : Ordinal} {P : (nim o).RightMoves → Sort*} (i : (nim o).RightMoves)
(H : ∀ a (H : a < o), P <| toRightMovesNim ⟨a, H⟩) : P i := by
rw [← toRightMovesNim.apply_symm_apply i]; apply H
#align pgame.right_moves_nim_rec_on PGame.rightMovesNimRecOn
@@ -2,16 +2,13 @@
Copyright (c) 2020 Fox Thomson. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Fox Thomson, Markus Himmel
-
-! This file was ported from Lean 3 source module set_theory.game.nim
-! leanprover-community/mathlib commit 92ca63f0fb391a9ca5f22d2409a6080e786d99f7
-! Please do not edit these lines, except to modify the commit id
-! if you have ported upstream changes.
-/
import Mathlib.Data.Nat.Bitwise
import Mathlib.SetTheory.Game.Birthday
import Mathlib.SetTheory.Game.Impartial
+#align_import set_theory.game.nim from "leanprover-community/mathlib"@"92ca63f0fb391a9ca5f22d2409a6080e786d99f7"
+
/-!
# Nim and the Sprague-Grundy theorem
The unported dependencies are