l3lab/ntp-mathlib huggingface dataset:
/-- Reflection in an affine subspace, which is expected to be nonempty
and complete. The word "reflection" is sometimes understood to mean
specifically reflection in a codimension-one subspace, and sometimes
more generally to cover operations such as reflection in a point. The
definition here, of reflection in an affine subspace, is a more
general sense of the word that includes both those common cases. -/
def reflection (s : AffineSubspace ℝ P) [Nonempty s] [HasOrthogonalProjection s.direction] :
    P ≃ᵃⁱ[ℝ] P :=
  AffineIsometryEquiv.mk'
    (fun p => ↑(orthogonalProjection s p) -ᵥ p +ᵥ (orthogonalProjection s p : P))
    (_root_.reflection s.direction) (↑(Classical.arbitrary s))
    (by
      intro p
      let v := p -ᵥ ↑(Classical.arbitrary s)
      let a : V := _root_.orthogonalProjection s.direction v
      

Proof state:
V : Type u_1
P : Type u_2
inst✝⁵ : NormedAddCommGroup V
inst✝⁴ : InnerProductSpace ℝ V
inst✝³ : MetricSpace P
inst✝² : NormedAddTorsor V P
s : AffineSubspace ℝ P
inst✝¹ : Nonempty ↥s
inst✝ : HasOrthogonalProjection (direction s)
p : P
v : V := p -ᵥ ↑(Classical.arbitrary ↥s)
a : V := ↑((_root_.orthogonalProjection (direction s)) v)
⊢ (fun p => ↑((orthogonalProjection s) p) -ᵥ p +ᵥ ↑((orthogonalProjection s) p)) p =
    (_root_.reflection (direction s)) (p -ᵥ ↑(Classical.arbitrary ↥s)) +ᵥ
      (fun p => ↑((orthogonalProjection s) p) -ᵥ p +ᵥ ↑((orthogonalProjection s) p)) ↑(Classical.arbitrary ↥s)

Next tactic:
let b : P := ↑(Classical.arbitrary s)
/-- Reflection in an affine subspace, which is expected to be nonempty
and complete. The word "reflection" is sometimes understood to mean
specifically reflection in a codimension-one subspace, and sometimes
more generally to cover operations such as reflection in a point. The
definition here, of reflection in an affine subspace, is a more
general sense of the word that includes both those common cases. -/
def reflection (s : AffineSubspace ℝ P) [Nonempty s] [HasOrthogonalProjection s.direction] :
    P ≃ᵃⁱ[ℝ] P :=
  AffineIsometryEquiv.mk'
    (fun p => ↑(orthogonalProjection s p) -ᵥ p +ᵥ (orthogonalProjection s p : P))
    (_root_.reflection s.direction) (↑(Classical.arbitrary s))
    (by
      intro p
      let v := p -ᵥ ↑(Classical.arbitrary s)
      let a : V := _root_.orthogonalProjection s.direction v
      let b : P := ↑(Classical.arbitrary s)
      

Proof state:
V : Type u_1
P : Type u_2
inst✝⁵ : NormedAddCommGroup V
inst✝⁴ : InnerProductSpace ℝ V
inst✝³ : MetricSpace P
inst✝² : NormedAddTorsor V P
s : AffineSubspace ℝ P
inst✝¹ : Nonempty ↥s
inst✝ : HasOrthogonalProjection (direction s)
p : P
v : V := p -ᵥ ↑(Classical.arbitrary ↥s)
a : V := ↑((_root_.orthogonalProjection (direction s)) v)
b : P := ↑(Classical.arbitrary ↥s)
⊢ (fun p => ↑((orthogonalProjection s) p) -ᵥ p +ᵥ ↑((orthogonalProjection s) p)) p =
    (_root_.reflection (direction s)) (p -ᵥ ↑(Classical.arbitrary ↥s)) +ᵥ
      (fun p => ↑((orthogonalProjection s) p) -ᵥ p +ᵥ ↑((orthogonalProjection s) p)) ↑(Classical.arbitrary ↥s)

Next tactic:
have key : a +ᵥ b -ᵥ (v +ᵥ b) +ᵥ (a +ᵥ b) = a + a - v +ᵥ (b -ᵥ b +ᵥ b) := by
        rw [← add_vadd, vsub_vadd_eq_vsub_sub, vsub_vadd, vadd_vsub]
        congr 1
        abel
/-- Reflection in an affine subspace, which is expected to be nonempty
and complete. The word "reflection" is sometimes understood to mean
specifically reflection in a codimension-one subspace, and sometimes
more generally to cover operations such as reflection in a point. The
definition here, of reflection in an affine subspace, is a more
general sense of the word that includes both those common cases. -/
def reflection (s : AffineSubspace ℝ P) [Nonempty s] [HasOrthogonalProjection s.direction] :
    P ≃ᵃⁱ[ℝ] P :=
  AffineIsometryEquiv.mk'
    (fun p => ↑(orthogonalProjection s p) -ᵥ p +ᵥ (orthogonalProjection s p : P))
    (_root_.reflection s.direction) (↑(Classical.arbitrary s))
    (by
      intro p
      let v := p -ᵥ ↑(Classical.arbitrary s)
      let a : V := _root_.orthogonalProjection s.direction v
      let b : P := ↑(Classical.arbitrary s)
      have key : a +ᵥ b -ᵥ (v +ᵥ b) +ᵥ (a +ᵥ b) = a + a - v +ᵥ (b -ᵥ b +ᵥ b) := by
        

Proof state:
V : Type u_1
P : Type u_2
inst✝⁵ : NormedAddCommGroup V
inst✝⁴ : InnerProductSpace ℝ V
inst✝³ : MetricSpace P
inst✝² : NormedAddTorsor V P
s : AffineSubspace ℝ P
inst✝¹ : Nonempty ↥s
inst✝ : HasOrthogonalProjection (direction s)
p : P
v : V := p -ᵥ ↑(Classical.arbitrary ↥s)
a : V := ↑((_root_.orthogonalProjection (direction s)) v)
b : P := ↑(Classical.arbitrary ↥s)
⊢ a +ᵥ b -ᵥ (v +ᵥ b) +ᵥ (a +ᵥ b) = a + a - v +ᵥ (b -ᵥ b +ᵥ b)

Next tactic:
rw [← add_vadd, vsub_vadd_eq_vsub_sub, vsub_vadd, vadd_vsub]
/-- Reflection in an affine subspace, which is expected to be nonempty
and complete. The word "reflection" is sometimes understood to mean
specifically reflection in a codimension-one subspace, and sometimes
more generally to cover operations such as reflection in a point. The
definition here, of reflection in an affine subspace, is a more
general sense of the word that includes both those common cases. -/
def reflection (s : AffineSubspace ℝ P) [Nonempty s] [HasOrthogonalProjection s.direction] :
    P ≃ᵃⁱ[ℝ] P :=
  AffineIsometryEquiv.mk'
    (fun p => ↑(orthogonalProjection s p) -ᵥ p +ᵥ (orthogonalProjection s p : P))
    (_root_.reflection s.direction) (↑(Classical.arbitrary s))
    (by
      intro p
      let v := p -ᵥ ↑(Classical.arbitrary s)
      let a : V := _root_.orthogonalProjection s.direction v
      let b : P := ↑(Classical.arbitrary s)
      have key : a +ᵥ b -ᵥ (v +ᵥ b) +ᵥ (a +ᵥ b) = a + a - v +ᵥ (b -ᵥ b +ᵥ b) := by
        rw [← add_vadd, vsub_vadd_eq_vsub_sub, vsub_vadd, vadd_vsub]
        

Proof state:
V : Type u_1
P : Type u_2
inst✝⁵ : NormedAddCommGroup V
inst✝⁴ : InnerProductSpace ℝ V
inst✝³ : MetricSpace P
inst✝² : NormedAddTorsor V P
s : AffineSubspace ℝ P
inst✝¹ : Nonempty ↥s
inst✝ : HasOrthogonalProjection (direction s)
p : P
v : V := p -ᵥ ↑(Classical.arbitrary ↥s)
a : V := ↑((_root_.orthogonalProjection (direction s)) v)
b : P := ↑(Classical.arbitrary ↥s)
⊢ a - v + a +ᵥ b = a + a - v +ᵥ b

Next tactic:
congr 1
/-- Reflection in an affine subspace, which is expected to be nonempty
and complete. The word "reflection" is sometimes understood to mean
specifically reflection in a codimension-one subspace, and sometimes
more generally to cover operations such as reflection in a point. The
definition here, of reflection in an affine subspace, is a more
general sense of the word that includes both those common cases. -/
def reflection (s : AffineSubspace ℝ P) [Nonempty s] [HasOrthogonalProjection s.direction] :
    P ≃ᵃⁱ[ℝ] P :=
  AffineIsometryEquiv.mk'
    (fun p => ↑(orthogonalProjection s p) -ᵥ p +ᵥ (orthogonalProjection s p : P))
    (_root_.reflection s.direction) (↑(Classical.arbitrary s))
    (by
      intro p
      let v := p -ᵥ ↑(Classical.arbitrary s)
      let a : V := _root_.orthogonalProjection s.direction v
      let b : P := ↑(Classical.arbitrary s)
      have key : a +ᵥ b -ᵥ (v +ᵥ b) +ᵥ (a +ᵥ b) = a + a - v +ᵥ (b -ᵥ b +ᵥ b) := by
        rw [← add_vadd, vsub_vadd_eq_vsub_sub, vsub_vadd, vadd_vsub]
        congr 1
        

Proof state:
case e_a
V : Type u_1
P : Type u_2
inst✝⁵ : NormedAddCommGroup V
inst✝⁴ : InnerProductSpace ℝ V
inst✝³ : MetricSpace P
inst✝² : NormedAddTorsor V P
s : AffineSubspace ℝ P
inst✝¹ : Nonempty ↥s
inst✝ : HasOrthogonalProjection (direction s)
p : P
v : V := p -ᵥ ↑(Classical.arbitrary ↥s)
a : V := ↑((_root_.orthogonalProjection (direction s)) v)
b : P := ↑(Classical.arbitrary ↥s)
⊢ a - v + a = a + a - v

Next tactic:
abel
/-- Reflection in an affine subspace, which is expected to be nonempty
and complete. The word "reflection" is sometimes understood to mean
specifically reflection in a codimension-one subspace, and sometimes
more generally to cover operations such as reflection in a point. The
definition here, of reflection in an affine subspace, is a more
general sense of the word that includes both those common cases. -/
def reflection (s : AffineSubspace ℝ P) [Nonempty s] [HasOrthogonalProjection s.direction] :
    P ≃ᵃⁱ[ℝ] P :=
  AffineIsometryEquiv.mk'
    (fun p => ↑(orthogonalProjection s p) -ᵥ p +ᵥ (orthogonalProjection s p : P))
    (_root_.reflection s.direction) (↑(Classical.arbitrary s))
    (by
      intro p
      let v := p -ᵥ ↑(Classical.arbitrary s)
      let a : V := _root_.orthogonalProjection s.direction v
      let b : P := ↑(Classical.arbitrary s)
      have key : a +ᵥ b -ᵥ (v +ᵥ b) +ᵥ (a +ᵥ b) = a + a - v +ᵥ (b -ᵥ b +ᵥ b) := by
        rw [← add_vadd, vsub_vadd_eq_vsub_sub, vsub_vadd, vadd_vsub]
        congr 1
        abel
      

Proof state:
V : Type u_1
P : Type u_2
inst✝⁵ : NormedAddCommGroup V
inst✝⁴ : InnerProductSpace ℝ V
inst✝³ : MetricSpace P
inst✝² : NormedAddTorsor V P
s : AffineSubspace ℝ P
inst✝¹ : Nonempty ↥s
inst✝ : HasOrthogonalProjection (direction s)
p : P
v : V := p -ᵥ ↑(Classical.arbitrary ↥s)
a : V := ↑((_root_.orthogonalProjection (direction s)) v)
b : P := ↑(Classical.arbitrary ↥s)
key : a +ᵥ b -ᵥ (v +ᵥ b) +ᵥ (a +ᵥ b) = a + a - v +ᵥ (b -ᵥ b +ᵥ b)
⊢ (fun p => ↑((orthogonalProjection s) p) -ᵥ p +ᵥ ↑((orthogonalProjection s) p)) p =
    (_root_.reflection (direction s)) (p -ᵥ ↑(Classical.arbitrary ↥s)) +ᵥ
      (fun p => ↑((orthogonalProjection s) p) -ᵥ p +ᵥ ↑((orthogonalProjection s) p)) ↑(Classical.arbitrary ↥s)

Next tactic:
dsimp only
/-- Reflection in an affine subspace, which is expected to be nonempty
and complete. The word "reflection" is sometimes understood to mean
specifically reflection in a codimension-one subspace, and sometimes
more generally to cover operations such as reflection in a point. The
definition here, of reflection in an affine subspace, is a more
general sense of the word that includes both those common cases. -/
def reflection (s : AffineSubspace ℝ P) [Nonempty s] [HasOrthogonalProjection s.direction] :
    P ≃ᵃⁱ[ℝ] P :=
  AffineIsometryEquiv.mk'
    (fun p => ↑(orthogonalProjection s p) -ᵥ p +ᵥ (orthogonalProjection s p : P))
    (_root_.reflection s.direction) (↑(Classical.arbitrary s))
    (by
      intro p
      let v := p -ᵥ ↑(Classical.arbitrary s)
      let a : V := _root_.orthogonalProjection s.direction v
      let b : P := ↑(Classical.arbitrary s)
      have key : a +ᵥ b -ᵥ (v +ᵥ b) +ᵥ (a +ᵥ b) = a + a - v +ᵥ (b -ᵥ b +ᵥ b) := by
        rw [← add_vadd, vsub_vadd_eq_vsub_sub, vsub_vadd, vadd_vsub]
        congr 1
        abel
      dsimp only
      

Proof state:
V : Type u_1
P : Type u_2
inst✝⁵ : NormedAddCommGroup V
inst✝⁴ : InnerProductSpace ℝ V
inst✝³ : MetricSpace P
inst✝² : NormedAddTorsor V P
s : AffineSubspace ℝ P
inst✝¹ : Nonempty ↥s
inst✝ : HasOrthogonalProjection (direction s)
p : P
v : V := p -ᵥ ↑(Classical.arbitrary ↥s)
a : V := ↑((_root_.orthogonalProjection (direction s)) v)
b : P := ↑(Classical.arbitrary ↥s)
key : a +ᵥ b -ᵥ (v +ᵥ b) +ᵥ (a +ᵥ b) = a + a - v +ᵥ (b -ᵥ b +ᵥ b)
⊢ ↑((orthogonalProjection s) p) -ᵥ p +ᵥ ↑((orthogonalProjection s) p) =
    (_root_.reflection (direction s)) (p -ᵥ ↑(Classical.arbitrary ↥s)) +ᵥ
      (↑((orthogonalProjection s) ↑(Classical.arbitrary ↥s)) -ᵥ ↑(Classical.arbitrary ↥s) +ᵥ
        ↑((orthogonalProjection s) ↑(Classical.arbitrary ↥s)))

Next tactic:
rwa [reflection_apply, (vsub_vadd p b).symm, AffineMap.map_vadd, orthogonalProjection_linear,
        vadd_vsub, orthogonalProjection_mem_subspace_eq_self, two_smul]
theorem eq_reflection_of_eq_subspace {s s' : AffineSubspace ℝ P} [Nonempty s] [Nonempty s']
    [HasOrthogonalProjection s.direction] [HasOrthogonalProjection s'.direction] (h : s = s')
    (p : P) : (reflection s p : P) = (reflection s' p : P) := by
  

Proof state:
V : Type u_1
P : Type u_2
inst✝⁷ : NormedAddCommGroup V
inst✝⁶ : InnerProductSpace ℝ V
inst✝⁵ : MetricSpace P
inst✝⁴ : NormedAddTorsor V P
s s' : AffineSubspace ℝ P
inst✝³ : Nonempty ↥s
inst✝² : Nonempty ↥s'
inst✝¹ : HasOrthogonalProjection (direction s)
inst✝ : HasOrthogonalProjection (direction s')
h : s = s'
p : P
⊢ (reflection s) p = (reflection s') p

Next tactic:
subst h
theorem eq_reflection_of_eq_subspace {s s' : AffineSubspace ℝ P} [Nonempty s] [Nonempty s']
    [HasOrthogonalProjection s.direction] [HasOrthogonalProjection s'.direction] (h : s = s')
    (p : P) : (reflection s p : P) = (reflection s' p : P) := by
  subst h
  

Proof state:
V : Type u_1
P : Type u_2
inst✝⁷ : NormedAddCommGroup V
inst✝⁶ : InnerProductSpace ℝ V
inst✝⁵ : MetricSpace P
inst✝⁴ : NormedAddTorsor V P
s : AffineSubspace ℝ P
inst✝³ : Nonempty ↥s
inst✝² : HasOrthogonalProjection (direction s)
p : P
inst✝¹ : Nonempty ↥s
inst✝ : HasOrthogonalProjection (direction s)
⊢ (reflection s) p = (reflection s) p

Next tactic:
rfl
/-- Reflecting twice in the same subspace. -/
@[simp]
theorem reflection_reflection (s : AffineSubspace ℝ P) [Nonempty s]
    [HasOrthogonalProjection s.direction] (p : P) : reflection s (reflection s p) = p := by
  

Proof state:
V : Type u_1
P : Type u_2
inst✝⁵ : NormedAddCommGroup V
inst✝⁴ : InnerProductSpace ℝ V
inst✝³ : MetricSpace P
inst✝² : NormedAddTorsor V P
s : AffineSubspace ℝ P
inst✝¹ : Nonempty ↥s
inst✝ : HasOrthogonalProjection (direction s)
p : P
⊢ (reflection s) ((reflection s) p) = p

Next tactic:
have : ∀ a : s, ∀ b : V, (_root_.orthogonalProjection s.direction) b = 0 →
      reflection s (reflection s (b +ᵥ (a : P))) = b +ᵥ (a : P) := by
    intro _ _ h
    simp [reflection, h]
/-- Reflecting twice in the same subspace. -/
@[simp]
theorem reflection_reflection (s : AffineSubspace ℝ P) [Nonempty s]
    [HasOrthogonalProjection s.direction] (p : P) : reflection s (reflection s p) = p := by
  have : ∀ a : s, ∀ b : V, (_root_.orthogonalProjection s.direction) b = 0 →
      reflection s (reflection s (b +ᵥ (a : P))) = b +ᵥ (a : P) := by
    

Proof state:
V : Type u_1
P : Type u_2
inst✝⁵ : NormedAddCommGroup V
inst✝⁴ : InnerProductSpace ℝ V
inst✝³ : MetricSpace P
inst✝² : NormedAddTorsor V P
s : AffineSubspace ℝ P
inst✝¹ : Nonempty ↥s
inst✝ : HasOrthogonalProjection (direction s)
p : P
⊢ ∀ (a : ↥s) (b : V),
    (_root_.orthogonalProjection (direction s)) b = 0 → (reflection s) ((reflection s) (b +ᵥ ↑a)) = b +ᵥ ↑a

Next tactic:
intro _ _ h
/-- Reflecting twice in the same subspace. -/
@[simp]
theorem reflection_reflection (s : AffineSubspace ℝ P) [Nonempty s]
    [HasOrthogonalProjection s.direction] (p : P) : reflection s (reflection s p) = p := by
  have : ∀ a : s, ∀ b : V, (_root_.orthogonalProjection s.direction) b = 0 →
      reflection s (reflection s (b +ᵥ (a : P))) = b +ᵥ (a : P) := by
    intro _ _ h
    

Proof state:
V : Type u_1
P : Type u_2
inst✝⁵ : NormedAddCommGroup V
inst✝⁴ : InnerProductSpace ℝ V
inst✝³ : MetricSpace P
inst✝² : NormedAddTorsor V P
s : AffineSubspace ℝ P
inst✝¹ : Nonempty ↥s
inst✝ : HasOrthogonalProjection (direction s)
p : P
a✝ : ↥s
b✝ : V
h : (_root_.orthogonalProjection (direction s)) b✝ = 0
⊢ (reflection s) ((reflection s) (b✝ +ᵥ ↑a✝)) = b✝ +ᵥ ↑a✝

Next tactic:
simp [reflection, h]
/-- Reflecting twice in the same subspace. -/
@[simp]
theorem reflection_reflection (s : AffineSubspace ℝ P) [Nonempty s]
    [HasOrthogonalProjection s.direction] (p : P) : reflection s (reflection s p) = p := by
  have : ∀ a : s, ∀ b : V, (_root_.orthogonalProjection s.direction) b = 0 →
      reflection s (reflection s (b +ᵥ (a : P))) = b +ᵥ (a : P) := by
    intro _ _ h
    simp [reflection, h]
  

Proof state:
V : Type u_1
P : Type u_2
inst✝⁵ : NormedAddCommGroup V
inst✝⁴ : InnerProductSpace ℝ V
inst✝³ : MetricSpace P
inst✝² : NormedAddTorsor V P
s : AffineSubspace ℝ P
inst✝¹ : Nonempty ↥s
inst✝ : HasOrthogonalProjection (direction s)
p : P
this :
  ∀ (a : ↥s) (b : V),
    (_root_.orthogonalProjection (direction s)) b = 0 → (reflection s) ((reflection s) (b +ᵥ ↑a)) = b +ᵥ ↑a
⊢ (reflection s) ((reflection s) p) = p

Next tactic:
rw [← vsub_vadd p (orthogonalProjection s p)]
/-- Reflecting twice in the same subspace. -/
@[simp]
theorem reflection_reflection (s : AffineSubspace ℝ P) [Nonempty s]
    [HasOrthogonalProjection s.direction] (p : P) : reflection s (reflection s p) = p := by
  have : ∀ a : s, ∀ b : V, (_root_.orthogonalProjection s.direction) b = 0 →
      reflection s (reflection s (b +ᵥ (a : P))) = b +ᵥ (a : P) := by
    intro _ _ h
    simp [reflection, h]
  rw [← vsub_vadd p (orthogonalProjection s p)]
  

Proof state:
V : Type u_1
P : Type u_2
inst✝⁵ : NormedAddCommGroup V
inst✝⁴ : InnerProductSpace ℝ V
inst✝³ : MetricSpace P
inst✝² : NormedAddTorsor V P
s : AffineSubspace ℝ P
inst✝¹ : Nonempty ↥s
inst✝ : HasOrthogonalProjection (direction s)
p : P
this :
  ∀ (a : ↥s) (b : V),
    (_root_.orthogonalProjection (direction s)) b = 0 → (reflection s) ((reflection s) (b +ᵥ ↑a)) = b +ᵥ ↑a
⊢ (reflection s) ((reflection s) (p -ᵥ ↑((orthogonalProjection s) p) +ᵥ ↑((orthogonalProjection s) p))) =
    p -ᵥ ↑((orthogonalProjection s) p) +ᵥ ↑((orthogonalProjection s) p)

Next tactic:
exact this (orthogonalProjection s p) _ (orthogonalProjection_vsub_orthogonalProjection s p)
/-- Reflection is its own inverse. -/
@[simp]
theorem reflection_symm (s : AffineSubspace ℝ P) [Nonempty s]
    [HasOrthogonalProjection s.direction] : (reflection s).symm = reflection s := by
  

Proof state:
V : Type u_1
P : Type u_2
inst✝⁵ : NormedAddCommGroup V
inst✝⁴ : InnerProductSpace ℝ V
inst✝³ : MetricSpace P
inst✝² : NormedAddTorsor V P
s : AffineSubspace ℝ P
inst✝¹ : Nonempty ↥s
inst✝ : HasOrthogonalProjection (direction s)
⊢ AffineIsometryEquiv.symm (reflection s) = reflection s

Next tactic:
ext
/-- Reflection is its own inverse. -/
@[simp]
theorem reflection_symm (s : AffineSubspace ℝ P) [Nonempty s]
    [HasOrthogonalProjection s.direction] : (reflection s).symm = reflection s := by
  ext
  

Proof state:
case h
V : Type u_1
P : Type u_2
inst✝⁵ : NormedAddCommGroup V
inst✝⁴ : InnerProductSpace ℝ V
inst✝³ : MetricSpace P
inst✝² : NormedAddTorsor V P
s : AffineSubspace ℝ P
inst✝¹ : Nonempty ↥s
inst✝ : HasOrthogonalProjection (direction s)
x✝ : P
⊢ (AffineIsometryEquiv.symm (reflection s)) x✝ = (reflection s) x✝

Next tactic:
rw [← (reflection s).injective.eq_iff]
/-- Reflection is its own inverse. -/
@[simp]
theorem reflection_symm (s : AffineSubspace ℝ P) [Nonempty s]
    [HasOrthogonalProjection s.direction] : (reflection s).symm = reflection s := by
  ext
  rw [← (reflection s).injective.eq_iff]
  

Proof state:
case h
V : Type u_1
P : Type u_2
inst✝⁵ : NormedAddCommGroup V
inst✝⁴ : InnerProductSpace ℝ V
inst✝³ : MetricSpace P
inst✝² : NormedAddTorsor V P
s : AffineSubspace ℝ P
inst✝¹ : Nonempty ↥s
inst✝ : HasOrthogonalProjection (direction s)
x✝ : P
⊢ (reflection s) ((AffineIsometryEquiv.symm (reflection s)) x✝) = (reflection s) ((reflection s) x✝)

Next tactic:
simp
/-- A point is its own reflection if and only if it is in the subspace. -/
theorem reflection_eq_self_iff {s : AffineSubspace ℝ P} [Nonempty s]
    [HasOrthogonalProjection s.direction] (p : P) : reflection s p = p ↔ p ∈ s := by
  

Proof state:
V : Type u_1
P : Type u_2
inst✝⁵ : NormedAddCommGroup V
inst✝⁴ : InnerProductSpace ℝ V
inst✝³ : MetricSpace P
inst✝² : NormedAddTorsor V P
s : AffineSubspace ℝ P
inst✝¹ : Nonempty ↥s
inst✝ : HasOrthogonalProjection (direction s)
p : P
⊢ (reflection s) p = p ↔ p ∈ s

Next tactic:
rw [← orthogonalProjection_eq_self_iff, reflection_apply]
/-- A point is its own reflection if and only if it is in the subspace. -/
theorem reflection_eq_self_iff {s : AffineSubspace ℝ P} [Nonempty s]
    [HasOrthogonalProjection s.direction] (p : P) : reflection s p = p ↔ p ∈ s := by
  rw [← orthogonalProjection_eq_self_iff, reflection_apply]
  

Proof state:
V : Type u_1
P : Type u_2
inst✝⁵ : NormedAddCommGroup V
inst✝⁴ : InnerProductSpace ℝ V
inst✝³ : MetricSpace P
inst✝² : NormedAddTorsor V P
s : AffineSubspace ℝ P
inst✝¹ : Nonempty ↥s
inst✝ : HasOrthogonalProjection (direction s)
p : P
⊢ ↑((orthogonalProjection s) p) -ᵥ p +ᵥ ↑((orthogonalProjection s) p) = p ↔ ↑((orthogonalProjection s) p) = p

Next tactic:
constructor
/-- A point is its own reflection if and only if it is in the subspace. -/
theorem reflection_eq_self_iff {s : AffineSubspace ℝ P} [Nonempty s]
    [HasOrthogonalProjection s.direction] (p : P) : reflection s p = p ↔ p ∈ s := by
  rw [← orthogonalProjection_eq_self_iff, reflection_apply]
  constructor
  · 

Proof state:
case mp
V : Type u_1
P : Type u_2
inst✝⁵ : NormedAddCommGroup V
inst✝⁴ : InnerProductSpace ℝ V
inst✝³ : MetricSpace P
inst✝² : NormedAddTorsor V P
s : AffineSubspace ℝ P
inst✝¹ : Nonempty ↥s
inst✝ : HasOrthogonalProjection (direction s)
p : P
⊢ ↑((orthogonalProjection s) p) -ᵥ p +ᵥ ↑((orthogonalProjection s) p) = p → ↑((orthogonalProjection s) p) = p

Next tactic:
intro h
/-- A point is its own reflection if and only if it is in the subspace. -/
theorem reflection_eq_self_iff {s : AffineSubspace ℝ P} [Nonempty s]
    [HasOrthogonalProjection s.direction] (p : P) : reflection s p = p ↔ p ∈ s := by
  rw [← orthogonalProjection_eq_self_iff, reflection_apply]
  constructor
  · intro h
    

Proof state:
case mp
V : Type u_1
P : Type u_2
inst✝⁵ : NormedAddCommGroup V
inst✝⁴ : InnerProductSpace ℝ V
inst✝³ : MetricSpace P
inst✝² : NormedAddTorsor V P
s : AffineSubspace ℝ P
inst✝¹ : Nonempty ↥s
inst✝ : HasOrthogonalProjection (direction s)
p : P
h : ↑((orthogonalProjection s) p) -ᵥ p +ᵥ ↑((orthogonalProjection s) p) = p
⊢ ↑((orthogonalProjection s) p) = p

Next tactic:
rw [← @vsub_eq_zero_iff_eq V, vadd_vsub_assoc, ← two_smul ℝ (↑(orthogonalProjection s p) -ᵥ p),
      smul_eq_zero] at h
/-- A point is its own reflection if and only if it is in the subspace. -/
theorem reflection_eq_self_iff {s : AffineSubspace ℝ P} [Nonempty s]
    [HasOrthogonalProjection s.direction] (p : P) : reflection s p = p ↔ p ∈ s := by
  rw [← orthogonalProjection_eq_self_iff, reflection_apply]
  constructor
  · intro h
    rw [← @vsub_eq_zero_iff_eq V, vadd_vsub_assoc, ← two_smul ℝ (↑(orthogonalProjection s p) -ᵥ p),
      smul_eq_zero] at h
    

Proof state:
case mp
V : Type u_1
P : Type u_2
inst✝⁵ : NormedAddCommGroup V
inst✝⁴ : InnerProductSpace ℝ V
inst✝³ : MetricSpace P
inst✝² : NormedAddTorsor V P
s : AffineSubspace ℝ P
inst✝¹ : Nonempty ↥s
inst✝ : HasOrthogonalProjection (direction s)
p : P
h : 2 = 0 ∨ ↑((orthogonalProjection s) p) -ᵥ p = 0
⊢ ↑((orthogonalProjection s) p) = p

Next tactic:
norm_num at h
/-- A point is its own reflection if and only if it is in the subspace. -/
theorem reflection_eq_self_iff {s : AffineSubspace ℝ P} [Nonempty s]
    [HasOrthogonalProjection s.direction] (p : P) : reflection s p = p ↔ p ∈ s := by
  rw [← orthogonalProjection_eq_self_iff, reflection_apply]
  constructor
  · intro h
    rw [← @vsub_eq_zero_iff_eq V, vadd_vsub_assoc, ← two_smul ℝ (↑(orthogonalProjection s p) -ᵥ p),
      smul_eq_zero] at h
    norm_num at h
    

Proof state:
case mp
V : Type u_1
P : Type u_2
inst✝⁵ : NormedAddCommGroup V
inst✝⁴ : InnerProductSpace ℝ V
inst✝³ : MetricSpace P
inst✝² : NormedAddTorsor V P
s : AffineSubspace ℝ P
inst✝¹ : Nonempty ↥s
inst✝ : HasOrthogonalProjection (direction s)
p : P
h : ↑((orthogonalProjection s) p) = p
⊢ ↑((orthogonalProjection s) p) = p

Next tactic:
exact h
/-- A point is its own reflection if and only if it is in the subspace. -/
theorem reflection_eq_self_iff {s : AffineSubspace ℝ P} [Nonempty s]
    [HasOrthogonalProjection s.direction] (p : P) : reflection s p = p ↔ p ∈ s := by
  rw [← orthogonalProjection_eq_self_iff, reflection_apply]
  constructor
  · intro h
    rw [← @vsub_eq_zero_iff_eq V, vadd_vsub_assoc, ← two_smul ℝ (↑(orthogonalProjection s p) -ᵥ p),
      smul_eq_zero] at h
    norm_num at h
    exact h
  · 

Proof state:
case mpr
V : Type u_1
P : Type u_2
inst✝⁵ : NormedAddCommGroup V
inst✝⁴ : InnerProductSpace ℝ V
inst✝³ : MetricSpace P
inst✝² : NormedAddTorsor V P
s : AffineSubspace ℝ P
inst✝¹ : Nonempty ↥s
inst✝ : HasOrthogonalProjection (direction s)
p : P
⊢ ↑((orthogonalProjection s) p) = p → ↑((orthogonalProjection s) p) -ᵥ p +ᵥ ↑((orthogonalProjection s) p) = p

Next tactic:
intro h