Documentation

Mathlib.SetTheory.PGame.Basic

Combinatorial pregames #

This is the first in a series of files developing the basic theory of combinatorial games, following Conway's book "On Numbers and Games":

The surreal numbers will be built as a quotient of a subtype of pregames.

A pregame (SetTheory.PGame below) is axiomatised via an inductive type, whose sole constructor takes two types (thought of as indexing the possible moves for the players Left and Right), and a pair of functions out of these types to SetTheory.PGame (thought of as describing the resulting game after making a move).

We may denote a game as {L|R}, where L and R stand for the collections of left and right moves. This notation is not currently used in Mathlib.

Conway induction #

By construction, the induction principle for pregames is exactly "Conway induction". That is, to prove some predicate SetTheory.PGame → Prop holds for all pregames, it suffices to prove that for every pregame g, if the predicate holds for every game resulting from making a move, then it also holds for g.

While it is often convenient to work "by induction" on pregames, in some situations this becomes awkward, so we also define accessor functions SetTheory.PGame.LeftMoves, SetTheory.PGame.RightMoves, SetTheory.PGame.moveLeft and SetTheory.PGame.moveRight. There is a relation PGame.Subsequent p q, saying that p can be reached by playing some non-empty sequence of moves starting from q, an instance WellFounded Subsequent, and a local tactic pgame_wf_tac which is helpful for discharging proof obligations in inductive proofs relying on this relation.

Future work #

References #

The material here is all drawn from

An interested reader may like to formalise some of the material from

Pre-game moves #

inductive SetTheory.PGame :
Type (u + 1)

The type of pre-games, before we have quotiented by equivalence (PGame.setoid). In ZFC, a combinatorial game is constructed from two sets of combinatorial games that have been constructed at an earlier stage. To do this in type theory, we say that a pre-game is built inductively from two families of pre-games indexed over any type in Type u. The resulting type PGame.{u} lives in Type (u+1), reflecting that it is a proper class in ZFC.

The indexing type for allowable moves by Left.

Equations

The indexing type for allowable moves by Right.

Equations

The new game after Left makes an allowed move.

Equations

The new game after Right makes an allowed move.

Equations
@[simp]
theorem SetTheory.PGame.leftMoves_mk {xl xr : Type u_1} {xL : xlPGame} {xR : xrPGame} :
(mk xl xr xL xR).LeftMoves = xl
@[simp]
theorem SetTheory.PGame.moveLeft_mk {xl xr : Type u_1} {xL : xlPGame} {xR : xrPGame} :
(mk xl xr xL xR).moveLeft = xL
@[simp]
theorem SetTheory.PGame.rightMoves_mk {xl xr : Type u_1} {xL : xlPGame} {xR : xrPGame} :
(mk xl xr xL xR).RightMoves = xr
@[simp]
theorem SetTheory.PGame.moveRight_mk {xl xr : Type u_1} {xL : xlPGame} {xR : xrPGame} :
(mk xl xr xL xR).moveRight = xR
theorem SetTheory.PGame.ext {x y : PGame} (hl : x.LeftMoves = y.LeftMoves) (hr : x.RightMoves = y.RightMoves) (hL : ∀ (i : x.LeftMoves) (j : y.LeftMoves), HEq i jx.moveLeft i = y.moveLeft j) (hR : ∀ (i : x.RightMoves) (j : y.RightMoves), HEq i jx.moveRight i = y.moveRight j) :
x = y

Construct a pre-game from list of pre-games describing the available moves for Left and Right.

Equations
  • One or more equations did not get rendered due to their size.
@[reducible, inline]

Converts a number into a left move for ofLists.

This is just an abbreviation for Equiv.ulift.symm

Equations
@[reducible, inline]

Converts a number into a right move for ofLists.

This is just an abbreviation for Equiv.ulift.symm

Equations
@[simp]
theorem SetTheory.PGame.ofLists_moveLeft {L R : List PGame} (i : Fin L.length) :
(ofLists L R).moveLeft { down := i } = L[i]
theorem SetTheory.PGame.ofLists_moveRight {L R : List PGame} (i : Fin R.length) :
(ofLists L R).moveRight { down := i } = R[i]
def SetTheory.PGame.moveRecOn {C : PGameSort u_1} (x : PGame) (IH : (y : PGame) → ((i : y.LeftMoves) → C (y.moveLeft i))((j : y.RightMoves) → C (y.moveRight j))C y) :
C x

A variant of PGame.recOn expressed in terms of PGame.moveLeft and PGame.moveRight.

Both this and PGame.recOn describe Conway induction on games.

Equations

IsOption x y means that x is either a left or right option for y.

theorem SetTheory.PGame.isOption_iff (a✝ a✝¹ : PGame) :
a✝.IsOption a✝¹ ( (i : a✝¹.LeftMoves), a✝ = a✝¹.moveLeft i) (i : a✝¹.RightMoves), a✝ = a✝¹.moveRight i
theorem SetTheory.PGame.IsOption.mk_left {xl xr : Type u} (xL : xlPGame) (xR : xrPGame) (i : xl) :
(xL i).IsOption (mk xl xr xL xR)
theorem SetTheory.PGame.IsOption.mk_right {xl xr : Type u} (xL : xlPGame) (xR : xrPGame) (i : xr) :
(xR i).IsOption (mk xl xr xL xR)

Subsequent x y says that x can be obtained by playing some nonempty sequence of moves from y. It is the transitive closure of IsOption.

Equations
@[simp]
theorem SetTheory.PGame.Subsequent.mk_left {xl xr : Type u_1} (xL : xlPGame) (xR : xrPGame) (i : xl) :
(xL i).Subsequent (mk xl xr xL xR)
@[simp]
theorem SetTheory.PGame.Subsequent.mk_right {xl xr : Type u_1} (xL : xlPGame) (xR : xrPGame) (j : xr) :
(xR j).Subsequent (mk xl xr xL xR)

Discharges proof obligations of the form Subsequent .. arising in termination proofs of definitions using well-founded recursion on PGame.

Equations
@[simp]
theorem SetTheory.PGame.Subsequent.mk_right' {xl xr : Type u} (xL : xlPGame) (xR : xrPGame) (j : (mk xl xr xL xR).RightMoves) :
(xR j).Subsequent (mk xl xr xL xR)
@[simp]
theorem SetTheory.PGame.Subsequent.moveRight_mk_left {xl xr : Type u} {xR : xrPGame} {i : xl} (xL : xlPGame) (j : (xL i).RightMoves) :
((xL i).moveRight j).Subsequent (mk xl xr xL xR)
@[simp]
theorem SetTheory.PGame.Subsequent.moveRight_mk_right {xl xr : Type u} {xL : xlPGame} {i : xr} (xR : xrPGame) (j : (xR i).RightMoves) :
((xR i).moveRight j).Subsequent (mk xl xr xL xR)
@[simp]
theorem SetTheory.PGame.Subsequent.moveLeft_mk_left {xl xr : Type u} {xR : xrPGame} {i : xl} (xL : xlPGame) (j : (xL i).LeftMoves) :
((xL i).moveLeft j).Subsequent (mk xl xr xL xR)
@[simp]
theorem SetTheory.PGame.Subsequent.moveLeft_mk_right {xl xr : Type u} {xL : xlPGame} {i : xr} (xR : xrPGame) (j : (xR i).LeftMoves) :
((xR i).moveLeft j).Subsequent (mk xl xr xL xR)

Basic pre-games #

Identity #

Two pre-games are identical if their left and right sets are identical. That is, Identical x y if every left move of x is identical to some left move of y, every right move of x is identical to some right move of y, and vice versa.

Equations
  • One or more equations did not get rendered due to their size.

Two pre-games are identical if their left and right sets are identical. That is, Identical x y if every left move of x is identical to some left move of y, every right move of x is identical to some right move of y, and vice versa.

Equations
theorem SetTheory.PGame.identical_iff {x y : PGame} :
x.Identical y (Relator.BiTotal fun (x1 : x.LeftMoves) (x2 : y.LeftMoves) => (x.moveLeft x1).Identical (y.moveLeft x2)) Relator.BiTotal fun (x1 : x.RightMoves) (x2 : y.RightMoves) => (x.moveRight x1).Identical (y.moveRight x2)

x ∈ₗ y if x is identical to some left move of y.

Equations

x ∈ᵣ y if x is identical to some right move of y.

Equations

x ∈ₗ y if x is identical to some left move of y.

Equations

x ∈ᵣ y if x is identical to some right move of y.

Equations

x ∈ₗ y if x is identical to some left move of y.

Equations

x ∈ᵣ y if x is identical to some right move of y.

Equations

If x and y are identical, then a left move of x is identical to some left move of y.

If x and y are identical, then a right move of x is identical to some right move of y.

theorem SetTheory.PGame.identical_iff' {x y : PGame} :
x.Identical y ((∀ (i : x.LeftMoves), (x.moveLeft i).memₗ y) ∀ (j : y.LeftMoves), (y.moveLeft j).memₗ x) (∀ (i : x.RightMoves), (x.moveRight i).memᵣ y) ∀ (j : y.RightMoves), (y.moveRight j).memᵣ x

Uses ∈ₗ and ∈ᵣ instead of .

theorem SetTheory.PGame.memₗ.congr_right {x y : PGame} :
x.Identical y∀ {w : PGame}, w.memₗ x w.memₗ y
theorem SetTheory.PGame.memᵣ.congr_right {x y : PGame} :
x.Identical y∀ {w : PGame}, w.memᵣ x w.memᵣ y
theorem SetTheory.PGame.memₗ.congr_left {x y : PGame} :
x.Identical y∀ {w : PGame}, x.memₗ w y.memₗ w
theorem SetTheory.PGame.memᵣ.congr_left {x y : PGame} :
x.Identical y∀ {w : PGame}, x.memᵣ w y.memᵣ w
theorem SetTheory.PGame.Identical.ext {x y : PGame} :
(∀ (z : PGame), z.memₗ x z.memₗ y)(∀ (z : PGame), z.memᵣ x z.memᵣ y)x.Identical y
theorem SetTheory.PGame.Identical.ext_iff {x y : PGame} :
x.Identical y (∀ (z : PGame), z.memₗ x z.memₗ y) ∀ (z : PGame), z.memᵣ x z.memᵣ y
theorem SetTheory.PGame.Identical.of_fn {x y : PGame} (l : x.LeftMovesy.LeftMoves) (il : y.LeftMovesx.LeftMoves) (r : x.RightMovesy.RightMoves) (ir : y.RightMovesx.RightMoves) (hl : ∀ (i : x.LeftMoves), (x.moveLeft i).Identical (y.moveLeft (l i))) (hil : ∀ (i : y.LeftMoves), (x.moveLeft (il i)).Identical (y.moveLeft i)) (hr : ∀ (i : x.RightMoves), (x.moveRight i).Identical (y.moveRight (r i))) (hir : ∀ (i : y.RightMoves), (x.moveRight (ir i)).Identical (y.moveRight i)) :

Show x ≡ y by giving an explicit correspondence between the moves of x and y.

theorem SetTheory.PGame.Identical.of_equiv {x y : PGame} (l : x.LeftMoves y.LeftMoves) (r : x.RightMoves y.RightMoves) (hl : ∀ (i : x.LeftMoves), (x.moveLeft i).Identical (y.moveLeft (l i))) (hr : ∀ (i : x.RightMoves), (x.moveRight i).Identical (y.moveRight (r i))) :

Relabellings #

inductive SetTheory.PGame.Relabelling :
PGamePGameType (u + 1)

Relabelling x y says that x and y are really the same game, just dressed up differently. Specifically, there is a bijection between the moves for Left in x and in y, and similarly for Right, and under these bijections we inductively have Relabellings for the consequent games.

Relabelling x y says that x and y are really the same game, just dressed up differently. Specifically, there is a bijection between the moves for Left in x and in y, and similarly for Right, and under these bijections we inductively have Relabellings for the consequent games.

Equations
def SetTheory.PGame.Relabelling.mk' {x y : PGame} (L : y.LeftMoves x.LeftMoves) (R : y.RightMoves x.RightMoves) (hL : (i : y.LeftMoves) → (x.moveLeft (L i)).Relabelling (y.moveLeft i)) (hR : (j : y.RightMoves) → (x.moveRight (R j)).Relabelling (y.moveRight j)) :

A constructor for relabellings swapping the equivalences.

Equations

The equivalence between left moves of x and y given by the relabelling.

Equations
@[simp]
theorem SetTheory.PGame.Relabelling.mk_leftMovesEquiv {x y : PGame} {L : x.LeftMoves y.LeftMoves} {R : x.RightMoves y.RightMoves} {hL : (i : x.LeftMoves) → (x.moveLeft i).Relabelling (y.moveLeft (L i))} {hR : (j : x.RightMoves) → (x.moveRight j).Relabelling (y.moveRight (R j))} :
(mk L R hL hR).leftMovesEquiv = L
@[simp]
theorem SetTheory.PGame.Relabelling.mk'_leftMovesEquiv {x y : PGame} {L : y.LeftMoves x.LeftMoves} {R : y.RightMoves x.RightMoves} {hL : (i : y.LeftMoves) → (x.moveLeft (L i)).Relabelling (y.moveLeft i)} {hR : (j : y.RightMoves) → (x.moveRight (R j)).Relabelling (y.moveRight j)} :
(mk' L R hL hR).leftMovesEquiv = L.symm

The equivalence between right moves of x and y given by the relabelling.

Equations
@[simp]
theorem SetTheory.PGame.Relabelling.mk_rightMovesEquiv {x y : PGame} {L : x.LeftMoves y.LeftMoves} {R : x.RightMoves y.RightMoves} {hL : (i : x.LeftMoves) → (x.moveLeft i).Relabelling (y.moveLeft (L i))} {hR : (j : x.RightMoves) → (x.moveRight j).Relabelling (y.moveRight (R j))} :
(mk L R hL hR).rightMovesEquiv = R
@[simp]
theorem SetTheory.PGame.Relabelling.mk'_rightMovesEquiv {x y : PGame} {L : y.LeftMoves x.LeftMoves} {R : y.RightMoves x.RightMoves} {hL : (i : y.LeftMoves) → (x.moveLeft (L i)).Relabelling (y.moveLeft i)} {hR : (j : y.RightMoves) → (x.moveRight (R j)).Relabelling (y.moveRight j)} :
(mk' L R hL hR).rightMovesEquiv = R.symm

A left move of x is a relabelling of a left move of y.

Equations

A left move of y is a relabelling of a left move of x.

Equations

A right move of x is a relabelling of a right move of y.

Equations

A right move of y is a relabelling of a right move of x.

Equations
@[irreducible]

The identity relabelling.

Equations
  • One or more equations did not get rendered due to their size.

Flip a relabelling.

Equations

Transitivity of relabelling.

Equations
  • One or more equations did not get rendered due to their size.

Any game without left or right moves is a relabelling of 0.

Equations
  • One or more equations did not get rendered due to their size.
def SetTheory.PGame.relabel {x : PGame} {xl' xr' : Type u_1} (el : xl' x.LeftMoves) (er : xr' x.RightMoves) :

Replace the types indexing the next moves for Left and Right by equivalent types.

Equations
@[simp]
theorem SetTheory.PGame.relabel_moveLeft' {x : PGame} {xl' xr' : Type u_1} (el : xl' x.LeftMoves) (er : xr' x.RightMoves) (i : xl') :
(relabel el er).moveLeft i = x.moveLeft (el i)
theorem SetTheory.PGame.relabel_moveLeft {x : PGame} {xl' xr' : Type u_1} (el : xl' x.LeftMoves) (er : xr' x.RightMoves) (i : x.LeftMoves) :
(relabel el er).moveLeft (el.symm i) = x.moveLeft i
@[simp]
theorem SetTheory.PGame.relabel_moveRight' {x : PGame} {xl' xr' : Type u_1} (el : xl' x.LeftMoves) (er : xr' x.RightMoves) (j : xr') :
(relabel el er).moveRight j = x.moveRight (er j)
theorem SetTheory.PGame.relabel_moveRight {x : PGame} {xl' xr' : Type u_1} (el : xl' x.LeftMoves) (er : xr' x.RightMoves) (j : x.RightMoves) :
(relabel el er).moveRight (er.symm j) = x.moveRight j
def SetTheory.PGame.relabelRelabelling {x : PGame} {xl' xr' : Type u_1} (el : xl' x.LeftMoves) (er : xr' x.RightMoves) :

The game obtained by relabelling the next moves is a relabelling of the original game.

Equations
  • One or more equations did not get rendered due to their size.

Inserting an option #

The pregame constructed by inserting x' as a new left option into x.

Equations

The pregame constructed by inserting x' as a new right option into x.

Equations

Inserting on the left and right commutes.