l3lab/ntp-mathlib huggingface dataset:
theorem measurableSet_iSup_of_mem_piiUnionInter (m : ι → MeasurableSpace α) (S : Set ι) (t : Set α)
    (ht : t ∈ piiUnionInter (fun n => { s | MeasurableSet[m n] s }) S) :
    MeasurableSet[⨆ i ∈ S, m i] t := by
  rcases ht with ⟨pt, hpt, ft, ht_m, rfl⟩
  refine' pt.measurableSet_biInter fun i hi => _
  suffices h_le : m i ≤ ⨆ i ∈ S, m i; exact h_le (ft i) (ht_m i hi)
  have hi' : i ∈ S := hpt hi
  

Proof state:
case h_le
α : Type u_1
ι : Type u_2
m : ι → MeasurableSpace α
S : Set ι
pt : Finset ι
hpt : ↑pt ⊆ S
ft : ι → Set α
ht_m : ∀ x ∈ pt, ft x ∈ (fun n => {s | MeasurableSet s}) x
i : ι
hi : i ∈ pt
hi' : i ∈ S
⊢ m i ≤ ⨆ i ∈ S, m i

Next tactic:
exact le_iSup₂ (f := fun i (_ : i ∈ S) => m i) i hi'
theorem generateFrom_piiUnionInter_measurableSet (m : ι → MeasurableSpace α) (S : Set ι) :
    generateFrom (piiUnionInter (fun n => { s | MeasurableSet[m n] s }) S) = ⨆ i ∈ S, m i := by
  

Proof state:
α : Type u_1
ι : Type u_2
m : ι → MeasurableSpace α
S : Set ι
⊢ generateFrom (piiUnionInter (fun n => {s | MeasurableSet s}) S) = ⨆ i ∈ S, m i

Next tactic:
refine' le_antisymm _ _
theorem generateFrom_piiUnionInter_measurableSet (m : ι → MeasurableSpace α) (S : Set ι) :
    generateFrom (piiUnionInter (fun n => { s | MeasurableSet[m n] s }) S) = ⨆ i ∈ S, m i := by
  refine' le_antisymm _ _
  · 

Proof state:
case refine'_1
α : Type u_1
ι : Type u_2
m : ι → MeasurableSpace α
S : Set ι
⊢ generateFrom (piiUnionInter (fun n => {s | MeasurableSet s}) S) ≤ ⨆ i ∈ S, m i

Next tactic:
rw [← @generateFrom_measurableSet α (⨆ i ∈ S, m i)]
theorem generateFrom_piiUnionInter_measurableSet (m : ι → MeasurableSpace α) (S : Set ι) :
    generateFrom (piiUnionInter (fun n => { s | MeasurableSet[m n] s }) S) = ⨆ i ∈ S, m i := by
  refine' le_antisymm _ _
  · rw [← @generateFrom_measurableSet α (⨆ i ∈ S, m i)]
    

Proof state:
case refine'_1
α : Type u_1
ι : Type u_2
m : ι → MeasurableSpace α
S : Set ι
⊢ generateFrom (piiUnionInter (fun n => {s | MeasurableSet s}) S) ≤ generateFrom {s | MeasurableSet s}

Next tactic:
exact generateFrom_mono (measurableSet_iSup_of_mem_piiUnionInter m S)
theorem generateFrom_piiUnionInter_measurableSet (m : ι → MeasurableSpace α) (S : Set ι) :
    generateFrom (piiUnionInter (fun n => { s | MeasurableSet[m n] s }) S) = ⨆ i ∈ S, m i := by
  refine' le_antisymm _ _
  · rw [← @generateFrom_measurableSet α (⨆ i ∈ S, m i)]
    exact generateFrom_mono (measurableSet_iSup_of_mem_piiUnionInter m S)
  · 

Proof state:
case refine'_2
α : Type u_1
ι : Type u_2
m : ι → MeasurableSpace α
S : Set ι
⊢ ⨆ i ∈ S, m i ≤ generateFrom (piiUnionInter (fun n => {s | MeasurableSet s}) S)

Next tactic:
refine' iSup₂_le fun i hi => _
theorem generateFrom_piiUnionInter_measurableSet (m : ι → MeasurableSpace α) (S : Set ι) :
    generateFrom (piiUnionInter (fun n => { s | MeasurableSet[m n] s }) S) = ⨆ i ∈ S, m i := by
  refine' le_antisymm _ _
  · rw [← @generateFrom_measurableSet α (⨆ i ∈ S, m i)]
    exact generateFrom_mono (measurableSet_iSup_of_mem_piiUnionInter m S)
  · refine' iSup₂_le fun i hi => _
    

Proof state:
case refine'_2
α : Type u_1
ι : Type u_2
m : ι → MeasurableSpace α
S : Set ι
i : ι
hi : i ∈ S
⊢ m i ≤ generateFrom (piiUnionInter (fun n => {s | MeasurableSet s}) S)

Next tactic:
rw [← @generateFrom_measurableSet α (m i)]
theorem generateFrom_piiUnionInter_measurableSet (m : ι → MeasurableSpace α) (S : Set ι) :
    generateFrom (piiUnionInter (fun n => { s | MeasurableSet[m n] s }) S) = ⨆ i ∈ S, m i := by
  refine' le_antisymm _ _
  · rw [← @generateFrom_measurableSet α (⨆ i ∈ S, m i)]
    exact generateFrom_mono (measurableSet_iSup_of_mem_piiUnionInter m S)
  · refine' iSup₂_le fun i hi => _
    rw [← @generateFrom_measurableSet α (m i)]
    

Proof state:
case refine'_2
α : Type u_1
ι : Type u_2
m : ι → MeasurableSpace α
S : Set ι
i : ι
hi : i ∈ S
⊢ generateFrom {s | MeasurableSet s} ≤ generateFrom (piiUnionInter (fun n => {s | MeasurableSet s}) S)

Next tactic:
exact generateFrom_mono (mem_piiUnionInter_of_measurableSet m hi)
@[ext]
theorem ext : ∀ {d₁ d₂ : DynkinSystem α}, (∀ s : Set α, d₁.Has s ↔ d₂.Has s) → d₁ = d₂
  | ⟨s₁, _, _, _⟩, ⟨s₂, _, _, _⟩, h => by
    

Proof state:
α : Type u_1
s₁ : Set α → Prop
has_empty✝¹ : s₁ ∅
has_compl✝¹ : ∀ {a : Set α}, s₁ a → s₁ aᶜ
has_iUnion_nat✝¹ : ∀ {f : ℕ → Set α}, Pairwise (Disjoint on f) → (∀ (i : ℕ), s₁ (f i)) → s₁ (⋃ i, f i)
s₂ : Set α → Prop
has_empty✝ : s₂ ∅
has_compl✝ : ∀ {a : Set α}, s₂ a → s₂ aᶜ
has_iUnion_nat✝ : ∀ {f : ℕ → Set α}, Pairwise (Disjoint on f) → (∀ (i : ℕ), s₂ (f i)) → s₂ (⋃ i, f i)
h :
  ∀ (s : Set α),
    Has { Has := s₁, has_empty := has_empty✝¹, has_compl := has_compl✝¹, has_iUnion_nat := has_iUnion_nat✝¹ } s ↔
      Has { Has := s₂, has_empty := has_empty✝, has_compl := has_compl✝, has_iUnion_nat := has_iUnion_nat✝ } s
⊢ { Has := s₁, has_empty := has_empty✝¹, has_compl := has_compl✝¹, has_iUnion_nat := has_iUnion_nat✝¹ } =
    { Has := s₂, has_empty := has_empty✝, has_compl := has_compl✝, has_iUnion_nat := has_iUnion_nat✝ }

Next tactic:
have : s₁ = s₂ := funext fun x => propext <| h x
@[ext]
theorem ext : ∀ {d₁ d₂ : DynkinSystem α}, (∀ s : Set α, d₁.Has s ↔ d₂.Has s) → d₁ = d₂
  | ⟨s₁, _, _, _⟩, ⟨s₂, _, _, _⟩, h => by
    have : s₁ = s₂ := funext fun x => propext <| h x
    

Proof state:
α : Type u_1
s₁ : Set α → Prop
has_empty✝¹ : s₁ ∅
has_compl✝¹ : ∀ {a : Set α}, s₁ a → s₁ aᶜ
has_iUnion_nat✝¹ : ∀ {f : ℕ → Set α}, Pairwise (Disjoint on f) → (∀ (i : ℕ), s₁ (f i)) → s₁ (⋃ i, f i)
s₂ : Set α → Prop
has_empty✝ : s₂ ∅
has_compl✝ : ∀ {a : Set α}, s₂ a → s₂ aᶜ
has_iUnion_nat✝ : ∀ {f : ℕ → Set α}, Pairwise (Disjoint on f) → (∀ (i : ℕ), s₂ (f i)) → s₂ (⋃ i, f i)
h :
  ∀ (s : Set α),
    Has { Has := s₁, has_empty := has_empty✝¹, has_compl := has_compl✝¹, has_iUnion_nat := has_iUnion_nat✝¹ } s ↔
      Has { Has := s₂, has_empty := has_empty✝, has_compl := has_compl✝, has_iUnion_nat := has_iUnion_nat✝ } s
this : s₁ = s₂
⊢ { Has := s₁, has_empty := has_empty✝¹, has_compl := has_compl✝¹, has_iUnion_nat := has_iUnion_nat✝¹ } =
    { Has := s₂, has_empty := has_empty✝, has_compl := has_compl✝, has_iUnion_nat := has_iUnion_nat✝ }

Next tactic:
subst this
@[ext]
theorem ext : ∀ {d₁ d₂ : DynkinSystem α}, (∀ s : Set α, d₁.Has s ↔ d₂.Has s) → d₁ = d₂
  | ⟨s₁, _, _, _⟩, ⟨s₂, _, _, _⟩, h => by
    have : s₁ = s₂ := funext fun x => propext <| h x
    subst this
    

Proof state:
α : Type u_1
s₁ : Set α → Prop
has_empty✝¹ : s₁ ∅
has_compl✝¹ : ∀ {a : Set α}, s₁ a → s₁ aᶜ
has_iUnion_nat✝¹ : ∀ {f : ℕ → Set α}, Pairwise (Disjoint on f) → (∀ (i : ℕ), s₁ (f i)) → s₁ (⋃ i, f i)
has_empty✝ : s₁ ∅
has_compl✝ : ∀ {a : Set α}, s₁ a → s₁ aᶜ
has_iUnion_nat✝ : ∀ {f : ℕ → Set α}, Pairwise (Disjoint on f) → (∀ (i : ℕ), s₁ (f i)) → s₁ (⋃ i, f i)
h :
  ∀ (s : Set α),
    Has { Has := s₁, has_empty := has_empty✝¹, has_compl := has_compl✝¹, has_iUnion_nat := has_iUnion_nat✝¹ } s ↔
      Has { Has := s₁, has_empty := has_empty✝, has_compl := has_compl✝, has_iUnion_nat := has_iUnion_nat✝ } s
⊢ { Has := s₁, has_empty := has_empty✝¹, has_compl := has_compl✝¹, has_iUnion_nat := has_iUnion_nat✝¹ } =
    { Has := s₁, has_empty := has_empty✝, has_compl := has_compl✝, has_iUnion_nat := has_iUnion_nat✝ }

Next tactic:
rfl
theorem has_compl_iff {a} : d.Has aᶜ ↔ d.Has a :=
  ⟨fun h => by 

Proof state:
α : Type u_1
d : DynkinSystem α
a : Set α
h : Has d aᶜ
⊢ Has d a

Next tactic:
simpa using d.has_compl h
theorem has_univ : d.Has univ := by 

Proof state:
α : Type u_1
d : DynkinSystem α
⊢ Has d univ

Next tactic:
simpa using d.has_compl d.has_empty
theorem has_iUnion {β} [Countable β] {f : β → Set α} (hd : Pairwise (Disjoint on f))
    (h : ∀ i, d.Has (f i)) : d.Has (⋃ i, f i) := by
  

Proof state:
α : Type u_1
d : DynkinSystem α
β : Type u_2
inst✝ : Countable β
f : β → Set α
hd : Pairwise (Disjoint on f)
h : ∀ (i : β), Has d (f i)
⊢ Has d (⋃ i, f i)

Next tactic:
cases nonempty_encodable β
theorem has_iUnion {β} [Countable β] {f : β → Set α} (hd : Pairwise (Disjoint on f))
    (h : ∀ i, d.Has (f i)) : d.Has (⋃ i, f i) := by
  cases nonempty_encodable β
  

Proof state:
case intro
α : Type u_1
d : DynkinSystem α
β : Type u_2
inst✝ : Countable β
f : β → Set α
hd : Pairwise (Disjoint on f)
h : ∀ (i : β), Has d (f i)
val✝ : Encodable β
⊢ Has d (⋃ i, f i)

Next tactic:
rw [← Encodable.iUnion_decode₂]
theorem has_iUnion {β} [Countable β] {f : β → Set α} (hd : Pairwise (Disjoint on f))
    (h : ∀ i, d.Has (f i)) : d.Has (⋃ i, f i) := by
  cases nonempty_encodable β
  rw [← Encodable.iUnion_decode₂]
  

Proof state:
case intro
α : Type u_1
d : DynkinSystem α
β : Type u_2
inst✝ : Countable β
f : β → Set α
hd : Pairwise (Disjoint on f)
h : ∀ (i : β), Has d (f i)
val✝ : Encodable β
⊢ Has d (⋃ i, ⋃ b ∈ Encodable.decode₂ β i, f b)

Next tactic:
exact
    d.has_iUnion_nat (Encodable.iUnion_decode₂_disjoint_on hd) fun n =>
      Encodable.iUnion_decode₂_cases d.has_empty h
theorem has_union {s₁ s₂ : Set α} (h₁ : d.Has s₁) (h₂ : d.Has s₂) (h : Disjoint s₁ s₂) :
    d.Has (s₁ ∪ s₂) := by
  

Proof state:
α : Type u_1
d : DynkinSystem α
s₁ s₂ : Set α
h₁ : Has d s₁
h₂ : Has d s₂
h : Disjoint s₁ s₂
⊢ Has d (s₁ ∪ s₂)

Next tactic:
rw [union_eq_iUnion]
theorem has_union {s₁ s₂ : Set α} (h₁ : d.Has s₁) (h₂ : d.Has s₂) (h : Disjoint s₁ s₂) :
    d.Has (s₁ ∪ s₂) := by
  rw [union_eq_iUnion]
  

Proof state:
α : Type u_1
d : DynkinSystem α
s₁ s₂ : Set α
h₁ : Has d s₁
h₂ : Has d s₂
h : Disjoint s₁ s₂
⊢ Has d (⋃ b, bif b then s₁ else s₂)

Next tactic:
exact d.has_iUnion (pairwise_disjoint_on_bool.2 h) (Bool.forall_bool.2 ⟨h₂, h₁⟩)
theorem has_diff {s₁ s₂ : Set α} (h₁ : d.Has s₁) (h₂ : d.Has s₂) (h : s₂ ⊆ s₁) :
    d.Has (s₁ \ s₂) := by
  

Proof state:
α : Type u_1
d : DynkinSystem α
s₁ s₂ : Set α
h₁ : Has d s₁
h₂ : Has d s₂
h : s₂ ⊆ s₁
⊢ Has d (s₁ \ s₂)

Next tactic:
apply d.has_compl_iff.1
theorem has_diff {s₁ s₂ : Set α} (h₁ : d.Has s₁) (h₂ : d.Has s₂) (h : s₂ ⊆ s₁) :
    d.Has (s₁ \ s₂) := by
  apply d.has_compl_iff.1
  

Proof state:
α : Type u_1
d : DynkinSystem α
s₁ s₂ : Set α
h₁ : Has d s₁
h₂ : Has d s₂
h : s₂ ⊆ s₁
⊢ Has d (s₁ \ s₂)ᶜ

Next tactic:
simp only [diff_eq, compl_inter, compl_compl]
theorem has_diff {s₁ s₂ : Set α} (h₁ : d.Has s₁) (h₂ : d.Has s₂) (h : s₂ ⊆ s₁) :
    d.Has (s₁ \ s₂) := by
  apply d.has_compl_iff.1
  simp only [diff_eq, compl_inter, compl_compl]
  

Proof state:
α : Type u_1
d : DynkinSystem α
s₁ s₂ : Set α
h₁ : Has d s₁
h₂ : Has d s₂
h : s₂ ⊆ s₁
⊢ Has d (s₁ᶜ ∪ s₂)

Next tactic:
exact d.has_union (d.has_compl h₁) h₂ (disjoint_compl_left.mono_right h)
theorem generateHas_compl {C : Set (Set α)} {s : Set α} : GenerateHas C sᶜ ↔ GenerateHas C s := by
  

Proof state:
α : Type u_1
d : DynkinSystem α
C : Set (Set α)
s : Set α
⊢ GenerateHas C sᶜ ↔ GenerateHas C s

Next tactic:
refine' ⟨_, GenerateHas.compl⟩
theorem generateHas_compl {C : Set (Set α)} {s : Set α} : GenerateHas C sᶜ ↔ GenerateHas C s := by
  refine' ⟨_, GenerateHas.compl⟩
  

Proof state:
α : Type u_1
d : DynkinSystem α
C : Set (Set α)
s : Set α
⊢ GenerateHas C sᶜ → GenerateHas C s

Next tactic:
intro h
theorem generateHas_compl {C : Set (Set α)} {s : Set α} : GenerateHas C sᶜ ↔ GenerateHas C s := by
  refine' ⟨_, GenerateHas.compl⟩
  intro h
  

Proof state:
α : Type u_1
d : DynkinSystem α
C : Set (Set α)
s : Set α
h : GenerateHas C sᶜ
⊢ GenerateHas C s

Next tactic:
convert GenerateHas.compl h
theorem generateHas_compl {C : Set (Set α)} {s : Set α} : GenerateHas C sᶜ ↔ GenerateHas C s := by
  refine' ⟨_, GenerateHas.compl⟩
  intro h
  convert GenerateHas.compl h
  

Proof state:
case h.e'_3
α : Type u_1
d : DynkinSystem α
C : Set (Set α)
s : Set α
h : GenerateHas C sᶜ
⊢ s = sᶜᶜ

Next tactic:
simp
/-- If a Dynkin system is closed under binary intersection, then it forms a `σ`-algebra. -/
def toMeasurableSpace (h_inter : ∀ s₁ s₂, d.Has s₁ → d.Has s₂ → d.Has (s₁ ∩ s₂)) :
    MeasurableSpace α where
  MeasurableSet' := d.Has
  measurableSet_empty := d.has_empty
  measurableSet_compl s h := d.has_compl h
  measurableSet_iUnion f hf := by
    

Proof state:
α : Type u_1
d : DynkinSystem α
h_inter : ∀ (s₁ s₂ : Set α), Has d s₁ → Has d s₂ → Has d (s₁ ∩ s₂)
f : ℕ → Set α
hf : ∀ (i : ℕ), Has d (f i)
⊢ Has d (⋃ i, f i)

Next tactic:
rw [← iUnion_disjointed]
/-- If a Dynkin system is closed under binary intersection, then it forms a `σ`-algebra. -/
def toMeasurableSpace (h_inter : ∀ s₁ s₂, d.Has s₁ → d.Has s₂ → d.Has (s₁ ∩ s₂)) :
    MeasurableSpace α where
  MeasurableSet' := d.Has
  measurableSet_empty := d.has_empty
  measurableSet_compl s h := d.has_compl h
  measurableSet_iUnion f hf := by
    rw [← iUnion_disjointed]
    

Proof state:
α : Type u_1
d : DynkinSystem α
h_inter : ∀ (s₁ s₂ : Set α), Has d s₁ → Has d s₂ → Has d (s₁ ∩ s₂)
f : ℕ → Set α
hf : ∀ (i : ℕ), Has d (f i)
⊢ Has d (⋃ n, disjointed (fun i => f i) n)

Next tactic:
exact
      d.has_iUnion (disjoint_disjointed _) fun n =>
        disjointedRec (fun (t : Set α) i h => h_inter _ _ h <| d.has_compl <| hf i) (hf n)
/-- If `s` is in a Dynkin system `d`, we can form the new Dynkin system `{s ∩ t | t ∈ d}`. -/
def restrictOn {s : Set α} (h : d.Has s) : DynkinSystem α where
  -- Porting note: `simp only []` required for a beta reduction
  Has t := d.Has (t ∩ s)
  has_empty := by 

Proof state:
α : Type u_1
d : DynkinSystem α
s : Set α
h : Has d s
⊢ (fun t => Has d (t ∩ s)) ∅

Next tactic:
simp [d.has_empty]
/-- If `s` is in a Dynkin system `d`, we can form the new Dynkin system `{s ∩ t | t ∈ d}`. -/
def restrictOn {s : Set α} (h : d.Has s) : DynkinSystem α where
  -- Porting note: `simp only []` required for a beta reduction
  Has t := d.Has (t ∩ s)
  has_empty := by simp [d.has_empty]
  has_compl {t} hts := by
    

Proof state:
α : Type u_1
d : DynkinSystem α
s : Set α
h : Has d s
t : Set α
hts : (fun t => Has d (t ∩ s)) t
⊢ (fun t => Has d (t ∩ s)) tᶜ

Next tactic:
simp only []
/-- If `s` is in a Dynkin system `d`, we can form the new Dynkin system `{s ∩ t | t ∈ d}`. -/
def restrictOn {s : Set α} (h : d.Has s) : DynkinSystem α where
  -- Porting note: `simp only []` required for a beta reduction
  Has t := d.Has (t ∩ s)
  has_empty := by simp [d.has_empty]
  has_compl {t} hts := by
    simp only []
    

Proof state:
α : Type u_1
d : DynkinSystem α
s : Set α
h : Has d s
t : Set α
hts : (fun t => Has d (t ∩ s)) t
⊢ Has d (tᶜ ∩ s)

Next tactic:
have : tᶜ ∩ s = (t ∩ s)ᶜ \ sᶜ := Set.ext fun x => by by_cases h : x ∈ s <;> simp [h]
/-- If `s` is in a Dynkin system `d`, we can form the new Dynkin system `{s ∩ t | t ∈ d}`. -/
def restrictOn {s : Set α} (h : d.Has s) : DynkinSystem α where
  -- Porting note: `simp only []` required for a beta reduction
  Has t := d.Has (t ∩ s)
  has_empty := by simp [d.has_empty]
  has_compl {t} hts := by
    simp only []
    have : tᶜ ∩ s = (t ∩ s)ᶜ \ sᶜ := Set.ext fun x => by 

Proof state:
α : Type u_1
d : DynkinSystem α
s : Set α
h : Has d s
t : Set α
hts : (fun t => Has d (t ∩ s)) t
x : α
⊢ x ∈ tᶜ ∩ s ↔ x ∈ (t ∩ s)ᶜ \ sᶜ

Next tactic:
by_cases h : x ∈ s
/-- If `s` is in a Dynkin system `d`, we can form the new Dynkin system `{s ∩ t | t ∈ d}`. -/
def restrictOn {s : Set α} (h : d.Has s) : DynkinSystem α where
  -- Porting note: `simp only []` required for a beta reduction
  Has t := d.Has (t ∩ s)
  has_empty := by simp [d.has_empty]
  has_compl {t} hts := by
    simp only []
    have : tᶜ ∩ s = (t ∩ s)ᶜ \ sᶜ := Set.ext fun x => by by_cases h : x ∈ s <;> 

Proof state:
case pos
α : Type u_1
d : DynkinSystem α
s : Set α
h✝ : Has d s
t : Set α
hts : (fun t => Has d (t ∩ s)) t
x : α
h : x ∈ s
⊢ x ∈ tᶜ ∩ s ↔ x ∈ (t ∩ s)ᶜ \ sᶜ

Next tactic:
simp [h]
/-- If `s` is in a Dynkin system `d`, we can form the new Dynkin system `{s ∩ t | t ∈ d}`. -/
def restrictOn {s : Set α} (h : d.Has s) : DynkinSystem α where
  -- Porting note: `simp only []` required for a beta reduction
  Has t := d.Has (t ∩ s)
  has_empty := by simp [d.has_empty]
  has_compl {t} hts := by
    simp only []
    have : tᶜ ∩ s = (t ∩ s)ᶜ \ sᶜ := Set.ext fun x => by by_cases h : x ∈ s <;> 

Proof state:
case neg
α : Type u_1
d : DynkinSystem α
s : Set α
h✝ : Has d s
t : Set α
hts : (fun t => Has d (t ∩ s)) t
x : α
h : x ∉ s
⊢ x ∈ tᶜ ∩ s ↔ x ∈ (t ∩ s)ᶜ \ sᶜ

Next tactic:
simp [h]
/-- If `s` is in a Dynkin system `d`, we can form the new Dynkin system `{s ∩ t | t ∈ d}`. -/
def restrictOn {s : Set α} (h : d.Has s) : DynkinSystem α where
  -- Porting note: `simp only []` required for a beta reduction
  Has t := d.Has (t ∩ s)
  has_empty := by simp [d.has_empty]
  has_compl {t} hts := by
    simp only []
    have : tᶜ ∩ s = (t ∩ s)ᶜ \ sᶜ := Set.ext fun x => by by_cases h : x ∈ s <;> simp [h]
    

Proof state:
α : Type u_1
d : DynkinSystem α
s : Set α
h : Has d s
t : Set α
hts : (fun t => Has d (t ∩ s)) t
this : tᶜ ∩ s = (t ∩ s)ᶜ \ sᶜ
⊢ Has d (tᶜ ∩ s)

Next tactic:
rw [this]
/-- If `s` is in a Dynkin system `d`, we can form the new Dynkin system `{s ∩ t | t ∈ d}`. -/
def restrictOn {s : Set α} (h : d.Has s) : DynkinSystem α where
  -- Porting note: `simp only []` required for a beta reduction
  Has t := d.Has (t ∩ s)
  has_empty := by simp [d.has_empty]
  has_compl {t} hts := by
    simp only []
    have : tᶜ ∩ s = (t ∩ s)ᶜ \ sᶜ := Set.ext fun x => by by_cases h : x ∈ s <;> simp [h]
    rw [this]
    

Proof state:
α : Type u_1
d : DynkinSystem α
s : Set α
h : Has d s
t : Set α
hts : (fun t => Has d (t ∩ s)) t
this : tᶜ ∩ s = (t ∩ s)ᶜ \ sᶜ
⊢ Has d ((t ∩ s)ᶜ \ sᶜ)

Next tactic:
exact
      d.has_diff (d.has_compl hts) (d.has_compl h)
        (compl_subset_compl.mpr <| inter_subset_right _ _)
/-- If `s` is in a Dynkin system `d`, we can form the new Dynkin system `{s ∩ t | t ∈ d}`. -/
def restrictOn {s : Set α} (h : d.Has s) : DynkinSystem α where
  -- Porting note: `simp only []` required for a beta reduction
  Has t := d.Has (t ∩ s)
  has_empty := by simp [d.has_empty]
  has_compl {t} hts := by
    simp only []
    have : tᶜ ∩ s = (t ∩ s)ᶜ \ sᶜ := Set.ext fun x => by by_cases h : x ∈ s <;> simp [h]
    rw [this]
    exact
      d.has_diff (d.has_compl hts) (d.has_compl h)
        (compl_subset_compl.mpr <| inter_subset_right _ _)
  has_iUnion_nat {f} hd hf := by
    

Proof state:
α : Type u_1
d : DynkinSystem α
s : Set α
h : Has d s
f : ℕ → Set α
hd : Pairwise (Disjoint on f)
hf : ∀ (i : ℕ), (fun t => Has d (t ∩ s)) (f i)
⊢ (fun t => Has d (t ∩ s)) (⋃ i, f i)

Next tactic:
simp only []
/-- If `s` is in a Dynkin system `d`, we can form the new Dynkin system `{s ∩ t | t ∈ d}`. -/
def restrictOn {s : Set α} (h : d.Has s) : DynkinSystem α where
  -- Porting note: `simp only []` required for a beta reduction
  Has t := d.Has (t ∩ s)
  has_empty := by simp [d.has_empty]
  has_compl {t} hts := by
    simp only []
    have : tᶜ ∩ s = (t ∩ s)ᶜ \ sᶜ := Set.ext fun x => by by_cases h : x ∈ s <;> simp [h]
    rw [this]
    exact
      d.has_diff (d.has_compl hts) (d.has_compl h)
        (compl_subset_compl.mpr <| inter_subset_right _ _)
  has_iUnion_nat {f} hd hf := by
    simp only []
    

Proof state:
α : Type u_1
d : DynkinSystem α
s : Set α
h : Has d s
f : ℕ → Set α
hd : Pairwise (Disjoint on f)
hf : ∀ (i : ℕ), (fun t => Has d (t ∩ s)) (f i)
⊢ Has d ((⋃ i, f i) ∩ s)

Next tactic:
rw [iUnion_inter]
/-- If `s` is in a Dynkin system `d`, we can form the new Dynkin system `{s ∩ t | t ∈ d}`. -/
def restrictOn {s : Set α} (h : d.Has s) : DynkinSystem α where
  -- Porting note: `simp only []` required for a beta reduction
  Has t := d.Has (t ∩ s)
  has_empty := by simp [d.has_empty]
  has_compl {t} hts := by
    simp only []
    have : tᶜ ∩ s = (t ∩ s)ᶜ \ sᶜ := Set.ext fun x => by by_cases h : x ∈ s <;> simp [h]
    rw [this]
    exact
      d.has_diff (d.has_compl hts) (d.has_compl h)
        (compl_subset_compl.mpr <| inter_subset_right _ _)
  has_iUnion_nat {f} hd hf := by
    simp only []
    rw [iUnion_inter]
    

Proof state:
α : Type u_1
d : DynkinSystem α
s : Set α
h : Has d s
f : ℕ → Set α
hd : Pairwise (Disjoint on f)
hf : ∀ (i : ℕ), (fun t => Has d (t ∩ s)) (f i)
⊢ Has d (⋃ i, f i ∩ s)

Next tactic:
refine' d.has_iUnion_nat _ hf
/-- If `s` is in a Dynkin system `d`, we can form the new Dynkin system `{s ∩ t | t ∈ d}`. -/
def restrictOn {s : Set α} (h : d.Has s) : DynkinSystem α where
  -- Porting note: `simp only []` required for a beta reduction
  Has t := d.Has (t ∩ s)
  has_empty := by simp [d.has_empty]
  has_compl {t} hts := by
    simp only []
    have : tᶜ ∩ s = (t ∩ s)ᶜ \ sᶜ := Set.ext fun x => by by_cases h : x ∈ s <;> simp [h]
    rw [this]
    exact
      d.has_diff (d.has_compl hts) (d.has_compl h)
        (compl_subset_compl.mpr <| inter_subset_right _ _)
  has_iUnion_nat {f} hd hf := by
    simp only []
    rw [iUnion_inter]
    refine' d.has_iUnion_nat _ hf
    

Proof state:
α : Type u_1
d : DynkinSystem α
s : Set α
h : Has d s
f : ℕ → Set α
hd : Pairwise (Disjoint on f)
hf : ∀ (i : ℕ), (fun t => Has d (t ∩ s)) (f i)
⊢ Pairwise (Disjoint on fun i => f i ∩ s)

Next tactic:
exact hd.mono fun i j => Disjoint.mono (inter_subset_left _ _) (inter_subset_left _ _)
theorem generate_inter {s : Set (Set α)} (hs : IsPiSystem s) {t₁ t₂ : Set α}
    (ht₁ : (generate s).Has t₁) (ht₂ : (generate s).Has t₂) : (generate s).Has (t₁ ∩ t₂) :=
  have : generate s ≤ (generate s).restrictOn ht₂ :=
    generate_le _ fun s₁ hs₁ =>
      have : (generate s).Has s₁ := GenerateHas.basic s₁ hs₁
      have : generate s ≤ (generate s).restrictOn this :=
        generate_le _ fun s₂ hs₂ =>
          show (generate s).Has (s₂ ∩ s₁) from
            (s₂ ∩ s₁).eq_empty_or_nonempty.elim (fun h => h.symm ▸ GenerateHas.empty) fun h =>
              GenerateHas.basic _ <| hs _ hs₂ _ hs₁ h
      have : (generate s).Has (t₂ ∩ s₁) := this _ ht₂
      show (generate s).Has (s₁ ∩ t₂) by 

Proof state:
α : Type u_1
d : DynkinSystem α
s : Set (Set α)
hs : IsPiSystem s
t₁ t₂ : Set α
ht₁ : Has (generate s) t₁
ht₂ : Has (generate s) t₂
s₁ : Set α
hs₁ : s₁ ∈ s
this✝¹ : Has (generate s) s₁
this✝ : generate s ≤ restrictOn (generate s) this✝¹
this : Has (generate s) (t₂ ∩ s₁)
⊢ Has (generate s) (s₁ ∩ t₂)

Next tactic:
rwa [inter_comm]
/-- **Dynkin's π-λ theorem**:
  Given a collection of sets closed under binary intersections, then the Dynkin system it
  generates is equal to the σ-algebra it generates.
  This result is known as the π-λ theorem.
  A collection of sets closed under binary intersection is called a π-system (often requiring
  additionally that it is non-empty, but we drop this condition in the formalization).
-/
theorem generateFrom_eq {s : Set (Set α)} (hs : IsPiSystem s) :
    generateFrom s = (generate s).toMeasurableSpace fun t₁ t₂ => generate_inter hs :=
  le_antisymm (generateFrom_le fun t ht => GenerateHas.basic t ht)
    (ofMeasurableSpace_le_ofMeasurableSpace_iff.mp <| by
      

Proof state:
α : Type u_1
d : DynkinSystem α
s : Set (Set α)
hs : IsPiSystem s
⊢ ofMeasurableSpace
      (toMeasurableSpace (generate s)
        (_ : ∀ (t₁ t₂ : Set α), Has (generate s) t₁ → Has (generate s) t₂ → Has (generate s) (t₁ ∩ t₂))) ≤
    ofMeasurableSpace (generateFrom s)

Next tactic:
rw [ofMeasurableSpace_toMeasurableSpace]
/-- **Dynkin's π-λ theorem**:
  Given a collection of sets closed under binary intersections, then the Dynkin system it
  generates is equal to the σ-algebra it generates.
  This result is known as the π-λ theorem.
  A collection of sets closed under binary intersection is called a π-system (often requiring
  additionally that it is non-empty, but we drop this condition in the formalization).
-/
theorem generateFrom_eq {s : Set (Set α)} (hs : IsPiSystem s) :
    generateFrom s = (generate s).toMeasurableSpace fun t₁ t₂ => generate_inter hs :=
  le_antisymm (generateFrom_le fun t ht => GenerateHas.basic t ht)
    (ofMeasurableSpace_le_ofMeasurableSpace_iff.mp <| by
      rw [ofMeasurableSpace_toMeasurableSpace]
      

Proof state:
α : Type u_1
d : DynkinSystem α
s : Set (Set α)
hs : IsPiSystem s
⊢ generate s ≤ ofMeasurableSpace (generateFrom s)

Next tactic:
exact generate_le _ fun t ht => measurableSet_generateFrom ht