l3lab/ntp-mathlib huggingface dataset:
/-- `Equiv` between `PartENat` and `ℕ∞` (for the order isomorphism see
`withTopOrderIso`). -/
noncomputable def withTopEquiv : PartENat ≃ ℕ∞ where
  toFun x := toWithTop x
  invFun x := ↑x
  left_inv x := by
    induction x using PartENat.casesOn <;>
    

Proof state:
case a
⊢ (fun x => ↑x) ((fun x => toWithTop x) ⊤) = ⊤

Next tactic:
intros
/-- `Equiv` between `PartENat` and `ℕ∞` (for the order isomorphism see
`withTopOrderIso`). -/
noncomputable def withTopEquiv : PartENat ≃ ℕ∞ where
  toFun x := toWithTop x
  invFun x := ↑x
  left_inv x := by
    induction x using PartENat.casesOn <;>
    

Proof state:
case a
n✝ : ℕ
⊢ (fun x => ↑x) ((fun x => toWithTop x) ↑n✝) = ↑n✝

Next tactic:
intros
/-- `Equiv` between `PartENat` and `ℕ∞` (for the order isomorphism see
`withTopOrderIso`). -/
noncomputable def withTopEquiv : PartENat ≃ ℕ∞ where
  toFun x := toWithTop x
  invFun x := ↑x
  left_inv x := by
    induction x using PartENat.casesOn <;>
    intros <;>
    

Proof state:
case a
⊢ (fun x => ↑x) ((fun x => toWithTop x) ⊤) = ⊤

Next tactic:
simp
/-- `Equiv` between `PartENat` and `ℕ∞` (for the order isomorphism see
`withTopOrderIso`). -/
noncomputable def withTopEquiv : PartENat ≃ ℕ∞ where
  toFun x := toWithTop x
  invFun x := ↑x
  left_inv x := by
    induction x using PartENat.casesOn <;>
    intros <;>
    

Proof state:
case a
n✝ : ℕ
⊢ (fun x => ↑x) ((fun x => toWithTop x) ↑n✝) = ↑n✝

Next tactic:
simp
/-- `Equiv` between `PartENat` and `ℕ∞` (for the order isomorphism see
`withTopOrderIso`). -/
noncomputable def withTopEquiv : PartENat ≃ ℕ∞ where
  toFun x := toWithTop x
  invFun x := ↑x
  left_inv x := by
    induction x using PartENat.casesOn <;>
    intros <;>
    simp <;>
    

Proof state:
case a
⊢ ↑⊤ = ⊤

Next tactic:
rfl
/-- `Equiv` between `PartENat` and `ℕ∞` (for the order isomorphism see
`withTopOrderIso`). -/
noncomputable def withTopEquiv : PartENat ≃ ℕ∞ where
  toFun x := toWithTop x
  invFun x := ↑x
  left_inv x := by
    induction x using PartENat.casesOn <;>
    intros <;>
    simp <;>
    

Proof state:
case a
n✝ : ℕ
⊢ ↑↑n✝ = ↑n✝

Next tactic:
rfl
/-- `Equiv` between `PartENat` and `ℕ∞` (for the order isomorphism see
`withTopOrderIso`). -/
noncomputable def withTopEquiv : PartENat ≃ ℕ∞ where
  toFun x := toWithTop x
  invFun x := ↑x
  left_inv x := by
    induction x using PartENat.casesOn <;>
    intros <;>
    simp <;>
    rfl
  right_inv x := by
    

Proof state:
x : ℕ∞
⊢ (fun x => toWithTop x) ((fun x => ↑x) x) = x

Next tactic:
simp [toWithTop_ofENat]
@[simp]
theorem withTopEquiv_zero : withTopEquiv 0 = 0 := by
  

Proof state:
⊢ withTopEquiv 0 = 0

Next tactic:
simpa only [Nat.cast_zero] using withTopEquiv_natCast 0
@[simp]
theorem withTopEquiv_one : withTopEquiv 1 = 1 := by
  

Proof state:
⊢ withTopEquiv 1 = 1

Next tactic:
simpa only [Nat.cast_one] using withTopEquiv_natCast 1
@[simp]
theorem withTopEquiv_symm_le {x y : ℕ∞} : withTopEquiv.symm x ≤ withTopEquiv.symm y ↔ x ≤ y := by
  

Proof state:
x y : ℕ∞
⊢ withTopEquiv.symm x ≤ withTopEquiv.symm y ↔ x ≤ y

Next tactic:
rw [← withTopEquiv_le]
@[simp]
theorem withTopEquiv_symm_le {x y : ℕ∞} : withTopEquiv.symm x ≤ withTopEquiv.symm y ↔ x ≤ y := by
  rw [← withTopEquiv_le]
  

Proof state:
x y : ℕ∞
⊢ withTopEquiv (withTopEquiv.symm x) ≤ withTopEquiv (withTopEquiv.symm y) ↔ x ≤ y

Next tactic:
simp
@[simp]
theorem withTopEquiv_symm_lt {x y : ℕ∞} : withTopEquiv.symm x < withTopEquiv.symm y ↔ x < y := by
  

Proof state:
x y : ℕ∞
⊢ withTopEquiv.symm x < withTopEquiv.symm y ↔ x < y

Next tactic:
rw [← withTopEquiv_lt]
@[simp]
theorem withTopEquiv_symm_lt {x y : ℕ∞} : withTopEquiv.symm x < withTopEquiv.symm y ↔ x < y := by
  rw [← withTopEquiv_lt]
  

Proof state:
x y : ℕ∞
⊢ withTopEquiv (withTopEquiv.symm x) < withTopEquiv (withTopEquiv.symm y) ↔ x < y

Next tactic:
simp
/-- `toWithTop` induces an additive monoid isomorphism between `PartENat` and `ℕ∞`. -/
noncomputable def withTopAddEquiv : PartENat ≃+ ℕ∞ :=
  { withTopEquiv with
    map_add' := fun x y => by
      

Proof state:
src✝ : PartENat ≃ ℕ∞ := withTopEquiv
x y : PartENat
⊢ Equiv.toFun
      { toFun := src✝.toFun, invFun := src✝.invFun, left_inv := (_ : Function.LeftInverse src✝.invFun src✝.toFun),
        right_inv := (_ : Function.RightInverse src✝.invFun src✝.toFun) }
      (x + y) =
    Equiv.toFun
        { toFun := src✝.toFun, invFun := src✝.invFun, left_inv := (_ : Function.LeftInverse src✝.invFun src✝.toFun),
          right_inv := (_ : Function.RightInverse src✝.invFun src✝.toFun) }
        x +
      Equiv.toFun
        { toFun := src✝.toFun, invFun := src✝.invFun, left_inv := (_ : Function.LeftInverse src✝.invFun src✝.toFun),
          right_inv := (_ : Function.RightInverse src✝.invFun src✝.toFun) }
        y

Next tactic:
simp only [withTopEquiv]
/-- `toWithTop` induces an additive monoid isomorphism between `PartENat` and `ℕ∞`. -/
noncomputable def withTopAddEquiv : PartENat ≃+ ℕ∞ :=
  { withTopEquiv with
    map_add' := fun x y => by
      simp only [withTopEquiv]
      

Proof state:
src✝ : PartENat ≃ ℕ∞ := withTopEquiv
x y : PartENat
⊢ toWithTop (x + y) = toWithTop x + toWithTop y

Next tactic:
exact toWithTop_add
theorem lt_wf : @WellFounded PartENat (· < ·) := by
  

Proof state:
⊢ WellFounded fun x x_1 => x < x_1

Next tactic:
classical
    change WellFounded fun a b : PartENat => a < b
    simp_rw [← withTopEquiv_lt]
    exact InvImage.wf _ wellFounded_lt
theorem lt_wf : @WellFounded PartENat (· < ·) := by
  classical
    

Proof state:
⊢ WellFounded fun x x_1 => x < x_1

Next tactic:
change WellFounded fun a b : PartENat => a < b
theorem lt_wf : @WellFounded PartENat (· < ·) := by
  classical
    change WellFounded fun a b : PartENat => a < b
    

Proof state:
⊢ WellFounded fun a b => a < b

Next tactic:
simp_rw [← withTopEquiv_lt]
theorem lt_wf : @WellFounded PartENat (· < ·) := by
  classical
    change WellFounded fun a b : PartENat => a < b
    simp_rw [← withTopEquiv_lt]
    

Proof state:
⊢ WellFounded fun a b => withTopEquiv a < withTopEquiv b

Next tactic:
exact InvImage.wf _ wellFounded_lt
theorem lt_find (n : ℕ) (h : ∀ m ≤ n, ¬P m) : (n : PartENat) < find P := by
  

Proof state:
P : ℕ → Prop
inst✝ : DecidablePred P
n : ℕ
h : ∀ m ≤ n, ¬P m
⊢ ↑n < find P

Next tactic:
rw [coe_lt_iff]
theorem lt_find (n : ℕ) (h : ∀ m ≤ n, ¬P m) : (n : PartENat) < find P := by
  rw [coe_lt_iff]
  

Proof state:
P : ℕ → Prop
inst✝ : DecidablePred P
n : ℕ
h : ∀ m ≤ n, ¬P m
⊢ ∀ (h : (find P).Dom), n < Part.get (find P) h

Next tactic:
intro h₁
theorem lt_find (n : ℕ) (h : ∀ m ≤ n, ¬P m) : (n : PartENat) < find P := by
  rw [coe_lt_iff]
  intro h₁
  

Proof state:
P : ℕ → Prop
inst✝ : DecidablePred P
n : ℕ
h : ∀ m ≤ n, ¬P m
h₁ : (find P).Dom
⊢ n < Part.get (find P) h₁

Next tactic:
rw [find_get]
theorem lt_find (n : ℕ) (h : ∀ m ≤ n, ¬P m) : (n : PartENat) < find P := by
  rw [coe_lt_iff]
  intro h₁
  rw [find_get]
  

Proof state:
P : ℕ → Prop
inst✝ : DecidablePred P
n : ℕ
h : ∀ m ≤ n, ¬P m
h₁ : (find P).Dom
⊢ n < Nat.find h₁

Next tactic:
have h₂ := @Nat.find_spec P _ h₁
theorem lt_find (n : ℕ) (h : ∀ m ≤ n, ¬P m) : (n : PartENat) < find P := by
  rw [coe_lt_iff]
  intro h₁
  rw [find_get]
  have h₂ := @Nat.find_spec P _ h₁
  

Proof state:
P : ℕ → Prop
inst✝ : DecidablePred P
n : ℕ
h : ∀ m ≤ n, ¬P m
h₁ : (find P).Dom
h₂ : P (Nat.find h₁)
⊢ n < Nat.find h₁

Next tactic:
revert h₂
theorem lt_find (n : ℕ) (h : ∀ m ≤ n, ¬P m) : (n : PartENat) < find P := by
  rw [coe_lt_iff]
  intro h₁
  rw [find_get]
  have h₂ := @Nat.find_spec P _ h₁
  revert h₂
  

Proof state:
P : ℕ → Prop
inst✝ : DecidablePred P
n : ℕ
h : ∀ m ≤ n, ¬P m
h₁ : (find P).Dom
⊢ P (Nat.find h₁) → n < Nat.find h₁

Next tactic:
contrapose!
theorem lt_find (n : ℕ) (h : ∀ m ≤ n, ¬P m) : (n : PartENat) < find P := by
  rw [coe_lt_iff]
  intro h₁
  rw [find_get]
  have h₂ := @Nat.find_spec P _ h₁
  revert h₂
  contrapose!
  

Proof state:
P : ℕ → Prop
inst✝ : DecidablePred P
n : ℕ
h : ∀ m ≤ n, ¬P m
h₁ : (find P).Dom
⊢ Nat.find h₁ ≤ n → ¬P (Nat.find h₁)

Next tactic:
exact h _
theorem lt_find_iff (n : ℕ) : (n : PartENat) < find P ↔ ∀ m ≤ n, ¬P m := by
  

Proof state:
P : ℕ → Prop
inst✝ : DecidablePred P
n : ℕ
⊢ ↑n < find P ↔ ∀ m ≤ n, ¬P m

Next tactic:
refine' ⟨_, lt_find P n⟩
theorem lt_find_iff (n : ℕ) : (n : PartENat) < find P ↔ ∀ m ≤ n, ¬P m := by
  refine' ⟨_, lt_find P n⟩
  

Proof state:
P : ℕ → Prop
inst✝ : DecidablePred P
n : ℕ
⊢ ↑n < find P → ∀ m ≤ n, ¬P m

Next tactic:
intro h m hm
theorem lt_find_iff (n : ℕ) : (n : PartENat) < find P ↔ ∀ m ≤ n, ¬P m := by
  refine' ⟨_, lt_find P n⟩
  intro h m hm
  

Proof state:
P : ℕ → Prop
inst✝ : DecidablePred P
n : ℕ
h : ↑n < find P
m : ℕ
hm : m ≤ n
⊢ ¬P m

Next tactic:
by_cases H : (find P).Dom
theorem lt_find_iff (n : ℕ) : (n : PartENat) < find P ↔ ∀ m ≤ n, ¬P m := by
  refine' ⟨_, lt_find P n⟩
  intro h m hm
  by_cases H : (find P).Dom
  · 

Proof state:
case pos
P : ℕ → Prop
inst✝ : DecidablePred P
n : ℕ
h : ↑n < find P
m : ℕ
hm : m ≤ n
H : (find P).Dom
⊢ ¬P m

Next tactic:
apply Nat.find_min H
theorem lt_find_iff (n : ℕ) : (n : PartENat) < find P ↔ ∀ m ≤ n, ¬P m := by
  refine' ⟨_, lt_find P n⟩
  intro h m hm
  by_cases H : (find P).Dom
  · apply Nat.find_min H
    

Proof state:
case pos
P : ℕ → Prop
inst✝ : DecidablePred P
n : ℕ
h : ↑n < find P
m : ℕ
hm : m ≤ n
H : (find P).Dom
⊢ m < Nat.find H

Next tactic:
rw [coe_lt_iff] at h
theorem lt_find_iff (n : ℕ) : (n : PartENat) < find P ↔ ∀ m ≤ n, ¬P m := by
  refine' ⟨_, lt_find P n⟩
  intro h m hm
  by_cases H : (find P).Dom
  · apply Nat.find_min H
    rw [coe_lt_iff] at h
    

Proof state:
case pos
P : ℕ → Prop
inst✝ : DecidablePred P
n : ℕ
h : ∀ (h : (find P).Dom), n < Part.get (find P) h
m : ℕ
hm : m ≤ n
H : (find P).Dom
⊢ m < Nat.find H

Next tactic:
specialize h H
theorem lt_find_iff (n : ℕ) : (n : PartENat) < find P ↔ ∀ m ≤ n, ¬P m := by
  refine' ⟨_, lt_find P n⟩
  intro h m hm
  by_cases H : (find P).Dom
  · apply Nat.find_min H
    rw [coe_lt_iff] at h
    specialize h H
    

Proof state:
case pos
P : ℕ → Prop
inst✝ : DecidablePred P
n m : ℕ
hm : m ≤ n
H : (find P).Dom
h : n < Part.get (find P) H
⊢ m < Nat.find H

Next tactic:
exact lt_of_le_of_lt hm h
theorem lt_find_iff (n : ℕ) : (n : PartENat) < find P ↔ ∀ m ≤ n, ¬P m := by
  refine' ⟨_, lt_find P n⟩
  intro h m hm
  by_cases H : (find P).Dom
  · apply Nat.find_min H
    rw [coe_lt_iff] at h
    specialize h H
    exact lt_of_le_of_lt hm h
  · 

Proof state:
case neg
P : ℕ → Prop
inst✝ : DecidablePred P
n : ℕ
h : ↑n < find P
m : ℕ
hm : m ≤ n
H : ¬(find P).Dom
⊢ ¬P m

Next tactic:
exact not_exists.mp H m
theorem find_le (n : ℕ) (h : P n) : find P ≤ n := by
  

Proof state:
P : ℕ → Prop
inst✝ : DecidablePred P
n : ℕ
h : P n
⊢ find P ≤ ↑n

Next tactic:
rw [le_coe_iff]
theorem find_le (n : ℕ) (h : P n) : find P ≤ n := by
  rw [le_coe_iff]
  

Proof state:
P : ℕ → Prop
inst✝ : DecidablePred P
n : ℕ
h : P n
⊢ ∃ (h : (find P).Dom), Part.get (find P) h ≤ n

Next tactic:
refine' ⟨⟨_, h⟩, @Nat.find_min' P _ _ _ h⟩
@[simp]
theorem rank_one [StrongRankCondition R] [DecidableEq n] :
    rank (1 : Matrix n n R) = Fintype.card n := by
  

Proof state:
l : Type u_1
m : Type u_2
n : Type u_3
o : Type u_4
R : Type u_5
m_fin : Fintype m
inst✝⁴ : Fintype n
inst✝³ : Fintype o
inst✝² : CommRing R
inst✝¹ : StrongRankCondition R
inst✝ : DecidableEq n
⊢ rank 1 = Fintype.card n

Next tactic:
rw [rank, mulVecLin_one, LinearMap.range_id, finrank_top, finrank_pi]
@[simp]
theorem rank_zero [Nontrivial R] : rank (0 : Matrix m n R) = 0 := by
  

Proof state:
l : Type u_1
m : Type u_2
n : Type u_3
o : Type u_4
R : Type u_5
m_fin : Fintype m
inst✝³ : Fintype n
inst✝² : Fintype o
inst✝¹ : CommRing R
inst✝ : Nontrivial R
⊢ rank 0 = 0

Next tactic:
rw [rank, mulVecLin_zero, LinearMap.range_zero, finrank_bot]
theorem rank_le_card_width [StrongRankCondition R] (A : Matrix m n R) :
    A.rank ≤ Fintype.card n := by
  

Proof state:
l : Type u_1
m : Type u_2
n : Type u_3
o : Type u_4
R : Type u_5
m_fin : Fintype m
inst✝³ : Fintype n
inst✝² : Fintype o
inst✝¹ : CommRing R
inst✝ : StrongRankCondition R
A : Matrix m n R
⊢ rank A ≤ Fintype.card n

Next tactic:
haveI : Module.Finite R (n → R) := Module.Finite.pi
theorem rank_le_card_width [StrongRankCondition R] (A : Matrix m n R) :
    A.rank ≤ Fintype.card n := by
  haveI : Module.Finite R (n → R) := Module.Finite.pi
  

Proof state:
l : Type u_1
m : Type u_2
n : Type u_3
o : Type u_4
R : Type u_5
m_fin : Fintype m
inst✝³ : Fintype n
inst✝² : Fintype o
inst✝¹ : CommRing R
inst✝ : StrongRankCondition R
A : Matrix m n R
this : Module.Finite R (n → R)
⊢ rank A ≤ Fintype.card n

Next tactic:
haveI : Module.Free R (n → R) := Module.Free.pi _ _
theorem rank_le_card_width [StrongRankCondition R] (A : Matrix m n R) :
    A.rank ≤ Fintype.card n := by
  haveI : Module.Finite R (n → R) := Module.Finite.pi
  haveI : Module.Free R (n → R) := Module.Free.pi _ _
  

Proof state:
l : Type u_1
m : Type u_2
n : Type u_3
o : Type u_4
R : Type u_5
m_fin : Fintype m
inst✝³ : Fintype n
inst✝² : Fintype o
inst✝¹ : CommRing R
inst✝ : StrongRankCondition R
A : Matrix m n R
this✝ : Module.Finite R (n → R)
this : Module.Free R (n → R)
⊢ rank A ≤ Fintype.card n

Next tactic:
exact A.mulVecLin.finrank_range_le.trans_eq (finrank_pi _)
theorem rank_mul_le_left [StrongRankCondition R] (A : Matrix m n R) (B : Matrix n o R) :
    (A * B).rank ≤ A.rank := by
  

Proof state:
l : Type u_1
m : Type u_2
n : Type u_3
o : Type u_4
R : Type u_5
m_fin : Fintype m
inst✝³ : Fintype n
inst✝² : Fintype o
inst✝¹ : CommRing R
inst✝ : StrongRankCondition R
A : Matrix m n R
B : Matrix n o R
⊢ rank (A * B) ≤ rank A

Next tactic:
rw [rank, rank, mulVecLin_mul]
theorem rank_mul_le_left [StrongRankCondition R] (A : Matrix m n R) (B : Matrix n o R) :
    (A * B).rank ≤ A.rank := by
  rw [rank, rank, mulVecLin_mul]
  

Proof state:
l : Type u_1
m : Type u_2
n : Type u_3
o : Type u_4
R : Type u_5
m_fin : Fintype m
inst✝³ : Fintype n
inst✝² : Fintype o
inst✝¹ : CommRing R
inst✝ : StrongRankCondition R
A : Matrix m n R
B : Matrix n o R
⊢ finrank R ↥(LinearMap.range (mulVecLin A ∘ₗ mulVecLin B)) ≤ finrank R ↥(LinearMap.range (mulVecLin A))

Next tactic:
exact Cardinal.toNat_le_of_le_of_lt_aleph0 (rank_lt_aleph0 _ _) (LinearMap.rank_comp_le_left _ _)
theorem rank_mul_le_right [StrongRankCondition R] (A : Matrix l m R) (B : Matrix m n R) :
    (A * B).rank ≤ B.rank := by
  

Proof state:
l : Type u_1
m : Type u_2
n : Type u_3
o : Type u_4
R : Type u_5
m_fin : Fintype m
inst✝³ : Fintype n
inst✝² : Fintype o
inst✝¹ : CommRing R
inst✝ : StrongRankCondition R
A : Matrix l m R
B : Matrix m n R
⊢ rank (A * B) ≤ rank B

Next tactic:
rw [rank, rank, mulVecLin_mul]
theorem rank_mul_le_right [StrongRankCondition R] (A : Matrix l m R) (B : Matrix m n R) :
    (A * B).rank ≤ B.rank := by
  rw [rank, rank, mulVecLin_mul]
  

Proof state:
l : Type u_1
m : Type u_2
n : Type u_3
o : Type u_4
R : Type u_5
m_fin : Fintype m
inst✝³ : Fintype n
inst✝² : Fintype o
inst✝¹ : CommRing R
inst✝ : StrongRankCondition R
A : Matrix l m R
B : Matrix m n R
⊢ finrank R ↥(LinearMap.range (mulVecLin A ∘ₗ mulVecLin B)) ≤ finrank R ↥(LinearMap.range (mulVecLin B))

Next tactic:
exact
    finrank_le_finrank_of_rank_le_rank (LinearMap.lift_rank_comp_le_right _ _) (rank_lt_aleph0 _ _)
theorem rank_unit [StrongRankCondition R] [DecidableEq n] (A : (Matrix n n R)ˣ) :
    (A : Matrix n n R).rank = Fintype.card n := by
  

Proof state:
l : Type u_1
m : Type u_2
n : Type u_3
o : Type u_4
R : Type u_5
m_fin : Fintype m
inst✝⁴ : Fintype n
inst✝³ : Fintype o
inst✝² : CommRing R
inst✝¹ : StrongRankCondition R
inst✝ : DecidableEq n
A : (Matrix n n R)ˣ
⊢ rank ↑A = Fintype.card n

Next tactic:
refine' le_antisymm (rank_le_card_width A) _
theorem rank_unit [StrongRankCondition R] [DecidableEq n] (A : (Matrix n n R)ˣ) :
    (A : Matrix n n R).rank = Fintype.card n := by
  refine' le_antisymm (rank_le_card_width A) _
  

Proof state:
l : Type u_1
m : Type u_2
n : Type u_3
o : Type u_4
R : Type u_5
m_fin : Fintype m
inst✝⁴ : Fintype n
inst✝³ : Fintype o
inst✝² : CommRing R
inst✝¹ : StrongRankCondition R
inst✝ : DecidableEq n
A : (Matrix n n R)ˣ
⊢ Fintype.card n ≤ rank ↑A

Next tactic:
have := rank_mul_le_left (A : Matrix n n R) (↑A⁻¹ : Matrix n n R)
theorem rank_unit [StrongRankCondition R] [DecidableEq n] (A : (Matrix n n R)ˣ) :
    (A : Matrix n n R).rank = Fintype.card n := by
  refine' le_antisymm (rank_le_card_width A) _
  have := rank_mul_le_left (A : Matrix n n R) (↑A⁻¹ : Matrix n n R)
  

Proof state:
l : Type u_1
m : Type u_2
n : Type u_3
o : Type u_4
R : Type u_5
m_fin : Fintype m
inst✝⁴ : Fintype n
inst✝³ : Fintype o
inst✝² : CommRing R
inst✝¹ : StrongRankCondition R
inst✝ : DecidableEq n
A : (Matrix n n R)ˣ
this : rank (↑A * ↑A⁻¹) ≤ rank ↑A
⊢ Fintype.card n ≤ rank ↑A

Next tactic:
rwa [← Units.val_mul, mul_inv_self, Units.val_one, rank_one] at this
theorem rank_of_isUnit [StrongRankCondition R] [DecidableEq n] (A : Matrix n n R) (h : IsUnit A) :
    A.rank = Fintype.card n := by
  

Proof state:
l : Type u_1
m : Type u_2
n : Type u_3
o : Type u_4
R : Type u_5
m_fin : Fintype m
inst✝⁴ : Fintype n
inst✝³ : Fintype o
inst✝² : CommRing R
inst✝¹ : StrongRankCondition R
inst✝ : DecidableEq n
A : Matrix n n R
h : IsUnit A
⊢ rank A = Fintype.card n

Next tactic:
obtain ⟨A, rfl⟩ := h
theorem rank_of_isUnit [StrongRankCondition R] [DecidableEq n] (A : Matrix n n R) (h : IsUnit A) :
    A.rank = Fintype.card n := by
  obtain ⟨A, rfl⟩ := h
  

Proof state:
case intro
l : Type u_1
m : Type u_2
n : Type u_3
o : Type u_4
R : Type u_5
m_fin : Fintype m
inst✝⁴ : Fintype n
inst✝³ : Fintype o
inst✝² : CommRing R
inst✝¹ : StrongRankCondition R
inst✝ : DecidableEq n
A : (Matrix n n R)ˣ
⊢ rank ↑A = Fintype.card n

Next tactic:
exact rank_unit A
/-- Right multiplying by an invertible matrix does not change the rank -/
lemma rank_mul_eq_left_of_isUnit_det [DecidableEq n]
    (A : Matrix n n R) (B : Matrix m n R) (hA : IsUnit A.det) :
    (B * A).rank = B.rank := by
  

Proof state:
l : Type u_1
m : Type u_2
n : Type u_3
o : Type u_4
R : Type u_5
m_fin : Fintype m
inst✝³ : Fintype n
inst✝² : Fintype o
inst✝¹ : CommRing R
inst✝ : DecidableEq n
A : Matrix n n R
B : Matrix m n R
hA : IsUnit (det A)
⊢ rank (B * A) = rank B

Next tactic:
suffices : Function.Surjective A.mulVecLin
/-- Right multiplying by an invertible matrix does not change the rank -/
lemma rank_mul_eq_left_of_isUnit_det [DecidableEq n]
    (A : Matrix n n R) (B : Matrix m n R) (hA : IsUnit A.det) :
    (B * A).rank = B.rank := by
  suffices : Function.Surjective A.mulVecLin
  · 

Proof state:
l : Type u_1
m : Type u_2
n : Type u_3
o : Type u_4
R : Type u_5
m_fin : Fintype m
inst✝³ : Fintype n
inst✝² : Fintype o
inst✝¹ : CommRing R
inst✝ : DecidableEq n
A : Matrix n n R
B : Matrix m n R
hA : IsUnit (det A)
this : Function.Surjective ⇑(mulVecLin A)
⊢ rank (B * A) = rank B

Next tactic:
rw [rank, mulVecLin_mul, LinearMap.range_comp_of_range_eq_top _
    (LinearMap.range_eq_top.mpr this), ← rank]
/-- Right multiplying by an invertible matrix does not change the rank -/
lemma rank_mul_eq_left_of_isUnit_det [DecidableEq n]
    (A : Matrix n n R) (B : Matrix m n R) (hA : IsUnit A.det) :
    (B * A).rank = B.rank := by
  suffices : Function.Surjective A.mulVecLin
  · rw [rank, mulVecLin_mul, LinearMap.range_comp_of_range_eq_top _
    (LinearMap.range_eq_top.mpr this), ← rank]
  

Proof state:
case this
l : Type u_1
m : Type u_2
n : Type u_3
o : Type u_4
R : Type u_5
m_fin : Fintype m
inst✝³ : Fintype n
inst✝² : Fintype o
inst✝¹ : CommRing R
inst✝ : DecidableEq n
A : Matrix n n R
B : Matrix m n R
hA : IsUnit (det A)
⊢ Function.Surjective ⇑(mulVecLin A)

Next tactic:
intro v
/-- Right multiplying by an invertible matrix does not change the rank -/
lemma rank_mul_eq_left_of_isUnit_det [DecidableEq n]
    (A : Matrix n n R) (B : Matrix m n R) (hA : IsUnit A.det) :
    (B * A).rank = B.rank := by
  suffices : Function.Surjective A.mulVecLin
  · rw [rank, mulVecLin_mul, LinearMap.range_comp_of_range_eq_top _
    (LinearMap.range_eq_top.mpr this), ← rank]
  intro v
  

Proof state:
case this
l : Type u_1
m : Type u_2
n : Type u_3
o : Type u_4
R : Type u_5
m_fin : Fintype m
inst✝³ : Fintype n
inst✝² : Fintype o
inst✝¹ : CommRing R
inst✝ : DecidableEq n
A : Matrix n n R
B : Matrix m n R
hA : IsUnit (det A)
v : n → R
⊢ ∃ a, (mulVecLin A) a = v

Next tactic:
exact ⟨(A⁻¹).mulVecLin v, by simp [mul_nonsing_inv _ hA]⟩
/-- Right multiplying by an invertible matrix does not change the rank -/
lemma rank_mul_eq_left_of_isUnit_det [DecidableEq n]
    (A : Matrix n n R) (B : Matrix m n R) (hA : IsUnit A.det) :
    (B * A).rank = B.rank := by
  suffices : Function.Surjective A.mulVecLin
  · rw [rank, mulVecLin_mul, LinearMap.range_comp_of_range_eq_top _
    (LinearMap.range_eq_top.mpr this), ← rank]
  intro v
  exact ⟨(A⁻¹).mulVecLin v, by 

Proof state:
l : Type u_1
m : Type u_2
n : Type u_3
o : Type u_4
R : Type u_5
m_fin : Fintype m
inst✝³ : Fintype n
inst✝² : Fintype o
inst✝¹ : CommRing R
inst✝ : DecidableEq n
A : Matrix n n R
B : Matrix m n R
hA : IsUnit (det A)
v : n → R
⊢ (mulVecLin A) ((mulVecLin A⁻¹) v) = v

Next tactic:
simp [mul_nonsing_inv _ hA]
/-- Left multiplying by an invertible matrix does not change the rank -/
lemma rank_mul_eq_right_of_isUnit_det [DecidableEq m]
    (A : Matrix m m R) (B : Matrix m n R) (hA : IsUnit A.det) :
    (A * B).rank = B.rank := by
  

Proof state:
l : Type u_1
m : Type u_2
n : Type u_3
o : Type u_4
R : Type u_5
m_fin : Fintype m
inst✝³ : Fintype n
inst✝² : Fintype o
inst✝¹ : CommRing R
inst✝ : DecidableEq m
A : Matrix m m R
B : Matrix m n R
hA : IsUnit (det A)
⊢ rank (A * B) = rank B

Next tactic:
let b : Basis m R (m → R) := Pi.basisFun R m
/-- Left multiplying by an invertible matrix does not change the rank -/
lemma rank_mul_eq_right_of_isUnit_det [DecidableEq m]
    (A : Matrix m m R) (B : Matrix m n R) (hA : IsUnit A.det) :
    (A * B).rank = B.rank := by
  let b : Basis m R (m → R) := Pi.basisFun R m
  

Proof state:
l : Type u_1
m : Type u_2
n : Type u_3
o : Type u_4
R : Type u_5
m_fin : Fintype m
inst✝³ : Fintype n
inst✝² : Fintype o
inst✝¹ : CommRing R
inst✝ : DecidableEq m
A : Matrix m m R
B : Matrix m n R
hA : IsUnit (det A)
b : Basis m R (m → R) := Pi.basisFun R m
⊢ rank (A * B) = rank B

Next tactic:
replace hA : IsUnit (LinearMap.toMatrix b b A.mulVecLin).det := by
    convert hA; rw [← LinearEquiv.eq_symm_apply]; rfl
/-- Left multiplying by an invertible matrix does not change the rank -/
lemma rank_mul_eq_right_of_isUnit_det [DecidableEq m]
    (A : Matrix m m R) (B : Matrix m n R) (hA : IsUnit A.det) :
    (A * B).rank = B.rank := by
  let b : Basis m R (m → R) := Pi.basisFun R m
  replace hA : IsUnit (LinearMap.toMatrix b b A.mulVecLin).det := by
    

Proof state:
l : Type u_1
m : Type u_2
n : Type u_3
o : Type u_4
R : Type u_5
m_fin : Fintype m
inst✝³ : Fintype n
inst✝² : Fintype o
inst✝¹ : CommRing R
inst✝ : DecidableEq m
A : Matrix m m R
B : Matrix m n R
hA : IsUnit (det A)
b : Basis m R (m → R) := Pi.basisFun R m
⊢ IsUnit (det ((LinearMap.toMatrix b b) (mulVecLin A)))

Next tactic:
convert hA
/-- Left multiplying by an invertible matrix does not change the rank -/
lemma rank_mul_eq_right_of_isUnit_det [DecidableEq m]
    (A : Matrix m m R) (B : Matrix m n R) (hA : IsUnit A.det) :
    (A * B).rank = B.rank := by
  let b : Basis m R (m → R) := Pi.basisFun R m
  replace hA : IsUnit (LinearMap.toMatrix b b A.mulVecLin).det := by
    convert hA; 

Proof state:
case h.e'_3.h.e'_6
l : Type u_1
m : Type u_2
n : Type u_3
o : Type u_4
R : Type u_5
m_fin : Fintype m
inst✝³ : Fintype n
inst✝² : Fintype o
inst✝¹ : CommRing R
inst✝ : DecidableEq m
A : Matrix m m R
B : Matrix m n R
hA : IsUnit (det A)
b : Basis m R (m → R) := Pi.basisFun R m
⊢ (LinearMap.toMatrix b b) (mulVecLin A) = A

Next tactic:
rw [← LinearEquiv.eq_symm_apply]