l3lab/ntp-mathlib huggingface dataset:
@[simp]
theorem isAdjointPair_toLinearMap₂ :
    LinearMap.IsAdjointPair (Matrix.toLinearMap₂ b₁ b₁ J) (Matrix.toLinearMap₂ b₂ b₂ J')
        (Matrix.toLin b₁ b₂ A) (Matrix.toLin b₂ b₁ A') ↔
      Matrix.IsAdjointPair J J' A A' := by
  rw [isAdjointPair_iff_comp_eq_compl₂]
  have h :
    ∀ B B' : M₁ →ₗ[R] M₂ →ₗ[R] R,
      B = B' ↔ LinearMap.toMatrix₂ b₁ b₂ B = LinearMap.toMatrix₂ b₁ b₂ B' := by
    intro B B'
    constructor <;> 

Proof state:
case mp
R : Type u_1
R₁ : Type u_2
R₂ : Type u_3
M : Type u_4
M₁ : Type u_5
M₂ : Type u_6
M₁' : Type u_7
M₂' : Type u_8
n : Type u_9
m : Type u_10
n' : Type u_11
m' : Type u_12
ι : Type u_13
inst✝⁸ : CommRing R
inst✝⁷ : AddCommMonoid M₁
inst✝⁶ : Module R M₁
inst✝⁵ : AddCommMonoid M₂
inst✝⁴ : Module R M₂
inst✝³ : Fintype n
inst✝² : Fintype n'
b₁ : Basis n R M₁
b₂ : Basis n' R M₂
J J₂ : Matrix n n R
J' : Matrix n' n' R
A : Matrix n' n R
A' : Matrix n n' R
A₁ : Matrix n n R
inst✝¹ : DecidableEq n
inst✝ : DecidableEq n'
B B' : M₁ →ₗ[R] M₂ →ₗ[R] R
⊢ B = B' → (toMatrix₂ b₁ b₂) B = (toMatrix₂ b₁ b₂) B'

Next tactic:
intro h
@[simp]
theorem isAdjointPair_toLinearMap₂ :
    LinearMap.IsAdjointPair (Matrix.toLinearMap₂ b₁ b₁ J) (Matrix.toLinearMap₂ b₂ b₂ J')
        (Matrix.toLin b₁ b₂ A) (Matrix.toLin b₂ b₁ A') ↔
      Matrix.IsAdjointPair J J' A A' := by
  rw [isAdjointPair_iff_comp_eq_compl₂]
  have h :
    ∀ B B' : M₁ →ₗ[R] M₂ →ₗ[R] R,
      B = B' ↔ LinearMap.toMatrix₂ b₁ b₂ B = LinearMap.toMatrix₂ b₁ b₂ B' := by
    intro B B'
    constructor <;> 

Proof state:
case mpr
R : Type u_1
R₁ : Type u_2
R₂ : Type u_3
M : Type u_4
M₁ : Type u_5
M₂ : Type u_6
M₁' : Type u_7
M₂' : Type u_8
n : Type u_9
m : Type u_10
n' : Type u_11
m' : Type u_12
ι : Type u_13
inst✝⁸ : CommRing R
inst✝⁷ : AddCommMonoid M₁
inst✝⁶ : Module R M₁
inst✝⁵ : AddCommMonoid M₂
inst✝⁴ : Module R M₂
inst✝³ : Fintype n
inst✝² : Fintype n'
b₁ : Basis n R M₁
b₂ : Basis n' R M₂
J J₂ : Matrix n n R
J' : Matrix n' n' R
A : Matrix n' n R
A' : Matrix n n' R
A₁ : Matrix n n R
inst✝¹ : DecidableEq n
inst✝ : DecidableEq n'
B B' : M₁ →ₗ[R] M₂ →ₗ[R] R
⊢ (toMatrix₂ b₁ b₂) B = (toMatrix₂ b₁ b₂) B' → B = B'

Next tactic:
intro h
@[simp]
theorem isAdjointPair_toLinearMap₂ :
    LinearMap.IsAdjointPair (Matrix.toLinearMap₂ b₁ b₁ J) (Matrix.toLinearMap₂ b₂ b₂ J')
        (Matrix.toLin b₁ b₂ A) (Matrix.toLin b₂ b₁ A') ↔
      Matrix.IsAdjointPair J J' A A' := by
  rw [isAdjointPair_iff_comp_eq_compl₂]
  have h :
    ∀ B B' : M₁ →ₗ[R] M₂ →ₗ[R] R,
      B = B' ↔ LinearMap.toMatrix₂ b₁ b₂ B = LinearMap.toMatrix₂ b₁ b₂ B' := by
    intro B B'
    constructor <;> intro h
    · 

Proof state:
case mp
R : Type u_1
R₁ : Type u_2
R₂ : Type u_3
M : Type u_4
M₁ : Type u_5
M₂ : Type u_6
M₁' : Type u_7
M₂' : Type u_8
n : Type u_9
m : Type u_10
n' : Type u_11
m' : Type u_12
ι : Type u_13
inst✝⁸ : CommRing R
inst✝⁷ : AddCommMonoid M₁
inst✝⁶ : Module R M₁
inst✝⁵ : AddCommMonoid M₂
inst✝⁴ : Module R M₂
inst✝³ : Fintype n
inst✝² : Fintype n'
b₁ : Basis n R M₁
b₂ : Basis n' R M₂
J J₂ : Matrix n n R
J' : Matrix n' n' R
A : Matrix n' n R
A' : Matrix n n' R
A₁ : Matrix n n R
inst✝¹ : DecidableEq n
inst✝ : DecidableEq n'
B B' : M₁ →ₗ[R] M₂ →ₗ[R] R
h : B = B'
⊢ (toMatrix₂ b₁ b₂) B = (toMatrix₂ b₁ b₂) B'

Next tactic:
rw [h]
@[simp]
theorem isAdjointPair_toLinearMap₂ :
    LinearMap.IsAdjointPair (Matrix.toLinearMap₂ b₁ b₁ J) (Matrix.toLinearMap₂ b₂ b₂ J')
        (Matrix.toLin b₁ b₂ A) (Matrix.toLin b₂ b₁ A') ↔
      Matrix.IsAdjointPair J J' A A' := by
  rw [isAdjointPair_iff_comp_eq_compl₂]
  have h :
    ∀ B B' : M₁ →ₗ[R] M₂ →ₗ[R] R,
      B = B' ↔ LinearMap.toMatrix₂ b₁ b₂ B = LinearMap.toMatrix₂ b₁ b₂ B' := by
    intro B B'
    constructor <;> intro h
    · rw [h]
    · 

Proof state:
case mpr
R : Type u_1
R₁ : Type u_2
R₂ : Type u_3
M : Type u_4
M₁ : Type u_5
M₂ : Type u_6
M₁' : Type u_7
M₂' : Type u_8
n : Type u_9
m : Type u_10
n' : Type u_11
m' : Type u_12
ι : Type u_13
inst✝⁸ : CommRing R
inst✝⁷ : AddCommMonoid M₁
inst✝⁶ : Module R M₁
inst✝⁵ : AddCommMonoid M₂
inst✝⁴ : Module R M₂
inst✝³ : Fintype n
inst✝² : Fintype n'
b₁ : Basis n R M₁
b₂ : Basis n' R M₂
J J₂ : Matrix n n R
J' : Matrix n' n' R
A : Matrix n' n R
A' : Matrix n n' R
A₁ : Matrix n n R
inst✝¹ : DecidableEq n
inst✝ : DecidableEq n'
B B' : M₁ →ₗ[R] M₂ →ₗ[R] R
h : (toMatrix₂ b₁ b₂) B = (toMatrix₂ b₁ b₂) B'
⊢ B = B'

Next tactic:
exact (LinearMap.toMatrix₂ b₁ b₂).injective h
@[simp]
theorem isAdjointPair_toLinearMap₂ :
    LinearMap.IsAdjointPair (Matrix.toLinearMap₂ b₁ b₁ J) (Matrix.toLinearMap₂ b₂ b₂ J')
        (Matrix.toLin b₁ b₂ A) (Matrix.toLin b₂ b₁ A') ↔
      Matrix.IsAdjointPair J J' A A' := by
  rw [isAdjointPair_iff_comp_eq_compl₂]
  have h :
    ∀ B B' : M₁ →ₗ[R] M₂ →ₗ[R] R,
      B = B' ↔ LinearMap.toMatrix₂ b₁ b₂ B = LinearMap.toMatrix₂ b₁ b₂ B' := by
    intro B B'
    constructor <;> intro h
    · rw [h]
    · exact (LinearMap.toMatrix₂ b₁ b₂).injective h
  

Proof state:
R : Type u_1
R₁ : Type u_2
R₂ : Type u_3
M : Type u_4
M₁ : Type u_5
M₂ : Type u_6
M₁' : Type u_7
M₂' : Type u_8
n : Type u_9
m : Type u_10
n' : Type u_11
m' : Type u_12
ι : Type u_13
inst✝⁸ : CommRing R
inst✝⁷ : AddCommMonoid M₁
inst✝⁶ : Module R M₁
inst✝⁵ : AddCommMonoid M₂
inst✝⁴ : Module R M₂
inst✝³ : Fintype n
inst✝² : Fintype n'
b₁ : Basis n R M₁
b₂ : Basis n' R M₂
J J₂ : Matrix n n R
J' : Matrix n' n' R
A : Matrix n' n R
A' : Matrix n n' R
A₁ : Matrix n n R
inst✝¹ : DecidableEq n
inst✝ : DecidableEq n'
h : ∀ (B B' : M₁ →ₗ[R] M₂ →ₗ[R] R), B = B' ↔ (toMatrix₂ b₁ b₂) B = (toMatrix₂ b₁ b₂) B'
⊢ (toLinearMap₂ b₂ b₂) J' ∘ₗ (toLin b₁ b₂) A = compl₂ ((toLinearMap₂ b₁ b₁) J) ((toLin b₂ b₁) A') ↔
    Matrix.IsAdjointPair J J' A A'

Next tactic:
simp_rw [h, LinearMap.toMatrix₂_comp b₂ b₂, LinearMap.toMatrix₂_compl₂ b₁ b₁,
    LinearMap.toMatrix_toLin, LinearMap.toMatrix₂_toLinearMap₂]
@[simp]
theorem isAdjointPair_toLinearMap₂ :
    LinearMap.IsAdjointPair (Matrix.toLinearMap₂ b₁ b₁ J) (Matrix.toLinearMap₂ b₂ b₂ J')
        (Matrix.toLin b₁ b₂ A) (Matrix.toLin b₂ b₁ A') ↔
      Matrix.IsAdjointPair J J' A A' := by
  rw [isAdjointPair_iff_comp_eq_compl₂]
  have h :
    ∀ B B' : M₁ →ₗ[R] M₂ →ₗ[R] R,
      B = B' ↔ LinearMap.toMatrix₂ b₁ b₂ B = LinearMap.toMatrix₂ b₁ b₂ B' := by
    intro B B'
    constructor <;> intro h
    · rw [h]
    · exact (LinearMap.toMatrix₂ b₁ b₂).injective h
  simp_rw [h, LinearMap.toMatrix₂_comp b₂ b₂, LinearMap.toMatrix₂_compl₂ b₁ b₁,
    LinearMap.toMatrix_toLin, LinearMap.toMatrix₂_toLinearMap₂]
  

Proof state:
R : Type u_1
R₁ : Type u_2
R₂ : Type u_3
M : Type u_4
M₁ : Type u_5
M₂ : Type u_6
M₁' : Type u_7
M₂' : Type u_8
n : Type u_9
m : Type u_10
n' : Type u_11
m' : Type u_12
ι : Type u_13
inst✝⁸ : CommRing R
inst✝⁷ : AddCommMonoid M₁
inst✝⁶ : Module R M₁
inst✝⁵ : AddCommMonoid M₂
inst✝⁴ : Module R M₂
inst✝³ : Fintype n
inst✝² : Fintype n'
b₁ : Basis n R M₁
b₂ : Basis n' R M₂
J J₂ : Matrix n n R
J' : Matrix n' n' R
A : Matrix n' n R
A' : Matrix n n' R
A₁ : Matrix n n R
inst✝¹ : DecidableEq n
inst✝ : DecidableEq n'
h : ∀ (B B' : M₁ →ₗ[R] M₂ →ₗ[R] R), B = B' ↔ (toMatrix₂ b₁ b₂) B = (toMatrix₂ b₁ b₂) B'
⊢ Aᵀ * J' = J * A' ↔ Matrix.IsAdjointPair J J' A A'

Next tactic:
rfl
theorem Matrix.isAdjointPair_equiv (P : Matrix n n R) (h : IsUnit P) :
    (Pᵀ * J * P).IsAdjointPair (Pᵀ * J * P) A₁ A₁ ↔
      J.IsAdjointPair J (P * A₁ * P⁻¹) (P * A₁ * P⁻¹) := by
  

Proof state:
R : Type u_1
R₁ : Type u_2
R₂ : Type u_3
M : Type u_4
M₁ : Type u_5
M₂ : Type u_6
M₁' : Type u_7
M₂' : Type u_8
n : Type u_9
m : Type u_10
n' : Type u_11
m' : Type u_12
ι : Type u_13
inst✝⁸ : CommRing R
inst✝⁷ : AddCommMonoid M₁
inst✝⁶ : Module R M₁
inst✝⁵ : AddCommMonoid M₂
inst✝⁴ : Module R M₂
inst✝³ : Fintype n
inst✝² : Fintype n'
b₁ : Basis n R M₁
b₂ : Basis n' R M₂
J J₂ : Matrix n n R
J' : Matrix n' n' R
A : Matrix n' n R
A' : Matrix n n' R
A₁ : Matrix n n R
inst✝¹ : DecidableEq n
inst✝ : DecidableEq n'
P : Matrix n n R
h : IsUnit P
⊢ IsAdjointPair (Pᵀ * J * P) (Pᵀ * J * P) A₁ A₁ ↔ IsAdjointPair J J (P * A₁ * P⁻¹) (P * A₁ * P⁻¹)

Next tactic:
have h' : IsUnit P.det := P.isUnit_iff_isUnit_det.mp h
theorem Matrix.isAdjointPair_equiv (P : Matrix n n R) (h : IsUnit P) :
    (Pᵀ * J * P).IsAdjointPair (Pᵀ * J * P) A₁ A₁ ↔
      J.IsAdjointPair J (P * A₁ * P⁻¹) (P * A₁ * P⁻¹) := by
  have h' : IsUnit P.det := P.isUnit_iff_isUnit_det.mp h
  

Proof state:
R : Type u_1
R₁ : Type u_2
R₂ : Type u_3
M : Type u_4
M₁ : Type u_5
M₂ : Type u_6
M₁' : Type u_7
M₂' : Type u_8
n : Type u_9
m : Type u_10
n' : Type u_11
m' : Type u_12
ι : Type u_13
inst✝⁸ : CommRing R
inst✝⁷ : AddCommMonoid M₁
inst✝⁶ : Module R M₁
inst✝⁵ : AddCommMonoid M₂
inst✝⁴ : Module R M₂
inst✝³ : Fintype n
inst✝² : Fintype n'
b₁ : Basis n R M₁
b₂ : Basis n' R M₂
J J₂ : Matrix n n R
J' : Matrix n' n' R
A : Matrix n' n R
A' : Matrix n n' R
A₁ : Matrix n n R
inst✝¹ : DecidableEq n
inst✝ : DecidableEq n'
P : Matrix n n R
h : IsUnit P
h' : IsUnit (det P)
⊢ IsAdjointPair (Pᵀ * J * P) (Pᵀ * J * P) A₁ A₁ ↔ IsAdjointPair J J (P * A₁ * P⁻¹) (P * A₁ * P⁻¹)

Next tactic:
let u := P.nonsingInvUnit h'
theorem Matrix.isAdjointPair_equiv (P : Matrix n n R) (h : IsUnit P) :
    (Pᵀ * J * P).IsAdjointPair (Pᵀ * J * P) A₁ A₁ ↔
      J.IsAdjointPair J (P * A₁ * P⁻¹) (P * A₁ * P⁻¹) := by
  have h' : IsUnit P.det := P.isUnit_iff_isUnit_det.mp h
  let u := P.nonsingInvUnit h'
  

Proof state:
R : Type u_1
R₁ : Type u_2
R₂ : Type u_3
M : Type u_4
M₁ : Type u_5
M₂ : Type u_6
M₁' : Type u_7
M₂' : Type u_8
n : Type u_9
m : Type u_10
n' : Type u_11
m' : Type u_12
ι : Type u_13
inst✝⁸ : CommRing R
inst✝⁷ : AddCommMonoid M₁
inst✝⁶ : Module R M₁
inst✝⁵ : AddCommMonoid M₂
inst✝⁴ : Module R M₂
inst✝³ : Fintype n
inst✝² : Fintype n'
b₁ : Basis n R M₁
b₂ : Basis n' R M₂
J J₂ : Matrix n n R
J' : Matrix n' n' R
A : Matrix n' n R
A' : Matrix n n' R
A₁ : Matrix n n R
inst✝¹ : DecidableEq n
inst✝ : DecidableEq n'
P : Matrix n n R
h : IsUnit P
h' : IsUnit (det P)
u : (Matrix n n R)ˣ := nonsingInvUnit P h'
⊢ IsAdjointPair (Pᵀ * J * P) (Pᵀ * J * P) A₁ A₁ ↔ IsAdjointPair J J (P * A₁ * P⁻¹) (P * A₁ * P⁻¹)

Next tactic:
let v := Pᵀ.nonsingInvUnit (P.isUnit_det_transpose h')
theorem Matrix.isAdjointPair_equiv (P : Matrix n n R) (h : IsUnit P) :
    (Pᵀ * J * P).IsAdjointPair (Pᵀ * J * P) A₁ A₁ ↔
      J.IsAdjointPair J (P * A₁ * P⁻¹) (P * A₁ * P⁻¹) := by
  have h' : IsUnit P.det := P.isUnit_iff_isUnit_det.mp h
  let u := P.nonsingInvUnit h'
  let v := Pᵀ.nonsingInvUnit (P.isUnit_det_transpose h')
  

Proof state:
R : Type u_1
R₁ : Type u_2
R₂ : Type u_3
M : Type u_4
M₁ : Type u_5
M₂ : Type u_6
M₁' : Type u_7
M₂' : Type u_8
n : Type u_9
m : Type u_10
n' : Type u_11
m' : Type u_12
ι : Type u_13
inst✝⁸ : CommRing R
inst✝⁷ : AddCommMonoid M₁
inst✝⁶ : Module R M₁
inst✝⁵ : AddCommMonoid M₂
inst✝⁴ : Module R M₂
inst✝³ : Fintype n
inst✝² : Fintype n'
b₁ : Basis n R M₁
b₂ : Basis n' R M₂
J J₂ : Matrix n n R
J' : Matrix n' n' R
A : Matrix n' n R
A' : Matrix n n' R
A₁ : Matrix n n R
inst✝¹ : DecidableEq n
inst✝ : DecidableEq n'
P : Matrix n n R
h : IsUnit P
h' : IsUnit (det P)
u : (Matrix n n R)ˣ := nonsingInvUnit P h'
v : (Matrix n n R)ˣ := nonsingInvUnit Pᵀ (_ : IsUnit (det Pᵀ))
⊢ IsAdjointPair (Pᵀ * J * P) (Pᵀ * J * P) A₁ A₁ ↔ IsAdjointPair J J (P * A₁ * P⁻¹) (P * A₁ * P⁻¹)

Next tactic:
let x := A₁ᵀ * Pᵀ * J
theorem Matrix.isAdjointPair_equiv (P : Matrix n n R) (h : IsUnit P) :
    (Pᵀ * J * P).IsAdjointPair (Pᵀ * J * P) A₁ A₁ ↔
      J.IsAdjointPair J (P * A₁ * P⁻¹) (P * A₁ * P⁻¹) := by
  have h' : IsUnit P.det := P.isUnit_iff_isUnit_det.mp h
  let u := P.nonsingInvUnit h'
  let v := Pᵀ.nonsingInvUnit (P.isUnit_det_transpose h')
  let x := A₁ᵀ * Pᵀ * J
  

Proof state:
R : Type u_1
R₁ : Type u_2
R₂ : Type u_3
M : Type u_4
M₁ : Type u_5
M₂ : Type u_6
M₁' : Type u_7
M₂' : Type u_8
n : Type u_9
m : Type u_10
n' : Type u_11
m' : Type u_12
ι : Type u_13
inst✝⁸ : CommRing R
inst✝⁷ : AddCommMonoid M₁
inst✝⁶ : Module R M₁
inst✝⁵ : AddCommMonoid M₂
inst✝⁴ : Module R M₂
inst✝³ : Fintype n
inst✝² : Fintype n'
b₁ : Basis n R M₁
b₂ : Basis n' R M₂
J J₂ : Matrix n n R
J' : Matrix n' n' R
A : Matrix n' n R
A' : Matrix n n' R
A₁ : Matrix n n R
inst✝¹ : DecidableEq n
inst✝ : DecidableEq n'
P : Matrix n n R
h : IsUnit P
h' : IsUnit (det P)
u : (Matrix n n R)ˣ := nonsingInvUnit P h'
v : (Matrix n n R)ˣ := nonsingInvUnit Pᵀ (_ : IsUnit (det Pᵀ))
x : Matrix n n R := A₁ᵀ * Pᵀ * J
⊢ IsAdjointPair (Pᵀ * J * P) (Pᵀ * J * P) A₁ A₁ ↔ IsAdjointPair J J (P * A₁ * P⁻¹) (P * A₁ * P⁻¹)

Next tactic:
let y := J * P * A₁
theorem Matrix.isAdjointPair_equiv (P : Matrix n n R) (h : IsUnit P) :
    (Pᵀ * J * P).IsAdjointPair (Pᵀ * J * P) A₁ A₁ ↔
      J.IsAdjointPair J (P * A₁ * P⁻¹) (P * A₁ * P⁻¹) := by
  have h' : IsUnit P.det := P.isUnit_iff_isUnit_det.mp h
  let u := P.nonsingInvUnit h'
  let v := Pᵀ.nonsingInvUnit (P.isUnit_det_transpose h')
  let x := A₁ᵀ * Pᵀ * J
  let y := J * P * A₁
  -- TODO(mathlib4#6607): fix elaboration so `val` isn't needed
  

Proof state:
R : Type u_1
R₁ : Type u_2
R₂ : Type u_3
M : Type u_4
M₁ : Type u_5
M₂ : Type u_6
M₁' : Type u_7
M₂' : Type u_8
n : Type u_9
m : Type u_10
n' : Type u_11
m' : Type u_12
ι : Type u_13
inst✝⁸ : CommRing R
inst✝⁷ : AddCommMonoid M₁
inst✝⁶ : Module R M₁
inst✝⁵ : AddCommMonoid M₂
inst✝⁴ : Module R M₂
inst✝³ : Fintype n
inst✝² : Fintype n'
b₁ : Basis n R M₁
b₂ : Basis n' R M₂
J J₂ : Matrix n n R
J' : Matrix n' n' R
A : Matrix n' n R
A' : Matrix n n' R
A₁ : Matrix n n R
inst✝¹ : DecidableEq n
inst✝ : DecidableEq n'
P : Matrix n n R
h : IsUnit P
h' : IsUnit (det P)
u : (Matrix n n R)ˣ := nonsingInvUnit P h'
v : (Matrix n n R)ˣ := nonsingInvUnit Pᵀ (_ : IsUnit (det Pᵀ))
x : Matrix n n R := A₁ᵀ * Pᵀ * J
y : Matrix n n R := J * P * A₁
⊢ IsAdjointPair (Pᵀ * J * P) (Pᵀ * J * P) A₁ A₁ ↔ IsAdjointPair J J (P * A₁ * P⁻¹) (P * A₁ * P⁻¹)

Next tactic:
suffices x * u.val = v.val * y ↔ (v⁻¹).val * x = y * (u⁻¹).val by
    dsimp only [Matrix.IsAdjointPair]
    simp only [Matrix.transpose_mul]
    simp only [← mul_assoc, P.transpose_nonsing_inv]
    -- porting note: the previous proof used `conv` and was causing timeouts, so we use `convert`
    convert this using 2
    · rw [mul_assoc, mul_assoc, ← mul_assoc J]
      rfl
    · rw [mul_assoc, mul_assoc, ← mul_assoc _ _ J]
      rfl
theorem Matrix.isAdjointPair_equiv (P : Matrix n n R) (h : IsUnit P) :
    (Pᵀ * J * P).IsAdjointPair (Pᵀ * J * P) A₁ A₁ ↔
      J.IsAdjointPair J (P * A₁ * P⁻¹) (P * A₁ * P⁻¹) := by
  have h' : IsUnit P.det := P.isUnit_iff_isUnit_det.mp h
  let u := P.nonsingInvUnit h'
  let v := Pᵀ.nonsingInvUnit (P.isUnit_det_transpose h')
  let x := A₁ᵀ * Pᵀ * J
  let y := J * P * A₁
  -- TODO(mathlib4#6607): fix elaboration so `val` isn't needed
  suffices x * u.val = v.val * y ↔ (v⁻¹).val * x = y * (u⁻¹).val by
    

Proof state:
R : Type u_1
R₁ : Type u_2
R₂ : Type u_3
M : Type u_4
M₁ : Type u_5
M₂ : Type u_6
M₁' : Type u_7
M₂' : Type u_8
n : Type u_9
m : Type u_10
n' : Type u_11
m' : Type u_12
ι : Type u_13
inst✝⁸ : CommRing R
inst✝⁷ : AddCommMonoid M₁
inst✝⁶ : Module R M₁
inst✝⁵ : AddCommMonoid M₂
inst✝⁴ : Module R M₂
inst✝³ : Fintype n
inst✝² : Fintype n'
b₁ : Basis n R M₁
b₂ : Basis n' R M₂
J J₂ : Matrix n n R
J' : Matrix n' n' R
A : Matrix n' n R
A' : Matrix n n' R
A₁ : Matrix n n R
inst✝¹ : DecidableEq n
inst✝ : DecidableEq n'
P : Matrix n n R
h : IsUnit P
h' : IsUnit (det P)
u : (Matrix n n R)ˣ := nonsingInvUnit P h'
v : (Matrix n n R)ˣ := nonsingInvUnit Pᵀ (_ : IsUnit (det Pᵀ))
x : Matrix n n R := A₁ᵀ * Pᵀ * J
y : Matrix n n R := J * P * A₁
this : x * ↑u = ↑v * y ↔ ↑v⁻¹ * x = y * ↑u⁻¹
⊢ IsAdjointPair (Pᵀ * J * P) (Pᵀ * J * P) A₁ A₁ ↔ IsAdjointPair J J (P * A₁ * P⁻¹) (P * A₁ * P⁻¹)

Next tactic:
dsimp only [Matrix.IsAdjointPair]
theorem Matrix.isAdjointPair_equiv (P : Matrix n n R) (h : IsUnit P) :
    (Pᵀ * J * P).IsAdjointPair (Pᵀ * J * P) A₁ A₁ ↔
      J.IsAdjointPair J (P * A₁ * P⁻¹) (P * A₁ * P⁻¹) := by
  have h' : IsUnit P.det := P.isUnit_iff_isUnit_det.mp h
  let u := P.nonsingInvUnit h'
  let v := Pᵀ.nonsingInvUnit (P.isUnit_det_transpose h')
  let x := A₁ᵀ * Pᵀ * J
  let y := J * P * A₁
  -- TODO(mathlib4#6607): fix elaboration so `val` isn't needed
  suffices x * u.val = v.val * y ↔ (v⁻¹).val * x = y * (u⁻¹).val by
    dsimp only [Matrix.IsAdjointPair]
    

Proof state:
R : Type u_1
R₁ : Type u_2
R₂ : Type u_3
M : Type u_4
M₁ : Type u_5
M₂ : Type u_6
M₁' : Type u_7
M₂' : Type u_8
n : Type u_9
m : Type u_10
n' : Type u_11
m' : Type u_12
ι : Type u_13
inst✝⁸ : CommRing R
inst✝⁷ : AddCommMonoid M₁
inst✝⁶ : Module R M₁
inst✝⁵ : AddCommMonoid M₂
inst✝⁴ : Module R M₂
inst✝³ : Fintype n
inst✝² : Fintype n'
b₁ : Basis n R M₁
b₂ : Basis n' R M₂
J J₂ : Matrix n n R
J' : Matrix n' n' R
A : Matrix n' n R
A' : Matrix n n' R
A₁ : Matrix n n R
inst✝¹ : DecidableEq n
inst✝ : DecidableEq n'
P : Matrix n n R
h : IsUnit P
h' : IsUnit (det P)
u : (Matrix n n R)ˣ := nonsingInvUnit P h'
v : (Matrix n n R)ˣ := nonsingInvUnit Pᵀ (_ : IsUnit (det Pᵀ))
x : Matrix n n R := A₁ᵀ * Pᵀ * J
y : Matrix n n R := J * P * A₁
this : x * ↑u = ↑v * y ↔ ↑v⁻¹ * x = y * ↑u⁻¹
⊢ A₁ᵀ * (Pᵀ * J * P) = Pᵀ * J * P * A₁ ↔ (P * A₁ * P⁻¹)ᵀ * J = J * (P * A₁ * P⁻¹)

Next tactic:
simp only [Matrix.transpose_mul]
theorem Matrix.isAdjointPair_equiv (P : Matrix n n R) (h : IsUnit P) :
    (Pᵀ * J * P).IsAdjointPair (Pᵀ * J * P) A₁ A₁ ↔
      J.IsAdjointPair J (P * A₁ * P⁻¹) (P * A₁ * P⁻¹) := by
  have h' : IsUnit P.det := P.isUnit_iff_isUnit_det.mp h
  let u := P.nonsingInvUnit h'
  let v := Pᵀ.nonsingInvUnit (P.isUnit_det_transpose h')
  let x := A₁ᵀ * Pᵀ * J
  let y := J * P * A₁
  -- TODO(mathlib4#6607): fix elaboration so `val` isn't needed
  suffices x * u.val = v.val * y ↔ (v⁻¹).val * x = y * (u⁻¹).val by
    dsimp only [Matrix.IsAdjointPair]
    simp only [Matrix.transpose_mul]
    

Proof state:
R : Type u_1
R₁ : Type u_2
R₂ : Type u_3
M : Type u_4
M₁ : Type u_5
M₂ : Type u_6
M₁' : Type u_7
M₂' : Type u_8
n : Type u_9
m : Type u_10
n' : Type u_11
m' : Type u_12
ι : Type u_13
inst✝⁸ : CommRing R
inst✝⁷ : AddCommMonoid M₁
inst✝⁶ : Module R M₁
inst✝⁵ : AddCommMonoid M₂
inst✝⁴ : Module R M₂
inst✝³ : Fintype n
inst✝² : Fintype n'
b₁ : Basis n R M₁
b₂ : Basis n' R M₂
J J₂ : Matrix n n R
J' : Matrix n' n' R
A : Matrix n' n R
A' : Matrix n n' R
A₁ : Matrix n n R
inst✝¹ : DecidableEq n
inst✝ : DecidableEq n'
P : Matrix n n R
h : IsUnit P
h' : IsUnit (det P)
u : (Matrix n n R)ˣ := nonsingInvUnit P h'
v : (Matrix n n R)ˣ := nonsingInvUnit Pᵀ (_ : IsUnit (det Pᵀ))
x : Matrix n n R := A₁ᵀ * Pᵀ * J
y : Matrix n n R := J * P * A₁
this : x * ↑u = ↑v * y ↔ ↑v⁻¹ * x = y * ↑u⁻¹
⊢ A₁ᵀ * (Pᵀ * J * P) = Pᵀ * J * P * A₁ ↔ P⁻¹ᵀ * (A₁ᵀ * Pᵀ) * J = J * (P * A₁ * P⁻¹)

Next tactic:
simp only [← mul_assoc, P.transpose_nonsing_inv]
theorem Matrix.isAdjointPair_equiv (P : Matrix n n R) (h : IsUnit P) :
    (Pᵀ * J * P).IsAdjointPair (Pᵀ * J * P) A₁ A₁ ↔
      J.IsAdjointPair J (P * A₁ * P⁻¹) (P * A₁ * P⁻¹) := by
  have h' : IsUnit P.det := P.isUnit_iff_isUnit_det.mp h
  let u := P.nonsingInvUnit h'
  let v := Pᵀ.nonsingInvUnit (P.isUnit_det_transpose h')
  let x := A₁ᵀ * Pᵀ * J
  let y := J * P * A₁
  -- TODO(mathlib4#6607): fix elaboration so `val` isn't needed
  suffices x * u.val = v.val * y ↔ (v⁻¹).val * x = y * (u⁻¹).val by
    dsimp only [Matrix.IsAdjointPair]
    simp only [Matrix.transpose_mul]
    simp only [← mul_assoc, P.transpose_nonsing_inv]
    -- porting note: the previous proof used `conv` and was causing timeouts, so we use `convert`
    

Proof state:
R : Type u_1
R₁ : Type u_2
R₂ : Type u_3
M : Type u_4
M₁ : Type u_5
M₂ : Type u_6
M₁' : Type u_7
M₂' : Type u_8
n : Type u_9
m : Type u_10
n' : Type u_11
m' : Type u_12
ι : Type u_13
inst✝⁸ : CommRing R
inst✝⁷ : AddCommMonoid M₁
inst✝⁶ : Module R M₁
inst✝⁵ : AddCommMonoid M₂
inst✝⁴ : Module R M₂
inst✝³ : Fintype n
inst✝² : Fintype n'
b₁ : Basis n R M₁
b₂ : Basis n' R M₂
J J₂ : Matrix n n R
J' : Matrix n' n' R
A : Matrix n' n R
A' : Matrix n n' R
A₁ : Matrix n n R
inst✝¹ : DecidableEq n
inst✝ : DecidableEq n'
P : Matrix n n R
h : IsUnit P
h' : IsUnit (det P)
u : (Matrix n n R)ˣ := nonsingInvUnit P h'
v : (Matrix n n R)ˣ := nonsingInvUnit Pᵀ (_ : IsUnit (det Pᵀ))
x : Matrix n n R := A₁ᵀ * Pᵀ * J
y : Matrix n n R := J * P * A₁
this : x * ↑u = ↑v * y ↔ ↑v⁻¹ * x = y * ↑u⁻¹
⊢ A₁ᵀ * Pᵀ * J * P = Pᵀ * J * P * A₁ ↔ Pᵀ⁻¹ * A₁ᵀ * Pᵀ * J = J * P * A₁ * P⁻¹

Next tactic:
convert this using 2
theorem Matrix.isAdjointPair_equiv (P : Matrix n n R) (h : IsUnit P) :
    (Pᵀ * J * P).IsAdjointPair (Pᵀ * J * P) A₁ A₁ ↔
      J.IsAdjointPair J (P * A₁ * P⁻¹) (P * A₁ * P⁻¹) := by
  have h' : IsUnit P.det := P.isUnit_iff_isUnit_det.mp h
  let u := P.nonsingInvUnit h'
  let v := Pᵀ.nonsingInvUnit (P.isUnit_det_transpose h')
  let x := A₁ᵀ * Pᵀ * J
  let y := J * P * A₁
  -- TODO(mathlib4#6607): fix elaboration so `val` isn't needed
  suffices x * u.val = v.val * y ↔ (v⁻¹).val * x = y * (u⁻¹).val by
    dsimp only [Matrix.IsAdjointPair]
    simp only [Matrix.transpose_mul]
    simp only [← mul_assoc, P.transpose_nonsing_inv]
    -- porting note: the previous proof used `conv` and was causing timeouts, so we use `convert`
    convert this using 2
    · 

Proof state:
case h.e'_1.h.e'_3
R : Type u_1
R₁ : Type u_2
R₂ : Type u_3
M : Type u_4
M₁ : Type u_5
M₂ : Type u_6
M₁' : Type u_7
M₂' : Type u_8
n : Type u_9
m : Type u_10
n' : Type u_11
m' : Type u_12
ι : Type u_13
inst✝⁸ : CommRing R
inst✝⁷ : AddCommMonoid M₁
inst✝⁶ : Module R M₁
inst✝⁵ : AddCommMonoid M₂
inst✝⁴ : Module R M₂
inst✝³ : Fintype n
inst✝² : Fintype n'
b₁ : Basis n R M₁
b₂ : Basis n' R M₂
J J₂ : Matrix n n R
J' : Matrix n' n' R
A : Matrix n' n R
A' : Matrix n n' R
A₁ : Matrix n n R
inst✝¹ : DecidableEq n
inst✝ : DecidableEq n'
P : Matrix n n R
h : IsUnit P
h' : IsUnit (det P)
u : (Matrix n n R)ˣ := nonsingInvUnit P h'
v : (Matrix n n R)ˣ := nonsingInvUnit Pᵀ (_ : IsUnit (det Pᵀ))
x : Matrix n n R := A₁ᵀ * Pᵀ * J
y : Matrix n n R := J * P * A₁
this : x * ↑u = ↑v * y ↔ ↑v⁻¹ * x = y * ↑u⁻¹
⊢ Pᵀ * J * P * A₁ = ↑v * y

Next tactic:
rw [mul_assoc, mul_assoc, ← mul_assoc J]
theorem Matrix.isAdjointPair_equiv (P : Matrix n n R) (h : IsUnit P) :
    (Pᵀ * J * P).IsAdjointPair (Pᵀ * J * P) A₁ A₁ ↔
      J.IsAdjointPair J (P * A₁ * P⁻¹) (P * A₁ * P⁻¹) := by
  have h' : IsUnit P.det := P.isUnit_iff_isUnit_det.mp h
  let u := P.nonsingInvUnit h'
  let v := Pᵀ.nonsingInvUnit (P.isUnit_det_transpose h')
  let x := A₁ᵀ * Pᵀ * J
  let y := J * P * A₁
  -- TODO(mathlib4#6607): fix elaboration so `val` isn't needed
  suffices x * u.val = v.val * y ↔ (v⁻¹).val * x = y * (u⁻¹).val by
    dsimp only [Matrix.IsAdjointPair]
    simp only [Matrix.transpose_mul]
    simp only [← mul_assoc, P.transpose_nonsing_inv]
    -- porting note: the previous proof used `conv` and was causing timeouts, so we use `convert`
    convert this using 2
    · rw [mul_assoc, mul_assoc, ← mul_assoc J]
      

Proof state:
case h.e'_1.h.e'_3
R : Type u_1
R₁ : Type u_2
R₂ : Type u_3
M : Type u_4
M₁ : Type u_5
M₂ : Type u_6
M₁' : Type u_7
M₂' : Type u_8
n : Type u_9
m : Type u_10
n' : Type u_11
m' : Type u_12
ι : Type u_13
inst✝⁸ : CommRing R
inst✝⁷ : AddCommMonoid M₁
inst✝⁶ : Module R M₁
inst✝⁵ : AddCommMonoid M₂
inst✝⁴ : Module R M₂
inst✝³ : Fintype n
inst✝² : Fintype n'
b₁ : Basis n R M₁
b₂ : Basis n' R M₂
J J₂ : Matrix n n R
J' : Matrix n' n' R
A : Matrix n' n R
A' : Matrix n n' R
A₁ : Matrix n n R
inst✝¹ : DecidableEq n
inst✝ : DecidableEq n'
P : Matrix n n R
h : IsUnit P
h' : IsUnit (det P)
u : (Matrix n n R)ˣ := nonsingInvUnit P h'
v : (Matrix n n R)ˣ := nonsingInvUnit Pᵀ (_ : IsUnit (det Pᵀ))
x : Matrix n n R := A₁ᵀ * Pᵀ * J
y : Matrix n n R := J * P * A₁
this : x * ↑u = ↑v * y ↔ ↑v⁻¹ * x = y * ↑u⁻¹
⊢ Pᵀ * (J * P * A₁) = ↑v * y

Next tactic:
rfl