l3lab/ntp-mathlib huggingface dataset:
theorem Algebra.leftMulMatrix_complex (z : ℂ) :
    Algebra.leftMulMatrix Complex.basisOneI z = !![z.re, -z.im; z.im, z.re] := by
  ext i j
  rw [Algebra.leftMulMatrix_eq_repr_mul, Complex.coe_basisOneI_repr, Complex.coe_basisOneI, mul_re,
    mul_im, Matrix.of_apply]
  fin_cases j
  · simp only [Fin.mk_zero, Matrix.cons_val_zero, one_re, mul_one, one_im, mul_zero, sub_zero,
      zero_add]
    fin_cases i <;> 

Proof state:
case a.h.head.tail.head
z : ℂ
⊢ Matrix.vecCons z.re ![z.im] { val := 1, isLt := (_ : (fun a => a < 2) 1) } =
    Matrix.vecCons ![z.re, -z.im] ![![z.im, z.re]] { val := 1, isLt := (_ : (fun a => a < 2) 1) } 0

Next tactic:
rfl
theorem Algebra.leftMulMatrix_complex (z : ℂ) :
    Algebra.leftMulMatrix Complex.basisOneI z = !![z.re, -z.im; z.im, z.re] := by
  ext i j
  rw [Algebra.leftMulMatrix_eq_repr_mul, Complex.coe_basisOneI_repr, Complex.coe_basisOneI, mul_re,
    mul_im, Matrix.of_apply]
  fin_cases j
  · simp only [Fin.mk_zero, Matrix.cons_val_zero, one_re, mul_one, one_im, mul_zero, sub_zero,
      zero_add]
    fin_cases i <;> rfl
  · 

Proof state:
case a.h.tail.head
z : ℂ
i : Fin 2
⊢ Matrix.vecCons
      (z.re * (Matrix.vecCons 1 ![I] { val := 1, isLt := (_ : (fun a => a < 2) 1) }).re -
        z.im * (Matrix.vecCons 1 ![I] { val := 1, isLt := (_ : (fun a => a < 2) 1) }).im)
      ![z.re * (Matrix.vecCons 1 ![I] { val := 1, isLt := (_ : (fun a => a < 2) 1) }).im +
          z.im * (Matrix.vecCons 1 ![I] { val := 1, isLt := (_ : (fun a => a < 2) 1) }).re]
      i =
    Matrix.vecCons ![z.re, -z.im] ![![z.im, z.re]] i { val := 1, isLt := (_ : (fun a => a < 2) 1) }

Next tactic:
simp only [Fin.mk_one, Matrix.cons_val_one, Matrix.head_cons, I_re, mul_zero, I_im, mul_one,
      zero_sub, add_zero]
theorem Algebra.leftMulMatrix_complex (z : ℂ) :
    Algebra.leftMulMatrix Complex.basisOneI z = !![z.re, -z.im; z.im, z.re] := by
  ext i j
  rw [Algebra.leftMulMatrix_eq_repr_mul, Complex.coe_basisOneI_repr, Complex.coe_basisOneI, mul_re,
    mul_im, Matrix.of_apply]
  fin_cases j
  · simp only [Fin.mk_zero, Matrix.cons_val_zero, one_re, mul_one, one_im, mul_zero, sub_zero,
      zero_add]
    fin_cases i <;> rfl
  · simp only [Fin.mk_one, Matrix.cons_val_one, Matrix.head_cons, I_re, mul_zero, I_im, mul_one,
      zero_sub, add_zero]
    

Proof state:
case a.h.tail.head
z : ℂ
i : Fin 2
⊢ Matrix.vecCons (-z.im) ![z.re] i = Matrix.vecCons ![z.re, -z.im] ![![z.im, z.re]] i 1

Next tactic:
fin_cases i
theorem Algebra.leftMulMatrix_complex (z : ℂ) :
    Algebra.leftMulMatrix Complex.basisOneI z = !![z.re, -z.im; z.im, z.re] := by
  ext i j
  rw [Algebra.leftMulMatrix_eq_repr_mul, Complex.coe_basisOneI_repr, Complex.coe_basisOneI, mul_re,
    mul_im, Matrix.of_apply]
  fin_cases j
  · simp only [Fin.mk_zero, Matrix.cons_val_zero, one_re, mul_one, one_im, mul_zero, sub_zero,
      zero_add]
    fin_cases i <;> rfl
  · simp only [Fin.mk_one, Matrix.cons_val_one, Matrix.head_cons, I_re, mul_zero, I_im, mul_one,
      zero_sub, add_zero]
    fin_cases i <;> 

Proof state:
case a.h.tail.head.head
z : ℂ
⊢ Matrix.vecCons (-z.im) ![z.re] { val := 0, isLt := (_ : 0 < 2) } =
    Matrix.vecCons ![z.re, -z.im] ![![z.im, z.re]] { val := 0, isLt := (_ : 0 < 2) } 1

Next tactic:
rfl
theorem Algebra.leftMulMatrix_complex (z : ℂ) :
    Algebra.leftMulMatrix Complex.basisOneI z = !![z.re, -z.im; z.im, z.re] := by
  ext i j
  rw [Algebra.leftMulMatrix_eq_repr_mul, Complex.coe_basisOneI_repr, Complex.coe_basisOneI, mul_re,
    mul_im, Matrix.of_apply]
  fin_cases j
  · simp only [Fin.mk_zero, Matrix.cons_val_zero, one_re, mul_one, one_im, mul_zero, sub_zero,
      zero_add]
    fin_cases i <;> rfl
  · simp only [Fin.mk_one, Matrix.cons_val_one, Matrix.head_cons, I_re, mul_zero, I_im, mul_one,
      zero_sub, add_zero]
    fin_cases i <;> 

Proof state:
case a.h.tail.head.tail.head
z : ℂ
⊢ Matrix.vecCons (-z.im) ![z.re] { val := 1, isLt := (_ : (fun a => a < 2) 1) } =
    Matrix.vecCons ![z.re, -z.im] ![![z.im, z.re]] { val := 1, isLt := (_ : (fun a => a < 2) 1) } 1

Next tactic:
rfl
theorem Algebra.trace_complex_apply (z : ℂ) : Algebra.trace ℝ ℂ z = 2 * z.re := by
  

Proof state:
z : ℂ
⊢ (trace ℝ ℂ) z = 2 * z.re

Next tactic:
rw [Algebra.trace_eq_matrix_trace Complex.basisOneI, Algebra.leftMulMatrix_complex,
    Matrix.trace_fin_two]
theorem Algebra.trace_complex_apply (z : ℂ) : Algebra.trace ℝ ℂ z = 2 * z.re := by
  rw [Algebra.trace_eq_matrix_trace Complex.basisOneI, Algebra.leftMulMatrix_complex,
    Matrix.trace_fin_two]
  

Proof state:
z : ℂ
⊢ Matrix.of ![![z.re, -z.im], ![z.im, z.re]] 0 0 + Matrix.of ![![z.re, -z.im], ![z.im, z.re]] 1 1 = 2 * z.re

Next tactic:
exact (two_mul _).symm
theorem Algebra.norm_complex_apply (z : ℂ) : Algebra.norm ℝ z = Complex.normSq z := by
  

Proof state:
z : ℂ
⊢ (norm ℝ) z = normSq z

Next tactic:
rw [Algebra.norm_eq_matrix_det Complex.basisOneI, Algebra.leftMulMatrix_complex,
    Matrix.det_fin_two, normSq_apply]
theorem Algebra.norm_complex_apply (z : ℂ) : Algebra.norm ℝ z = Complex.normSq z := by
  rw [Algebra.norm_eq_matrix_det Complex.basisOneI, Algebra.leftMulMatrix_complex,
    Matrix.det_fin_two, normSq_apply]
  

Proof state:
z : ℂ
⊢ Matrix.of ![![z.re, -z.im], ![z.im, z.re]] 0 0 * Matrix.of ![![z.re, -z.im], ![z.im, z.re]] 1 1 -
      Matrix.of ![![z.re, -z.im], ![z.im, z.re]] 0 1 * Matrix.of ![![z.re, -z.im], ![z.im, z.re]] 1 0 =
    z.re * z.re + z.im * z.im

Next tactic:
simp
theorem Int.measurable_floor [OpensMeasurableSpace R] : Measurable (Int.floor : R → ℤ) :=
  measurable_to_countable fun x => by
    

Proof state:
α : Type u_1
R : Type u_2
inst✝⁶ : MeasurableSpace α
inst✝⁵ : LinearOrderedRing R
inst✝⁴ : FloorRing R
inst✝³ : TopologicalSpace R
inst✝² : OrderTopology R
inst✝¹ : MeasurableSpace R
inst✝ : OpensMeasurableSpace R
x : R
⊢ MeasurableSet (floor ⁻¹' {⌊x⌋})

Next tactic:
simpa only [Int.preimage_floor_singleton] using measurableSet_Ico
theorem Int.measurable_ceil [OpensMeasurableSpace R] : Measurable (Int.ceil : R → ℤ) :=
  measurable_to_countable fun x => by
    

Proof state:
α : Type u_1
R : Type u_2
inst✝⁶ : MeasurableSpace α
inst✝⁵ : LinearOrderedRing R
inst✝⁴ : FloorRing R
inst✝³ : TopologicalSpace R
inst✝² : OrderTopology R
inst✝¹ : MeasurableSpace R
inst✝ : OpensMeasurableSpace R
x : R
⊢ MeasurableSet (ceil ⁻¹' {⌈x⌉})

Next tactic:
simpa only [Int.preimage_ceil_singleton] using measurableSet_Ioc
theorem measurable_fract [BorelSpace R] : Measurable (Int.fract : R → R) := by
  

Proof state:
α : Type u_1
R : Type u_2
inst✝⁶ : MeasurableSpace α
inst✝⁵ : LinearOrderedRing R
inst✝⁴ : FloorRing R
inst✝³ : TopologicalSpace R
inst✝² : OrderTopology R
inst✝¹ : MeasurableSpace R
inst✝ : BorelSpace R
⊢ Measurable Int.fract

Next tactic:
intro s hs
theorem measurable_fract [BorelSpace R] : Measurable (Int.fract : R → R) := by
  intro s hs
  

Proof state:
α : Type u_1
R : Type u_2
inst✝⁶ : MeasurableSpace α
inst✝⁵ : LinearOrderedRing R
inst✝⁴ : FloorRing R
inst✝³ : TopologicalSpace R
inst✝² : OrderTopology R
inst✝¹ : MeasurableSpace R
inst✝ : BorelSpace R
s : Set R
hs : MeasurableSet s
⊢ MeasurableSet (Int.fract ⁻¹' s)

Next tactic:
rw [Int.preimage_fract]
theorem measurable_fract [BorelSpace R] : Measurable (Int.fract : R → R) := by
  intro s hs
  rw [Int.preimage_fract]
  

Proof state:
α : Type u_1
R : Type u_2
inst✝⁶ : MeasurableSpace α
inst✝⁵ : LinearOrderedRing R
inst✝⁴ : FloorRing R
inst✝³ : TopologicalSpace R
inst✝² : OrderTopology R
inst✝¹ : MeasurableSpace R
inst✝ : BorelSpace R
s : Set R
hs : MeasurableSet s
⊢ MeasurableSet (⋃ m, (fun x => x - ↑m) ⁻¹' (s ∩ Ico 0 1))

Next tactic:
exact MeasurableSet.iUnion fun z => measurable_id.sub_const _ (hs.inter measurableSet_Ico)
theorem MeasurableSet.image_fract [BorelSpace R] {s : Set R} (hs : MeasurableSet s) :
    MeasurableSet (Int.fract '' s) := by
  

Proof state:
α : Type u_1
R : Type u_2
inst✝⁶ : MeasurableSpace α
inst✝⁵ : LinearOrderedRing R
inst✝⁴ : FloorRing R
inst✝³ : TopologicalSpace R
inst✝² : OrderTopology R
inst✝¹ : MeasurableSpace R
inst✝ : BorelSpace R
s : Set R
hs : MeasurableSet s
⊢ MeasurableSet (Int.fract '' s)

Next tactic:
simp only [Int.image_fract, sub_eq_add_neg, image_add_right']
theorem MeasurableSet.image_fract [BorelSpace R] {s : Set R} (hs : MeasurableSet s) :
    MeasurableSet (Int.fract '' s) := by
  simp only [Int.image_fract, sub_eq_add_neg, image_add_right']
  

Proof state:
α : Type u_1
R : Type u_2
inst✝⁶ : MeasurableSpace α
inst✝⁵ : LinearOrderedRing R
inst✝⁴ : FloorRing R
inst✝³ : TopologicalSpace R
inst✝² : OrderTopology R
inst✝¹ : MeasurableSpace R
inst✝ : BorelSpace R
s : Set R
hs : MeasurableSet s
⊢ MeasurableSet (⋃ m, (fun x => x + ↑m) ⁻¹' s ∩ Ico 0 1)

Next tactic:
exact MeasurableSet.iUnion fun m => (measurable_add_const _ hs).inter measurableSet_Ico
theorem Nat.measurable_floor : Measurable (Nat.floor : R → ℕ) :=
  measurable_to_countable fun n => by
    

Proof state:
α : Type u_1
R : Type u_2
inst✝⁶ : MeasurableSpace α
inst✝⁵ : LinearOrderedSemiring R
inst✝⁴ : FloorSemiring R
inst✝³ : TopologicalSpace R
inst✝² : OrderTopology R
inst✝¹ : MeasurableSpace R
inst✝ : OpensMeasurableSpace R
f : α → R
n : R
⊢ MeasurableSet (floor ⁻¹' {⌊n⌋₊})

Next tactic:
rcases eq_or_ne ⌊n⌋₊ 0 with h | h
theorem Nat.measurable_floor : Measurable (Nat.floor : R → ℕ) :=
  measurable_to_countable fun n => by
    rcases eq_or_ne ⌊n⌋₊ 0 with h | h <;> 

Proof state:
case inl
α : Type u_1
R : Type u_2
inst✝⁶ : MeasurableSpace α
inst✝⁵ : LinearOrderedSemiring R
inst✝⁴ : FloorSemiring R
inst✝³ : TopologicalSpace R
inst✝² : OrderTopology R
inst✝¹ : MeasurableSpace R
inst✝ : OpensMeasurableSpace R
f : α → R
n : R
h : ⌊n⌋₊ = 0
⊢ MeasurableSet (floor ⁻¹' {⌊n⌋₊})

Next tactic:
simp [h, Nat.preimage_floor_of_ne_zero, -floor_eq_zero]
theorem Nat.measurable_floor : Measurable (Nat.floor : R → ℕ) :=
  measurable_to_countable fun n => by
    rcases eq_or_ne ⌊n⌋₊ 0 with h | h <;> 

Proof state:
case inr
α : Type u_1
R : Type u_2
inst✝⁶ : MeasurableSpace α
inst✝⁵ : LinearOrderedSemiring R
inst✝⁴ : FloorSemiring R
inst✝³ : TopologicalSpace R
inst✝² : OrderTopology R
inst✝¹ : MeasurableSpace R
inst✝ : OpensMeasurableSpace R
f : α → R
n : R
h : ⌊n⌋₊ ≠ 0
⊢ MeasurableSet (floor ⁻¹' {⌊n⌋₊})

Next tactic:
simp [h, Nat.preimage_floor_of_ne_zero, -floor_eq_zero]
theorem Nat.measurable_ceil : Measurable (Nat.ceil : R → ℕ) :=
  measurable_to_countable fun n => by
    

Proof state:
α : Type u_1
R : Type u_2
inst✝⁶ : MeasurableSpace α
inst✝⁵ : LinearOrderedSemiring R
inst✝⁴ : FloorSemiring R
inst✝³ : TopologicalSpace R
inst✝² : OrderTopology R
inst✝¹ : MeasurableSpace R
inst✝ : OpensMeasurableSpace R
f : α → R
n : R
⊢ MeasurableSet (ceil ⁻¹' {⌈n⌉₊})

Next tactic:
rcases eq_or_ne ⌈n⌉₊ 0 with h | h
theorem Nat.measurable_ceil : Measurable (Nat.ceil : R → ℕ) :=
  measurable_to_countable fun n => by
    rcases eq_or_ne ⌈n⌉₊ 0 with h | h <;> 

Proof state:
case inl
α : Type u_1
R : Type u_2
inst✝⁶ : MeasurableSpace α
inst✝⁵ : LinearOrderedSemiring R
inst✝⁴ : FloorSemiring R
inst✝³ : TopologicalSpace R
inst✝² : OrderTopology R
inst✝¹ : MeasurableSpace R
inst✝ : OpensMeasurableSpace R
f : α → R
n : R
h : ⌈n⌉₊ = 0
⊢ MeasurableSet (ceil ⁻¹' {⌈n⌉₊})

Next tactic:
simp_all [h, Nat.preimage_ceil_of_ne_zero, -ceil_eq_zero]
theorem Nat.measurable_ceil : Measurable (Nat.ceil : R → ℕ) :=
  measurable_to_countable fun n => by
    rcases eq_or_ne ⌈n⌉₊ 0 with h | h <;> 

Proof state:
case inr
α : Type u_1
R : Type u_2
inst✝⁶ : MeasurableSpace α
inst✝⁵ : LinearOrderedSemiring R
inst✝⁴ : FloorSemiring R
inst✝³ : TopologicalSpace R
inst✝² : OrderTopology R
inst✝¹ : MeasurableSpace R
inst✝ : OpensMeasurableSpace R
f : α → R
n : R
h : ⌈n⌉₊ ≠ 0
⊢ MeasurableSet (ceil ⁻¹' {⌈n⌉₊})

Next tactic:
simp_all [h, Nat.preimage_ceil_of_ne_zero, -ceil_eq_zero]
/--
A monoid is *graphic* if, for all `x` and `y`, the *graphic identity*
`(x * y) * x = x * y` holds.  For a unital shelf, this graphic
identity holds.
-/
lemma act_act_self_eq (x y : S) : (x ◃ y) ◃ x = x ◃ y := by
  

Proof state:
S : Type u_1
inst✝ : UnitalShelf S
x y : S
⊢ (x ◃ y) ◃ x = x ◃ y

Next tactic:
have h : (x ◃ y) ◃ x = (x ◃ y) ◃ (x ◃ 1) := by rw [act_one]
/--
A monoid is *graphic* if, for all `x` and `y`, the *graphic identity*
`(x * y) * x = x * y` holds.  For a unital shelf, this graphic
identity holds.
-/
lemma act_act_self_eq (x y : S) : (x ◃ y) ◃ x = x ◃ y := by
  have h : (x ◃ y) ◃ x = (x ◃ y) ◃ (x ◃ 1) := by 

Proof state:
S : Type u_1
inst✝ : UnitalShelf S
x y : S
⊢ (x ◃ y) ◃ x = (x ◃ y) ◃ x ◃ 1

Next tactic:
rw [act_one]
/--
A monoid is *graphic* if, for all `x` and `y`, the *graphic identity*
`(x * y) * x = x * y` holds.  For a unital shelf, this graphic
identity holds.
-/
lemma act_act_self_eq (x y : S) : (x ◃ y) ◃ x = x ◃ y := by
  have h : (x ◃ y) ◃ x = (x ◃ y) ◃ (x ◃ 1) := by rw [act_one]
  

Proof state:
S : Type u_1
inst✝ : UnitalShelf S
x y : S
h : (x ◃ y) ◃ x = (x ◃ y) ◃ x ◃ 1
⊢ (x ◃ y) ◃ x = x ◃ y

Next tactic:
rw [h, ← Shelf.self_distrib, act_one]
lemma act_idem (x : S) : (x ◃ x) = x := by 

Proof state:
S : Type u_1
inst✝ : UnitalShelf S
x : S
⊢ x ◃ x = x

Next tactic:
rw [← act_one x, ← Shelf.self_distrib, act_one, act_one]
lemma act_self_act_eq (x y : S) : x ◃ (x ◃ y) = x ◃ y := by
  

Proof state:
S : Type u_1
inst✝ : UnitalShelf S
x y : S
⊢ x ◃ x ◃ y = x ◃ y

Next tactic:
have h : x ◃ (x ◃ y) = (x ◃ 1) ◃ (x ◃ y) := by rw [act_one]
lemma act_self_act_eq (x y : S) : x ◃ (x ◃ y) = x ◃ y := by
  have h : x ◃ (x ◃ y) = (x ◃ 1) ◃ (x ◃ y) := by 

Proof state:
S : Type u_1
inst✝ : UnitalShelf S
x y : S
⊢ x ◃ x ◃ y = (x ◃ 1) ◃ x ◃ y

Next tactic:
rw [act_one]
lemma act_self_act_eq (x y : S) : x ◃ (x ◃ y) = x ◃ y := by
  have h : x ◃ (x ◃ y) = (x ◃ 1) ◃ (x ◃ y) := by rw [act_one]
  

Proof state:
S : Type u_1
inst✝ : UnitalShelf S
x y : S
h : x ◃ x ◃ y = (x ◃ 1) ◃ x ◃ y
⊢ x ◃ x ◃ y = x ◃ y

Next tactic:
rw [h, ← Shelf.self_distrib, one_act]
/--
The associativity of a unital shelf comes for free.
-/
lemma assoc (x y z : S) : (x ◃ y) ◃ z = x ◃ y ◃ z := by
  

Proof state:
S : Type u_1
inst✝ : UnitalShelf S
x y z : S
⊢ (x ◃ y) ◃ z = x ◃ y ◃ z

Next tactic:
rw [self_distrib, self_distrib, act_act_self_eq, act_self_act_eq]
theorem left_cancel (x : R) {y y' : R} : x ◃ y = x ◃ y' ↔ y = y' := by
  

Proof state:
R : Type u_1
inst✝ : Rack R
x y y' : R
⊢ x ◃ y = x ◃ y' ↔ y = y'

Next tactic:
constructor
theorem left_cancel (x : R) {y y' : R} : x ◃ y = x ◃ y' ↔ y = y' := by
  constructor
  

Proof state:
case mp
R : Type u_1
inst✝ : Rack R
x y y' : R
⊢ x ◃ y = x ◃ y' → y = y'
case mpr R : Type u_1 inst✝ : Rack R x y y' : R ⊢ y = y' → x ◃ y = x ◃ y'

Next tactic:
apply (act' x).injective
theorem left_cancel (x : R) {y y' : R} : x ◃ y = x ◃ y' ↔ y = y' := by
  constructor
  apply (act' x).injective
  

Proof state:
case mpr
R : Type u_1
inst✝ : Rack R
x y y' : R
⊢ y = y' → x ◃ y = x ◃ y'

Next tactic:
rintro rfl
theorem left_cancel (x : R) {y y' : R} : x ◃ y = x ◃ y' ↔ y = y' := by
  constructor
  apply (act' x).injective
  rintro rfl
  

Proof state:
case mpr
R : Type u_1
inst✝ : Rack R
x y : R
⊢ x ◃ y = x ◃ y

Next tactic:
rfl
theorem left_cancel_inv (x : R) {y y' : R} : x ◃⁻¹ y = x ◃⁻¹ y' ↔ y = y' := by
  

Proof state:
R : Type u_1
inst✝ : Rack R
x y y' : R
⊢ x ◃⁻¹ y = x ◃⁻¹ y' ↔ y = y'

Next tactic:
constructor
theorem left_cancel_inv (x : R) {y y' : R} : x ◃⁻¹ y = x ◃⁻¹ y' ↔ y = y' := by
  constructor
  

Proof state:
case mp
R : Type u_1
inst✝ : Rack R
x y y' : R
⊢ x ◃⁻¹ y = x ◃⁻¹ y' → y = y'
case mpr R : Type u_1 inst✝ : Rack R x y y' : R ⊢ y = y' → x ◃⁻¹ y = x ◃⁻¹ y'

Next tactic:
apply (act' x).symm.injective
theorem left_cancel_inv (x : R) {y y' : R} : x ◃⁻¹ y = x ◃⁻¹ y' ↔ y = y' := by
  constructor
  apply (act' x).symm.injective
  

Proof state:
case mpr
R : Type u_1
inst✝ : Rack R
x y y' : R
⊢ y = y' → x ◃⁻¹ y = x ◃⁻¹ y'

Next tactic:
rintro rfl
theorem left_cancel_inv (x : R) {y y' : R} : x ◃⁻¹ y = x ◃⁻¹ y' ↔ y = y' := by
  constructor
  apply (act' x).symm.injective
  rintro rfl
  

Proof state:
case mpr
R : Type u_1
inst✝ : Rack R
x y : R
⊢ x ◃⁻¹ y = x ◃⁻¹ y

Next tactic:
rfl
theorem self_distrib_inv {x y z : R} : x ◃⁻¹ y ◃⁻¹ z = (x ◃⁻¹ y) ◃⁻¹ x ◃⁻¹ z := by
  

Proof state:
R : Type u_1
inst✝ : Rack R
x y z : R
⊢ x ◃⁻¹ y ◃⁻¹ z = (x ◃⁻¹ y) ◃⁻¹ x ◃⁻¹ z

Next tactic:
rw [← left_cancel (x ◃⁻¹ y), right_inv, ← left_cancel x, right_inv, self_distrib]
theorem self_distrib_inv {x y z : R} : x ◃⁻¹ y ◃⁻¹ z = (x ◃⁻¹ y) ◃⁻¹ x ◃⁻¹ z := by
  rw [← left_cancel (x ◃⁻¹ y), right_inv, ← left_cancel x, right_inv, self_distrib]
  

Proof state:
R : Type u_1
inst✝ : Rack R
x y z : R
⊢ (x ◃ x ◃⁻¹ y) ◃ x ◃ x ◃⁻¹ y ◃⁻¹ z = z

Next tactic:
repeat' rw [right_inv]
theorem self_distrib_inv {x y z : R} : x ◃⁻¹ y ◃⁻¹ z = (x ◃⁻¹ y) ◃⁻¹ x ◃⁻¹ z := by
  rw [← left_cancel (x ◃⁻¹ y), right_inv, ← left_cancel x, right_inv, self_distrib]
  repeat' 

Proof state:
R : Type u_1
inst✝ : Rack R
x y z : R
⊢ (x ◃ x ◃⁻¹ y) ◃ x ◃ x ◃⁻¹ y ◃⁻¹ z = z

Next tactic:
rw [right_inv]
theorem self_distrib_inv {x y z : R} : x ◃⁻¹ y ◃⁻¹ z = (x ◃⁻¹ y) ◃⁻¹ x ◃⁻¹ z := by
  rw [← left_cancel (x ◃⁻¹ y), right_inv, ← left_cancel x, right_inv, self_distrib]
  repeat' 

Proof state:
R : Type u_1
inst✝ : Rack R
x y z : R
⊢ y ◃ x ◃ x ◃⁻¹ y ◃⁻¹ z = z

Next tactic:
rw [right_inv]
theorem self_distrib_inv {x y z : R} : x ◃⁻¹ y ◃⁻¹ z = (x ◃⁻¹ y) ◃⁻¹ x ◃⁻¹ z := by
  rw [← left_cancel (x ◃⁻¹ y), right_inv, ← left_cancel x, right_inv, self_distrib]
  repeat' 

Proof state:
R : Type u_1
inst✝ : Rack R
x y z : R
⊢ y ◃ y ◃⁻¹ z = z

Next tactic:
rw [right_inv]
/-- The *adjoint action* of a rack on itself is `op'`, and the adjoint
action of `x ◃ y` is the conjugate of the action of `y` by the action
of `x`. It is another way to understand the self-distributivity axiom.

This is used in the natural rack homomorphism `toConj` from `R` to
`Conj (R ≃ R)` defined by `op'`.
-/
theorem ad_conj {R : Type*} [Rack R] (x y : R) : act' (x ◃ y) = act' x * act' y * (act' x)⁻¹ := by
  

Proof state:
R✝ : Type u_1
inst✝¹ : Rack R✝
R : Type u_2
inst✝ : Rack R
x y : R
⊢ act' (x ◃ y) = act' x * act' y * (act' x)⁻¹

Next tactic:
rw [eq_mul_inv_iff_mul_eq]
/-- The *adjoint action* of a rack on itself is `op'`, and the adjoint
action of `x ◃ y` is the conjugate of the action of `y` by the action
of `x`. It is another way to understand the self-distributivity axiom.

This is used in the natural rack homomorphism `toConj` from `R` to
`Conj (R ≃ R)` defined by `op'`.
-/
theorem ad_conj {R : Type*} [Rack R] (x y : R) : act' (x ◃ y) = act' x * act' y * (act' x)⁻¹ := by
  rw [eq_mul_inv_iff_mul_eq]; 

Proof state:
R✝ : Type u_1
inst✝¹ : Rack R✝
R : Type u_2
inst✝ : Rack R
x y : R
⊢ act' (x ◃ y) * act' x = act' x * act' y

Next tactic:
ext z
/-- The *adjoint action* of a rack on itself is `op'`, and the adjoint
action of `x ◃ y` is the conjugate of the action of `y` by the action
of `x`. It is another way to understand the self-distributivity axiom.

This is used in the natural rack homomorphism `toConj` from `R` to
`Conj (R ≃ R)` defined by `op'`.
-/
theorem ad_conj {R : Type*} [Rack R] (x y : R) : act' (x ◃ y) = act' x * act' y * (act' x)⁻¹ := by
  rw [eq_mul_inv_iff_mul_eq]; ext z
  

Proof state:
case H
R✝ : Type u_1
inst✝¹ : Rack R✝
R : Type u_2
inst✝ : Rack R
x y z : R
⊢ (act' (x ◃ y) * act' x) z = (act' x * act' y) z

Next tactic:
apply self_distrib.symm
/-- The opposite rack, swapping the roles of `◃` and `◃⁻¹`.
-/
instance oppositeRack : Rack Rᵐᵒᵖ
    where
  act x y := op (invAct (unop x) (unop y))
  self_distrib := by
    

Proof state:
R : Type u_1
inst✝ : Rack R
⊢ ∀ {x y z : Rᵐᵒᵖ},
    (fun x y => op (unop x ◃⁻¹ unop y)) x ((fun x y => op (unop x ◃⁻¹ unop y)) y z) =
      (fun x y => op (unop x ◃⁻¹ unop y)) ((fun x y => op (unop x ◃⁻¹ unop y)) x y)
        ((fun x y => op (unop x ◃⁻¹ unop y)) x z)

Next tactic:
intro x y z
/-- The opposite rack, swapping the roles of `◃` and `◃⁻¹`.
-/
instance oppositeRack : Rack Rᵐᵒᵖ
    where
  act x y := op (invAct (unop x) (unop y))
  self_distrib := by
    intro x y z
    

Proof state:
R : Type u_1
inst✝ : Rack R
x y z : Rᵐᵒᵖ
⊢ (fun x y => op (unop x ◃⁻¹ unop y)) x ((fun x y => op (unop x ◃⁻¹ unop y)) y z) =
    (fun x y => op (unop x ◃⁻¹ unop y)) ((fun x y => op (unop x ◃⁻¹ unop y)) x y)
      ((fun x y => op (unop x ◃⁻¹ unop y)) x z)

Next tactic:
induction x using MulOpposite.rec'
/-- The opposite rack, swapping the roles of `◃` and `◃⁻¹`.
-/
instance oppositeRack : Rack Rᵐᵒᵖ
    where
  act x y := op (invAct (unop x) (unop y))
  self_distrib := by
    intro x y z
    induction x using MulOpposite.rec'
    

Proof state:
case h
R : Type u_1
inst✝ : Rack R
y z : Rᵐᵒᵖ
X✝ : R
⊢ (fun x y => op (unop x ◃⁻¹ unop y)) (op X✝) ((fun x y => op (unop x ◃⁻¹ unop y)) y z) =
    (fun x y => op (unop x ◃⁻¹ unop y)) ((fun x y => op (unop x ◃⁻¹ unop y)) (op X✝) y)
      ((fun x y => op (unop x ◃⁻¹ unop y)) (op X✝) z)

Next tactic:
induction y using MulOpposite.rec'
/-- The opposite rack, swapping the roles of `◃` and `◃⁻¹`.
-/
instance oppositeRack : Rack Rᵐᵒᵖ
    where
  act x y := op (invAct (unop x) (unop y))
  self_distrib := by
    intro x y z
    induction x using MulOpposite.rec'
    induction y using MulOpposite.rec'
    

Proof state:
case h.h
R : Type u_1
inst✝ : Rack R
z : Rᵐᵒᵖ
X✝¹ X✝ : R
⊢ (fun x y => op (unop x ◃⁻¹ unop y)) (op X✝¹) ((fun x y => op (unop x ◃⁻¹ unop y)) (op X✝) z) =
    (fun x y => op (unop x ◃⁻¹ unop y)) ((fun x y => op (unop x ◃⁻¹ unop y)) (op X✝¹) (op X✝))
      ((fun x y => op (unop x ◃⁻¹ unop y)) (op X✝¹) z)

Next tactic:
induction z using MulOpposite.rec'
/-- The opposite rack, swapping the roles of `◃` and `◃⁻¹`.
-/
instance oppositeRack : Rack Rᵐᵒᵖ
    where
  act x y := op (invAct (unop x) (unop y))
  self_distrib := by
    intro x y z
    induction x using MulOpposite.rec'
    induction y using MulOpposite.rec'
    induction z using MulOpposite.rec'
    

Proof state:
case h.h.h
R : Type u_1
inst✝ : Rack R
X✝² X✝¹ X✝ : R
⊢ (fun x y => op (unop x ◃⁻¹ unop y)) (op X✝²) ((fun x y => op (unop x ◃⁻¹ unop y)) (op X✝¹) (op X✝)) =
    (fun x y => op (unop x ◃⁻¹ unop y)) ((fun x y => op (unop x ◃⁻¹ unop y)) (op X✝²) (op X✝¹))
      ((fun x y => op (unop x ◃⁻¹ unop y)) (op X✝²) (op X✝))

Next tactic:
simp only [op_inj, unop_op, op_unop]
/-- The opposite rack, swapping the roles of `◃` and `◃⁻¹`.
-/
instance oppositeRack : Rack Rᵐᵒᵖ
    where
  act x y := op (invAct (unop x) (unop y))
  self_distrib := by
    intro x y z
    induction x using MulOpposite.rec'
    induction y using MulOpposite.rec'
    induction z using MulOpposite.rec'
    simp only [op_inj, unop_op, op_unop]
    

Proof state:
case h.h.h
R : Type u_1
inst✝ : Rack R
X✝² X✝¹ X✝ : R
⊢ X✝² ◃⁻¹ X✝¹ ◃⁻¹ X✝ = (X✝² ◃⁻¹ X✝¹) ◃⁻¹ X✝² ◃⁻¹ X✝

Next tactic:
rw [self_distrib_inv]
/-- The opposite rack, swapping the roles of `◃` and `◃⁻¹`.
-/
instance oppositeRack : Rack Rᵐᵒᵖ
    where
  act x y := op (invAct (unop x) (unop y))
  self_distrib := by
    intro x y z
    induction x using MulOpposite.rec'
    induction y using MulOpposite.rec'
    induction z using MulOpposite.rec'
    simp only [op_inj, unop_op, op_unop]
    rw [self_distrib_inv]
  invAct x y := op (Shelf.act (unop x) (unop y))
  left_inv := MulOpposite.rec' fun x => MulOpposite.rec' fun y => by 

Proof state:
R : Type u_1
inst✝ : Rack R
x y : R
⊢ (fun x y => op (unop x ◃ unop y)) (op x) (op x ◃ op y) = op y

Next tactic:
simp
/-- The opposite rack, swapping the roles of `◃` and `◃⁻¹`.
-/
instance oppositeRack : Rack Rᵐᵒᵖ
    where
  act x y := op (invAct (unop x) (unop y))
  self_distrib := by
    intro x y z
    induction x using MulOpposite.rec'
    induction y using MulOpposite.rec'
    induction z using MulOpposite.rec'
    simp only [op_inj, unop_op, op_unop]
    rw [self_distrib_inv]
  invAct x y := op (Shelf.act (unop x) (unop y))
  left_inv := MulOpposite.rec' fun x => MulOpposite.rec' fun y => by simp
  right_inv := MulOpposite.rec' fun x => MulOpposite.rec' fun y => by 

Proof state:
R : Type u_1
inst✝ : Rack R
x y : R
⊢ op x ◃ (fun x y => op (unop x ◃ unop y)) (op x) (op y) = op y

Next tactic:
simp
@[simp]
theorem self_act_act_eq {x y : R} : (x ◃ x) ◃ y = x ◃ y := by 

Proof state:
R : Type u_1
inst✝ : Rack R
x y : R
⊢ (x ◃ x) ◃ y = x ◃ y

Next tactic:
rw [← right_inv x y, ← self_distrib]
@[simp]
theorem self_invAct_invAct_eq {x y : R} : (x ◃⁻¹ x) ◃⁻¹ y = x ◃⁻¹ y := by
  

Proof state:
R : Type u_1
inst✝ : Rack R
x y : R
⊢ (x ◃⁻¹ x) ◃⁻¹ y = x ◃⁻¹ y

Next tactic:
have h := @self_act_act_eq _ _ (op x) (op y)