Zulip Chat Archive

Stream: mathlib4

Topic: Ionescu-Tulcea partialTraj restrictions


Gaëtan Serré (Aug 14 2025 at 09:03):

I'm trying to show that, if I have two families of Markov kernels that are equals on a pi set, then the restrictions of partialTraj to this set should be equals too. For now I have this:

import Mathlib

open MeasureTheory ProbabilityTheory Set

namespace MeasureTheory.Measure

variable {ι : Type*} [Fintype ι] {α : ι  Type*} [ i, MeasurableSpace (α i)]
  {μ ν : Measure ( i, α i)} [IsFiniteMeasure μ]

/-- Two measures on a finite product space are equal if they agree on all measurable rectangles
of the form `univ.pi s`, provided one of them is finite. -/
lemma pi_space_eq
    (h :  s :  i, Set (α i), ( i, MeasurableSet (s i))  μ (univ.pi s) = ν (univ.pi s)) :
    μ = ν := by
  refine Measure.FiniteSpanningSetsIn.ext
    generateFrom_pi.symm (IsPiSystem.pi (fun _ => MeasurableSpace.isPiSystem_measurableSet)) ?_ ?_
  · refine { set := fun _ => univ, set_mem := ?_, finite := ?_, spanning := ?_ }
    · intro i
      use (fun _ => univ)
      refine ⟨?_, Set.pi_univ univ
      exact mem_univ_pi.mpr (fun _ => MeasurableSet.univ)
    · exact fun _ => measure_lt_top _ _
    · exact iUnion_const univ
  · rintro _ s, hs, rfl
    rw [mem_univ_pi] at hs
    exact h s hs

end MeasureTheory.Measure

variable {α : Type*} [MeasurableSpace α]
  (κ₁ κ₂ : (n : )  Kernel (Π _ : Finset.Iic n, α) α)
  [ n, IsMarkovKernel (κ₁ n)] [ n, IsMarkovKernel (κ₂ n)]
  {s : Set α} (hs : MeasurableSet s)
  (h :  n, (univ.pi (fun _ => s)).EqOn (fun a => κ₁ n a) (fun a => κ₂ n a))

example {a b : } (hab : a  b) :  e  univ.pi (fun _ => s),
    (Kernel.partialTraj (X := fun _ => α) κ₁ a b e).restrict (univ.pi (fun _ => s)) =
    (Kernel.partialTraj (X := fun _ => α) κ₂ a b e).restrict (univ.pi (fun _ => s)) := by
  intro e e_mem
  refine Measure.pi_space_eq ?_
  intro B B_m
  let C := fun i => (B i)  s
  induction b, hab using Nat.le_induction with
    | base => simp
    | succ k h hk =>
      simp only [Kernel.partialTraj_succ_eq_comp h, Kernel.partialTraj_succ_self]
      sorry

(don't mind Measure.pi_space_eq, it probably already exists somewhere in Mathlib).

Like you can see, my first thought was to trying to prove it by induction but I'm getting stuck very quickly. I feel that it might be possible to prove this exact statement by continuing in this direction but I'm afraid it will become very difficult to unfold all these definitions.

I was wondering if there is a way to either change the statement or use another proof strategy (most likely both) to make the proof easier.

Etienne Marion (Aug 14 2025 at 09:25):

I am not at the computer right now but I can have a look later

Gaëtan Serré (Aug 14 2025 at 09:27):

Etienne Marion said:

I am not at the computer right now but I can have a look later

Sure, thanks a lot! Also thank you for work in formalizing this theorem

Etienne Marion (Aug 14 2025 at 19:23):

Ok, I managed to prove that the partialTraj associated to a family of restricted kernels is the restriction of the partialTraj, it should get you to your result easily. The only sorrys are measurability goals which shouldn't be an issue. I did not take the time to clean the proof up so it is quite messy, there are certainly many parts which can be factored out as separate lemmas to avoid all those measurability goals.

import Mathlib

open MeasureTheory ProbabilityTheory Finset Kernel

variable {X :   Type*} {mX :  n, MeasurableSpace (X n)} {a b : } {κ : (n : )  Kernel (Π i : Iic n, X i) (X (n + 1))}

example {s : Π n, Set (X n)} [ n, IsSFiniteKernel (κ n)] (hs :  n, MeasurableSet (s n)) (hab : a  b) {x : Π i : Iic a, X i}
    (hx : x  Set.univ.pi (fun i : Iic a  s i)) :
    partialTraj (fun n  (κ n).restrict (hs (n + 1))) a b x =
    (partialTraj κ a b x).restrict (Set.univ.pi (fun i  s i)) := by
  induction b, hab using Nat.le_induction with
  | base =>
    simp only [partialTraj_self, id_apply]
    classical
    rw [restrict_dirac', if_pos hx]
    sorry
  | succ b hab hb =>
    ext t ht
    rw [partialTraj_succ_eq_comp hab, Kernel.comp_apply' _ _ _ ht, hb, Measure.restrict_apply ht,
      partialTraj_succ_eq_comp hab, Kernel.comp_apply',
       lintegral_add_compl (μ := partialTraj κ a b x) _ (.univ_pi fun i  hs i),
       add_zero (∫⁻ _, _ ∂_)]
    · congrm ?_ + ?_
      · refine setLIntegral_congr_fun (.univ_pi fun i  hs i) fun y hy  ?_
        simp_rw [partialTraj_succ_self]
        rw [Kernel.map_apply', Kernel.id_prod_apply', Kernel.map_apply', Kernel.restrict_apply',
          Kernel.map_apply', Kernel.id_prod_apply', Kernel.map_apply']
        · congr
          ext z
          change _ 
            IicProdIoc b (b + 1) (y, MeasurableEquiv.piSingleton b z)  Set.univ.pi (fun _  s _)
          simp [IicProdIoc, MeasurableEquiv.piSingleton]
          constructor
          · intro h i hi
            split_ifs with h'
            · simp only [Set.mem_pi, Set.mem_univ, forall_const, Subtype.forall, mem_Iic] at hy
              exact hy i h'
            obtain rfl : i = b + 1 := by omega
            exact h
          · intro h
            convert h (b + 1) le_rfl
            simp
        any_goals fun_prop
        all_goals sorry
      · symm
        apply setLIntegral_eq_zero
        · exact .compl (.univ_pi fun _  hs _)
        intro y hy
        simp only [Pi.zero_apply]
        rw [partialTraj_succ_self, Kernel.map_apply', Kernel.id_prod_apply', Kernel.map_apply']
        · convert measure_empty
          · ext z
            simp only [MeasurableEquiv.piSingleton, MeasurableEquiv.coe_mk, Equiv.coe_fn_mk,
              Set.preimage_inter, Set.mem_inter_iff, Set.mem_preimage, Set.mem_pi, Set.mem_univ,
              IicProdIoc, forall_const, Subtype.forall, mem_Iic, Set.mem_empty_iff_false, iff_false,
              not_and, not_forall]
            intro h1
            simp only [Set.mem_compl_iff, Set.mem_pi, Set.mem_univ, forall_const, Subtype.forall,
              mem_Iic, not_forall] at hy
            obtain i, hi1, hi2 := hy
            refine i, by omega, ?_⟩
            simpa [hi1]
          infer_instance
        all_goals sorry
    · exact ht.inter (.univ_pi fun _  hs _)

Etienne Marion (Aug 14 2025 at 19:32):

I think the path you take was the right one, but it requires a bit of API about restriction to make the proof nice. Some of this API unfortunately requires some nasty unfolding, but I hope that we can identify a small set of lemmas which once proved will avoid unfolding in other proofs.

Gaëtan Serré (Aug 14 2025 at 19:32):

Wow thanks a lot! I did not expect you to prove this entirely :sweat_smile:! I'll prove the remaining sorries and, if I can, factor out some intermediate lemmas. I'm currently writing a paper about formalization of a theorem on meta global optimization algorithms and I wanted to use the Ionescu-Tulcea theorem to construct a measure on infinite sequence of iterations. I'll make sure to cite your paper as well as this discussion.

Etienne Marion (Aug 14 2025 at 19:36):

I'm glad I could help! It's really nice to see this part of the library being used :grinning_face_with_smiling_eyes:

Gaëtan Serré (Aug 14 2025 at 19:36):

Etienne Marion said:

I think the path you take was the right one, but it requires a bit of API about restriction to make the proof nice. Some of this API unfortunately requires some nasty unfolding, but I hope that we can identify a small set of lemmas which once proved will avoid unfolding in other proofs.

Ok that's reassuring. Indeed, I felt like it was very hard to "propagate" the restriction through the definition of partialTraj. Even getting access to the family of kernels that construct partialTraj was not trivial, but it might not be possible to make it easier.

Gaëtan Serré (Aug 14 2025 at 21:07):

I proved the sorries (I had to use a utility lemma to simplify the proofs on measurability. For some reasons, I did not found it in Mathlib) and I proved my original statement by induction.

import Mathlib

open MeasureTheory ProbabilityTheory Finset Kernel

namespace ProbabilityTheory

lemma measurableSet_apply {α β : Type*} [MeasurableSpace α] [MeasurableSpace β] {f : α  β}
    (hf : Measurable f) {s : Set β} (hs : MeasurableSet s) : MeasurableSet (f ⁻¹' s) := hf hs

variable {X :   Type*} [ n, MeasurableSpace (X n)] {a b : }
{κ : (n : )  Kernel (Π i : Iic n, X i) (X (n + 1))}

/- https://leanprover.zulipchat.com/#narrow/channel/287929-mathlib4/topic/Ionescu-Tulcea.20partialTraj.20restrictions -/

lemma Kernel.partialTraj_restrict {s : Π n, Set (X n)} [ n, IsSFiniteKernel (κ n)]
    (hs :  n, MeasurableSet (s n)) (hab : a  b) {x : Π i : Iic a, X i}
    (hx : x  Set.univ.pi (fun i : Iic a  s i)) :
    partialTraj (fun n  (κ n).restrict (hs (n + 1))) a b x =
    (partialTraj κ a b x).restrict (Set.univ.pi (fun i  s i)) := by
  induction b, hab using Nat.le_induction with
  | base =>
    simp only [partialTraj_self, id_apply]
    classical
    rw [restrict_dirac', if_pos hx]
    exact MeasurableSet.univ_pi fun i  hs i
  | succ b hab hb =>
    ext t ht
    rw [partialTraj_succ_eq_comp hab, Kernel.comp_apply' _ _ _ ht, hb, Measure.restrict_apply ht,
      partialTraj_succ_eq_comp hab, Kernel.comp_apply',
       lintegral_add_compl (μ := partialTraj κ a b x) _ (.univ_pi fun i  hs i),
       add_zero (∫⁻ _, _ ∂_)]
    · have m_inter_t_pi := (ht.inter (MeasurableSet.univ_pi fun i  hs i))
      congrm ?_ + ?_
      · refine setLIntegral_congr_fun (.univ_pi fun i  hs i) fun y hy  ?_
        simp_rw [partialTraj_succ_self]
        rw [Kernel.map_apply', Kernel.id_prod_apply', Kernel.map_apply', Kernel.restrict_apply',
          Kernel.map_apply', Kernel.id_prod_apply', Kernel.map_apply']
        · congr
          ext z
          change _ 
            IicProdIoc b (b + 1) (y, MeasurableEquiv.piSingleton b z)  Set.univ.pi (fun _  s _)
          simp only [MeasurableEquiv.piSingleton, MeasurableEquiv.coe_mk, Equiv.coe_fn_mk,
            Set.mem_pi, Set.mem_univ, IicProdIoc, forall_const, Subtype.forall, mem_Iic]
          constructor
          · intro h i hi
            split_ifs with h'
            · simp only [Set.mem_pi, Set.mem_univ, forall_const, Subtype.forall, mem_Iic] at hy
              exact hy i h'
            obtain rfl : i = b + 1 := by omega
            exact h
          · intro h
            convert h (b + 1) le_rfl
            simp
        any_goals fun_prop
        · exact measurableSet_apply (by fun_prop) <| measurableSet_apply (by fun_prop) m_inter_t_pi
        · exact measurableSet_apply (by fun_prop) m_inter_t_pi
        · exact m_inter_t_pi
        · refine (MeasurableEquiv.piSingleton b).measurableSet_preimage.mpr ?_
          exact measurableSet_apply (by fun_prop) <| measurableSet_apply (by fun_prop) ht
        · exact measurableSet_apply (by fun_prop) <| measurableSet_apply (by fun_prop) ht
        · exact measurableSet_apply (by fun_prop) ht
        · exact ht
      · symm
        apply setLIntegral_eq_zero
        · exact .compl (.univ_pi fun _  hs _)
        intro y hy
        simp only [Pi.zero_apply]
        rw [partialTraj_succ_self, Kernel.map_apply', Kernel.id_prod_apply', Kernel.map_apply']
        · convert measure_empty
          · ext z
            simp only [MeasurableEquiv.piSingleton, MeasurableEquiv.coe_mk, Equiv.coe_fn_mk,
              Set.preimage_inter, Set.mem_inter_iff, Set.mem_preimage, Set.mem_pi, Set.mem_univ,
              IicProdIoc, forall_const, Subtype.forall, mem_Iic, Set.mem_empty_iff_false, iff_false,
              not_and, not_forall]
            intro h1
            simp only [Set.mem_compl_iff, Set.mem_pi, Set.mem_univ, forall_const, Subtype.forall,
              mem_Iic, not_forall] at hy
            obtain i, hi1, hi2 := hy
            refine i, by omega, ?_⟩
            simpa [hi1]
          infer_instance
        · exact (MeasurableEquiv.piSingleton b).measurable
        · suffices Measurable (IicProdIoc b (b + 1)  (Prod.mk y)) from
            this m_inter_t_pi
          fun_prop
        · suffices Measurable (IicProdIoc b (b + 1)) from
            this m_inter_t_pi
          fun_prop
        · fun_prop
        · exact m_inter_t_pi
    · exact ht.inter (.univ_pi fun _  hs _)

end ProbabilityTheory

open Set

variable {α : Type*} [MeasurableSpace α]
  (κ₁ κ₂ : (n : )  Kernel (Π _ : Finset.Iic n, α) α)
  [ n, IsMarkovKernel (κ₁ n)] [ n, IsMarkovKernel (κ₂ n)]
  {s : Set α} (hs : MeasurableSet s)
  (h :  n, (univ.pi (fun _ => s)).EqOn (fun a => κ₁ n a) (fun a => κ₂ n a))

example {a b : } (hab : a  b) :  e  univ.pi (fun _ => s),
    (Kernel.partialTraj (X := fun _ => α) κ₁ a b e).restrict (univ.pi (fun _ => s)) =
    (Kernel.partialTraj (X := fun _ => α) κ₂ a b e).restrict (univ.pi (fun _ => s)) := by

  intro e he
  rw [ Kernel.partialTraj_restrict (fun _ => hs) hab he,
     Kernel.partialTraj_restrict (fun _ => hs) hab he]
  induction b, hab using Nat.le_induction with
  | base => simp
  | succ b hab hb =>
    simp only [Kernel.partialTraj_succ_eq_comp hab, comp_apply]
    rw [hb]
    ext t ht
    rw [Measure.bind_apply ht (Kernel.aemeasurable _),
      Measure.bind_apply ht (Kernel.aemeasurable _),
      Kernel.partialTraj_restrict (fun _ => hs) hab he]
    suffices (univ.pi (fun _ => s)).EqOn
        (fun a => partialTraj (X := fun _ => α) (fun n  (κ₁ n).restrict hs) b (b + 1) a t)
        (fun a => partialTraj (X := fun _ => α) (fun n  (κ₂ n).restrict hs) b (b + 1) a t) by
      rw [setLIntegral_congr_fun (MeasurableSet.univ_pi fun i  hs) this]
    intro a a_mem
    simp only [partialTraj_succ_self]
    rw [Kernel.map_apply' _ (by exact measurable_IicProdIoc),
      Kernel.map_apply' _ (by exact measurable_IicProdIoc),
      Kernel.id_prod_apply', Kernel.id_prod_apply',
      Kernel.map_apply', Kernel.map_apply',
      Kernel.restrict_apply', Kernel.restrict_apply']
    simp_rw [h b a_mem]
    any_goals fun_prop
    any_goals exact measurableSet_apply (by fun_prop) <| measurableSet_apply (by fun_prop)
      <| measurableSet_apply (measurable_IicProdIoc) ht
    · exact measurableSet_apply (by fun_prop) <| measurableSet_apply (measurable_IicProdIoc) ht
    · exact measurableSet_apply (by fun_prop) <| measurableSet_apply (measurable_IicProdIoc) ht
    any_goals exact measurableSet_apply (measurable_IicProdIoc) ht
    any_goals exact ht

The proofs are messy but they work! Thanks a lot again!

Etienne Marion (Aug 14 2025 at 21:19):

You're welcome! The lemma you added is MeasurableSet.preimage.


Last updated: Dec 20 2025 at 21:32 UTC