l3lab/ntp-mathlib huggingface dataset:
theorem edist_vsub_vsub_le (p₁ p₂ p₃ p₄ : P) :
    edist (p₁ -ᵥ p₂) (p₃ -ᵥ p₄) ≤ edist p₁ p₃ + edist p₂ p₄ := by
  simp only [edist_nndist]
  

Proof state:
α : Type u_1
V : Type u_2
P : Type u_3
W : Type u_4
Q : Type u_5
inst✝⁵ : SeminormedAddCommGroup V
inst✝⁴ : PseudoMetricSpace P
inst✝³ : NormedAddTorsor V P
inst✝² : NormedAddCommGroup W
inst✝¹ : MetricSpace Q
inst✝ : NormedAddTorsor W Q
p₁ p₂ p₃ p₄ : P
⊢ ↑(nndist (p₁ -ᵥ p₂) (p₃ -ᵥ p₄)) ≤ ↑(nndist p₁ p₃) + ↑(nndist p₂ p₄)

Next tactic:
norm_cast
theorem edist_vsub_vsub_le (p₁ p₂ p₃ p₄ : P) :
    edist (p₁ -ᵥ p₂) (p₃ -ᵥ p₄) ≤ edist p₁ p₃ + edist p₂ p₄ := by
  simp only [edist_nndist]
  norm_cast  -- porting note: was apply_mod_cast
  

Proof state:
α : Type u_1
V : Type u_2
P : Type u_3
W : Type u_4
Q : Type u_5
inst✝⁵ : SeminormedAddCommGroup V
inst✝⁴ : PseudoMetricSpace P
inst✝³ : NormedAddTorsor V P
inst✝² : NormedAddCommGroup W
inst✝¹ : MetricSpace Q
inst✝ : NormedAddTorsor W Q
p₁ p₂ p₃ p₄ : P
⊢ nndist (p₁ -ᵥ p₂) (p₃ -ᵥ p₄) ≤ nndist p₁ p₃ + nndist p₂ p₄

Next tactic:
apply dist_vsub_vsub_le
/-- The pseudodistance defines a pseudometric space structure on the torsor. This
is not an instance because it depends on `V` to define a `MetricSpace P`. -/
def pseudoMetricSpaceOfNormedAddCommGroupOfAddTorsor (V P : Type*) [SeminormedAddCommGroup V]
    [AddTorsor V P] : PseudoMetricSpace P where
  dist x y := ‖(x -ᵥ y : V)‖
  -- porting note: `edist_dist` is no longer an `autoParam`
  edist_dist _ _ := by simp only [← ENNReal.ofReal_eq_coe_nnreal]
  dist_self x := by 

Proof state:
α : Type u_1
V✝ : Type u_2
P✝ : Type u_3
W : Type u_4
Q : Type u_5
inst✝⁷ : SeminormedAddCommGroup V✝
inst✝⁶ : PseudoMetricSpace P✝
inst✝⁵ : NormedAddTorsor V✝ P✝
inst✝⁴ : NormedAddCommGroup W
inst✝³ : MetricSpace Q
inst✝² : NormedAddTorsor W Q
V : Type u_6
P : Type u_7
inst✝¹ : SeminormedAddCommGroup V
inst✝ : AddTorsor V P
x : P
⊢ dist x x = 0

Next tactic:
simp
/-- The pseudodistance defines a pseudometric space structure on the torsor. This
is not an instance because it depends on `V` to define a `MetricSpace P`. -/
def pseudoMetricSpaceOfNormedAddCommGroupOfAddTorsor (V P : Type*) [SeminormedAddCommGroup V]
    [AddTorsor V P] : PseudoMetricSpace P where
  dist x y := ‖(x -ᵥ y : V)‖
  -- porting note: `edist_dist` is no longer an `autoParam`
  edist_dist _ _ := by simp only [← ENNReal.ofReal_eq_coe_nnreal]
  dist_self x := by simp
  dist_comm x y := by 

Proof state:
α : Type u_1
V✝ : Type u_2
P✝ : Type u_3
W : Type u_4
Q : Type u_5
inst✝⁷ : SeminormedAddCommGroup V✝
inst✝⁶ : PseudoMetricSpace P✝
inst✝⁵ : NormedAddTorsor V✝ P✝
inst✝⁴ : NormedAddCommGroup W
inst✝³ : MetricSpace Q
inst✝² : NormedAddTorsor W Q
V : Type u_6
P : Type u_7
inst✝¹ : SeminormedAddCommGroup V
inst✝ : AddTorsor V P
x y : P
⊢ dist x y = dist y x

Next tactic:
simp only [← neg_vsub_eq_vsub_rev y x, norm_neg]
/-- The pseudodistance defines a pseudometric space structure on the torsor. This
is not an instance because it depends on `V` to define a `MetricSpace P`. -/
def pseudoMetricSpaceOfNormedAddCommGroupOfAddTorsor (V P : Type*) [SeminormedAddCommGroup V]
    [AddTorsor V P] : PseudoMetricSpace P where
  dist x y := ‖(x -ᵥ y : V)‖
  -- porting note: `edist_dist` is no longer an `autoParam`
  edist_dist _ _ := by simp only [← ENNReal.ofReal_eq_coe_nnreal]
  dist_self x := by simp
  dist_comm x y := by simp only [← neg_vsub_eq_vsub_rev y x, norm_neg]
  dist_triangle x y z := by
    

Proof state:
α : Type u_1
V✝ : Type u_2
P✝ : Type u_3
W : Type u_4
Q : Type u_5
inst✝⁷ : SeminormedAddCommGroup V✝
inst✝⁶ : PseudoMetricSpace P✝
inst✝⁵ : NormedAddTorsor V✝ P✝
inst✝⁴ : NormedAddCommGroup W
inst✝³ : MetricSpace Q
inst✝² : NormedAddTorsor W Q
V : Type u_6
P : Type u_7
inst✝¹ : SeminormedAddCommGroup V
inst✝ : AddTorsor V P
x y z : P
⊢ dist x z ≤ dist x y + dist y z

Next tactic:
change ‖x -ᵥ z‖ ≤ ‖x -ᵥ y‖ + ‖y -ᵥ z‖
/-- The pseudodistance defines a pseudometric space structure on the torsor. This
is not an instance because it depends on `V` to define a `MetricSpace P`. -/
def pseudoMetricSpaceOfNormedAddCommGroupOfAddTorsor (V P : Type*) [SeminormedAddCommGroup V]
    [AddTorsor V P] : PseudoMetricSpace P where
  dist x y := ‖(x -ᵥ y : V)‖
  -- porting note: `edist_dist` is no longer an `autoParam`
  edist_dist _ _ := by simp only [← ENNReal.ofReal_eq_coe_nnreal]
  dist_self x := by simp
  dist_comm x y := by simp only [← neg_vsub_eq_vsub_rev y x, norm_neg]
  dist_triangle x y z := by
    change ‖x -ᵥ z‖ ≤ ‖x -ᵥ y‖ + ‖y -ᵥ z‖
    

Proof state:
α : Type u_1
V✝ : Type u_2
P✝ : Type u_3
W : Type u_4
Q : Type u_5
inst✝⁷ : SeminormedAddCommGroup V✝
inst✝⁶ : PseudoMetricSpace P✝
inst✝⁵ : NormedAddTorsor V✝ P✝
inst✝⁴ : NormedAddCommGroup W
inst✝³ : MetricSpace Q
inst✝² : NormedAddTorsor W Q
V : Type u_6
P : Type u_7
inst✝¹ : SeminormedAddCommGroup V
inst✝ : AddTorsor V P
x y z : P
⊢ ‖x -ᵥ z‖ ≤ ‖x -ᵥ y‖ + ‖y -ᵥ z‖

Next tactic:
rw [← vsub_add_vsub_cancel]
/-- The pseudodistance defines a pseudometric space structure on the torsor. This
is not an instance because it depends on `V` to define a `MetricSpace P`. -/
def pseudoMetricSpaceOfNormedAddCommGroupOfAddTorsor (V P : Type*) [SeminormedAddCommGroup V]
    [AddTorsor V P] : PseudoMetricSpace P where
  dist x y := ‖(x -ᵥ y : V)‖
  -- porting note: `edist_dist` is no longer an `autoParam`
  edist_dist _ _ := by simp only [← ENNReal.ofReal_eq_coe_nnreal]
  dist_self x := by simp
  dist_comm x y := by simp only [← neg_vsub_eq_vsub_rev y x, norm_neg]
  dist_triangle x y z := by
    change ‖x -ᵥ z‖ ≤ ‖x -ᵥ y‖ + ‖y -ᵥ z‖
    rw [← vsub_add_vsub_cancel]
    

Proof state:
α : Type u_1
V✝ : Type u_2
P✝ : Type u_3
W : Type u_4
Q : Type u_5
inst✝⁷ : SeminormedAddCommGroup V✝
inst✝⁶ : PseudoMetricSpace P✝
inst✝⁵ : NormedAddTorsor V✝ P✝
inst✝⁴ : NormedAddCommGroup W
inst✝³ : MetricSpace Q
inst✝² : NormedAddTorsor W Q
V : Type u_6
P : Type u_7
inst✝¹ : SeminormedAddCommGroup V
inst✝ : AddTorsor V P
x y z : P
⊢ ‖x -ᵥ ?p2 + (?p2 -ᵥ z)‖ ≤ ‖x -ᵥ y‖ + ‖y -ᵥ z‖
case p2
α : Type u_1
V✝ : Type u_2
P✝ : Type u_3
W : Type u_4
Q : Type u_5
inst✝⁷ : SeminormedAddCommGroup V✝
inst✝⁶ : PseudoMetricSpace P✝
inst✝⁵ : NormedAddTorsor V✝ P✝
inst✝⁴ : NormedAddCommGroup W
inst✝³ : MetricSpace Q
inst✝² : NormedAddTorsor W Q
V : Type u_6
P : Type u_7
inst✝¹ : SeminormedAddCommGroup V
inst✝ : AddTorsor V P
x y z : P
⊢ P

Next tactic:
apply norm_add_le
/-- The pseudodistance defines a pseudometric space structure on the torsor. This
is not an instance because it depends on `V` to define a `MetricSpace P`. -/
def pseudoMetricSpaceOfNormedAddCommGroupOfAddTorsor (V P : Type*) [SeminormedAddCommGroup V]
    [AddTorsor V P] : PseudoMetricSpace P where
  dist x y := ‖(x -ᵥ y : V)‖
  -- porting note: `edist_dist` is no longer an `autoParam`
  edist_dist _ _ := by 

Proof state:
α : Type u_1
V✝ : Type u_2
P✝ : Type u_3
W : Type u_4
Q : Type u_5
inst✝⁷ : SeminormedAddCommGroup V✝
inst✝⁶ : PseudoMetricSpace P✝
inst✝⁵ : NormedAddTorsor V✝ P✝
inst✝⁴ : NormedAddCommGroup W
inst✝³ : MetricSpace Q
inst✝² : NormedAddTorsor W Q
V : Type u_6
P : Type u_7
inst✝¹ : SeminormedAddCommGroup V
inst✝ : AddTorsor V P
x✝¹ x✝ : P
⊢ (fun x y => ↑{ val := ‖x -ᵥ y‖, property := (_ : 0 ≤ ‖x -ᵥ y‖) }) x✝¹ x✝ = ENNReal.ofReal (dist x✝¹ x✝)

Next tactic:
simp only [← ENNReal.ofReal_eq_coe_nnreal]
/-- The distance defines a metric space structure on the torsor. This
is not an instance because it depends on `V` to define a `MetricSpace P`. -/
def metricSpaceOfNormedAddCommGroupOfAddTorsor (V P : Type*) [NormedAddCommGroup V]
    [AddTorsor V P] : MetricSpace P where
  dist x y := ‖(x -ᵥ y : V)‖
  edist_dist _ _ := by simp only; rw [ENNReal.ofReal_eq_coe_nnreal]
  dist_self x := by 

Proof state:
α : Type u_1
V✝ : Type u_2
P✝ : Type u_3
W : Type u_4
Q : Type u_5
inst✝⁷ : SeminormedAddCommGroup V✝
inst✝⁶ : PseudoMetricSpace P✝
inst✝⁵ : NormedAddTorsor V✝ P✝
inst✝⁴ : NormedAddCommGroup W
inst✝³ : MetricSpace Q
inst✝² : NormedAddTorsor W Q
V : Type u_6
P : Type u_7
inst✝¹ : NormedAddCommGroup V
inst✝ : AddTorsor V P
x : P
⊢ dist x x = 0

Next tactic:
simp
/-- The distance defines a metric space structure on the torsor. This
is not an instance because it depends on `V` to define a `MetricSpace P`. -/
def metricSpaceOfNormedAddCommGroupOfAddTorsor (V P : Type*) [NormedAddCommGroup V]
    [AddTorsor V P] : MetricSpace P where
  dist x y := ‖(x -ᵥ y : V)‖
  edist_dist _ _ := by simp only; rw [ENNReal.ofReal_eq_coe_nnreal]
  dist_self x := by simp
  eq_of_dist_eq_zero h := by simpa using h
  dist_comm x y := by 

Proof state:
α : Type u_1
V✝ : Type u_2
P✝ : Type u_3
W : Type u_4
Q : Type u_5
inst✝⁷ : SeminormedAddCommGroup V✝
inst✝⁶ : PseudoMetricSpace P✝
inst✝⁵ : NormedAddTorsor V✝ P✝
inst✝⁴ : NormedAddCommGroup W
inst✝³ : MetricSpace Q
inst✝² : NormedAddTorsor W Q
V : Type u_6
P : Type u_7
inst✝¹ : NormedAddCommGroup V
inst✝ : AddTorsor V P
x y : P
⊢ dist x y = dist y x

Next tactic:
simp only [← neg_vsub_eq_vsub_rev y x, norm_neg]
/-- The distance defines a metric space structure on the torsor. This
is not an instance because it depends on `V` to define a `MetricSpace P`. -/
def metricSpaceOfNormedAddCommGroupOfAddTorsor (V P : Type*) [NormedAddCommGroup V]
    [AddTorsor V P] : MetricSpace P where
  dist x y := ‖(x -ᵥ y : V)‖
  edist_dist _ _ := by simp only; rw [ENNReal.ofReal_eq_coe_nnreal]
  dist_self x := by simp
  eq_of_dist_eq_zero h := by simpa using h
  dist_comm x y := by simp only [← neg_vsub_eq_vsub_rev y x, norm_neg]
  dist_triangle x y z := by
    

Proof state:
α : Type u_1
V✝ : Type u_2
P✝ : Type u_3
W : Type u_4
Q : Type u_5
inst✝⁷ : SeminormedAddCommGroup V✝
inst✝⁶ : PseudoMetricSpace P✝
inst✝⁵ : NormedAddTorsor V✝ P✝
inst✝⁴ : NormedAddCommGroup W
inst✝³ : MetricSpace Q
inst✝² : NormedAddTorsor W Q
V : Type u_6
P : Type u_7
inst✝¹ : NormedAddCommGroup V
inst✝ : AddTorsor V P
x y z : P
⊢ dist x z ≤ dist x y + dist y z

Next tactic:
change ‖x -ᵥ z‖ ≤ ‖x -ᵥ y‖ + ‖y -ᵥ z‖
/-- The distance defines a metric space structure on the torsor. This
is not an instance because it depends on `V` to define a `MetricSpace P`. -/
def metricSpaceOfNormedAddCommGroupOfAddTorsor (V P : Type*) [NormedAddCommGroup V]
    [AddTorsor V P] : MetricSpace P where
  dist x y := ‖(x -ᵥ y : V)‖
  edist_dist _ _ := by simp only; rw [ENNReal.ofReal_eq_coe_nnreal]
  dist_self x := by simp
  eq_of_dist_eq_zero h := by simpa using h
  dist_comm x y := by simp only [← neg_vsub_eq_vsub_rev y x, norm_neg]
  dist_triangle x y z := by
    change ‖x -ᵥ z‖ ≤ ‖x -ᵥ y‖ + ‖y -ᵥ z‖
    

Proof state:
α : Type u_1
V✝ : Type u_2
P✝ : Type u_3
W : Type u_4
Q : Type u_5
inst✝⁷ : SeminormedAddCommGroup V✝
inst✝⁶ : PseudoMetricSpace P✝
inst✝⁵ : NormedAddTorsor V✝ P✝
inst✝⁴ : NormedAddCommGroup W
inst✝³ : MetricSpace Q
inst✝² : NormedAddTorsor W Q
V : Type u_6
P : Type u_7
inst✝¹ : NormedAddCommGroup V
inst✝ : AddTorsor V P
x y z : P
⊢ ‖x -ᵥ z‖ ≤ ‖x -ᵥ y‖ + ‖y -ᵥ z‖

Next tactic:
rw [← vsub_add_vsub_cancel]
/-- The distance defines a metric space structure on the torsor. This
is not an instance because it depends on `V` to define a `MetricSpace P`. -/
def metricSpaceOfNormedAddCommGroupOfAddTorsor (V P : Type*) [NormedAddCommGroup V]
    [AddTorsor V P] : MetricSpace P where
  dist x y := ‖(x -ᵥ y : V)‖
  edist_dist _ _ := by simp only; rw [ENNReal.ofReal_eq_coe_nnreal]
  dist_self x := by simp
  eq_of_dist_eq_zero h := by simpa using h
  dist_comm x y := by simp only [← neg_vsub_eq_vsub_rev y x, norm_neg]
  dist_triangle x y z := by
    change ‖x -ᵥ z‖ ≤ ‖x -ᵥ y‖ + ‖y -ᵥ z‖
    rw [← vsub_add_vsub_cancel]
    

Proof state:
α : Type u_1
V✝ : Type u_2
P✝ : Type u_3
W : Type u_4
Q : Type u_5
inst✝⁷ : SeminormedAddCommGroup V✝
inst✝⁶ : PseudoMetricSpace P✝
inst✝⁵ : NormedAddTorsor V✝ P✝
inst✝⁴ : NormedAddCommGroup W
inst✝³ : MetricSpace Q
inst✝² : NormedAddTorsor W Q
V : Type u_6
P : Type u_7
inst✝¹ : NormedAddCommGroup V
inst✝ : AddTorsor V P
x y z : P
⊢ ‖x -ᵥ ?p2 + (?p2 -ᵥ z)‖ ≤ ‖x -ᵥ y‖ + ‖y -ᵥ z‖
case p2
α : Type u_1
V✝ : Type u_2
P✝ : Type u_3
W : Type u_4
Q : Type u_5
inst✝⁷ : SeminormedAddCommGroup V✝
inst✝⁶ : PseudoMetricSpace P✝
inst✝⁵ : NormedAddTorsor V✝ P✝
inst✝⁴ : NormedAddCommGroup W
inst✝³ : MetricSpace Q
inst✝² : NormedAddTorsor W Q
V : Type u_6
P : Type u_7
inst✝¹ : NormedAddCommGroup V
inst✝ : AddTorsor V P
x y z : P
⊢ P

Next tactic:
apply norm_add_le
/-- The distance defines a metric space structure on the torsor. This
is not an instance because it depends on `V` to define a `MetricSpace P`. -/
def metricSpaceOfNormedAddCommGroupOfAddTorsor (V P : Type*) [NormedAddCommGroup V]
    [AddTorsor V P] : MetricSpace P where
  dist x y := ‖(x -ᵥ y : V)‖
  edist_dist _ _ := by 

Proof state:
α : Type u_1
V✝ : Type u_2
P✝ : Type u_3
W : Type u_4
Q : Type u_5
inst✝⁷ : SeminormedAddCommGroup V✝
inst✝⁶ : PseudoMetricSpace P✝
inst✝⁵ : NormedAddTorsor V✝ P✝
inst✝⁴ : NormedAddCommGroup W
inst✝³ : MetricSpace Q
inst✝² : NormedAddTorsor W Q
V : Type u_6
P : Type u_7
inst✝¹ : NormedAddCommGroup V
inst✝ : AddTorsor V P
x✝¹ x✝ : P
⊢ (fun x y => ↑{ val := ‖x -ᵥ y‖, property := (_ : 0 ≤ ‖x -ᵥ y‖) }) x✝¹ x✝ = ENNReal.ofReal (dist x✝¹ x✝)

Next tactic:
simp only
/-- The distance defines a metric space structure on the torsor. This
is not an instance because it depends on `V` to define a `MetricSpace P`. -/
def metricSpaceOfNormedAddCommGroupOfAddTorsor (V P : Type*) [NormedAddCommGroup V]
    [AddTorsor V P] : MetricSpace P where
  dist x y := ‖(x -ᵥ y : V)‖
  edist_dist _ _ := by simp only; 

Proof state:
α : Type u_1
V✝ : Type u_2
P✝ : Type u_3
W : Type u_4
Q : Type u_5
inst✝⁷ : SeminormedAddCommGroup V✝
inst✝⁶ : PseudoMetricSpace P✝
inst✝⁵ : NormedAddTorsor V✝ P✝
inst✝⁴ : NormedAddCommGroup W
inst✝³ : MetricSpace Q
inst✝² : NormedAddTorsor W Q
V : Type u_6
P : Type u_7
inst✝¹ : NormedAddCommGroup V
inst✝ : AddTorsor V P
x✝¹ x✝ : P
⊢ ↑{ val := ‖x✝¹ -ᵥ x✝‖, property := (_ : 0 ≤ ‖x✝¹ -ᵥ x✝‖) } = ENNReal.ofReal ‖x✝¹ -ᵥ x✝‖

Next tactic:
rw [ENNReal.ofReal_eq_coe_nnreal]
/-- The distance defines a metric space structure on the torsor. This
is not an instance because it depends on `V` to define a `MetricSpace P`. -/
def metricSpaceOfNormedAddCommGroupOfAddTorsor (V P : Type*) [NormedAddCommGroup V]
    [AddTorsor V P] : MetricSpace P where
  dist x y := ‖(x -ᵥ y : V)‖
  edist_dist _ _ := by simp only; rw [ENNReal.ofReal_eq_coe_nnreal]
  dist_self x := by simp
  eq_of_dist_eq_zero h := by 

Proof state:
α : Type u_1
V✝ : Type u_2
P✝ : Type u_3
W : Type u_4
Q : Type u_5
inst✝⁷ : SeminormedAddCommGroup V✝
inst✝⁶ : PseudoMetricSpace P✝
inst✝⁵ : NormedAddTorsor V✝ P✝
inst✝⁴ : NormedAddCommGroup W
inst✝³ : MetricSpace Q
inst✝² : NormedAddTorsor W Q
V : Type u_6
P : Type u_7
inst✝¹ : NormedAddCommGroup V
inst✝ : AddTorsor V P
x✝ y✝ : P
h : dist x✝ y✝ = 0
⊢ x✝ = y✝

Next tactic:
simpa using h
theorem IsClosed.vadd_right_of_isCompact {s : Set V} {t : Set P} (hs : IsClosed s)
    (ht : IsCompact t) : IsClosed (s +ᵥ t) := by
  -- This result is still true for any `AddTorsor` where `-ᵥ` is continuous,
  -- but we don't yet have a nice way to state it.
  

Proof state:
α : Type u_1
V : Type u_2
P : Type u_3
W : Type u_4
Q : Type u_5
inst✝⁵ : SeminormedAddCommGroup V
inst✝⁴ : PseudoMetricSpace P
inst✝³ : NormedAddTorsor V P
inst✝² : NormedAddCommGroup W
inst✝¹ : MetricSpace Q
inst✝ : NormedAddTorsor W Q
s : Set V
t : Set P
hs : IsClosed s
ht : IsCompact t
⊢ IsClosed (s +ᵥ t)

Next tactic:
refine IsSeqClosed.isClosed (fun u p husv hup ↦ ?_)
theorem IsClosed.vadd_right_of_isCompact {s : Set V} {t : Set P} (hs : IsClosed s)
    (ht : IsCompact t) : IsClosed (s +ᵥ t) := by
  -- This result is still true for any `AddTorsor` where `-ᵥ` is continuous,
  -- but we don't yet have a nice way to state it.
  refine IsSeqClosed.isClosed (fun u p husv hup ↦ ?_)
  

Proof state:
α : Type u_1
V : Type u_2
P : Type u_3
W : Type u_4
Q : Type u_5
inst✝⁵ : SeminormedAddCommGroup V
inst✝⁴ : PseudoMetricSpace P
inst✝³ : NormedAddTorsor V P
inst✝² : NormedAddCommGroup W
inst✝¹ : MetricSpace Q
inst✝ : NormedAddTorsor W Q
s : Set V
t : Set P
hs : IsClosed s
ht : IsCompact t
u : ℕ → P
p : P
husv : ∀ (n : ℕ), u n ∈ s +ᵥ t
hup : Tendsto u atTop (𝓝 p)
⊢ p ∈ s +ᵥ t

Next tactic:
choose! a v hav using husv
theorem IsClosed.vadd_right_of_isCompact {s : Set V} {t : Set P} (hs : IsClosed s)
    (ht : IsCompact t) : IsClosed (s +ᵥ t) := by
  -- This result is still true for any `AddTorsor` where `-ᵥ` is continuous,
  -- but we don't yet have a nice way to state it.
  refine IsSeqClosed.isClosed (fun u p husv hup ↦ ?_)
  choose! a v hav using husv
  

Proof state:
α : Type u_1
V : Type u_2
P : Type u_3
W : Type u_4
Q : Type u_5
inst✝⁵ : SeminormedAddCommGroup V
inst✝⁴ : PseudoMetricSpace P
inst✝³ : NormedAddTorsor V P
inst✝² : NormedAddCommGroup W
inst✝¹ : MetricSpace Q
inst✝ : NormedAddTorsor W Q
s : Set V
t : Set P
hs : IsClosed s
ht : IsCompact t
u : ℕ → P
p : P
hup : Tendsto u atTop (𝓝 p)
a : ℕ → V
v : ℕ → P
hav : ∀ (n : ℕ), a n ∈ s ∧ v n ∈ t ∧ (fun x x_1 => x +ᵥ x_1) (a n) (v n) = u n
⊢ p ∈ s +ᵥ t

Next tactic:
rcases ht.isSeqCompact fun n ↦ (hav n).2.1 with ⟨q, hqt, φ, φ_mono, hφq⟩
theorem IsClosed.vadd_right_of_isCompact {s : Set V} {t : Set P} (hs : IsClosed s)
    (ht : IsCompact t) : IsClosed (s +ᵥ t) := by
  -- This result is still true for any `AddTorsor` where `-ᵥ` is continuous,
  -- but we don't yet have a nice way to state it.
  refine IsSeqClosed.isClosed (fun u p husv hup ↦ ?_)
  choose! a v hav using husv
  rcases ht.isSeqCompact fun n ↦ (hav n).2.1 with ⟨q, hqt, φ, φ_mono, hφq⟩
  

Proof state:
case intro.intro.intro.intro
α : Type u_1
V : Type u_2
P : Type u_3
W : Type u_4
Q : Type u_5
inst✝⁵ : SeminormedAddCommGroup V
inst✝⁴ : PseudoMetricSpace P
inst✝³ : NormedAddTorsor V P
inst✝² : NormedAddCommGroup W
inst✝¹ : MetricSpace Q
inst✝ : NormedAddTorsor W Q
s : Set V
t : Set P
hs : IsClosed s
ht : IsCompact t
u : ℕ → P
p : P
hup : Tendsto u atTop (𝓝 p)
a : ℕ → V
v : ℕ → P
hav : ∀ (n : ℕ), a n ∈ s ∧ v n ∈ t ∧ (fun x x_1 => x +ᵥ x_1) (a n) (v n) = u n
q : P
hqt : q ∈ t
φ : ℕ → ℕ
φ_mono : StrictMono φ
hφq : Tendsto ((fun n => v n) ∘ φ) atTop (𝓝 q)
⊢ p ∈ s +ᵥ t

Next tactic:
refine ⟨p -ᵥ q, q, hs.mem_of_tendsto ((hup.comp φ_mono.tendsto_atTop).vsub hφq)
    (eventually_of_forall fun n ↦ ?_), hqt, vsub_vadd _ _⟩
theorem IsClosed.vadd_right_of_isCompact {s : Set V} {t : Set P} (hs : IsClosed s)
    (ht : IsCompact t) : IsClosed (s +ᵥ t) := by
  -- This result is still true for any `AddTorsor` where `-ᵥ` is continuous,
  -- but we don't yet have a nice way to state it.
  refine IsSeqClosed.isClosed (fun u p husv hup ↦ ?_)
  choose! a v hav using husv
  rcases ht.isSeqCompact fun n ↦ (hav n).2.1 with ⟨q, hqt, φ, φ_mono, hφq⟩
  refine ⟨p -ᵥ q, q, hs.mem_of_tendsto ((hup.comp φ_mono.tendsto_atTop).vsub hφq)
    (eventually_of_forall fun n ↦ ?_), hqt, vsub_vadd _ _⟩
  

Proof state:
case intro.intro.intro.intro
α : Type u_1
V : Type u_2
P : Type u_3
W : Type u_4
Q : Type u_5
inst✝⁵ : SeminormedAddCommGroup V
inst✝⁴ : PseudoMetricSpace P
inst✝³ : NormedAddTorsor V P
inst✝² : NormedAddCommGroup W
inst✝¹ : MetricSpace Q
inst✝ : NormedAddTorsor W Q
s : Set V
t : Set P
hs : IsClosed s
ht : IsCompact t
u : ℕ → P
p : P
hup : Tendsto u atTop (𝓝 p)
a : ℕ → V
v : ℕ → P
hav : ∀ (n : ℕ), a n ∈ s ∧ v n ∈ t ∧ (fun x x_1 => x +ᵥ x_1) (a n) (v n) = u n
q : P
hqt : q ∈ t
φ : ℕ → ℕ
φ_mono : StrictMono φ
hφq : Tendsto ((fun n => v n) ∘ φ) atTop (𝓝 q)
n : ℕ
⊢ (u ∘ φ -ᵥ (fun n => v n) ∘ φ) n ∈ s

Next tactic:
convert (hav (φ n)).1 using 1
theorem IsClosed.vadd_right_of_isCompact {s : Set V} {t : Set P} (hs : IsClosed s)
    (ht : IsCompact t) : IsClosed (s +ᵥ t) := by
  -- This result is still true for any `AddTorsor` where `-ᵥ` is continuous,
  -- but we don't yet have a nice way to state it.
  refine IsSeqClosed.isClosed (fun u p husv hup ↦ ?_)
  choose! a v hav using husv
  rcases ht.isSeqCompact fun n ↦ (hav n).2.1 with ⟨q, hqt, φ, φ_mono, hφq⟩
  refine ⟨p -ᵥ q, q, hs.mem_of_tendsto ((hup.comp φ_mono.tendsto_atTop).vsub hφq)
    (eventually_of_forall fun n ↦ ?_), hqt, vsub_vadd _ _⟩
  convert (hav (φ n)).1 using 1
  

Proof state:
case h.e'_4
α : Type u_1
V : Type u_2
P : Type u_3
W : Type u_4
Q : Type u_5
inst✝⁵ : SeminormedAddCommGroup V
inst✝⁴ : PseudoMetricSpace P
inst✝³ : NormedAddTorsor V P
inst✝² : NormedAddCommGroup W
inst✝¹ : MetricSpace Q
inst✝ : NormedAddTorsor W Q
s : Set V
t : Set P
hs : IsClosed s
ht : IsCompact t
u : ℕ → P
p : P
hup : Tendsto u atTop (𝓝 p)
a : ℕ → V
v : ℕ → P
hav : ∀ (n : ℕ), a n ∈ s ∧ v n ∈ t ∧ (fun x x_1 => x +ᵥ x_1) (a n) (v n) = u n
q : P
hqt : q ∈ t
φ : ℕ → ℕ
φ_mono : StrictMono φ
hφq : Tendsto ((fun n => v n) ∘ φ) atTop (𝓝 q)
n : ℕ
⊢ (u ∘ φ -ᵥ (fun n => v n) ∘ φ) n = a (φ n)

Next tactic:
exact (eq_vadd_iff_vsub_eq _ _ _).mp (hav (φ n)).2.2.symm
@[simp]
theorem LinearMap.dualMap_id : (LinearMap.id : M₁ →ₗ[R] M₁).dualMap = LinearMap.id := by
  

Proof state:
R : Type u
inst✝⁴ : CommSemiring R
M₁ : Type v
M₂ : Type v'
inst✝³ : AddCommMonoid M₁
inst✝² : Module R M₁
inst✝¹ : AddCommMonoid M₂
inst✝ : Module R M₂
⊢ dualMap id = id

Next tactic:
ext
@[simp]
theorem LinearMap.dualMap_id : (LinearMap.id : M₁ →ₗ[R] M₁).dualMap = LinearMap.id := by
  ext
  

Proof state:
case h.h
R : Type u
inst✝⁴ : CommSemiring R
M₁ : Type v
M₂ : Type v'
inst✝³ : AddCommMonoid M₁
inst✝² : Module R M₁
inst✝¹ : AddCommMonoid M₂
inst✝ : Module R M₂
x✝¹ : Dual R M₁
x✝ : M₁
⊢ ((dualMap id) x✝¹) x✝ = (id x✝¹) x✝

Next tactic:
rfl
/-- If a linear map is surjective, then its dual is injective. -/
theorem LinearMap.dualMap_injective_of_surjective {f : M₁ →ₗ[R] M₂} (hf : Function.Surjective f) :
    Function.Injective f.dualMap := by
  

Proof state:
R : Type u
inst✝⁴ : CommSemiring R
M₁ : Type v
M₂ : Type v'
inst✝³ : AddCommMonoid M₁
inst✝² : Module R M₁
inst✝¹ : AddCommMonoid M₂
inst✝ : Module R M₂
f : M₁ →ₗ[R] M₂
hf : Function.Surjective ⇑f
⊢ Function.Injective ⇑(dualMap f)

Next tactic:
intro φ ψ h
/-- If a linear map is surjective, then its dual is injective. -/
theorem LinearMap.dualMap_injective_of_surjective {f : M₁ →ₗ[R] M₂} (hf : Function.Surjective f) :
    Function.Injective f.dualMap := by
  intro φ ψ h
  

Proof state:
R : Type u
inst✝⁴ : CommSemiring R
M₁ : Type v
M₂ : Type v'
inst✝³ : AddCommMonoid M₁
inst✝² : Module R M₁
inst✝¹ : AddCommMonoid M₂
inst✝ : Module R M₂
f : M₁ →ₗ[R] M₂
hf : Function.Surjective ⇑f
φ ψ : Dual R M₂
h : (dualMap f) φ = (dualMap f) ψ
⊢ φ = ψ

Next tactic:
ext x
/-- If a linear map is surjective, then its dual is injective. -/
theorem LinearMap.dualMap_injective_of_surjective {f : M₁ →ₗ[R] M₂} (hf : Function.Surjective f) :
    Function.Injective f.dualMap := by
  intro φ ψ h
  ext x
  

Proof state:
case h
R : Type u
inst✝⁴ : CommSemiring R
M₁ : Type v
M₂ : Type v'
inst✝³ : AddCommMonoid M₁
inst✝² : Module R M₁
inst✝¹ : AddCommMonoid M₂
inst✝ : Module R M₂
f : M₁ →ₗ[R] M₂
hf : Function.Surjective ⇑f
φ ψ : Dual R M₂
h : (dualMap f) φ = (dualMap f) ψ
x : M₂
⊢ φ x = ψ x

Next tactic:
obtain ⟨y, rfl⟩ := hf x
/-- If a linear map is surjective, then its dual is injective. -/
theorem LinearMap.dualMap_injective_of_surjective {f : M₁ →ₗ[R] M₂} (hf : Function.Surjective f) :
    Function.Injective f.dualMap := by
  intro φ ψ h
  ext x
  obtain ⟨y, rfl⟩ := hf x
  

Proof state:
case h.intro
R : Type u
inst✝⁴ : CommSemiring R
M₁ : Type v
M₂ : Type v'
inst✝³ : AddCommMonoid M₁
inst✝² : Module R M₁
inst✝¹ : AddCommMonoid M₂
inst✝ : Module R M₂
f : M₁ →ₗ[R] M₂
hf : Function.Surjective ⇑f
φ ψ : Dual R M₂
h : (dualMap f) φ = (dualMap f) ψ
y : M₁
⊢ φ (f y) = ψ (f y)

Next tactic:
exact congr_arg (fun g : Module.Dual R M₁ => g y) h
@[simp]
theorem LinearEquiv.dualMap_refl :
    (LinearEquiv.refl R M₁).dualMap = LinearEquiv.refl R (Dual R M₁) := by
  

Proof state:
R : Type u
inst✝⁴ : CommSemiring R
M₁ : Type v
M₂ : Type v'
inst✝³ : AddCommMonoid M₁
inst✝² : Module R M₁
inst✝¹ : AddCommMonoid M₂
inst✝ : Module R M₂
⊢ dualMap (refl R M₁) = refl R (Dual R M₁)

Next tactic:
ext
@[simp]
theorem LinearEquiv.dualMap_refl :
    (LinearEquiv.refl R M₁).dualMap = LinearEquiv.refl R (Dual R M₁) := by
  ext
  

Proof state:
case h.h
R : Type u
inst✝⁴ : CommSemiring R
M₁ : Type v
M₂ : Type v'
inst✝³ : AddCommMonoid M₁
inst✝² : Module R M₁
inst✝¹ : AddCommMonoid M₂
inst✝ : Module R M₂
x✝¹ : Dual R M₁
x✝ : M₁
⊢ ((dualMap (refl R M₁)) x✝¹) x✝ = ((refl R (Dual R M₁)) x✝¹) x✝

Next tactic:
rfl