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, since Lean's inductive types aren't powerful enough
to express this on their own. See the docstring on GameFunctor
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.
Game moves #
Well-founded games up to identity.
IGame
uses the set-theoretic notion of equality on games, meaning that two IGame
s are equal
exactly when their left and right sets of options are.
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. The quotient Game
of games
up to equality is defined in CombinatorialGames.Game.Basic
.
More precisely, IGame
is the inductive type for the single constructor
| ofSets (s t : Set IGame.{u}) [Small.{u} s] [Small.{u} t] : IGame.{u}
(though for technical reasons it's not literally defined as such). A consequence of this is that
there is no infinite line of play. See LGame
for a definition of loopy games.
Equations
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 other game types.
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.
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 other game types.
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.
Conventions for notations in identifiers:
- The recommended spelling of
{· | ·}ᴵ
in identifiers isofSets
.
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. You rarely need to use this explicitly, as the termination checker will handle things for you.
See ofSetsRecOn
for an alternate form.
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. You rarely need to use this explicitly, as the termination checker will handle things for you.
See moveRecOn
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
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 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
.
Conventions for notations in identifiers:
- The recommended spelling of
⧏
in identifiers islf
.
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 games, in terms of 0 ⧏
.
The definition of x ⧏ 0
on games, in terms of ≤ 0
.
The definition of x ≤ y
on 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 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
.
Conventions for notations in identifiers:
- The recommended spelling of
≈
in identifiers isequiv
.
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
.
Conventions for notations in identifiers:
- The recommended spelling of
‖
in identifiers isfuzzy
.
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
- 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 NatOrdinal.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.instCommMagma = { toMul := IGame.instMul, mul_comm := IGame.mul_comm'✝ }
Equations
- IGame.instMulZeroClass = { toMul := IGame.instMul, toZero := IGame.instZero, zero_mul := IGame.zero_mul'✝, mul_zero := IGame.instMulZeroClass._proof_1 }
Equations
- IGame.instMulOneClass = { toOne := IGame.instOne, toMul := IGame.instMul, one_mul := IGame.one_mul'✝, mul_one := IGame.instMulOneClass._proof_1 }
Equations
- IGame.instHasDistribNeg = { toInvolutiveNeg := IGame.instInvolutiveNeg, neg_mul := IGame.neg_mul'✝, mul_neg := IGame.instHasDistribNeg._proof_1 }
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⁻¹
.