Combinatorial (pre-)games #
The basic theory of combinatorial games, following Conway's book On Numbers and Games
.
In ZFC, games are built inductively out of two other sets of games, representing the options for two
players Left and Right. In Lean, we instead define the type of games IGame
as arising from two
Small
sets of games, with notation {s | t}ᴵ
(see IGame.ofSets
). A u
-small type α : Type v
is one that is equivalent to some β : Type u
, and the distinction between small and large types in
a given universe closely mimics the ZFC distinction between sets and proper classes.
This definition requires some amount of setup, which we achieve through an auxiliary type PGame
.
This type was historically the foundation for game theory in Lean, but it has now been superseded by
IGame
, a quotient of it with the correct notion of equality. See the docstring on PGame
for more
information.
We are also interested in further quotients of IGame
. The quotient of games under equivalence
x ≈ y ↔ x ≤ y ∧ y ≤ x
, which in the literature is often what is meant by a "combinatorial game",
is defined as Game
in CombinatorialGames.Game.Basic
. The surreal numbers Surreal
are defined
as a quotient (of a subtype) of games in CombinatorialGames.Surreal.Basic
.
Conway induction #
Most constructions within game theory, and as such, many proofs within it, are done by structural induction. Structural induction on games is sometimes called "Conway induction".
The most straightforward way to employ Conway induction is by using the termination checker, with
the auxiliary igame_wf
tactic. This uses solve_by_elim
to search the context for proofs of the
form y ∈ x.leftMoves
or y ∈ x.rightMoves
, which prove termination. Alternatively, you can use
the explicit recursion principles IGame.ofSetsRecOn
or IGame.moveRecOn
.
Order properties #
Pregames have both a ≤
and a <
relation, satisfying the properties of a Preorder
. The relation
0 < x
means that x
can always be won by Left, while 0 ≤ x
means that x
can be won by Left as
the second player. Likewise, x < 0
means that x
can always be won by Right, while x ≤ 0
means
that x
can be won by Right as the second player.
Note that we don't actually prove these characterizations. Indeed, in Conway's setup, combinatorial
game theory can be done entirely without the concept of a strategy. For instance, IGame.zero_le
implies that if 0 ≤ x
, then any move by Right satisfies ¬ x ≤ 0
, and IGame.zero_lf
implies
that if ¬ x ≤ 0
, then some move by Left satisfies 0 ≤ x
. The strategy is thus already encoded
within these game relations.
For convenience, we define notation x ⧏ y
(pronounced "less or fuzzy") for ¬ y ≤ x
, notation
x ‖ y
for ¬ x ≤ y ∧ ¬ y ≤ x
, and notation x ≈ y
for x ≤ y ∧ y ≤ x
.
You can prove most (simple) inequalities on concrete games through the game_cmp
tactic, which
repeatedly unfolds the definition of ≤
and applies simp
until it solves the goal.
Algebraic structures #
Most of the usual arithmetic operations can be defined for games. Addition is defined for
x = {s₁ | t₁}ᴵ
and y = {s₂ | t₂}ᴵ
by x + y = {s₁ + y, x + s₂ | t₁ + y, x + t₂}ᴵ
. Negation is
defined by -{s | t}ᴵ = {-t | -s}ᴵ
.
The order structures interact in the expected way with arithmetic. In particular, Game
is an
OrderedAddCommGroup
. Meanwhile, IGame
satisfies the slightly weaker axioms of a
SubtractionCommMonoid
, since the equation x - x = 0
is only true up to equivalence.
Pre-games #
The type of "pre-games", before we have quotiented by equivalence (identicalSetoid
).
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.
This type was historically the foundation for game theory in Lean, but this led to many annoyances.
Most impactfully, this type has a notion of equality that is too strict: two games 0 = { | }
could
be distinct (and unprovably so!) if the indexed families of left and right sets were two distinct
empty types. To get the correct notion of equality, we define IGame
as the quotient of this type
by the Identical
relation, representing extensional equivalence.
This type has thus been relegated to an auxiliary construction for IGame
. You should not build
any substantial theory based on this type.
Instances For
The indexing type for allowable moves by Right.
Equations
- (PGame.mk l β a a_1).RightMoves = β
Instances For
The new game after Right makes an allowed move.
Instances For
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.
IGame
is defined as a quotient of PGame
under this relation.
Equations
- (PGame.mk α β xL xR).Identical (PGame.mk α_1 β_1 yL yR) = ((Relator.BiTotal fun (i : α) (j : α_1) => (xL i).Identical (yL j)) ∧ Relator.BiTotal fun (i : β) (j : β_1) => (xR i).Identical (yR j))
Instances For
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.
IGame
is defined as a quotient of PGame
under this relation.
Equations
- PGame.«term_≡_» = Lean.ParserDescr.trailingNode `PGame.«term_≡_» 50 51 (Lean.ParserDescr.binary `andthen (Lean.ParserDescr.symbol " ≡ ") (Lean.ParserDescr.cat `term 51))
Instances For
Equations
- PGame.identicalSetoid = { r := PGame.Identical, iseqv := PGame.identicalSetoid._proof_1 }
Instances For
If x ≡ y
, then a right move of x
is identical to some right move of y
.
If x ≡ y
, then a right move of y
is identical to some right move of x
.
Game moves #
Games up to identity.
IGame
uses the set-theoretic notion of equality on games, compared to PGame
's 'type-theoretic'
notion of equality.
This is not the same equivalence as used broadly in combinatorial game theory literature, as a game
like {0, 1 | 0}
is not identical to {1 | 0}
, despite being equivalent. However, many theorems
can be proven over the 'identical' equivalence relation, and the literature may occasionally
specifically use the 'identical' equivalence relation for this reason.
For the more common game equivalence from literature, see Game.Basic
.
Equations
Instances For
Alias of the reverse direction of IGame.mk_eq_mk
.
The set of left moves of the game.
Equations
- IGame.leftMoves = Quotient.lift (fun (x : PGame) => IGame.mk '' Set.range x.moveLeft) IGame.leftMoves._proof_1
Instances For
The set of right moves of the game.
Equations
- IGame.rightMoves = Quotient.lift (fun (x : PGame) => IGame.mk '' Set.range x.moveRight) IGame.rightMoves._proof_1
Instances For
Conway recursion: build data for a game by recursively building it on its left and right sets.
See ofSetsRecOn
for an alternate form.
Equations
- One or more equations did not get rendered due to their size.
Instances For
A (proper) subposition is any game in the transitive closure of IsOption
.
Instances For
Equations
- IGame.instWellFoundedRelation = { rel := IGame.Subposition, wf := ⋯ }
Discharges proof obligations of the form ⊢ Subposition ..
arising in termination proofs
of definitions using well-founded recursion on IGame
.
Equations
- IGame.tacticIgame_wf = Lean.ParserDescr.node `IGame.tacticIgame_wf 1024 (Lean.ParserDescr.nonReservedSymbol "igame_wf" false)
Instances For
Construct an IGame
from its left and right sets.
This is given notation {s | t}ᴵ
, where the superscript I
is to disambiguate from set builder
notation, and from the analogous constructors on Game
and Surreal
.
This function is regrettably noncomputable. Among other issues, sets simply do not carry data in
Lean. To perform computations on IGame
we can instead make use of the game_cmp
tactic.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Construct an IGame
from its left and right sets.
This is given notation {s | t}ᴵ
, where the superscript I
is to disambiguate from set builder
notation, and from the analogous constructors on Game
and Surreal
.
This function is regrettably noncomputable. Among other issues, sets simply do not carry data in
Lean. To perform computations on IGame
we can instead make use of the game_cmp
tactic.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Conway recursion: build data for a game by recursively building it on its left and right sets.
See moveRecOn
for an alternate form.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Basic games #
Order relations #
The less or equal relation on games.
If 0 ≤ x
, then Left can win x
as the second player. x ≤ y
means that 0 ≤ y - x
.
Equations
- One or more equations did not get rendered due to their size.
The less or fuzzy relation on pre-games. x ⧏ y
is notation for ¬ y ≤ x
.
If 0 ⧏ x
, then Left can win x
as the first player. x ⧏ y
means that 0 ⧏ y - x
.
Equations
- IGame.«term_⧏_» = Lean.ParserDescr.trailingNode `IGame.«term_⧏_» 50 50 (Lean.ParserDescr.binary `andthen (Lean.ParserDescr.symbol " ⧏ ") (Lean.ParserDescr.cat `term 50))
Instances For
The definition of 0 ≤ x
on pre-games, in terms of 0 ⧏
.
The definition of x ⧏ 0
on pre-games, in terms of ≤ 0
.
The definition of x ≤ y
on pre-games, in terms of ≤
two moves later.
Note that it's often more convenient to use le_iff_forall_lf
, which only unfolds the definition by
one step.
The definition of x ⧏ y
on pre-games, in terms of ⧏
two moves later.
Note that it's often more convenient to use lf_iff_exists_le
, which only unfolds the definition by
one step.
Equations
- IGame.instPreorder = { toLE := IGame.instLE, lt := fun (a b : IGame) => a ≤ b ∧ ¬b ≤ a, le_refl := ⋯, le_trans := ⋯, lt_iff_le_not_ge := IGame.instPreorder._proof_1 }
The equivalence relation x ≈ y
means that x ≤ y
and y ≤ x
. This is notation for
AntisymmRel (⬝ ≤ ⬝) x y
.
Equations
- IGame.«term_≈_» = Lean.ParserDescr.trailingNode `IGame.«term_≈_» 50 51 (Lean.ParserDescr.binary `andthen (Lean.ParserDescr.symbol " ≈ ") (Lean.ParserDescr.cat `term 51))
Instances For
The "fuzzy" relation x ‖ y
means that x ⧏ y
and y ⧏ x
. This is notation for
IncompRel (⬝ ≤ ⬝) x y
.
Equations
- IGame.«term_‖_» = Lean.ParserDescr.trailingNode `IGame.«term_‖_» 50 50 (Lean.ParserDescr.binary `andthen (Lean.ParserDescr.symbol " ‖ ") (Lean.ParserDescr.cat `term 50))
Instances For
Equations
- One or more equations did not get rendered due to their size.
Instances For
Equations
- One or more equations did not get rendered due to their size.
Instances For
Negation #
The negative of a game is defined by -{s | t}ᴵ = {-t | -s}ᴵ
.
Equations
- IGame.instNeg = { neg := IGame.neg'✝ }
Equations
- IGame.instInvolutiveNeg = { toNeg := IGame.instNeg, neg_neg := IGame.instInvolutiveNeg._proof_1 }
Equations
- IGame.instNegZeroClass = { toZero := IGame.instZero, toNeg := IGame.instNeg, neg_zero := IGame.instNegZeroClass._proof_1 }
Alias of the reverse direction of IGame.neg_equiv_neg_iff
.
Addition and subtraction #
The sum of x = {s₁ | t₁}ᴵ
and y = {s₂ | t₂}ᴵ
is {s₁ + y, x + s₂ | t₁ + y, x + t₂}ᴵ
.
Equations
- IGame.instAdd = { add := IGame.add'✝ }
Equations
- IGame.instAddZeroClass = { toZero := IGame.instZero, toAdd := IGame.instAdd, zero_add := IGame.instAddZeroClass._proof_1, add_zero := IGame.instAddZeroClass._proof_2 }
Equations
- One or more equations did not get rendered due to their size.
The subtraction of x
and y
is defined as x + (-y)
.
Equations
- One or more equations did not get rendered due to their size.
Equations
- One or more equations did not get rendered due to their size.
The sum of a game and its negative is equivalent, though not necessarily identical to zero.
The sum of a game and its negative is equivalent, though not necessarily identical to zero.
We define the NatCast
instance as ↑0 = 0
and ↑(n + 1) = {{↑n} | ∅}ᴵ
.
Note that this is equivalent, but not identical, to the more common definition ↑n = {Iio n | ∅}ᴵ
.
For that, use Ordinal.toIGame
.
Equations
- One or more equations did not get rendered due to their size.
Equations
- IGame.instIntCast = { intCast := fun (x : ℤ) => match x with | Int.ofNat n => ↑n | Int.negSucc n => -(↑n + 1) }
Every right option of an integer is equal to a larger integer.
Multiplication #
Equations
- One or more equations did not get rendered due to their size.
Instances For
The product of x = {s₁ | t₁}ᴵ
and y = {s₂ | t₂}ᴵ
is
{a₁ * y + x * b₁ - a₁ * b₁ | a₂ * y + x * b₂ - a₂ * b₂}ᴵ
, where (a₁, b₁) ∈ s₁ ×ˢ s₂ ∪ t₁ ×ˢ t₂
and (a₂, b₂) ∈ s₁ ×ˢ t₂ ∪ t₁ ×ˢ s₂
.
Using IGame.mulOption
, this can alternatively be written as
x * y = {mulOption x y a₁ b₁ | mulOption x y a₂ b₂}ᴵ
.
Equations
- IGame.instMul = { mul := IGame.mul' }
Equations
- IGame.instMulZeroClass = { toMul := IGame.instMul, toZero := IGame.instZero, zero_mul := IGame.instMulZeroClass._proof_1, mul_zero := IGame.instMulZeroClass._proof_2 }
Equations
- IGame.instMulOneClass = { toOne := IGame.instOne, toMul := IGame.instMul, one_mul := IGame.instMulOneClass._proof_1, mul_one := IGame.instMulOneClass._proof_2 }
Equations
- IGame.instCommMagma = { toMul := IGame.instMul, mul_comm := IGame.mul_comm'✝ }
Equations
- IGame.instHasDistribNeg = { toInvolutiveNeg := IGame.instInvolutiveNeg, neg_mul := IGame.neg_mul'✝, mul_neg := IGame.mul_neg'✝ }
Distributivity and associativity only hold up to equivalence; we prove this in
CombinatorialGames.Game.Basic
.
Division #
The inverse of a positive game x = {s | t}ᴵ
is {s' | t'}ᴵ
, where s'
and t'
are the
smallest sets such that 0 ∈ s'
, and such that (1 + (z - x) * a) / z, (1 + (y - x) * b) / y ∈ s'
and (1 + (y - x) * a) / y, (1 + (z - x) * b) / z ∈ t'
for y ∈ s
positive, z ∈ t
, a ∈ s'
, and
b ∈ t'
.
If x
is negative, we define x⁻¹ = -(-x)⁻¹
. For any other game, we set x⁻¹ = 0
.
If x
is a non-zero numeric game, then x * x⁻¹ ≈ 1
. The value of this function on any non-numeric
game should be treated as a junk value.
The general option of x⁻¹
looks like (1 + (y - x) * a) / y
, for y
an option of x
, and
a
some other "earlier" option of x⁻¹
.
Instances For
An induction principle on left and right moves of x⁻¹
.