l3lab/ntp-mathlib huggingface dataset:
@[simp]
theorem self_invAct_invAct_eq {x y : R} : (x ◃⁻¹ x) ◃⁻¹ y = x ◃⁻¹ y := by
  have h := @self_act_act_eq _ _ (op x) (op y)
  

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

Next tactic:
simpa using h
@[simp]
theorem self_act_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:
rw [← left_cancel (x ◃ x)]
@[simp]
theorem self_act_invAct_eq {x y : R} : (x ◃ x) ◃⁻¹ y = x ◃⁻¹ y := by
  rw [← left_cancel (x ◃ x)]
  

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

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

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

Next tactic:
rw [self_act_act_eq]
@[simp]
theorem self_act_invAct_eq {x y : R} : (x ◃ x) ◃⁻¹ y = x ◃⁻¹ y := by
  rw [← left_cancel (x ◃ x)]
  rw [right_inv]
  rw [self_act_act_eq]
  

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

Next tactic:
rw [right_inv]
@[simp]
theorem self_invAct_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:
have h := @self_act_invAct_eq _ _ (op x) (op y)
@[simp]
theorem self_invAct_act_eq {x y : R} : (x ◃⁻¹ x) ◃ y = x ◃ y := by
  have h := @self_act_invAct_eq _ _ (op x) (op y)
  

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

Next tactic:
simpa using h
theorem self_act_eq_iff_eq {x y : R} : x ◃ x = y ◃ y ↔ x = y := by
  

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

Next tactic:
constructor
theorem self_act_eq_iff_eq {x y : R} : x ◃ x = y ◃ y ↔ x = y := by
  constructor; 

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

Next tactic:
swap
theorem self_act_eq_iff_eq {x y : R} : x ◃ x = y ◃ y ↔ x = y := by
  constructor; swap; 

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

Next tactic:
rintro rfl
theorem self_act_eq_iff_eq {x y : R} : x ◃ x = y ◃ y ↔ x = y := by
  constructor; swap; rintro rfl; 

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

Next tactic:
rfl
theorem self_act_eq_iff_eq {x y : R} : x ◃ x = y ◃ y ↔ x = y := by
  constructor; swap; rintro rfl; rfl
  

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

Next tactic:
intro h
theorem self_act_eq_iff_eq {x y : R} : x ◃ x = y ◃ y ↔ x = y := by
  constructor; swap; rintro rfl; rfl
  intro h
  

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

Next tactic:
trans (x ◃ x) ◃⁻¹ x ◃ x
theorem self_act_eq_iff_eq {x y : R} : x ◃ x = y ◃ y ↔ x = y := by
  constructor; swap; rintro rfl; rfl
  intro h
  trans (x ◃ x) ◃⁻¹ x ◃ x
  

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

Next tactic:
rw [← left_cancel (x ◃ x), right_inv, self_act_act_eq]
theorem self_act_eq_iff_eq {x y : R} : x ◃ x = y ◃ y ↔ x = y := by
  constructor; swap; rintro rfl; rfl
  intro h
  trans (x ◃ x) ◃⁻¹ x ◃ x
  rw [← left_cancel (x ◃ x), right_inv, self_act_act_eq]
  

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

Next tactic:
rw [h, ← left_cancel (y ◃ y), right_inv, self_act_act_eq]
theorem self_invAct_eq_iff_eq {x y : R} : x ◃⁻¹ x = y ◃⁻¹ y ↔ x = y := by
  

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

Next tactic:
have h := @self_act_eq_iff_eq _ _ (op x) (op y)
theorem self_invAct_eq_iff_eq {x y : R} : x ◃⁻¹ x = y ◃⁻¹ y ↔ x = y := by
  have h := @self_act_eq_iff_eq _ _ (op x) (op y)
  

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

Next tactic:
simpa using h
/-- The map `x ↦ x ◃ x` is a bijection.  (This has applications for the
regular isotopy version of the Reidemeister I move for knot diagrams.)
-/
def selfApplyEquiv (R : Type*) [Rack R] : R ≃ R
    where
  toFun x := x ◃ x
  invFun x := x ◃⁻¹ x
  left_inv x := by 

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

Next tactic:
simp
/-- The map `x ↦ x ◃ x` is a bijection.  (This has applications for the
regular isotopy version of the Reidemeister I move for knot diagrams.)
-/
def selfApplyEquiv (R : Type*) [Rack R] : R ≃ R
    where
  toFun x := x ◃ x
  invFun x := x ◃⁻¹ x
  left_inv x := by simp
  right_inv x := by 

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

Next tactic:
simp
theorem involutory_invAct_eq_act {R : Type*} [Rack R] (h : IsInvolutory R) (x y : R) :
    x ◃⁻¹ y = x ◃ y := by
  

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

Next tactic:
rw [← left_cancel x, right_inv, h x]
/-- Associative racks are uninteresting.
-/
theorem assoc_iff_id {R : Type*} [Rack R] {x y z : R} : x ◃ y ◃ z = (x ◃ y) ◃ z ↔ x ◃ z = z := by
  

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

Next tactic:
rw [self_distrib]
/-- Associative racks are uninteresting.
-/
theorem assoc_iff_id {R : Type*} [Rack R] {x y z : R} : x ◃ y ◃ z = (x ◃ y) ◃ z ↔ x ◃ z = z := by
  rw [self_distrib]
  

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

Next tactic:
rw [left_cancel]
/-- The identity homomorphism -/
def id (S : Type*) [Shelf S] : S →◃ S where
  toFun := fun x => x
  map_act' := by 

Proof state:
S₁ : Type u_1
S₂ : Type u_2
S₃ : Type u_3
inst✝³ : Shelf S₁
inst✝² : Shelf S₂
inst✝¹ : Shelf S₃
S : Type u_4
inst✝ : Shelf S
⊢ ∀ {x y : S}, (fun x => x) (x ◃ y) = (fun x => x) x ◃ (fun x => x) y

Next tactic:
simp
/-- The composition of shelf homomorphisms -/
def comp (g : S₂ →◃ S₃) (f : S₁ →◃ S₂) : S₁ →◃ S₃
    where
  toFun := g.toFun ∘ f.toFun
  map_act' := by 

Proof state:
S₁ : Type u_1
S₂ : Type u_2
S₃ : Type u_3
inst✝² : Shelf S₁
inst✝¹ : Shelf S₂
inst✝ : Shelf S₃
g : S₂ →◃ S₃
f : S₁ →◃ S₂
⊢ ∀ {x y : S₁}, (g.toFun ∘ f.toFun) (x ◃ y) = (g.toFun ∘ f.toFun) x ◃ (g.toFun ∘ f.toFun) y

Next tactic:
simp
@[simp]
theorem fix_inv {x : Q} : x ◃⁻¹ x = x := by
  

Proof state:
Q : Type u_1
inst✝ : Quandle Q
x : Q
⊢ x ◃⁻¹ x = x

Next tactic:
rw [← left_cancel x]
@[simp]
theorem fix_inv {x : Q} : x ◃⁻¹ x = x := by
  rw [← left_cancel x]
  

Proof state:
Q : Type u_1
inst✝ : Quandle Q
x : Q
⊢ x ◃ x ◃⁻¹ x = x ◃ x

Next tactic:
simp
instance oppositeQuandle : Quandle Qᵐᵒᵖ where
  fix := by
    

Proof state:
Q : Type u_1
inst✝ : Quandle Q
⊢ ∀ {x : Qᵐᵒᵖ}, x ◃ x = x

Next tactic:
intro x
instance oppositeQuandle : Quandle Qᵐᵒᵖ where
  fix := by
    intro x
    

Proof state:
Q : Type u_1
inst✝ : Quandle Q
x : Qᵐᵒᵖ
⊢ x ◃ x = x

Next tactic:
induction' x using MulOpposite.rec'
instance oppositeQuandle : Quandle Qᵐᵒᵖ where
  fix := by
    intro x
    induction' x using MulOpposite.rec'
    

Proof state:
case h
Q : Type u_1
inst✝ : Quandle Q
X✝ : Q
⊢ op X✝ ◃ op X✝ = op X✝

Next tactic:
simp
instance Conj.quandle (G : Type*) [Group G] : Quandle (Conj G)
    where
  act x := @MulAut.conj G _ x
  self_distrib := by
    

Proof state:
Q : Type u_1
inst✝¹ : Quandle Q
G : Type u_2
inst✝ : Group G
⊢ ∀ {x y z : Conj G},
    (fun x => ⇑(MulAut.conj x)) x ((fun x => ⇑(MulAut.conj x)) y z) =
      (fun x => ⇑(MulAut.conj x)) ((fun x => ⇑(MulAut.conj x)) x y) ((fun x => ⇑(MulAut.conj x)) x z)

Next tactic:
intro x y z
instance Conj.quandle (G : Type*) [Group G] : Quandle (Conj G)
    where
  act x := @MulAut.conj G _ x
  self_distrib := by
    intro x y z
    

Proof state:
Q : Type u_1
inst✝¹ : Quandle Q
G : Type u_2
inst✝ : Group G
x y z : Conj G
⊢ (fun x => ⇑(MulAut.conj x)) x ((fun x => ⇑(MulAut.conj x)) y z) =
    (fun x => ⇑(MulAut.conj x)) ((fun x => ⇑(MulAut.conj x)) x y) ((fun x => ⇑(MulAut.conj x)) x z)

Next tactic:
dsimp only [MulAut.conj_apply]
instance Conj.quandle (G : Type*) [Group G] : Quandle (Conj G)
    where
  act x := @MulAut.conj G _ x
  self_distrib := by
    intro x y z
    dsimp only [MulAut.conj_apply]
    

Proof state:
Q : Type u_1
inst✝¹ : Quandle Q
G : Type u_2
inst✝ : Group G
x y z : Conj G
⊢ x * (y * z * y⁻¹) * x⁻¹ = x * y * x⁻¹ * (x * z * x⁻¹) * (x * y * x⁻¹)⁻¹

Next tactic:
simp [mul_assoc]
instance Conj.quandle (G : Type*) [Group G] : Quandle (Conj G)
    where
  act x := @MulAut.conj G _ x
  self_distrib := by
    intro x y z
    dsimp only [MulAut.conj_apply]
    simp [mul_assoc]
  invAct x := (@MulAut.conj G _ x).symm
  left_inv x y := by
    

Proof state:
Q : Type u_1
inst✝¹ : Quandle Q
G : Type u_2
inst✝ : Group G
x y : Conj G
⊢ (fun x => ⇑(MulEquiv.symm (MulAut.conj x))) x (x ◃ y) = y

Next tactic:
simp [act', mul_assoc]
instance Conj.quandle (G : Type*) [Group G] : Quandle (Conj G)
    where
  act x := @MulAut.conj G _ x
  self_distrib := by
    intro x y z
    dsimp only [MulAut.conj_apply]
    simp [mul_assoc]
  invAct x := (@MulAut.conj G _ x).symm
  left_inv x y := by
    simp [act', mul_assoc]
  right_inv x y := by
    

Proof state:
Q : Type u_1
inst✝¹ : Quandle Q
G : Type u_2
inst✝ : Group G
x y : Conj G
⊢ x ◃ (fun x => ⇑(MulEquiv.symm (MulAut.conj x))) x y = y

Next tactic:
simp [act', mul_assoc]
instance Conj.quandle (G : Type*) [Group G] : Quandle (Conj G)
    where
  act x := @MulAut.conj G _ x
  self_distrib := by
    intro x y z
    dsimp only [MulAut.conj_apply]
    simp [mul_assoc]
  invAct x := (@MulAut.conj G _ x).symm
  left_inv x y := by
    simp [act', mul_assoc]
  right_inv x y := by
    simp [act', mul_assoc]
  fix := by 

Proof state:
Q : Type u_1
inst✝¹ : Quandle Q
G : Type u_2
inst✝ : Group G
⊢ ∀ {x : Conj G}, x ◃ x = x

Next tactic:
simp
theorem conj_swap {G : Type*} [Group G] (x y : Conj G) : x ◃ y = y ↔ y ◃ x = x := by
  

Proof state:
Q : Type u_1
inst✝¹ : Quandle Q
G : Type u_2
inst✝ : Group G
x y : Conj G
⊢ x ◃ y = y ↔ y ◃ x = x

Next tactic:
dsimp [Conj] at *
theorem conj_swap {G : Type*} [Group G] (x y : Conj G) : x ◃ y = y ↔ y ◃ x = x := by
  dsimp [Conj] at *; 

Proof state:
Q : Type u_1
inst✝¹ : Quandle Q
G : Type u_2
inst✝ : Group G
x y : Conj G
⊢ x * y * x⁻¹ = y ↔ y * x * y⁻¹ = x

Next tactic:
constructor
theorem conj_swap {G : Type*} [Group G] (x y : Conj G) : x ◃ y = y ↔ y ◃ x = x := by
  dsimp [Conj] at *; constructor
  

Proof state:
case mp
Q : Type u_1
inst✝¹ : Quandle Q
G : Type u_2
inst✝ : Group G
x y : Conj G
⊢ x * y * x⁻¹ = y → y * x * y⁻¹ = x
case mpr Q : Type u_1 inst✝¹ : Quandle Q G : Type u_2 inst✝ : Group G x y : Conj G ⊢ y * x * y⁻¹ = x → x * y * x⁻¹ = y

Next tactic:
repeat' intro h; conv_rhs => rw [eq_mul_inv_of_mul_eq (eq_mul_inv_of_mul_eq h)]; simp
theorem conj_swap {G : Type*} [Group G] (x y : Conj G) : x ◃ y = y ↔ y ◃ x = x := by
  dsimp [Conj] at *; constructor
  repeat' 

Proof state:
case mp
Q : Type u_1
inst✝¹ : Quandle Q
G : Type u_2
inst✝ : Group G
x y : Conj G
⊢ x * y * x⁻¹ = y → y * x * y⁻¹ = x

Next tactic:
intro h
theorem conj_swap {G : Type*} [Group G] (x y : Conj G) : x ◃ y = y ↔ y ◃ x = x := by
  dsimp [Conj] at *; constructor
  repeat' intro h; 

Proof state:
case mp
Q : Type u_1
inst✝¹ : Quandle Q
G : Type u_2
inst✝ : Group G
x y : Conj G
h : x * y * x⁻¹ = y
⊢ y * x * y⁻¹ = x

Next tactic:
conv_rhs => rw [eq_mul_inv_of_mul_eq (eq_mul_inv_of_mul_eq h)]; simp
theorem conj_swap {G : Type*} [Group G] (x y : Conj G) : x ◃ y = y ↔ y ◃ x = x := by
  dsimp [Conj] at *; constructor
  repeat' intro h; conv_rhs => 

Proof state:
Q : Type u_1
inst✝¹ : Quandle Q
G : Type u_2
inst✝ : Group G
x y : Conj G
h : x * y * x⁻¹ = y
| x

Next tactic:
rw [eq_mul_inv_of_mul_eq (eq_mul_inv_of_mul_eq h)]; simp
theorem conj_swap {G : Type*} [Group G] (x y : Conj G) : x ◃ y = y ↔ y ◃ x = x := by
  dsimp [Conj] at *; constructor
  repeat' intro h; conv_rhs => 

Proof state:
Q : Type u_1
inst✝¹ : Quandle Q
G : Type u_2
inst✝ : Group G
x y : Conj G
h : x * y * x⁻¹ = y
| x

Next tactic:
rw [eq_mul_inv_of_mul_eq (eq_mul_inv_of_mul_eq h)]
theorem conj_swap {G : Type*} [Group G] (x y : Conj G) : x ◃ y = y ↔ y ◃ x = x := by
  dsimp [Conj] at *; constructor
  repeat' intro h; conv_rhs => rw [eq_mul_inv_of_mul_eq (eq_mul_inv_of_mul_eq h)]; 

Proof state:
Q : Type u_1
inst✝¹ : Quandle Q
G : Type u_2
inst✝ : Group G
x y : Conj G
h : x * y * x⁻¹ = y
| y * x⁻¹⁻¹ * y⁻¹

Next tactic:
simp
theorem conj_swap {G : Type*} [Group G] (x y : Conj G) : x ◃ y = y ↔ y ◃ x = x := by
  dsimp [Conj] at *; constructor
  repeat' 

Proof state:
case mpr
Q : Type u_1
inst✝¹ : Quandle Q
G : Type u_2
inst✝ : Group G
x y : Conj G
⊢ y * x * y⁻¹ = x → x * y * x⁻¹ = y

Next tactic:
intro h
theorem conj_swap {G : Type*} [Group G] (x y : Conj G) : x ◃ y = y ↔ y ◃ x = x := by
  dsimp [Conj] at *; constructor
  repeat' intro h; 

Proof state:
case mpr
Q : Type u_1
inst✝¹ : Quandle Q
G : Type u_2
inst✝ : Group G
x y : Conj G
h : y * x * y⁻¹ = x
⊢ x * y * x⁻¹ = y

Next tactic:
conv_rhs => rw [eq_mul_inv_of_mul_eq (eq_mul_inv_of_mul_eq h)]; simp
theorem conj_swap {G : Type*} [Group G] (x y : Conj G) : x ◃ y = y ↔ y ◃ x = x := by
  dsimp [Conj] at *; constructor
  repeat' intro h; conv_rhs => 

Proof state:
Q : Type u_1
inst✝¹ : Quandle Q
G : Type u_2
inst✝ : Group G
x y : Conj G
h : y * x * y⁻¹ = x
| y

Next tactic:
rw [eq_mul_inv_of_mul_eq (eq_mul_inv_of_mul_eq h)]; simp
theorem conj_swap {G : Type*} [Group G] (x y : Conj G) : x ◃ y = y ↔ y ◃ x = x := by
  dsimp [Conj] at *; constructor
  repeat' intro h; conv_rhs => 

Proof state:
Q : Type u_1
inst✝¹ : Quandle Q
G : Type u_2
inst✝ : Group G
x y : Conj G
h : y * x * y⁻¹ = x
| y

Next tactic:
rw [eq_mul_inv_of_mul_eq (eq_mul_inv_of_mul_eq h)]
theorem conj_swap {G : Type*} [Group G] (x y : Conj G) : x ◃ y = y ↔ y ◃ x = x := by
  dsimp [Conj] at *; constructor
  repeat' intro h; conv_rhs => rw [eq_mul_inv_of_mul_eq (eq_mul_inv_of_mul_eq h)]; 

Proof state:
Q : Type u_1
inst✝¹ : Quandle Q
G : Type u_2
inst✝ : Group G
x y : Conj G
h : y * x * y⁻¹ = x
| x * y⁻¹⁻¹ * x⁻¹

Next tactic:
simp
/-- `Conj` is functorial
-/
def Conj.map {G : Type*} {H : Type*} [Group G] [Group H] (f : G →* H) : Conj G →◃ Conj H
    where
  toFun := f
  map_act' := by 

Proof state:
Q : Type u_1
inst✝² : Quandle Q
G : Type u_2
H : Type u_3
inst✝¹ : Group G
inst✝ : Group H
f : G →* H
⊢ ∀ {x y : Conj G}, f (x ◃ y) = f x ◃ f y

Next tactic:
simp
theorem dihedralAct.inv (n : ℕ) (a : ZMod n) : Function.Involutive (dihedralAct n a) := by
  

Proof state:
Q : Type u_1
inst✝ : Quandle Q
n : ℕ
a : ZMod n
⊢ Function.Involutive (dihedralAct n a)

Next tactic:
intro b
theorem dihedralAct.inv (n : ℕ) (a : ZMod n) : Function.Involutive (dihedralAct n a) := by
  intro b
  

Proof state:
Q : Type u_1
inst✝ : Quandle Q
n : ℕ
a b : ZMod n
⊢ dihedralAct n a (dihedralAct n a b) = b

Next tactic:
dsimp only [dihedralAct]
theorem dihedralAct.inv (n : ℕ) (a : ZMod n) : Function.Involutive (dihedralAct n a) := by
  intro b
  dsimp only [dihedralAct]
  

Proof state:
Q : Type u_1
inst✝ : Quandle Q
n : ℕ
a b : ZMod n
⊢ 2 * a - (2 * a - b) = b

Next tactic:
simp
instance (n : ℕ) : Quandle (Dihedral n)
    where
  act := dihedralAct n
  self_distrib := by
    

Proof state:
Q : Type u_1
inst✝ : Quandle Q
n : ℕ
⊢ ∀ {x y z : Dihedral n}, dihedralAct n x (dihedralAct n y z) = dihedralAct n (dihedralAct n x y) (dihedralAct n x z)

Next tactic:
intro x y z
instance (n : ℕ) : Quandle (Dihedral n)
    where
  act := dihedralAct n
  self_distrib := by
    intro x y z
    

Proof state:
Q : Type u_1
inst✝ : Quandle Q
n : ℕ
x y z : Dihedral n
⊢ dihedralAct n x (dihedralAct n y z) = dihedralAct n (dihedralAct n x y) (dihedralAct n x z)

Next tactic:
simp only [dihedralAct]
instance (n : ℕ) : Quandle (Dihedral n)
    where
  act := dihedralAct n
  self_distrib := by
    intro x y z
    simp only [dihedralAct]
    

Proof state:
Q : Type u_1
inst✝ : Quandle Q
n : ℕ
x y z : Dihedral n
⊢ 2 * x - (2 * y - z) = 2 * (2 * x - y) - (2 * x - z)

Next tactic:
ring_nf
instance (n : ℕ) : Quandle (Dihedral n)
    where
  act := dihedralAct n
  self_distrib := by
    intro x y z
    simp only [dihedralAct]
    ring_nf
  invAct := dihedralAct n
  left_inv x := (dihedralAct.inv n x).leftInverse
  right_inv x := (dihedralAct.inv n x).rightInverse
  fix := by
    

Proof state:
Q : Type u_1
inst✝ : Quandle Q
n : ℕ
⊢ ∀ {x : Dihedral n}, x ◃ x = x

Next tactic:
intro x
instance (n : ℕ) : Quandle (Dihedral n)
    where
  act := dihedralAct n
  self_distrib := by
    intro x y z
    simp only [dihedralAct]
    ring_nf
  invAct := dihedralAct n
  left_inv x := (dihedralAct.inv n x).leftInverse
  right_inv x := (dihedralAct.inv n x).rightInverse
  fix := by
    intro x
    

Proof state:
Q : Type u_1
inst✝ : Quandle Q
n : ℕ
x : Dihedral n
⊢ x ◃ x = x

Next tactic:
simp only [dihedralAct]
instance (n : ℕ) : Quandle (Dihedral n)
    where
  act := dihedralAct n
  self_distrib := by
    intro x y z
    simp only [dihedralAct]
    ring_nf
  invAct := dihedralAct n
  left_inv x := (dihedralAct.inv n x).leftInverse
  right_inv x := (dihedralAct.inv n x).rightInverse
  fix := by
    intro x
    simp only [dihedralAct]
    

Proof state:
Q : Type u_1
inst✝ : Quandle Q
n : ℕ
x : Dihedral n
⊢ 2 * x - x = x

Next tactic:
ring_nf
/-- This is the natural rack homomorphism to the conjugation quandle of the group `R ≃ R`
that acts on the rack.
-/
def toConj (R : Type*) [Rack R] : R →◃ Quandle.Conj (R ≃ R)
    where
  toFun := act'
  map_act' := by
    

Proof state:
R : Type u_1
inst✝ : Rack R
⊢ ∀ {x y : R}, act' (x ◃ y) = act' x ◃ act' y

Next tactic:
intro x y
/-- This is the natural rack homomorphism to the conjugation quandle of the group `R ≃ R`
that acts on the rack.
-/
def toConj (R : Type*) [Rack R] : R →◃ Quandle.Conj (R ≃ R)
    where
  toFun := act'
  map_act' := by
    intro x y
    

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

Next tactic:
exact ad_conj x y
instance PreEnvelGroup.setoid (R : Type*) [Rack R] : Setoid (PreEnvelGroup R)
    where
  r := PreEnvelGroupRel R
  iseqv := by
    

Proof state:
R : Type u_1
inst✝ : Rack R
⊢ Equivalence (PreEnvelGroupRel R)

Next tactic:
constructor
instance PreEnvelGroup.setoid (R : Type*) [Rack R] : Setoid (PreEnvelGroup R)
    where
  r := PreEnvelGroupRel R
  iseqv := by
    constructor
    · 

Proof state:
case refl
R : Type u_1
inst✝ : Rack R
⊢ ∀ (x : PreEnvelGroup R), PreEnvelGroupRel R x x

Next tactic:
apply PreEnvelGroupRel.refl
instance PreEnvelGroup.setoid (R : Type*) [Rack R] : Setoid (PreEnvelGroup R)
    where
  r := PreEnvelGroupRel R
  iseqv := by
    constructor
    · apply PreEnvelGroupRel.refl
    · 

Proof state:
case symm
R : Type u_1
inst✝ : Rack R
⊢ ∀ {x y : PreEnvelGroup R}, PreEnvelGroupRel R x y → PreEnvelGroupRel R y x

Next tactic:
apply PreEnvelGroupRel.symm
instance PreEnvelGroup.setoid (R : Type*) [Rack R] : Setoid (PreEnvelGroup R)
    where
  r := PreEnvelGroupRel R
  iseqv := by
    constructor
    · apply PreEnvelGroupRel.refl
    · apply PreEnvelGroupRel.symm
    · 

Proof state:
case trans
R : Type u_1
inst✝ : Rack R
⊢ ∀ {x y z : PreEnvelGroup R}, PreEnvelGroupRel R x y → PreEnvelGroupRel R y z → PreEnvelGroupRel R x z

Next tactic:
apply PreEnvelGroupRel.trans
/-- Show that `toEnvelGroup.mapAux` sends equivalent expressions to equal terms.
-/
theorem well_def {R : Type*} [Rack R] {G : Type*} [Group G] (f : R →◃ Quandle.Conj G) :
    ∀ {a b : PreEnvelGroup R},
      PreEnvelGroupRel' R a b → toEnvelGroup.mapAux f a = toEnvelGroup.mapAux f b
  | a, _, PreEnvelGroupRel'.refl => rfl
  | a, b, PreEnvelGroupRel'.symm h => (well_def f h).symm
  | a, b, PreEnvelGroupRel'.trans hac hcb => Eq.trans (well_def f hac) (well_def f hcb)
  | _, _, PreEnvelGroupRel'.congr_mul ha hb => by
    

Proof state:
R : Type u_1
inst✝¹ : Rack R
G : Type u_2
inst✝ : Group G
f : R →◃ Quandle.Conj G
a✝ b✝ a'✝ b'✝ : PreEnvelGroup R
ha : PreEnvelGroupRel' R a✝ a'✝
hb : PreEnvelGroupRel' R b✝ b'✝
⊢ mapAux f (PreEnvelGroup.mul a✝ b✝) = mapAux f (PreEnvelGroup.mul a'✝ b'✝)

Next tactic:
simp [toEnvelGroup.mapAux, well_def f ha, well_def f hb]
/-- Show that `toEnvelGroup.mapAux` sends equivalent expressions to equal terms.
-/
theorem well_def {R : Type*} [Rack R] {G : Type*} [Group G] (f : R →◃ Quandle.Conj G) :
    ∀ {a b : PreEnvelGroup R},
      PreEnvelGroupRel' R a b → toEnvelGroup.mapAux f a = toEnvelGroup.mapAux f b
  | a, _, PreEnvelGroupRel'.refl => rfl
  | a, b, PreEnvelGroupRel'.symm h => (well_def f h).symm
  | a, b, PreEnvelGroupRel'.trans hac hcb => Eq.trans (well_def f hac) (well_def f hcb)
  | _, _, PreEnvelGroupRel'.congr_mul ha hb => by
    simp [toEnvelGroup.mapAux, well_def f ha, well_def f hb]
  | _, _, congr_inv ha => by 

Proof state:
R : Type u_1
inst✝¹ : Rack R
G : Type u_2
inst✝ : Group G
f : R →◃ Quandle.Conj G
a✝ a'✝ : PreEnvelGroup R
ha : PreEnvelGroupRel' R a✝ a'✝
⊢ mapAux f (PreEnvelGroup.inv a✝) = mapAux f (PreEnvelGroup.inv a'✝)

Next tactic:
simp [toEnvelGroup.mapAux, well_def f ha]
/-- Show that `toEnvelGroup.mapAux` sends equivalent expressions to equal terms.
-/
theorem well_def {R : Type*} [Rack R] {G : Type*} [Group G] (f : R →◃ Quandle.Conj G) :
    ∀ {a b : PreEnvelGroup R},
      PreEnvelGroupRel' R a b → toEnvelGroup.mapAux f a = toEnvelGroup.mapAux f b
  | a, _, PreEnvelGroupRel'.refl => rfl
  | a, b, PreEnvelGroupRel'.symm h => (well_def f h).symm
  | a, b, PreEnvelGroupRel'.trans hac hcb => Eq.trans (well_def f hac) (well_def f hcb)
  | _, _, PreEnvelGroupRel'.congr_mul ha hb => by
    simp [toEnvelGroup.mapAux, well_def f ha, well_def f hb]
  | _, _, congr_inv ha => by simp [toEnvelGroup.mapAux, well_def f ha]
  | _, _, assoc a b c => by 

Proof state:
R : Type u_1
inst✝¹ : Rack R
G : Type u_2
inst✝ : Group G
f : R →◃ Quandle.Conj G
a b c : PreEnvelGroup R
⊢ mapAux f (PreEnvelGroup.mul (PreEnvelGroup.mul a b) c) = mapAux f (PreEnvelGroup.mul a (PreEnvelGroup.mul b c))

Next tactic:
apply mul_assoc
/-- Show that `toEnvelGroup.mapAux` sends equivalent expressions to equal terms.
-/
theorem well_def {R : Type*} [Rack R] {G : Type*} [Group G] (f : R →◃ Quandle.Conj G) :
    ∀ {a b : PreEnvelGroup R},
      PreEnvelGroupRel' R a b → toEnvelGroup.mapAux f a = toEnvelGroup.mapAux f b
  | a, _, PreEnvelGroupRel'.refl => rfl
  | a, b, PreEnvelGroupRel'.symm h => (well_def f h).symm
  | a, b, PreEnvelGroupRel'.trans hac hcb => Eq.trans (well_def f hac) (well_def f hcb)
  | _, _, PreEnvelGroupRel'.congr_mul ha hb => by
    simp [toEnvelGroup.mapAux, well_def f ha, well_def f hb]
  | _, _, congr_inv ha => by simp [toEnvelGroup.mapAux, well_def f ha]
  | _, _, assoc a b c => by apply mul_assoc
  | _, _, PreEnvelGroupRel'.one_mul a => by 

Proof state:
R : Type u_1
inst✝¹ : Rack R
G : Type u_2
inst✝ : Group G
f : R →◃ Quandle.Conj G
a : PreEnvelGroup R
⊢ mapAux f (PreEnvelGroup.mul unit a) = mapAux f a

Next tactic:
simp [toEnvelGroup.mapAux]
/-- Show that `toEnvelGroup.mapAux` sends equivalent expressions to equal terms.
-/
theorem well_def {R : Type*} [Rack R] {G : Type*} [Group G] (f : R →◃ Quandle.Conj G) :
    ∀ {a b : PreEnvelGroup R},
      PreEnvelGroupRel' R a b → toEnvelGroup.mapAux f a = toEnvelGroup.mapAux f b
  | a, _, PreEnvelGroupRel'.refl => rfl
  | a, b, PreEnvelGroupRel'.symm h => (well_def f h).symm
  | a, b, PreEnvelGroupRel'.trans hac hcb => Eq.trans (well_def f hac) (well_def f hcb)
  | _, _, PreEnvelGroupRel'.congr_mul ha hb => by
    simp [toEnvelGroup.mapAux, well_def f ha, well_def f hb]
  | _, _, congr_inv ha => by simp [toEnvelGroup.mapAux, well_def f ha]
  | _, _, assoc a b c => by apply mul_assoc
  | _, _, PreEnvelGroupRel'.one_mul a => by simp [toEnvelGroup.mapAux]
  | _, _, PreEnvelGroupRel'.mul_one a => by 

Proof state:
R : Type u_1
inst✝¹ : Rack R
G : Type u_2
inst✝ : Group G
f : R →◃ Quandle.Conj G
a : PreEnvelGroup R
⊢ mapAux f (PreEnvelGroup.mul a unit) = mapAux f a

Next tactic:
simp [toEnvelGroup.mapAux]