l3lab/ntp-mathlib huggingface dataset:
theorem isConnected_setOf_wOppSide {s : AffineSubspace ℝ P} (x : P) (h : (s : Set P).Nonempty) :
    IsConnected { y | s.WOppSide x y } := by
  obtain ⟨p, hp⟩ := h
  haveI : Nonempty s := ⟨⟨p, hp⟩⟩
  by_cases hx : x ∈ s
  · simp only [wOppSide_of_left_mem, hx]
    have := AddTorsor.connectedSpace V P
    exact isConnected_univ
  · 

Proof state:
case neg
R : Type u_1
V : Type u_2
V' : Type u_3
P : Type u_4
P' : Type u_5
inst✝³ : SeminormedAddCommGroup V
inst✝² : NormedSpace ℝ V
inst✝¹ : PseudoMetricSpace P
inst✝ : NormedAddTorsor V P
s : AffineSubspace ℝ P
x p : P
hp : p ∈ ↑s
this : Nonempty ↥s
hx : x ∉ s
⊢ IsConnected {y | WOppSide s x y}

Next tactic:
rw [setOf_wOppSide_eq_image2 hx hp, ← Set.image_prod]
theorem isConnected_setOf_wOppSide {s : AffineSubspace ℝ P} (x : P) (h : (s : Set P).Nonempty) :
    IsConnected { y | s.WOppSide x y } := by
  obtain ⟨p, hp⟩ := h
  haveI : Nonempty s := ⟨⟨p, hp⟩⟩
  by_cases hx : x ∈ s
  · simp only [wOppSide_of_left_mem, hx]
    have := AddTorsor.connectedSpace V P
    exact isConnected_univ
  · rw [setOf_wOppSide_eq_image2 hx hp, ← Set.image_prod]
    

Proof state:
case neg
R : Type u_1
V : Type u_2
V' : Type u_3
P : Type u_4
P' : Type u_5
inst✝³ : SeminormedAddCommGroup V
inst✝² : NormedSpace ℝ V
inst✝¹ : PseudoMetricSpace P
inst✝ : NormedAddTorsor V P
s : AffineSubspace ℝ P
x p : P
hp : p ∈ ↑s
this : Nonempty ↥s
hx : x ∉ s
⊢ IsConnected ((fun x_1 => x_1.1 • (x -ᵥ p) +ᵥ x_1.2) '' Set.Iic 0 ×ˢ ↑s)

Next tactic:
refine' (isConnected_Iic.prod (isConnected_iff_connectedSpace.2 _)).image _
      ((continuous_fst.smul continuous_const).vadd continuous_snd).continuousOn
theorem isConnected_setOf_wOppSide {s : AffineSubspace ℝ P} (x : P) (h : (s : Set P).Nonempty) :
    IsConnected { y | s.WOppSide x y } := by
  obtain ⟨p, hp⟩ := h
  haveI : Nonempty s := ⟨⟨p, hp⟩⟩
  by_cases hx : x ∈ s
  · simp only [wOppSide_of_left_mem, hx]
    have := AddTorsor.connectedSpace V P
    exact isConnected_univ
  · rw [setOf_wOppSide_eq_image2 hx hp, ← Set.image_prod]
    refine' (isConnected_Iic.prod (isConnected_iff_connectedSpace.2 _)).image _
      ((continuous_fst.smul continuous_const).vadd continuous_snd).continuousOn
    

Proof state:
case neg
R : Type u_1
V : Type u_2
V' : Type u_3
P : Type u_4
P' : Type u_5
inst✝³ : SeminormedAddCommGroup V
inst✝² : NormedSpace ℝ V
inst✝¹ : PseudoMetricSpace P
inst✝ : NormedAddTorsor V P
s : AffineSubspace ℝ P
x p : P
hp : p ∈ ↑s
this : Nonempty ↥s
hx : x ∉ s
⊢ ConnectedSpace ↑↑s

Next tactic:
convert AddTorsor.connectedSpace s.direction s
theorem isPreconnected_setOf_wOppSide (s : AffineSubspace ℝ P) (x : P) :
    IsPreconnected { y | s.WOppSide x y } := by
  

Proof state:
R : Type u_1
V : Type u_2
V' : Type u_3
P : Type u_4
P' : Type u_5
inst✝³ : SeminormedAddCommGroup V
inst✝² : NormedSpace ℝ V
inst✝¹ : PseudoMetricSpace P
inst✝ : NormedAddTorsor V P
s : AffineSubspace ℝ P
x : P
⊢ IsPreconnected {y | WOppSide s x y}

Next tactic:
rcases Set.eq_empty_or_nonempty (s : Set P) with (h | h)
theorem isPreconnected_setOf_wOppSide (s : AffineSubspace ℝ P) (x : P) :
    IsPreconnected { y | s.WOppSide x y } := by
  rcases Set.eq_empty_or_nonempty (s : Set P) with (h | h)
  · 

Proof state:
case inl
R : Type u_1
V : Type u_2
V' : Type u_3
P : Type u_4
P' : Type u_5
inst✝³ : SeminormedAddCommGroup V
inst✝² : NormedSpace ℝ V
inst✝¹ : PseudoMetricSpace P
inst✝ : NormedAddTorsor V P
s : AffineSubspace ℝ P
x : P
h : ↑s = ∅
⊢ IsPreconnected {y | WOppSide s x y}

Next tactic:
rw [coe_eq_bot_iff] at h
theorem isPreconnected_setOf_wOppSide (s : AffineSubspace ℝ P) (x : P) :
    IsPreconnected { y | s.WOppSide x y } := by
  rcases Set.eq_empty_or_nonempty (s : Set P) with (h | h)
  · rw [coe_eq_bot_iff] at h
    

Proof state:
case inl
R : Type u_1
V : Type u_2
V' : Type u_3
P : Type u_4
P' : Type u_5
inst✝³ : SeminormedAddCommGroup V
inst✝² : NormedSpace ℝ V
inst✝¹ : PseudoMetricSpace P
inst✝ : NormedAddTorsor V P
s : AffineSubspace ℝ P
x : P
h : s = ⊥
⊢ IsPreconnected {y | WOppSide s x y}

Next tactic:
simp only [h, not_wOppSide_bot]
theorem isPreconnected_setOf_wOppSide (s : AffineSubspace ℝ P) (x : P) :
    IsPreconnected { y | s.WOppSide x y } := by
  rcases Set.eq_empty_or_nonempty (s : Set P) with (h | h)
  · rw [coe_eq_bot_iff] at h
    simp only [h, not_wOppSide_bot]
    

Proof state:
case inl
R : Type u_1
V : Type u_2
V' : Type u_3
P : Type u_4
P' : Type u_5
inst✝³ : SeminormedAddCommGroup V
inst✝² : NormedSpace ℝ V
inst✝¹ : PseudoMetricSpace P
inst✝ : NormedAddTorsor V P
s : AffineSubspace ℝ P
x : P
h : s = ⊥
⊢ IsPreconnected {y | False}

Next tactic:
exact isPreconnected_empty
theorem isPreconnected_setOf_wOppSide (s : AffineSubspace ℝ P) (x : P) :
    IsPreconnected { y | s.WOppSide x y } := by
  rcases Set.eq_empty_or_nonempty (s : Set P) with (h | h)
  · rw [coe_eq_bot_iff] at h
    simp only [h, not_wOppSide_bot]
    exact isPreconnected_empty
  · 

Proof state:
case inr
R : Type u_1
V : Type u_2
V' : Type u_3
P : Type u_4
P' : Type u_5
inst✝³ : SeminormedAddCommGroup V
inst✝² : NormedSpace ℝ V
inst✝¹ : PseudoMetricSpace P
inst✝ : NormedAddTorsor V P
s : AffineSubspace ℝ P
x : P
h : Set.Nonempty ↑s
⊢ IsPreconnected {y | WOppSide s x y}

Next tactic:
exact (isConnected_setOf_wOppSide x h).isPreconnected
theorem isConnected_setOf_sOppSide {s : AffineSubspace ℝ P} {x : P} (hx : x ∉ s)
    (h : (s : Set P).Nonempty) : IsConnected { y | s.SOppSide x y } := by
  

Proof state:
R : Type u_1
V : Type u_2
V' : Type u_3
P : Type u_4
P' : Type u_5
inst✝³ : SeminormedAddCommGroup V
inst✝² : NormedSpace ℝ V
inst✝¹ : PseudoMetricSpace P
inst✝ : NormedAddTorsor V P
s : AffineSubspace ℝ P
x : P
hx : x ∉ s
h : Set.Nonempty ↑s
⊢ IsConnected {y | SOppSide s x y}

Next tactic:
obtain ⟨p, hp⟩ := h
theorem isConnected_setOf_sOppSide {s : AffineSubspace ℝ P} {x : P} (hx : x ∉ s)
    (h : (s : Set P).Nonempty) : IsConnected { y | s.SOppSide x y } := by
  obtain ⟨p, hp⟩ := h
  

Proof state:
case intro
R : Type u_1
V : Type u_2
V' : Type u_3
P : Type u_4
P' : Type u_5
inst✝³ : SeminormedAddCommGroup V
inst✝² : NormedSpace ℝ V
inst✝¹ : PseudoMetricSpace P
inst✝ : NormedAddTorsor V P
s : AffineSubspace ℝ P
x : P
hx : x ∉ s
p : P
hp : p ∈ ↑s
⊢ IsConnected {y | SOppSide s x y}

Next tactic:
haveI : Nonempty s := ⟨⟨p, hp⟩⟩
theorem isConnected_setOf_sOppSide {s : AffineSubspace ℝ P} {x : P} (hx : x ∉ s)
    (h : (s : Set P).Nonempty) : IsConnected { y | s.SOppSide x y } := by
  obtain ⟨p, hp⟩ := h
  haveI : Nonempty s := ⟨⟨p, hp⟩⟩
  

Proof state:
case intro
R : Type u_1
V : Type u_2
V' : Type u_3
P : Type u_4
P' : Type u_5
inst✝³ : SeminormedAddCommGroup V
inst✝² : NormedSpace ℝ V
inst✝¹ : PseudoMetricSpace P
inst✝ : NormedAddTorsor V P
s : AffineSubspace ℝ P
x : P
hx : x ∉ s
p : P
hp : p ∈ ↑s
this : Nonempty ↥s
⊢ IsConnected {y | SOppSide s x y}

Next tactic:
rw [setOf_sOppSide_eq_image2 hx hp, ← Set.image_prod]
theorem isConnected_setOf_sOppSide {s : AffineSubspace ℝ P} {x : P} (hx : x ∉ s)
    (h : (s : Set P).Nonempty) : IsConnected { y | s.SOppSide x y } := by
  obtain ⟨p, hp⟩ := h
  haveI : Nonempty s := ⟨⟨p, hp⟩⟩
  rw [setOf_sOppSide_eq_image2 hx hp, ← Set.image_prod]
  

Proof state:
case intro
R : Type u_1
V : Type u_2
V' : Type u_3
P : Type u_4
P' : Type u_5
inst✝³ : SeminormedAddCommGroup V
inst✝² : NormedSpace ℝ V
inst✝¹ : PseudoMetricSpace P
inst✝ : NormedAddTorsor V P
s : AffineSubspace ℝ P
x : P
hx : x ∉ s
p : P
hp : p ∈ ↑s
this : Nonempty ↥s
⊢ IsConnected ((fun x_1 => x_1.1 • (x -ᵥ p) +ᵥ x_1.2) '' Set.Iio 0 ×ˢ ↑s)

Next tactic:
refine' (isConnected_Iio.prod (isConnected_iff_connectedSpace.2 _)).image _
    ((continuous_fst.smul continuous_const).vadd continuous_snd).continuousOn
theorem isConnected_setOf_sOppSide {s : AffineSubspace ℝ P} {x : P} (hx : x ∉ s)
    (h : (s : Set P).Nonempty) : IsConnected { y | s.SOppSide x y } := by
  obtain ⟨p, hp⟩ := h
  haveI : Nonempty s := ⟨⟨p, hp⟩⟩
  rw [setOf_sOppSide_eq_image2 hx hp, ← Set.image_prod]
  refine' (isConnected_Iio.prod (isConnected_iff_connectedSpace.2 _)).image _
    ((continuous_fst.smul continuous_const).vadd continuous_snd).continuousOn
  

Proof state:
case intro
R : Type u_1
V : Type u_2
V' : Type u_3
P : Type u_4
P' : Type u_5
inst✝³ : SeminormedAddCommGroup V
inst✝² : NormedSpace ℝ V
inst✝¹ : PseudoMetricSpace P
inst✝ : NormedAddTorsor V P
s : AffineSubspace ℝ P
x : P
hx : x ∉ s
p : P
hp : p ∈ ↑s
this : Nonempty ↥s
⊢ ConnectedSpace ↑↑s

Next tactic:
convert AddTorsor.connectedSpace s.direction s
theorem isPreconnected_setOf_sOppSide (s : AffineSubspace ℝ P) (x : P) :
    IsPreconnected { y | s.SOppSide x y } := by
  

Proof state:
R : Type u_1
V : Type u_2
V' : Type u_3
P : Type u_4
P' : Type u_5
inst✝³ : SeminormedAddCommGroup V
inst✝² : NormedSpace ℝ V
inst✝¹ : PseudoMetricSpace P
inst✝ : NormedAddTorsor V P
s : AffineSubspace ℝ P
x : P
⊢ IsPreconnected {y | SOppSide s x y}

Next tactic:
rcases Set.eq_empty_or_nonempty (s : Set P) with (h | h)
theorem isPreconnected_setOf_sOppSide (s : AffineSubspace ℝ P) (x : P) :
    IsPreconnected { y | s.SOppSide x y } := by
  rcases Set.eq_empty_or_nonempty (s : Set P) with (h | h)
  · 

Proof state:
case inl
R : Type u_1
V : Type u_2
V' : Type u_3
P : Type u_4
P' : Type u_5
inst✝³ : SeminormedAddCommGroup V
inst✝² : NormedSpace ℝ V
inst✝¹ : PseudoMetricSpace P
inst✝ : NormedAddTorsor V P
s : AffineSubspace ℝ P
x : P
h : ↑s = ∅
⊢ IsPreconnected {y | SOppSide s x y}

Next tactic:
rw [coe_eq_bot_iff] at h
theorem isPreconnected_setOf_sOppSide (s : AffineSubspace ℝ P) (x : P) :
    IsPreconnected { y | s.SOppSide x y } := by
  rcases Set.eq_empty_or_nonempty (s : Set P) with (h | h)
  · rw [coe_eq_bot_iff] at h
    

Proof state:
case inl
R : Type u_1
V : Type u_2
V' : Type u_3
P : Type u_4
P' : Type u_5
inst✝³ : SeminormedAddCommGroup V
inst✝² : NormedSpace ℝ V
inst✝¹ : PseudoMetricSpace P
inst✝ : NormedAddTorsor V P
s : AffineSubspace ℝ P
x : P
h : s = ⊥
⊢ IsPreconnected {y | SOppSide s x y}

Next tactic:
simp only [h, not_sOppSide_bot]
theorem isPreconnected_setOf_sOppSide (s : AffineSubspace ℝ P) (x : P) :
    IsPreconnected { y | s.SOppSide x y } := by
  rcases Set.eq_empty_or_nonempty (s : Set P) with (h | h)
  · rw [coe_eq_bot_iff] at h
    simp only [h, not_sOppSide_bot]
    

Proof state:
case inl
R : Type u_1
V : Type u_2
V' : Type u_3
P : Type u_4
P' : Type u_5
inst✝³ : SeminormedAddCommGroup V
inst✝² : NormedSpace ℝ V
inst✝¹ : PseudoMetricSpace P
inst✝ : NormedAddTorsor V P
s : AffineSubspace ℝ P
x : P
h : s = ⊥
⊢ IsPreconnected {y | False}

Next tactic:
exact isPreconnected_empty
theorem isPreconnected_setOf_sOppSide (s : AffineSubspace ℝ P) (x : P) :
    IsPreconnected { y | s.SOppSide x y } := by
  rcases Set.eq_empty_or_nonempty (s : Set P) with (h | h)
  · rw [coe_eq_bot_iff] at h
    simp only [h, not_sOppSide_bot]
    exact isPreconnected_empty
  · 

Proof state:
case inr
R : Type u_1
V : Type u_2
V' : Type u_3
P : Type u_4
P' : Type u_5
inst✝³ : SeminormedAddCommGroup V
inst✝² : NormedSpace ℝ V
inst✝¹ : PseudoMetricSpace P
inst✝ : NormedAddTorsor V P
s : AffineSubspace ℝ P
x : P
h : Set.Nonempty ↑s
⊢ IsPreconnected {y | SOppSide s x y}

Next tactic:
by_cases hx : x ∈ s
theorem isPreconnected_setOf_sOppSide (s : AffineSubspace ℝ P) (x : P) :
    IsPreconnected { y | s.SOppSide x y } := by
  rcases Set.eq_empty_or_nonempty (s : Set P) with (h | h)
  · rw [coe_eq_bot_iff] at h
    simp only [h, not_sOppSide_bot]
    exact isPreconnected_empty
  · by_cases hx : x ∈ s
    · 

Proof state:
case pos
R : Type u_1
V : Type u_2
V' : Type u_3
P : Type u_4
P' : Type u_5
inst✝³ : SeminormedAddCommGroup V
inst✝² : NormedSpace ℝ V
inst✝¹ : PseudoMetricSpace P
inst✝ : NormedAddTorsor V P
s : AffineSubspace ℝ P
x : P
h : Set.Nonempty ↑s
hx : x ∈ s
⊢ IsPreconnected {y | SOppSide s x y}

Next tactic:
simp only [hx, SOppSide, not_true, false_and_iff, and_false_iff]
theorem isPreconnected_setOf_sOppSide (s : AffineSubspace ℝ P) (x : P) :
    IsPreconnected { y | s.SOppSide x y } := by
  rcases Set.eq_empty_or_nonempty (s : Set P) with (h | h)
  · rw [coe_eq_bot_iff] at h
    simp only [h, not_sOppSide_bot]
    exact isPreconnected_empty
  · by_cases hx : x ∈ s
    · simp only [hx, SOppSide, not_true, false_and_iff, and_false_iff]
      

Proof state:
case pos
R : Type u_1
V : Type u_2
V' : Type u_3
P : Type u_4
P' : Type u_5
inst✝³ : SeminormedAddCommGroup V
inst✝² : NormedSpace ℝ V
inst✝¹ : PseudoMetricSpace P
inst✝ : NormedAddTorsor V P
s : AffineSubspace ℝ P
x : P
h : Set.Nonempty ↑s
hx : x ∈ s
⊢ IsPreconnected {y | False}

Next tactic:
exact isPreconnected_empty
theorem isPreconnected_setOf_sOppSide (s : AffineSubspace ℝ P) (x : P) :
    IsPreconnected { y | s.SOppSide x y } := by
  rcases Set.eq_empty_or_nonempty (s : Set P) with (h | h)
  · rw [coe_eq_bot_iff] at h
    simp only [h, not_sOppSide_bot]
    exact isPreconnected_empty
  · by_cases hx : x ∈ s
    · simp only [hx, SOppSide, not_true, false_and_iff, and_false_iff]
      exact isPreconnected_empty
    · 

Proof state:
case neg
R : Type u_1
V : Type u_2
V' : Type u_3
P : Type u_4
P' : Type u_5
inst✝³ : SeminormedAddCommGroup V
inst✝² : NormedSpace ℝ V
inst✝¹ : PseudoMetricSpace P
inst✝ : NormedAddTorsor V P
s : AffineSubspace ℝ P
x : P
h : Set.Nonempty ↑s
hx : x ∉ s
⊢ IsPreconnected {y | SOppSide s x y}

Next tactic:
exact (isConnected_setOf_sOppSide hx h).isPreconnected
@[simp]
theorem count_zero : count p 0 = 0 := by
  

Proof state:
p : ℕ → Prop
inst✝ : DecidablePred p
⊢ count p 0 = 0

Next tactic:
rw [count, List.range_zero, List.countP, List.countP.go]
/-- A fintype instance for the set relevant to `Nat.count`. Locally an instance in locale `count` -/
def CountSet.fintype (n : ℕ) : Fintype { i // i < n ∧ p i } := by
  

Proof state:
p : ℕ → Prop
inst✝ : DecidablePred p
n : ℕ
⊢ Fintype { i // i < n ∧ p i }

Next tactic:
apply Fintype.ofFinset ((Finset.range n).filter p)
/-- A fintype instance for the set relevant to `Nat.count`. Locally an instance in locale `count` -/
def CountSet.fintype (n : ℕ) : Fintype { i // i < n ∧ p i } := by
  apply Fintype.ofFinset ((Finset.range n).filter p)
  

Proof state:
p : ℕ → Prop
inst✝ : DecidablePred p
n : ℕ
⊢ ∀ (x : ℕ), x ∈ filter p (range n) ↔ x ∈ fun x => x < n ∧ p x

Next tactic:
intro x
/-- A fintype instance for the set relevant to `Nat.count`. Locally an instance in locale `count` -/
def CountSet.fintype (n : ℕ) : Fintype { i // i < n ∧ p i } := by
  apply Fintype.ofFinset ((Finset.range n).filter p)
  intro x
  

Proof state:
p : ℕ → Prop
inst✝ : DecidablePred p
n x : ℕ
⊢ x ∈ filter p (range n) ↔ x ∈ fun x => x < n ∧ p x

Next tactic:
rw [mem_filter, mem_range]
/-- A fintype instance for the set relevant to `Nat.count`. Locally an instance in locale `count` -/
def CountSet.fintype (n : ℕ) : Fintype { i // i < n ∧ p i } := by
  apply Fintype.ofFinset ((Finset.range n).filter p)
  intro x
  rw [mem_filter, mem_range]
  

Proof state:
p : ℕ → Prop
inst✝ : DecidablePred p
n x : ℕ
⊢ x < n ∧ p x ↔ x ∈ fun x => x < n ∧ p x

Next tactic:
rfl
theorem count_eq_card_filter_range (n : ℕ) : count p n = ((range n).filter p).card := by
  

Proof state:
p : ℕ → Prop
inst✝ : DecidablePred p
n : ℕ
⊢ count p n = card (filter p (range n))

Next tactic:
rw [count, List.countP_eq_length_filter]
theorem count_eq_card_filter_range (n : ℕ) : count p n = ((range n).filter p).card := by
  rw [count, List.countP_eq_length_filter]
  

Proof state:
p : ℕ → Prop
inst✝ : DecidablePred p
n : ℕ
⊢ List.length (List.filter (fun b => decide (p b)) (List.range n)) = card (filter p (range n))

Next tactic:
rfl
/-- `count p n` can be expressed as the cardinality of `{k // k < n ∧ p k}`. -/
theorem count_eq_card_fintype (n : ℕ) : count p n = Fintype.card { k : ℕ // k < n ∧ p k } := by
  

Proof state:
p : ℕ → Prop
inst✝ : DecidablePred p
n : ℕ
⊢ count p n = Fintype.card { k // k < n ∧ p k }

Next tactic:
rw [count_eq_card_filter_range, ← Fintype.card_ofFinset, ← CountSet.fintype]
/-- `count p n` can be expressed as the cardinality of `{k // k < n ∧ p k}`. -/
theorem count_eq_card_fintype (n : ℕ) : count p n = Fintype.card { k : ℕ // k < n ∧ p k } := by
  rw [count_eq_card_filter_range, ← Fintype.card_ofFinset, ← CountSet.fintype]
  

Proof state:
p : ℕ → Prop
inst✝ : DecidablePred p
n : ℕ
⊢ (Fintype.card ↑fun x => x < n ∧ p x) = Fintype.card { k // k < n ∧ p k }

Next tactic:
rfl
theorem count_succ (n : ℕ) : count p (n + 1) = count p n + if p n then 1 else 0 := by
  

Proof state:
p : ℕ → Prop
inst✝ : DecidablePred p
n : ℕ
⊢ count p (n + 1) = count p n + if p n then 1 else 0

Next tactic:
split_ifs with h
theorem count_succ (n : ℕ) : count p (n + 1) = count p n + if p n then 1 else 0 := by
  split_ifs with h <;> 

Proof state:
case pos
p : ℕ → Prop
inst✝ : DecidablePred p
n : ℕ
h : p n
⊢ count p (n + 1) = count p n + 1

Next tactic:
simp [count, List.range_succ, h]
theorem count_succ (n : ℕ) : count p (n + 1) = count p n + if p n then 1 else 0 := by
  split_ifs with h <;> 

Proof state:
case neg
p : ℕ → Prop
inst✝ : DecidablePred p
n : ℕ
h : ¬p n
⊢ count p (n + 1) = count p n + 0

Next tactic:
simp [count, List.range_succ, h]
@[mono]
theorem count_monotone : Monotone (count p) :=
  monotone_nat_of_le_succ fun n ↦ by 

Proof state:
p : ℕ → Prop
inst✝ : DecidablePred p
n : ℕ
⊢ count p n ≤ count p (n + 1)

Next tactic:
by_cases h : p n
@[mono]
theorem count_monotone : Monotone (count p) :=
  monotone_nat_of_le_succ fun n ↦ by by_cases h : p n <;> 

Proof state:
case pos
p : ℕ → Prop
inst✝ : DecidablePred p
n : ℕ
h : p n
⊢ count p n ≤ count p (n + 1)

Next tactic:
simp [count_succ, h]
@[mono]
theorem count_monotone : Monotone (count p) :=
  monotone_nat_of_le_succ fun n ↦ by by_cases h : p n <;> 

Proof state:
case neg
p : ℕ → Prop
inst✝ : DecidablePred p
n : ℕ
h : ¬p n
⊢ count p n ≤ count p (n + 1)

Next tactic:
simp [count_succ, h]
theorem count_add (a b : ℕ) : count p (a + b) = count p a + count (fun k ↦ p (a + k)) b := by
  

Proof state:
p : ℕ → Prop
inst✝ : DecidablePred p
a b : ℕ
⊢ count p (a + b) = count p a + count (fun k => p (a + k)) b

Next tactic:
have : Disjoint ((range a).filter p) (((range b).map <| addLeftEmbedding a).filter p) := by
    apply disjoint_filter_filter
    rw [Finset.disjoint_left]
    simp_rw [mem_map, mem_range, addLeftEmbedding_apply]
    rintro x hx ⟨c, _, rfl⟩
    exact (self_le_add_right _ _).not_lt hx
theorem count_add (a b : ℕ) : count p (a + b) = count p a + count (fun k ↦ p (a + k)) b := by
  have : Disjoint ((range a).filter p) (((range b).map <| addLeftEmbedding a).filter p) := by
    

Proof state:
p : ℕ → Prop
inst✝ : DecidablePred p
a b : ℕ
⊢ Disjoint (filter p (range a)) (filter p (map (addLeftEmbedding a) (range b)))

Next tactic:
apply disjoint_filter_filter
theorem count_add (a b : ℕ) : count p (a + b) = count p a + count (fun k ↦ p (a + k)) b := by
  have : Disjoint ((range a).filter p) (((range b).map <| addLeftEmbedding a).filter p) := by
    apply disjoint_filter_filter
    

Proof state:
case a
p : ℕ → Prop
inst✝ : DecidablePred p
a b : ℕ
⊢ Disjoint (range a) (map (addLeftEmbedding a) (range b))

Next tactic:
rw [Finset.disjoint_left]
theorem count_add (a b : ℕ) : count p (a + b) = count p a + count (fun k ↦ p (a + k)) b := by
  have : Disjoint ((range a).filter p) (((range b).map <| addLeftEmbedding a).filter p) := by
    apply disjoint_filter_filter
    rw [Finset.disjoint_left]
    

Proof state:
case a
p : ℕ → Prop
inst✝ : DecidablePred p
a b : ℕ
⊢ ∀ ⦃a_1 : ℕ⦄, a_1 ∈ range a → a_1 ∉ map (addLeftEmbedding a) (range b)

Next tactic:
simp_rw [mem_map, mem_range, addLeftEmbedding_apply]
theorem count_add (a b : ℕ) : count p (a + b) = count p a + count (fun k ↦ p (a + k)) b := by
  have : Disjoint ((range a).filter p) (((range b).map <| addLeftEmbedding a).filter p) := by
    apply disjoint_filter_filter
    rw [Finset.disjoint_left]
    simp_rw [mem_map, mem_range, addLeftEmbedding_apply]
    

Proof state:
case a
p : ℕ → Prop
inst✝ : DecidablePred p
a b : ℕ
⊢ ∀ ⦃a_1 : ℕ⦄, a_1 < a → ¬∃ a_3 < b, a + a_3 = a_1

Next tactic:
rintro x hx ⟨c, _, rfl⟩
theorem count_add (a b : ℕ) : count p (a + b) = count p a + count (fun k ↦ p (a + k)) b := by
  have : Disjoint ((range a).filter p) (((range b).map <| addLeftEmbedding a).filter p) := by
    apply disjoint_filter_filter
    rw [Finset.disjoint_left]
    simp_rw [mem_map, mem_range, addLeftEmbedding_apply]
    rintro x hx ⟨c, _, rfl⟩
    

Proof state:
case a.intro.intro
p : ℕ → Prop
inst✝ : DecidablePred p
a b c : ℕ
left✝ : c < b
hx : a + c < a
⊢ False

Next tactic:
exact (self_le_add_right _ _).not_lt hx
theorem count_add (a b : ℕ) : count p (a + b) = count p a + count (fun k ↦ p (a + k)) b := by
  have : Disjoint ((range a).filter p) (((range b).map <| addLeftEmbedding a).filter p) := by
    apply disjoint_filter_filter
    rw [Finset.disjoint_left]
    simp_rw [mem_map, mem_range, addLeftEmbedding_apply]
    rintro x hx ⟨c, _, rfl⟩
    exact (self_le_add_right _ _).not_lt hx
  

Proof state:
p : ℕ → Prop
inst✝ : DecidablePred p
a b : ℕ
this : Disjoint (filter p (range a)) (filter p (map (addLeftEmbedding a) (range b)))
⊢ count p (a + b) = count p a + count (fun k => p (a + k)) b

Next tactic:
simp_rw [count_eq_card_filter_range, range_add, filter_union, card_disjoint_union this,
    filter_map, addLeftEmbedding, card_map]
theorem count_add (a b : ℕ) : count p (a + b) = count p a + count (fun k ↦ p (a + k)) b := by
  have : Disjoint ((range a).filter p) (((range b).map <| addLeftEmbedding a).filter p) := by
    apply disjoint_filter_filter
    rw [Finset.disjoint_left]
    simp_rw [mem_map, mem_range, addLeftEmbedding_apply]
    rintro x hx ⟨c, _, rfl⟩
    exact (self_le_add_right _ _).not_lt hx
  simp_rw [count_eq_card_filter_range, range_add, filter_union, card_disjoint_union this,
    filter_map, addLeftEmbedding, card_map]
  

Proof state:
p : ℕ → Prop
inst✝ : DecidablePred p
a b : ℕ
this : Disjoint (filter p (range a)) (filter p (map (addLeftEmbedding a) (range b)))
⊢ card (filter p (range a)) +
      card (filter (p ∘ ⇑{ toFun := fun h => a + h, inj' := (_ : Function.Injective fun x => a + x) }) (range b)) =
    card (filter p (range a)) + card (filter (fun k => p (a + k)) (range b))

Next tactic:
rfl
theorem count_add' (a b : ℕ) : count p (a + b) = count (fun k ↦ p (k + b)) a + count p b := by
  

Proof state:
p : ℕ → Prop
inst✝ : DecidablePred p
a b : ℕ
⊢ count p (a + b) = count (fun k => p (k + b)) a + count p b

Next tactic:
rw [add_comm, count_add, add_comm]
theorem count_add' (a b : ℕ) : count p (a + b) = count (fun k ↦ p (k + b)) a + count p b := by
  rw [add_comm, count_add, add_comm]
  

Proof state:
p : ℕ → Prop
inst✝ : DecidablePred p
a b : ℕ
⊢ count (fun k => p (b + k)) a + count p b = count (fun k => p (k + b)) a + count p b

Next tactic:
simp_rw [add_comm b]
theorem count_one : count p 1 = if p 0 then 1 else 0 := by 

Proof state:
p : ℕ → Prop
inst✝ : DecidablePred p
⊢ count p 1 = if p 0 then 1 else 0

Next tactic:
simp [count_succ]
theorem count_succ' (n : ℕ) :
    count p (n + 1) = count (fun k ↦ p (k + 1)) n + if p 0 then 1 else 0 := by
  

Proof state:
p : ℕ → Prop
inst✝ : DecidablePred p
n : ℕ
⊢ count p (n + 1) = count (fun k => p (k + 1)) n + if p 0 then 1 else 0

Next tactic:
rw [count_add', count_one]
@[simp]
theorem count_lt_count_succ_iff {n : ℕ} : count p n < count p (n + 1) ↔ p n := by
  

Proof state:
p : ℕ → Prop
inst✝ : DecidablePred p
n : ℕ
⊢ count p n < count p (n + 1) ↔ p n

Next tactic:
by_cases h : p n
@[simp]
theorem count_lt_count_succ_iff {n : ℕ} : count p n < count p (n + 1) ↔ p n := by
  by_cases h : p n <;> 

Proof state:
case pos
p : ℕ → Prop
inst✝ : DecidablePred p
n : ℕ
h : p n
⊢ count p n < count p (n + 1) ↔ p n

Next tactic:
simp [count_succ, h]
@[simp]
theorem count_lt_count_succ_iff {n : ℕ} : count p n < count p (n + 1) ↔ p n := by
  by_cases h : p n <;> 

Proof state:
case neg
p : ℕ → Prop
inst✝ : DecidablePred p
n : ℕ
h : ¬p n
⊢ count p n < count p (n + 1) ↔ p n

Next tactic:
simp [count_succ, h]
theorem count_succ_eq_succ_count_iff {n : ℕ} : count p (n + 1) = count p n + 1 ↔ p n := by
  

Proof state:
p : ℕ → Prop
inst✝ : DecidablePred p
n : ℕ
⊢ count p (n + 1) = count p n + 1 ↔ p n

Next tactic:
by_cases h : p n
theorem count_succ_eq_succ_count_iff {n : ℕ} : count p (n + 1) = count p n + 1 ↔ p n := by
  by_cases h : p n <;> 

Proof state:
case pos
p : ℕ → Prop
inst✝ : DecidablePred p
n : ℕ
h : p n
⊢ count p (n + 1) = count p n + 1 ↔ p n

Next tactic:
simp [h, count_succ]