Encyclopedia Patterns Patterns Gray Cycle Brgc
ARTICLE 3 claims 3 theorems
Patterns Gray Cycle Brgc
A Gray cycle is a loop through every binary pattern of a given length, changing exactly one bit per step; the BRGC construction builds one for any dimension without assuming any axioms.
Gray cycles by reflection
A Gray cycle is a closed loop that visits every binary pattern of a fixed length exactly once, with each step flipping exactly one bit. For two bits, the cycle 00, 01, 11, 10, back to 00 works: every two-bit pattern appears, and each move changes a single digit. The binary reflected Gray code (BRGC) is the classic recursive recipe for building such a cycle in any number of dimensions. It starts with the single pattern for zero bits, then at each stage copies the previous list, reverses the copy, and appends a new bit to each entry: a 0 for the original list and a 1 for the reversed one. This reflection trick, known since Frank Gray's 1953 patent, guarantees that consecutive patterns differ in one bit even across the wrap-around from last to first.
The BRGC has a well-known closed form: the code for a number n is n XOR (n shifted right by one). That formula is convenient, but it is not the definition. The recursive construction is the definition, and it works for any dimension d, producing a list of exactly 2^d patterns. For d = 3, the cycle runs 000, 001, 011, 010, 110, 111, 101, 100 and then back to 000. Each step flips one bit, and the final step from 100 to 000 also flips one bit, so the wrap-around condition holds. The same property holds for every positive dimension, which is what makes the BRGC a genuine cycle rather than merely a path.
In Recognition Science, the framework models patterns as functions from a finite set of coordinates to bits, and a Gray cycle is a path through all such patterns with one-bit adjacency. The framework's machine-checked library of formal theorems contains a module that builds the BRGC recursively and proves its two essential properties. The first proof shows the construction never repeats a pattern: the path is injective, so it visits 2^d distinct patterns. The second proof shows one-bit adjacency holds at every step, including the wrap-around, for every dimension d greater than zero. These two facts together mean the path is a genuine cycle that covers every pattern exactly once.
The module packages these results into two ready-made objects: a GrayCycle, which is the path with its injectivity and adjacency proofs, and a GrayCover, which adds the proof that the cycle covers every pattern. Both are built for any positive dimension without assuming any axioms beyond the standard logical ones, and without relying on the bitwise XOR formula. The construction is self-contained: it uses only the recursive definition and the framework's basic pattern vocabulary. What this establishes in plain language is that a Gray cycle exists in every dimension, and the recursive reflection recipe is enough to build it and certify its properties mechanically.
THEOREM brgcPath_injective · IndisputableMonolith/Patterns/GrayCycleBRGC.lean
theorem brgcPath_injective : ∀ d : Nat, Function.Injective (brgcPath d)
| 0 => by
intro i j _
-- `Fin 1` is a subsingleton (only `0`)
simpa [Fin.eq_zero i, Fin.eq_zero j]
| (d + 1) => by
intro i j hij
-- unfold the `d+1` definition and reduce to injectivity of the appended halves
classical
let T : Nat := 2 ^ d
have hTT : 2 ^ (d + 1) = T + T := by
simpa [T, twoPow_succ_eq_add d]
let left : Fin T → Pattern (d + 1) := fun k => snocBit (brgcPath d k) false
let right : Fin T → Pattern (d + 1) := fun k => snocBit (brgcPath d (Fin.rev k)) true
have hij' :
Fin.append left right (i.cast hTT) = Fin.append left right (j.cast hTT) := by
simpa [brgcPath, T, hTT, left, right] using hij
have hleft_inj : Function.Injective left := by
intro a b hab
have hab' : brgcPath d a = brgcPath d b := by
funext k
have := congrArg (fun p : Pattern (d + 1) => p k.castSucc) hab
simpa [left, snocBit] using this
exact (brgcPath_injective d) hab'
have hright_inj : Function.Injective right := by
intro a b hab
have hab' : brgcPath d (Fin.rev a) = brgcPath d (Fin.rev b) := by
funext k
have := congrArg (fun p : Pattern (d + 1) => p k.castSucc) hab
simpa [right, snocBit] using this
have : Fin.rev a = Fin.rev b := (brgcPath_injective d) hab'
exact Fin.rev_injective this
have hdis : ∀ a b : Fin T, left a ≠ right b := by
intro a b hab
have := congrArg (fun p : Pattern (d + 1) => p (Fin.last d)) hab
-- last coordinate is the appended bit: false on left, true on right
simpa [left, right] using this
have happ_inj : Function.Injective (Fin.append left right) :=
(Fin.append_injective_iff (xs := left) (ys := right)).2 ⟨hleft_inj, hright_inj, hdis⟩
have hcast : i.cast hTT = j.cast hTT := happ_inj hij'
-- cast back along the inverse equality
have := congrArg (Fin.cast hTT.symm) hcast
simpa [hTT] using this
THEOREM brgc_oneBit_step · IndisputableMonolith/Patterns/GrayCycleBRGC.lean
theorem brgc_oneBit_step : ∀ {d : Nat}, 0 < d →
∀ i : Fin (2 ^ d), OneBitDiff (brgcPath d i) (brgcPath d (i + 1))
| 0, hdpos => (Nat.not_lt_zero _ hdpos).elim
| 1, _ => by
intro i
-- dimension 1: the cycle is `0 → 1 → 0`, so the only bit flips each step
fin_cases i
· -- 0 → 1
have : OneBitDiff (snocBit (brgcPath 0 0) false) (snocBit (brgcPath 0 0) true) :=
oneBitDiff_snocBit_flip (p := brgcPath 0 0)
simpa [brgcPath] using this
· -- 1 → 0 (wrap), use symmetry
have h : OneBitDiff (snocBit (brgcPath 0 0) false) (snocBit (brgcPath 0 0) true) :=
oneBitDiff_snocBit_flip (p := brgcPath 0 0)
have : OneBitDiff (snocBit (brgcPath 0 0) true) (snocBit (brgcPath 0 0) false) :=
OneBitDiff_symm h
simpa [brgcPath] using this
| (d + 2), _ => by
-- Inductive step: assume one-bit stepping for dimension `d+1`, prove for `d+2`.
have ih :
∀ i : Fin (2 ^ (d + 1)), OneBitDiff (brgcPath (d + 1) i) (brgcPath (d + 1) (i + 1)) :=
brgc_oneBit_step (d := d + 1) (Nat.succ_pos _)
intro i
classical
let T : Nat := 2 ^ (d + 1)
have hTT : 2 ^ (d + 2) = T + T := by
simpa [T] using twoPow_succ_eq_add (d := d + 1)
let left : Fin T → Pattern (d + 2) := fun k => snocBit (brgcPath (d + 1) k) false
let right : Fin T → Pattern (d + 2) := fun k => snocBit (brgcPath (d + 1) (Fin.rev k)) true
let i' : Fin (T + T) := i.cast hTT
have hTpos : 0 < T := pow_pos (by decide : 0 < (2 : Nat)) (d + 1)
letI : NeZero T := ⟨Nat.ne_zero_of_lt hTpos⟩
letI : NeZero (T + T) := ⟨Nat.ne_zero_of_lt (Nat.add_pos_left hTpos T)⟩
have hcast_succ : (i + 1).cast hTT = i' + 1 := by
-- `cast` commutes with `+1` along definitional equalities
simpa [i'] using (cast_add_one (n := 2 ^ (d + 2)) (m := T + T) (h := hTT) i)
-- Reduce to the `Fin (T+T)` index space.
have hTTgoal : OneBitDiff (Fin.append left right i') (Fin.append left right (i' + 1)) := by
-- case split on whether `i'` lies in the left or right half, and whether we cross a boundary
induction i' using Fin.addCases with
| left k =>
-- i' = castAdd T k
by_cases hk : k.val + 1 < T
· -- successor stays in the left half
have hk_big : (Fin.castAdd T k : Fin (T + T)).val + 1 < T + T := by
-- k.val + 1 < T ≤ T+T
exact lt_of_lt_of_le hk (Nat.le_add_right T T)
have hnext : (Fin.castAdd T k : Fin (T + T)) + 1 = Fin.castAdd T (k + 1) := by
apply Fin.ext
have hk1 : (k + 1).val = k.val + 1 :=
Fin.val_add_one_of_lt' (n := T) (i := k) hk
have hk'1 : ((Fin.castAdd T k : Fin (T + T)) + 1).val =
(Fin.castAdd T k : Fin (T + T)).val + 1 :=
Fin.val_add_one_of_lt' (n := T + T) (i := Fin.castAdd T k) hk_big
simpa [hk1] using hk'1
-- adjacency comes from IH in dimension d+1, lifted through `snocBit`
have hstep : OneBitDiff (brgcPath (d + 1) k) (brgcPath (d + 1) (k + 1)) := ih k
have hstep' : OneBitDiff (left k) (left (k + 1)) :=
oneBitDiff_snocBit_same false hstep
-- rewrite the `append` evaluations
simpa [Fin.append_left, hnext, left, right] using hstep'
· -- boundary: last element of left half steps into the first element of right half
have hkval : k.val = T - 1 := by
have hle : k.val + 1 ≤ T := Nat.succ_le_of_lt k.isLt
have hge : T ≤ k.val + 1 := Nat.le_of_not_gt hk
have : k.val + 1 = T := Nat.le_antisymm hle hge
exact Nat.eq_sub_of_add_eq this
have hnext : (Fin.castAdd T k : Fin (T + T)) + 1 = Fin.natAdd T 0 := by
apply Fin.ext
-- both have value `T`
have hT1 : 1 ≤ T := Nat.succ_le_of_lt hTpos
have hkplus : (Fin.castAdd T k : Fin (T + T)).val + 1 = T := by
-- `(castAdd T k).val = k.val = T-1`
simpa [hkval, Nat.sub_add_cancel hT1]
have hk_big : (Fin.castAdd T k : Fin (T + T)).val + 1 < T + T := by
-- `T < T+T` since `T>0`
have hT1 : 1 ≤ T := Nat.succ_le_of_lt hTpos
have hTlt : T < T + T := by
have hle : T + 1 ≤ T + T := Nat.add_le_add_left hT1 T
exact lt_of_lt_of_le (Nat.lt_succ_self T) hle
-- rewrite the LHS using `hkplus : (castAdd ...).val + 1 = T`
exact hkplus.symm ▸ hTlt
have hk'1 : ((Fin.castAdd T k : Fin (T + T)) + 1).val =
(Fin.castAdd T k : Fin (T + T)).val + 1 :=
Fin.val_add_one_of_lt' (n := T + T) (i := Fin.castAdd T k) hk_big
have hval : ((Fin.castAdd T k : Fin (T + T)) + 1).val = T := by
exact hk'1.trans hkplus
-- `natAdd T 0` has val `T`
simpa [hval]
-- show underlying index on the right is also `k` (since `rev 0` is last)
have hrev0 : Fin.rev (0 : Fin T) = k := by
apply Fin.ext
-- `rev 0` has value `T-1`
simpa [hkval] using (Fin.val_rev_zero (n := T))
have hstep' : OneBitDiff (left k) (right 0) := by
-- same underlying pattern, last bit flips
simpa [left, right, hrev0] using (oneBitDiff_snocBit_flip (p := brgcPath (d + 1) k))
-- rewrite `append` at the boundary indices explicitly (avoid `natAdd`/`addNat` mismatch issues)
have happL : Fin.append left right (Fin.castAdd T k) = left k := by
simpa using (Fin.append_left (u := left) (v := right) k)
have happNext : Fin.append left right ((Fin.castAdd T k : Fin (T + T)) + 1) = right 0 := by
have : Fin.append left right (Fin.natAdd T (0 : Fin T)) = right 0 := by
simpa using (Fin.append_right (u := left) (v := right) (i := (0 : Fin T)))
simpa [hnext] using this
have hstep0 : OneBitDiff (Fin.append left right (Fin.castAdd T k)) (right 0) := by
simpa [happL] using hstep'
-- replace `right 0` with the `append` at the successor index
simpa [happNext.symm] using hstep0
| right k =>
-- i' = natAdd T k
by_cases hk : k.val + 1 < T
· -- successor stays in the right half
have hk_big : (Fin.natAdd T k : Fin (T + T)).val + 1 < T + T := by
-- (T + k.val) + 1 < T + T since k.val + 1 < T
have : T + (k.val + 1) < T + T := Nat.add_lt_add_left hk T
simpa [Fin.natAdd, Nat.add_assoc] using this
have hnext : (Fin.natAdd T k : Fin (T + T)) + 1 = Fin.natAdd T (k + 1) := by
apply Fin.ext
have hk1 : (k + 1).val = k.val + 1 :=
Fin.val_add_one_of_lt' (n := T) (i := k) hk
have hk'1 : ((Fin.natAdd T k : Fin (T + T)) + 1).val =
(Fin.natAdd T k : Fin (T + T)).val + 1 :=
Fin.val_add_one_of_lt' (n := T + T) (i := Fin.natAdd T k) hk_big
simpa [hk1, Nat.add_assoc, Nat.add_left_comm, Nat.add_comm] using hk'1
-- adjacency comes from IH in dimension d+1, but the right half is reversed
have hrevStep : OneBitDiff
(brgcPath (d + 1) (Fin.rev (k + 1))) (brgcPath (d + 1) ((Fin.rev (k + 1)) + 1)) := ih (Fin.rev (k + 1))
have hrevRel : (Fin.rev (k + 1) : Fin T) + 1 = Fin.rev k := by
-- rev(k+1) + 1 = rev(k) when k.val+1 < T
-- use the helper lemma on `Fin T`
simpa [Nat.add_assoc] using (rev_add_one_eq (n := T) (i := k) hk)
have hstep0 : OneBitDiff (brgcPath (d + 1) (Fin.rev (k + 1))) (brgcPath (d + 1) (Fin.rev k)) := by
simpa [hrevRel] using hrevStep
have hstep1 : OneBitDiff (brgcPath (d + 1) (Fin.rev k)) (brgcPath (d + 1) (Fin.rev (k + 1))) :=
OneBitDiff_symm hstep0
have hstep' : OneBitDiff (right k) (right (k + 1)) :=
oneBitDiff_snocBit_same true hstep1
-- rewrite `append` on the right half via a successor-index evaluation
have happK : Fin.append left right (Fin.natAdd T k) = right k := by
simpa using (Fin.append_right (u := left) (v := right) (i := k))
-- switch to the `addNat` presentation used by the simplifier in this file
have hnextAdd : (k.addNat T : Fin (T + T)) + 1 = (k + 1).addNat T := by
-- rewrite both `natAdd` endpoints into `addNat`
simpa [natAdd_eq_addNat (T := T) (k := k), natAdd_eq_addNat (T := T) (k := (k + 1))] using hnext
have happK' : Fin.append left right (k.addNat T) = right k := by
have : Fin.append left right (Fin.natAdd T k) = right k := by
simpa using (Fin.append_right (u := left) (v := right) (i := k))
simpa [natAdd_eq_addNat (T := T) (k := k)] using this
have happNext : Fin.append left right (k.addNat T + 1) = right (k + 1) := by
have : Fin.append left right (Fin.natAdd T (k + 1)) = right (k + 1) := by
simpa using (Fin.append_right (u := left) (v := right) (i := (k + 1)))
have : Fin.append left right ((k + 1).addNat T) = right (k + 1) := by
simpa [natAdd_eq_addNat (T := T) (k := (k + 1))] using this
simpa [hnextAdd.symm] using this
have hstep0 : OneBitDiff (Fin.append left right (k.addNat T)) (right (k + 1)) := by
simpa [happK'] using hstep'
simpa [happNext.symm] using hstep0
· -- boundary: last element of right half wraps back to the first element of left half
have hkval : k.val = T - 1 := by
have hle : k.val + 1 ≤ T := Nat.succ_le_of_lt k.isLt
have hge : T ≤ k.val + 1 := Nat.le_of_not_gt hk
have : k.val + 1 = T := Nat.le_antisymm hle hge
exact Nat.eq_sub_of_add_eq this
have hnext : (Fin.natAdd T k : Fin (T + T)) + 1 = Fin.castAdd T 0 := by
apply Fin.ext
-- last element in `Fin (T+T)` wraps to `0`
have hT1 : 1 ≤ T := Nat.succ_le_of_lt hTpos
have hsum : k.val + T + 1 = T + T := by
calc
k.val + T + 1 = (T - 1) + T + 1 := by simp [hkval]
_ = (T - 1) + 1 + T := by
simp [Nat.add_assoc, Nat.add_left_comm, Nat.add_comm]
_ = T + T := by
simp [Nat.sub_add_cancel hT1, Nat.add_assoc]
-- `((natAdd T k) + 1).val = ((k.val + T) + 1) % (T+T) = 0`
-- (the RHS `castAdd T 0` has value 0)
have : ((k.val + T + 1) % (T + T)) = 0 := by
simpa [hsum, Nat.mod_self]
simpa [Fin.val_add] using this
have hrev_last : Fin.rev k = (0 : Fin T) := by
apply Fin.ext
-- rev(last) has value 0
have hT1 : 1 ≤ T := Nat.succ_le_of_lt hTpos
have : (T - 1 + 1) = T := Nat.sub_add_cancel hT1
simp [Fin.val_rev, hkval, this]
have hstep' : OneBitDiff (right k) (left 0) := by
-- last bit flips from `true` to `false`
have hflip : OneBitDiff (snocBit (brgcPath (d + 1) 0) false) (snocBit (brgcPath (d + 1) 0) true) :=
oneBitDiff_snocBit_flip (p := brgcPath (d + 1) 0)
have hflip' : OneBitDiff (snocBit (brgcPath (d + 1) 0) true) (snocBit (brgcPat
-- … truncated for the page; open the module for the rest.
THEOREM brgcGrayCycle · brgcGrayCover · IndisputableMonolith/Patterns/GrayCycleBRGC.lean
noncomputable def brgcGrayCycle (d : Nat) (hdpos : 0 < d) : GrayCycle d :=
{ path := brgcPath d
inj := brgcPath_injective d
oneBit_step := brgc_oneBit_step (d := d) hdpos
}
noncomputable def brgcGrayCover (d : Nat) (hdpos : 0 < d) : GrayCover d (2 ^ d) :=
{ path := brgcPath d
complete := by
classical
have h_inj : Function.Injective (brgcPath d) := brgcPath_injective d
have h_card : Fintype.card (Fin (2 ^ d)) = Fintype.card (Pattern d) := by
simp [Patterns.card_pattern]
have h_bij : Function.Bijective (brgcPath d) :=
(Fintype.bijective_iff_injective_and_card (brgcPath d)).2 ⟨h_inj, h_card⟩
exact h_bij.2
oneBit_step := brgc_oneBit_step (d := d) hdpos
}
What this page does not claim
The module does not use the bitwise formula gray(n) = n XOR (n >> 1) anywhere in its construction or proofs. The existence of Gray cycles in every dimension does not by itself force any physical constant or dimension count. The framework's library proves the BRGC properties, but it does not claim this construction is the only possible Gray cycle.
Verify this page
Every tagged claim above names its theorem. To check one yourself rather than trust this page, elaborate the source module with Lean 4 and audit its axiom basis:
$ lake env lean IndisputableMonolith/Patterns/GrayCycleBRGC.lean
expected axiom basis: [propext, Classical.choice, Quot.sound] (the Lean kernel's standard three; no RS-specific axioms)
A page whose claims cannot be reproduced this way does not ship. In production, every anchor links to the exact declaration in the public source release, and this block carries the build receipt for the page itself.
Derived articles
This page is generated by a question-recursion engine: the questions its answers raise become the next pages. The current agenda, with open targets marked red:
- How does the BRGC construction relate to the eight-tick recognition cycle in the framework's forcing chain?
- What role do Gray cycles play in the framework's account of spatial dimensions?
- Does the framework use Gray cycles in any physical measurement or prediction, or only as a structural object?
MACHINE LAYER · GROUNDED CLAIM TABLE · CLICK TO EXPAND
THEOREM brgcPath_injective · IndisputableMonolith/Patterns/GrayCycleBRGC.lean
theorem brgcPath_injective : ∀ d : Nat, Function.Injective (brgcPath d) | 0 => by intro i j _ -- `Fin 1` is a subsingleton (only `0`) simpa [Fin.eq_zero i, Fin.eq_zero j] | (d + 1) => by intro i j hij -- unfold the `d+1` definition and reduce to injectivity of the appended halves classical let T : Nat := 2 ^ d have hTT : 2 ^ (d + 1) = T + T := by simpa [T, twoPow_succ_eq_add d] let left : Fin T → Pattern (d + 1) := fun k => snocBit (brgcPath d k) false let right : Fin T → Pattern (d + 1) := fun k => snocBit (brgcPath d (Fin.rev k)) true have hij' : Fin.append left right (i.cast hTT) = Fin.append left right (j.cast hTT) := by simpa [brgcPath, T, hTT, left, right] using hij have hleft_inj : Function.Injective left := by intro a b hab have hab' : brgcPath d a = brgcPath d b := by funext k have := congrArg (fun p : Pattern (d + 1) => p k.castSucc) hab simpa [left, snocBit] using this exact (brgcPath_injective d) hab' have hright_inj : Function.Injective right := by intro a b hab have hab' : brgcPath d (Fin.rev a) = brgcPath d (Fin.rev b) := by funext k have := congrArg (fun p : Pattern (d + 1) => p k.castSucc) hab simpa [right, snocBit] using this have : Fin.rev a = Fin.rev b := (brgcPath_injective d) hab' exact Fin.rev_injective this have hdis : ∀ a b : Fin T, left a ≠ right b := by intro a b hab have := congrArg (fun p : Pattern (d + 1) => p (Fin.last d)) hab -- last coordinate is the appended bit: false on left, true on right simpa [left, right] using this have happ_inj : Function.Injective (Fin.append left right) := (Fin.append_injective_iff (xs := left) (ys := right)).2 ⟨hleft_inj, hright_inj, hdis⟩ have hcast : i.cast hTT = j.cast hTT := happ_inj hij' -- cast back along the inverse equality have := congrArg (Fin.cast hTT.symm) hcast simpa [hTT] using thisThe BRGC construction never repeats a pattern: the path is injective, so it visits 2^d distinct patterns. brgcPath_injective · IndisputableMonolith/Patterns/GrayCycleBRGC.leanTHEOREM brgc_oneBit_step · IndisputableMonolith/Patterns/GrayCycleBRGC.lean
theorem brgc_oneBit_step : ∀ {d : Nat}, 0 < d → ∀ i : Fin (2 ^ d), OneBitDiff (brgcPath d i) (brgcPath d (i + 1)) | 0, hdpos => (Nat.not_lt_zero _ hdpos).elim | 1, _ => by intro i -- dimension 1: the cycle is `0 → 1 → 0`, so the only bit flips each step fin_cases i · -- 0 → 1 have : OneBitDiff (snocBit (brgcPath 0 0) false) (snocBit (brgcPath 0 0) true) := oneBitDiff_snocBit_flip (p := brgcPath 0 0) simpa [brgcPath] using this · -- 1 → 0 (wrap), use symmetry have h : OneBitDiff (snocBit (brgcPath 0 0) false) (snocBit (brgcPath 0 0) true) := oneBitDiff_snocBit_flip (p := brgcPath 0 0) have : OneBitDiff (snocBit (brgcPath 0 0) true) (snocBit (brgcPath 0 0) false) := OneBitDiff_symm h simpa [brgcPath] using this | (d + 2), _ => by -- Inductive step: assume one-bit stepping for dimension `d+1`, prove for `d+2`. have ih : ∀ i : Fin (2 ^ (d + 1)), OneBitDiff (brgcPath (d + 1) i) (brgcPath (d + 1) (i + 1)) := brgc_oneBit_step (d := d + 1) (Nat.succ_pos _) intro i classical let T : Nat := 2 ^ (d + 1) have hTT : 2 ^ (d + 2) = T + T := by simpa [T] using twoPow_succ_eq_add (d := d + 1) let left : Fin T → Pattern (d + 2) := fun k => snocBit (brgcPath (d + 1) k) false let right : Fin T → Pattern (d + 2) := fun k => snocBit (brgcPath (d + 1) (Fin.rev k)) true let i' : Fin (T + T) := i.cast hTT have hTpos : 0 < T := pow_pos (by decide : 0 < (2 : Nat)) (d + 1) letI : NeZero T := ⟨Nat.ne_zero_of_lt hTpos⟩ letI : NeZero (T + T) := ⟨Nat.ne_zero_of_lt (Nat.add_pos_left hTpos T)⟩ have hcast_succ : (i + 1).cast hTT = i' + 1 := by -- `cast` commutes with `+1` along definitional equalities simpa [i'] using (cast_add_one (n := 2 ^ (d + 2)) (m := T + T) (h := hTT) i) -- Reduce to the `Fin (T+T)` index space. have hTTgoal : OneBitDiff (Fin.append left right i') (Fin.append left right (i' + 1)) := by -- case split on whether `i'` lies in the left or right half, and whether we cross a boundary induction i' using Fin.addCases with | left k => -- i' = castAdd T k by_cases hk : k.val + 1 < T · -- successor stays in the left half have hk_big : (Fin.castAdd T k : Fin (T + T)).val + 1 < T + T := by -- k.val + 1 < T ≤ T+T exact lt_of_lt_of_le hk (Nat.le_add_right T T) have hnext : (Fin.castAdd T k : Fin (T + T)) + 1 = Fin.castAdd T (k + 1) := by apply Fin.ext have hk1 : (k + 1).val = k.val + 1 := Fin.val_add_one_of_lt' (n := T) (i := k) hk have hk'1 : ((Fin.castAdd T k : Fin (T + T)) + 1).val = (Fin.castAdd T k : Fin (T + T)).val + 1 := Fin.val_add_one_of_lt' (n := T + T) (i := Fin.castAdd T k) hk_big simpa [hk1] using hk'1 -- adjacency comes from IH in dimension d+1, lifted through `snocBit` have hstep : OneBitDiff (brgcPath (d + 1) k) (brgcPath (d + 1) (k + 1)) := ih k have hstep' : OneBitDiff (left k) (left (k + 1)) := oneBitDiff_snocBit_same false hstep -- rewrite the `append` evaluations simpa [Fin.append_left, hnext, left, right] using hstep' · -- boundary: last element of left half steps into the first element of right half have hkval : k.val = T - 1 := by have hle : k.val + 1 ≤ T := Nat.succ_le_of_lt k.isLt have hge : T ≤ k.val + 1 := Nat.le_of_not_gt hk have : k.val + 1 = T := Nat.le_antisymm hle hge exact Nat.eq_sub_of_add_eq this have hnext : (Fin.castAdd T k : Fin (T + T)) + 1 = Fin.natAdd T 0 := by apply Fin.ext -- both have value `T` have hT1 : 1 ≤ T := Nat.succ_le_of_lt hTpos have hkplus : (Fin.castAdd T k : Fin (T + T)).val + 1 = T := by -- `(castAdd T k).val = k.val = T-1` simpa [hkval, Nat.sub_add_cancel hT1] have hk_big : (Fin.castAdd T k : Fin (T + T)).val + 1 < T + T := by -- `T < T+T` since `T>0` have hT1 : 1 ≤ T := Nat.succ_le_of_lt hTpos have hTlt : T < T + T := by have hle : T + 1 ≤ T + T := Nat.add_le_add_left hT1 T exact lt_of_lt_of_le (Nat.lt_succ_self T) hle -- rewrite the LHS using `hkplus : (castAdd ...).val + 1 = T` exact hkplus.symm ▸ hTlt have hk'1 : ((Fin.castAdd T k : Fin (T + T)) + 1).val = (Fin.castAdd T k : Fin (T + T)).val + 1 := Fin.val_add_one_of_lt' (n := T + T) (i := Fin.castAdd T k) hk_big have hval : ((Fin.castAdd T k : Fin (T + T)) + 1).val = T := by exact hk'1.trans hkplus -- `natAdd T 0` has val `T` simpa [hval] -- show underlying index on the right is also `k` (since `rev 0` is last) have hrev0 : Fin.rev (0 : Fin T) = k := by apply Fin.ext -- `rev 0` has value `T-1` simpa [hkval] using (Fin.val_rev_zero (n := T)) have hstep' : OneBitDiff (left k) (right 0) := by -- same underlying pattern, last bit flips simpa [left, right, hrev0] using (oneBitDiff_snocBit_flip (p := brgcPath (d + 1) k)) -- rewrite `append` at the boundary indices explicitly (avoid `natAdd`/`addNat` mismatch issues) have happL : Fin.append left right (Fin.castAdd T k) = left k := by simpa using (Fin.append_left (u := left) (v := right) k) have happNext : Fin.append left right ((Fin.castAdd T k : Fin (T + T)) + 1) = right 0 := by have : Fin.append left right (Fin.natAdd T (0 : Fin T)) = right 0 := by simpa using (Fin.append_right (u := left) (v := right) (i := (0 : Fin T))) simpa [hnext] using this have hstep0 : OneBitDiff (Fin.append left right (Fin.castAdd T k)) (right 0) := by simpa [happL] using hstep' -- replace `right 0` with the `append` at the successor index simpa [happNext.symm] using hstep0 | right k => -- i' = natAdd T k by_cases hk : k.val + 1 < T · -- successor stays in the right half have hk_big : (Fin.natAdd T k : Fin (T + T)).val + 1 < T + T := by -- (T + k.val) + 1 < T + T since k.val + 1 < T have : T + (k.val + 1) < T + T := Nat.add_lt_add_left hk T simpa [Fin.natAdd, Nat.add_assoc] using this have hnext : (Fin.natAdd T k : Fin (T + T)) + 1 = Fin.natAdd T (k + 1) := by apply Fin.ext have hk1 : (k + 1).val = k.val + 1 := Fin.val_add_one_of_lt' (n := T) (i := k) hk have hk'1 : ((Fin.natAdd T k : Fin (T + T)) + 1).val = (Fin.natAdd T k : Fin (T + T)).val + 1 := Fin.val_add_one_of_lt' (n := T + T) (i := Fin.natAdd T k) hk_big simpa [hk1, Nat.add_assoc, Nat.add_left_comm, Nat.add_comm] using hk'1 -- adjacency comes from IH in dimension d+1, but the right half is reversed have hrevStep : OneBitDiff (brgcPath (d + 1) (Fin.rev (k + 1))) (brgcPath (d + 1) ((Fin.rev (k + 1)) + 1)) := ih (Fin.rev (k + 1)) have hrevRel : (Fin.rev (k + 1) : Fin T) + 1 = Fin.rev k := by -- rev(k+1) + 1 = rev(k) when k.val+1 < T -- use the helper lemma on `Fin T` simpa [Nat.add_assoc] using (rev_add_one_eq (n := T) (i := k) hk) have hstep0 : OneBitDiff (brgcPath (d + 1) (Fin.rev (k + 1))) (brgcPath (d + 1) (Fin.rev k)) := by simpa [hrevRel] using hrevStep have hstep1 : OneBitDiff (brgcPath (d + 1) (Fin.rev k)) (brgcPath (d + 1) (Fin.rev (k + 1))) := OneBitDiff_symm hstep0 have hstep' : OneBitDiff (right k) (right (k + 1)) := oneBitDiff_snocBit_same true hstep1 -- rewrite `append` on the right half via a successor-index evaluation have happK : Fin.append left right (Fin.natAdd T k) = right k := by simpa using (Fin.append_right (u := left) (v := right) (i := k)) -- switch to the `addNat` presentation used by the simplifier in this file have hnextAdd : (k.addNat T : Fin (T + T)) + 1 = (k + 1).addNat T := by -- rewrite both `natAdd` endpoints into `addNat` simpa [natAdd_eq_addNat (T := T) (k := k), natAdd_eq_addNat (T := T) (k := (k + 1))] using hnext have happK' : Fin.append left right (k.addNat T) = right k := by have : Fin.append left right (Fin.natAdd T k) = right k := by simpa using (Fin.append_right (u := left) (v := right) (i := k)) simpa [natAdd_eq_addNat (T := T) (k := k)] using this have happNext : Fin.append left right (k.addNat T + 1) = right (k + 1) := by have : Fin.append left right (Fin.natAdd T (k + 1)) = right (k + 1) := by simpa using (Fin.append_right (u := left) (v := right) (i := (k + 1))) have : Fin.append left right ((k + 1).addNat T) = right (k + 1) := by simpa [natAdd_eq_addNat (T := T) (k := (k + 1))] using this simpa [hnextAdd.symm] using this have hstep0 : OneBitDiff (Fin.append left right (k.addNat T)) (right (k + 1)) := by simpa [happK'] using hstep' simpa [happNext.symm] using hstep0 · -- boundary: last element of right half wraps back to the first element of left half have hkval : k.val = T - 1 := by have hle : k.val + 1 ≤ T := Nat.succ_le_of_lt k.isLt have hge : T ≤ k.val + 1 := Nat.le_of_not_gt hk have : k.val + 1 = T := Nat.le_antisymm hle hge exact Nat.eq_sub_of_add_eq this have hnext : (Fin.natAdd T k : Fin (T + T)) + 1 = Fin.castAdd T 0 := by apply Fin.ext -- last element in `Fin (T+T)` wraps to `0` have hT1 : 1 ≤ T := Nat.succ_le_of_lt hTpos have hsum : k.val + T + 1 = T + T := by calc k.val + T + 1 = (T - 1) + T + 1 := by simp [hkval] _ = (T - 1) + 1 + T := by simp [Nat.add_assoc, Nat.add_left_comm, Nat.add_comm] _ = T + T := by simp [Nat.sub_add_cancel hT1, Nat.add_assoc] -- `((natAdd T k) + 1).val = ((k.val + T) + 1) % (T+T) = 0` -- (the RHS `castAdd T 0` has value 0) have : ((k.val + T + 1) % (T + T)) = 0 := by simpa [hsum, Nat.mod_self] simpa [Fin.val_add] using this have hrev_last : Fin.rev k = (0 : Fin T) := by apply Fin.ext -- rev(last) has value 0 have hT1 : 1 ≤ T := Nat.succ_le_of_lt hTpos have : (T - 1 + 1) = T := Nat.sub_add_cancel hT1 simp [Fin.val_rev, hkval, this] have hstep' : OneBitDiff (right k) (left 0) := by -- last bit flips from `true` to `false` have hflip : OneBitDiff (snocBit (brgcPath (d + 1) 0) false) (snocBit (brgcPath (d + 1) 0) true) := oneBitDiff_snocBit_flip (p := brgcPath (d + 1) 0) have hflip' : OneBitDiff (snocBit (brgcPath (d + 1) 0) true) (snocBit (brgcPat -- … truncated for the page; open the module for the rest.One-bit adjacency holds at every step, including the wrap-around, for every dimension d greater than zero. brgc_oneBit_step · IndisputableMonolith/Patterns/GrayCycleBRGC.leanTHEOREM brgcGrayCycle · brgcGrayCover · IndisputableMonolith/Patterns/GrayCycleBRGC.lean
noncomputable def brgcGrayCycle (d : Nat) (hdpos : 0 < d) : GrayCycle d := { path := brgcPath d inj := brgcPath_injective d oneBit_step := brgc_oneBit_step (d := d) hdpos }noncomputable def brgcGrayCover (d : Nat) (hdpos : 0 < d) : GrayCover d (2 ^ d) := { path := brgcPath d complete := by classical have h_inj : Function.Injective (brgcPath d) := brgcPath_injective d have h_card : Fintype.card (Fin (2 ^ d)) = Fintype.card (Pattern d) := by simp [Patterns.card_pattern] have h_bij : Function.Bijective (brgcPath d) := (Fintype.bijective_iff_injective_and_card (brgcPath d)).2 ⟨h_inj, h_card⟩ exact h_bij.2 oneBit_step := brgc_oneBit_step (d := d) hdpos }The module packages these results into a GrayCycle and a GrayCover, both built for any positive dimension without assuming any axioms beyond the standard logical ones. brgcGrayCycle · brgcGrayCover · IndisputableMonolith/Patterns/GrayCycleBRGC.lean