Theory HOL-Analysis.Rectifiable_Path

theory Rectifiable_Path
  imports Bounded_Variation Path_Connected Equivalence_Lebesgue_Henstock_Integration
begin


section ‹Rectifiable paths and arc-length reparametrization›

definition rectifiable_path :: (real  'a::euclidean_space)  bool where
  rectifiable_path g  path g  has_bounded_variation_on g {0..1}

definition path_length :: (real  'a::euclidean_space)  real where
  path_length g = vector_variation {0..1} g

text ‹
  We can factor a BV function through its variation.  Moreover the factor is
  Lipschitz (hence continuous) on its domain, though without continuity of the
  original function that domain may not be an interval.
›

lemma factor_through_variation:
  fixes f :: real  'a::euclidean_space
  assumes has_bounded_variation_on f {a..b}
  shows g. (x  {a..b}. f x = g (vector_variation {a..x} f)) 
             continuous_on ((λx. vector_variation {a..x} f) ` {a..b}) g 
             (u  (λx. vector_variation {a..x} f) ` {a..b}.
              v  (λx. vector_variation {a..x} f) ` {a..b}.
                dist (g u) (g v)  dist u v)
proof -
  define S where S  (λx. vector_variation {a..x} f) ` {a..b}
  have claim1: g. (x  {a..b}. f x = g (vector_variation {a..x} f)) 
                    (u  S. v  S. dist (g u) (g v)  dist u v)
  proof (cases {a..b} = {})
    case True
    then show ?thesis unfolding S_def by auto
  next
    case False
    then have ab: a  b by auto
    define V where V x  vector_variation {a..x} f for x
    ― ‹Key injectivity-up-to-@{term f} property: @{term V x = V y} implies @{term f x = f y}
    have f_eq: f x = f y
      if x  {a..b} y  {a..b} V x = V y for x y
    proof -
      ― ‹Core argument: if @{term p  q} with matching variation, then @{term f p = f q}
      have core: f p = f q
        if p  q p  {a..b} q  {a..b} V p = V q for p q
      proof -
        have bv_aq: has_bounded_variation_on f {a..q}
          using has_bounded_variation_on_subset[OF assms] that ab by auto
        have p_in: p  {a..q} using that by auto
        have vv0: vector_variation {p..q} f = 0
          by (metis V_def add.right_neutral add_left_cancel bv_aq
              V p = V q vector_variation_combine p_in)
        have bv_pq: has_bounded_variation_on f {p..q}
          using has_bounded_variation_on_subset[OF assms] that by auto
        from vector_variation_const_eq[OF bv_pq is_interval_cc] vv0
        show f p = f q using that by force
      qed
      show f x = f y
        using core[of x y] core[of y x] that by argo
    qed
    ― ‹Construct the factor @{term g} via Hilbert choice›
    define g where g v  f (SOME x. x  {a..b}  V x = v) for v
    have g_factor: f x = g (V x) if x  {a..b} for x
      unfolding g_def
      by (metis (mono_tags, lifting) f_eq someI that)
    ― ‹Lipschitz property›
    have g_lip: dist (g u) (g v)  dist u v
      if u  S v  S for u v
    proof -
      from that obtain x y where
        x: x  {a..b} u = V x and y: y  {a..b} v = V y
        unfolding S_def V_def by auto
      ― ‹WLOG @{term x  y}
      have lip: dist (g (V x)) (g (V y))  dist (V x) (V y)
        if xy: x  y x  {a..b} y  {a..b} for x y
      proof -
        have bv_ay: has_bounded_variation_on f {a..y}
          using has_bounded_variation_on_subset[OF assms] xy(2,3) ab by auto
        have x_in: x  {a..y} using xy by auto
        from vector_variation_combine[OF bv_ay x_in]
        have V_split: V y = V x + vector_variation {x..y} f
          unfolding V_def .
        have bv_xy: has_bounded_variation_on f {x..y}
          using has_bounded_variation_on_subset[OF assms] xy(1,2,3) by auto
        have Vx_le_Vy: V x  V y
          using V_split vector_variation_pos_le[OF bv_xy] by linarith
        have dist (g (V x)) (g (V y)) = dist (f x) (f y)
          using g_factor xy(2,3) by simp
        also have  = norm (f x - f y) by (simp add: dist_norm)
        also have   vector_variation {x..y} f
          using vector_variation_ge_norm_function[OF bv_xy] xy(1) by auto
        also have  = V y - V x using V_split by simp
        also have  = dist (V x) (V y) using Vx_le_Vy by (simp add: dist_real_def)
        finally show ?thesis .
      qed
      show ?thesis
      proof (cases x  y)
        case True then show ?thesis using lip x y by auto
      next
        case nle: False
        then have y  x by auto
        then have dist (g (V y)) (g (V x))  dist (V y) (V x)
          using lip y(1) x(1) by auto
        then show ?thesis using x y by (simp add: dist_commute)
      qed
    qed
    show ?thesis
      using g_factor g_lip unfolding V_def by auto
  qed
  moreover
  have continuous_on S g if u  S. v  S. dist (g u) (g v)  dist u v for g :: "real'a"
    using continuous_on_iff order_le_less_trans that by blast
  ultimately show ?thesis
    using S_def by blast
qed

lemma factor_continuous_through_variation:
  fixes f :: real  'a::euclidean_space
  assumes a  b
    and continuous_on {a..b} f
    and has_bounded_variation_on f {a..b}
  defines l  vector_variation {a..b} f
  obtains g where x  {a..b}. f x = g (vector_variation {a..x} f)
    and continuous_on {0..l} g
    and u  {0..l}. v  {0..l}. dist (g u) (g v)  dist u v
    and has_bounded_variation_on g {0..l}
    and (λx. vector_variation {a..x} f) ` {a..b} = {0..l}
    and g ` {0..l} = f ` {a..b}
    and x  {0..l}. vector_variation {0..x} g = x
proof -
  define S where S  (λx. vector_variation {a..x} f) ` {a..b}
  obtain g where g_factor: x  {a..b}. f x = g (vector_variation {a..x} f)
    and g_cont: continuous_on S g
    and g_lip: u  S. v  S. dist (g u) (g v)  dist u v
    using factor_through_variation[OF assms(3)] unfolding S_def by blast
  define V where V  λx. vector_variation {a..x} f
  have V_a: V a = 0
    unfolding V_def using vector_variation_on_null[of a a f] by simp
  have V_b: V b = l
    unfolding V_def l_def by simp
  have V_mono: V x  V y if x  {a..b} y  {a..b} x  y for x y
  proof -
    have bv_ay: has_bounded_variation_on f {a..y}
      using has_bounded_variation_on_subset[OF assms(3)] that by auto
    have V y = V x + vector_variation {x..y} f
      unfolding V_def using vector_variation_combine[OF bv_ay] that by auto
    moreover have vector_variation {x..y} f  0
      by (rule vector_variation_pos_le[OF has_bounded_variation_on_subset[OF assms(3)]])
         (use that in auto)
    ultimately show ?thesis by linarith
  qed
  have V_cont: continuous_on {a..b} V
    unfolding V_def continuous_on_eq_continuous_within
    using vector_variation_continuous[OF assms(3)] assms(2)[unfolded continuous_on_eq_continuous_within]
    by simp
  have S_eq: S = {0..l}
  proof (rule antisym)
    show S  {0..l}
      using V_a V_b V_mono a  b unfolding S_def V_def by force
    show {0..l}  S
    proof -
      have connected S
        unfolding S_def V_def[symmetric]
        using connected_continuous_image[OF V_cont] by auto
      moreover have 0  S using V_a a  b unfolding S_def V_def by force
      moreover have l  S using V_b a  b unfolding S_def V_def by force
      ultimately show ?thesis using connected_contains_Icc by blast
    qed
  qed
  show thesis
  proof
    show g_bv: has_bounded_variation_on g {0..l}
      using Lipschitz_imp_has_bounded_variation[where B=1]
      by (metis S_eq bounded_closed_interval dist_norm g_lip mult_1)
    show g ` {0..l} = f ` {a..b}
        using S_def S_eq g_factor by auto
    have vector_variation {0..x} g = x if x  {0..l} for x
    proof (rule antisym)
      ― ‹Upper bound: 1-Lipschitz implies variation is at most length of interval›
      show vector_variation {0..x} g  x
      proof (rule has_bounded_variation_works(2)[OF has_bounded_variation_on_subset[OF g_bv]])
        show {0..x}  {0..l} using that by auto
      next
        fix d t assume dt: d division_of t t  {0..x}
        have (kd. norm (g (Sup k) - g (Inf k)))  (kd. content k)
        proof (rule sum_mono)
          fix k assume kd: k  d
          obtain lk uk where k_eq: k = {lk..uk} and lk_le: lk  uk
            by (metis atLeastatMost_empty_iff2 box_real(2) division_ofD(3,4) dt(1) kd)
          have k_sub: k  {0..x} using division_ofD(2)[OF dt(1) kd] dt(2) by auto
          then have lk_in: lk  {0..l} and uk_in: uk  {0..l}
            using k_eq lk_le that by auto
          have norm (g (Sup k) - g (Inf k)) = norm (g uk - g lk)
            using lk_le k_eq by (simp add: cbox_interval)
          also have   dist (g uk) (g lk) by (simp add: dist_norm)
          also have   dist uk lk
            using g_lip lk_in uk_in S_eq by auto
          also have  = uk - lk using lk_le by (simp add: dist_real_def)
          also have  = content k using lk_le k_eq by (simp add: cbox_interval)
          finally show norm (g (Sup k) - g (Inf k))  content k .
        qed
        also have (kd. content k)  content (cbox 0 x)
          using subadditive_content_division[OF dt(1)] dt(2)
          by (simp add: cbox_interval)
        also have  = x using that by (simp add: cbox_interval)
        finally show (kd. norm (g (Sup k) - g (Inf k)))  x .
      qed
    next
      ― ‹Lower bound: variation of @{term g} on @{term {0..x}} at least  @{term x} 
           via factoring through @{term f}
      show x  vector_variation {0..x} g
      proof -
        have x_in_S: x  S using that S_eq by auto
        then obtain t where t_in: t  {a..b} and Vt: V t = x
          unfolding S_def V_def by auto
        have bv_at: has_bounded_variation_on f {a..t}
          using has_bounded_variation_on_subset[OF assms(3)] t_in by auto
        have mono_V_at: mono_on {a..t} V
          unfolding mono_on_def using V_mono t_in by auto
        have g_bv_0x: has_bounded_variation_on g {V a..V t}
          using has_bounded_variation_on_subset[OF g_bv] V_a Vt that by auto
            ― ‹@{term g  V} agrees with @{term f} on @{term {a..t}}
        have gV_eq_f: g (V u) = f u if u  {a..t} for u
          using g_factor t_in that V_def by auto
            ― ‹Therefore their variations on @{term {a..t}} are equal›
        have var_eq: vector_variation {a..t} (g  V) = vector_variation {a..t} f
        proof -
          have eq: norm ((g  V) (Sup k) - (g  V) (Inf k)) = norm (f (Sup k) - f (Inf k))
            if div: d division_of s s  {a..t} and kd: k  d for d s k
          proof -
            obtain lk uk where k = cbox lk uk k  {} and lu: lk  uk
              using division_ofD(3,4)[OF div(1) kd] by auto
            then have k_eq: k = {lk..uk} and Inf_k: Inf k = lk and Sup_k: Sup k = uk
              using k = cbox lk uk by (auto simp: cbox_interval)
            have k  {a..t}
              using division_ofD(2)[OF div(1) kd] div(2) by auto
            then have Inf k  {a..t} Sup k  {a..t} using lu Inf_k Sup_k k_eq by auto
            then show ?thesis using gV_eq_f by (simp add: comp_def)
          qed
          have sum_eq: (kd. norm ((g  V) (Sup k) - (g  V) (Inf k))) =
              (kd. norm (f (Sup k) - f (Inf k)))
            if d division_of s s  {a..t} for d s
            by (intro sum.cong refl eq[OF that])
          have {kd. norm ((g  V) (Sup k) - (g  V) (Inf k)) |d. s. d division_of s  s  {a..t}}
              = {kd. norm (f (Sup k) - f (Inf k)) |d. s. d division_of s  s  {a..t}}
            (is ?L = ?R)
          proof (rule antisym; rule subsetI)
            fix v assume v  ?L
            then obtain d s where ds: d division_of s s  {a..t}
              and v = (kd. norm ((g  V) (Sup k) - (g  V) (Inf k))) by auto
            then have v = (kd. norm (f (Sup k) - f (Inf k)))
              using sum_eq[OF ds] by simp
            then show v  ?R using ds by blast
          next
            fix v assume v  ?R
            then obtain d s where ds: d division_of s s  {a..t}
              and v = (kd. norm (f (Sup k) - f (Inf k))) by auto
            then have v = (kd. norm ((g  V) (Sup k) - (g  V) (Inf k)))
              using sum_eq[OF ds] by simp
            then show v  ?L using ds by blast
          qed
          then show ?thesis
            unfolding vector_variation_def set_variation_def comp_def by auto
        qed
          ― ‹Composition lemma: variation of @{term g  V} on 
               @{term {a..t}} is at most variation of @{term g} on @{term {V a..V t}}
        have vector_variation {a..t} (g  V)  vector_variation {V a..V t} g
          using has_bounded_variation_compose_monotone(2)[OF g_bv_0x mono_V_at] .
        then have vector_variation {a..t} f  vector_variation {0..x} g
          using var_eq V_a Vt by simp
        moreover have x = vector_variation {a..t} f
          using Vt[symmetric] by (simp add: V_def)
        ultimately show ?thesis by linarith
      qed
    qed
    then show x{0..l}. vector_variation {0..x} g = x
      by blast
  qed (use S_def S_eq g_cont g_factor g_lip  in auto)+
qed

text ‹Arc-length reparametrization and existence of shortest paths.›

lemma arc_length_reparametrization:
  fixes g :: real  'a::euclidean_space
  assumes rectifiable_path g
  obtains h where
    rectifiable_path h
    path_image h = path_image g
    pathstart h = pathstart g
    pathfinish h = pathfinish g
    path_length h = path_length g
    arc g  arc h
    simple_path g  simple_path h
    t  {0..1}. path_length (subpath 0 t h) = path_length g * t
    x  {0..1}. y  {0..1}.
        dist (h x) (h y)  path_length g * dist x y
proof -
  define l where l  path_length g
  from assms have g_path: path g and g_bv: has_bounded_variation_on g {0..1}
    unfolding rectifiable_path_def by auto
  then have g_cont: continuous_on {0..1} g
    by (simp add: path_def pathin_def continuous_map_iff_continuous)
  have l_eq: l = vector_variation {0..1} g
    unfolding l_def path_length_def by simp
  obtain h where
    h_factor: x  {0..1}. g x = h (vector_variation {0..x} g)
    and h_cont: continuous_on {0..l} h
    and h_lip: u  {0..l}. v  {0..l}. dist (h u) (h v)  dist u v
    and h_bv: has_bounded_variation_on h {0..l}
    and h_image_var: (λx. vector_variation {0..x} g) ` {0..1} = {0..l}
    and h_image: h ` {0..l} = g ` {0..1}
    and h_var: x  {0..l}. vector_variation {0..x} h = x
    using factor_continuous_through_variation[of 0 1 g, folded l_eq]
    using g_cont g_bv by auto
  have l_nonneg: 0  l
    using vector_variation_pos_le[OF g_bv] l_eq by simp
  have scale_image: (λx. x *R l) ` {0..1} = {0..l}
    using l_nonneg image_mult_atLeastAtMost_if'[of l 0 1] by auto
  have scale_mono: mono_on {0..1} (λx. x *R l)
    using l_nonneg by (intro mono_onI) (simp add: mult_right_mono)
  have h_0: h 0 = g 0
    using h_factor[rule_format, of 0] vector_variation_on_null[of 0 0 g]
    by simp
  have h_l: h l = g 1
    using h_factor[rule_format, of 1] l_eq by simp
  show ?thesis
  proof
    show rectifiable_path (h  (λx. x *R l))
    proof -
      have continuous_on {0..1} (λx. x * l)
        by (intro continuous_intros)
      then have path: path (h  (λx. x *R l))
        unfolding path_def pathin_def continuous_map_iff_continuous
        using continuous_on_compose[of {0..1} λx. x * l h] h_cont scale_image
        by (simp add: image_comp comp_def)
      have bv: has_bounded_variation_on (h  (λx. x *R l)) {0..1}
        using has_bounded_variation_compose_monotone(1)[OF _ scale_mono] h_bv
        by simp
      show ?thesis
        unfolding rectifiable_path_def using path bv by simp
    qed
    show path_image (h  (λx. x *R l)) = path_image g
      unfolding path_image_def image_comp[symmetric] scale_image
      using h_image by simp
    show pathstart (h  (λx. x *R l)) = pathstart g
      unfolding pathstart_def using h_0 by simp
    show pathfinish (h  (λx. x *R l)) = pathfinish g
      unfolding pathfinish_def using h_l by simp
    show path_length (h  (λx. x *R l)) = path_length g
    proof -
      have h_var_l: vector_variation {0..l} h = l
        using h_var l_nonneg by simp
      have upper: vector_variation {0..1} (h  (λx. x *R l))  l
        by (metis (no_types, lifting) h_bv h_var_l has_bounded_variation_compose_monotone(2) pth_1
            pth_4(1) scale_mono)
      have lower: l  vector_variation {0..1} (h  (λx. x *R l))
      proof (cases l = 0)
        case True
        then show ?thesis
          using vector_variation_pos_le[OF has_bounded_variation_compose_monotone(1)[OF _ scale_mono] ] h_bv
          by simp
      next
        case False
        then have l_pos: 0 < l using l_nonneg by simp
        have inv_mono: mono_on {0..l} (λx. x / l)
          using l_pos by (intro mono_onI) (simp add: divide_right_mono)
        have inv_bv: has_bounded_variation_on (h  (λx. x *R l)) {(0::real) / l..l / l}
          using has_bounded_variation_compose_monotone(1)[OF _ scale_mono] h_bv l_pos
          by simp
        have eq: (h  (λx. x *R l))  (λx. x / l) = h (is ?lhs = ?rhs)
          using False by auto
        have vector_variation {0..l} ((h  (λx. x *R l))  (λx. x / l))
               vector_variation {0 / l..l / l} (h  (λx. x *R l))
          using has_bounded_variation_compose_monotone(2)[OF inv_bv inv_mono] .
        then show ?thesis
          using eq h_var_l l_pos by simp
      qed
      show ?thesis
        unfolding path_length_def using upper lower l_eq by linarith
    qed
    show arc (h  (λx. x *R l)) if arc g
    proof -
      have g_inj: inj_on g {0..1}
        using arc_def that by blast
      have l_pos: 0 < l
      proof (rule ccontr)
        assume ¬ 0 < l
        then have l = 0 using l_nonneg by simp
        then have c. t  {0..1}. g t = c
          using vector_variation_const_eq[OF g_bv] l_eq by auto
        then have g 0 = g 1 by auto
        then show False using arc_distinct_ends[OF that]
          unfolding pathstart_def pathfinish_def by simp
      qed
      have h_inj: inj_on h {0..l}
        using that
        by (smt (verit, ccfv_SIG) arcD h_factor h_image_var image_iff linorder_inj_onI')
      have scale_inj: inj_on (λx. x *R l) {0..1}
        using l_pos by (intro inj_onI) simp
      have comp_inj: inj_on (h  (λx. x *R l)) {0..1}
        using comp_inj_on[OF scale_inj] h_inj scale_image by auto
      show arc (h  (λx. x *R l))
        unfolding arc_def using comp_inj
        using rectifiable_path (h  (λx. x *R l)) rectifiable_path_def by blast
    qed
    show simple_path (h  (λx. x *R l)) if sp: simple_path g
    proof -
      have g_lf: loop_free g
        using simple_path_def that by blast
      have l_pos: 0 < l
      proof (rule ccontr)
        assume ¬ 0 < l
        then have l = 0 using l_nonneg by simp
        then obtain c where t  {0..1}. g t = c
          using vector_variation_const_eq[OF g_bv] l_eq by auto
        then have eq: g 0 = g (1/2) by auto
        then show False
          using g_lf[unfolded loop_free_def, rule_format, of 0 1/2] by auto
      qed
      show simple_path (h  (λx. x *R l))
        unfolding simple_path_def
      proof (intro conjI)
        show path (h  (λx. x *R l))
          using rectifiable_path (h  (λx. x *R l)) rectifiable_path_def by blast
        show loop_free (h  (λx. x *R l))
          unfolding loop_free_def comp_def
        proof (intro ballI impI)
          fix x y assume x01: x  {0..1} and y01: y  {0..1}
            and eq: h (x *R l) = h (y *R l)
          have xl_in: x * l  {0..l} and yl_in: y * l  {0..l}
            using x01 y01 l_nonneg mult_right_mono[of _ 1 l] by auto
          from xl_in obtain s where s01: s  {0..1} and xs: x * l = vector_variation {0..s} g
            using h_image_var[symmetric] by auto
          from yl_in obtain t where t01: t  {0..1} and yt: y * l = vector_variation {0..t} g
            using h_image_var[symmetric] by auto
          have g s = h (vector_variation {0..s} g) using h_factor s01 by auto
          also have  = h (y * l) using xs eq by simp
          also have  = h (vector_variation {0..t} g) using yt by simp
          also have  = g t using h_factor t01 by auto
          finally have s = t  s = 0  t = 1  s = 1  t = 0
            using g_lf s01 t01 unfolding loop_free_def by blast
          then have x * l = y * l  x * l = 0  y * l = l  x * l = l  y * l = 0
            using xs yt l_eq vector_variation_on_null[of 0 0 g] by auto
          then show x = y  x = 0  y = 1  x = 1  y = 0
            using l_pos by auto
        qed
      qed
    qed
    show t  {0..1}. path_length (subpath 0 t (h  (λx. x *R l))) = path_length g * t
    proof (intro ballI)
      fix t :: real assume t01: t  {0..1}
      then have t_nonneg: 0  t and t_le1: t  1 by auto
      define m where m = t * l
      have m_nonneg: 0  m unfolding m_def using t_nonneg l_nonneg by simp
      have m_le_l: m  l unfolding m_def
        using mult_right_mono[of t 1 l] t_le1 l_nonneg by simp
      have m_in: m  {0..l} using m_nonneg m_le_l by simp
      have sub_eq: subpath 0 t (h  (λx. x *R l)) = h  (λx. x *R m)
        unfolding subpath_def comp_def m_def by (auto simp: algebra_simps)
      have scale_m_image: (λx. x *R m) ` {0..1} = {0..m}
        using m_nonneg image_mult_atLeastAtMost_if'[of m 0 1] by auto
      have scale_m_mono: mono_on {0..1} (λx. x *R m)
        using m_nonneg by (intro mono_onI) (simp add: mult_right_mono)
      have h_bv_m: has_bounded_variation_on h {0..m}
        using has_bounded_variation_on_subset[OF h_bv] m_le_l m_nonneg by auto
      have h_var_m: vector_variation {0..m} h = m
        using h_var m_in by auto
      have upper: vector_variation {0..1} (h  (λx. x *R m))  m
        by (metis (no_types, lifting) h_bv_m h_var_m has_bounded_variation_compose_monotone(2)
            pth_1 pth_4(1) scale_m_mono)
      have lower: m  vector_variation {0..1} (h  (λx. x *R m))
      proof (cases m = 0)
        case True
        then show ?thesis
          using vector_variation_pos_le[OF has_bounded_variation_compose_monotone(1)[OF _ scale_m_mono]]
            h_bv_m by simp
      next
        case False
        then have m_pos: 0 < m using m_nonneg by simp
        have inv_mono: mono_on {0..m} (λx. x / m)
          using m_pos by (intro mono_onI) (simp add: divide_right_mono)
        have inv_bv: has_bounded_variation_on (h  (λx. x *R m)) {(0::real) / m..m / m}
          using has_bounded_variation_compose_monotone(1)[OF _ scale_m_mono] h_bv_m m_pos
          by simp
        have eq: (h  (λx. x *R m))  (λx. x / m) = h
          using False by auto
        have vector_variation {0..m} ((h  (λx. x *R m))  (λx. x / m))
               vector_variation {0 / m..m / m} (h  (λx. x *R m))
          using has_bounded_variation_compose_monotone(2)[OF inv_bv inv_mono] .
        then show ?thesis
          using eq h_var_m m_pos by simp
      qed
      show path_length (subpath 0 t (h  (λx. x *R l))) = path_length g * t
        unfolding path_length_def sub_eq l_eq[symmetric]
        using upper lower m_def by (simp add: mult.commute)
    qed
    show x  {0..1}. y  {0..1}.
        dist ((h  (λx. x *R l)) x) ((h  (λx. x *R l)) y)  path_length g * dist x y
    proof (intro ballI)
      fix x y :: real assume x  {0..1} y  {0..1}
      then have x * l  {0..l} y * l  {0..l}
        using l_nonneg mult_right_mono[of _ 1 l] by auto
      then have dist (h (x * l)) (h (y * l))  dist (x * l) (y * l)
        using h_lip by auto
      also have  = l * dist x y
        unfolding dist_real_def using l_nonneg
        by (simp add: abs_mult left_diff_distrib[symmetric])
      finally show dist ((h  (λx. x *R l)) x) ((h  (λx. x *R l)) y)  path_length g * dist x y
        unfolding l_def comp_def by simp
    qed
  qed
qed

corollary bounded_variation_absolutely_integrable_real_interval:
  fixes f :: "real  'm::euclidean_space"
  assumes "f integrable_on {a..b}"
    and "d. d division_of {a..b}  sum (λK. norm(integral K f)) d  B"
  shows "f absolutely_integrable_on {a..b}"
  by (metis assms bounded_variation_absolutely_integrable_interval interval_cbox)

lemma absolutely_integrable_bounded_variation_eq:
  fixes f :: real  'a::euclidean_space
  shows f absolutely_integrable_on {a..b} 
    f integrable_on {a..b} 
    has_bounded_variation_on (λt. integral {a..t} f) {a..b}
  (is ?L  ?R)
proof
  assume L: ?L
  then have int: f integrable_on {a..b}
    using absolutely_integrable_on_def by blast
  have nint: (λx. norm (f x)) integrable_on {a..b}
    using L absolutely_integrable_on_def by blast
  have bv: has_bounded_variation_on (λt. integral {a..t} f) {a..b}
    unfolding has_bounded_variation_on_def has_bounded_setvariation_on_def
  proof (intro exI allI impI)
    fix d t assume dt: d division_of t  t  {a..b}
    then have div: d division_of t and sub: t  {a..b} by auto
    have (kd. norm (integral {a..Sup k} f - integral {a..Inf k} f))
        = (kd. norm (integral k f))
    proof (rule sum.cong[OF refl])
      fix k assume kd: k  d
      obtain c e where ke: k = {c..e} c  e
        using division_ofD(4)[OF div kd] unfolding box_real
        by (metis atLeastatMost_empty_iff2 division_ofD(3) dt kd)
      have ksub: k  {a..b} using division_ofD(2)[OF div kd] sub by auto
      then have ce_sub: a  c e  b using ke by auto
      have Inf k = c Sup k = e using ke by auto
      have fint_ac: f integrable_on {a..c}
        using integrable_on_subinterval[OF int] ce_sub c  e by auto
      have fint_ce: f integrable_on {c..e}
        using integrable_on_subinterval[OF int] ce_sub ke by auto
      have fint_ae: f integrable_on {a..e}
        using integrable_on_subinterval[OF int] ce_sub by auto
      have integral {a..e} f = integral {a..c} f + integral {c..e} f
        by (simp add: Henstock_Kurzweil_Integration.integral_combine ce_sub(1) fint_ae ke(2))
      then have integral {a..e} f - integral {a..c} f = integral {c..e} f
        by simp
      then show norm (integral {a..Sup k} f - integral {a..Inf k} f) = norm (integral k f)
        using Inf k = c Sup k = e ke by auto
    qed
    also have   (kd. integral k (λx. norm (f x)))
    proof (rule sum_mono)
      fix k assume k  d
      obtain c e where ke: k = {c..e} c  e
        using division_ofD(4)[OF div k  d] unfolding box_real
        by (metis atLeastatMost_empty_iff2 division_ofD(3) dt k  d)
      have ksub: k  {a..b} using division_ofD(2)[OF div k  d] sub by auto
      have fint: f integrable_on k
        using integrable_on_subinterval[OF int] ksub ke(1) by blast
      show norm (integral k f)  integral k (λx. norm (f x))
        using Henstock_Kurzweil_Integration.integral_norm_bound_integral fint
              integrable_on_subinterval ke(1) ksub nint by blast
    qed
    also have   integral t (λx. norm (f x))
      by (metis dt integrable_on_subdivision integral_combine_division_topdown landau_omega.R_refl
      nint)
    also have   integral {a..b} (λx. norm (f x))
      by (metis dt integrable_on_subdivision integral_subset_le nint norm_ge_zero)
    finally show (kd. norm (integral {a..Sup k} f - integral {a..Inf k} f))
         integral {a..b} (λx. norm (f x)) .
  qed
  show ?R using int bv by blast
next
  assume R: ?R
  then have int: f integrable_on {a..b}
    and bv: has_bounded_variation_on (λt. integral {a..t} f) {a..b}
    by auto
 then obtain B where B: d t. d division_of t  t  {a..b} 
          (kd. norm (integral {a..Sup k} f - integral {a..Inf k} f))  B
   unfolding has_bounded_variation_on_def has_bounded_setvariation_on_def by meson
  show ?L
  proof (rule bounded_variation_absolutely_integrable_real_interval[OF int])
    fix d assume ddiv: d division_of {a..b}
    have (kd. norm (integral k f))
        = (kd. norm (integral {a..Sup k} f - integral {a..Inf k} f))
    proof (rule sum.cong[OF refl])
      fix k assume kd: k  d
      obtain c e where ke: k = {c..e} c  e
        using division_ofD(4)[OF ddiv kd] unfolding box_real
        by (metis atLeastatMost_empty_iff2 division_ofD(3) ddiv kd)
      have ksub: k  {a..b} using division_ofD(2)[OF ddiv kd] by auto
      then have ce_sub: a  c e  b using ke by auto
      have Inf k = c Sup k = e using ke by auto
      have fint_ac: f integrable_on {a..c}
        using integrable_on_subinterval[OF int] ce_sub c  e by auto
      have fint_ce: f integrable_on {c..e}
        using integrable_on_subinterval[OF int] ce_sub ke by auto
      have fint_ae: f integrable_on {a..e}
        using integrable_on_subinterval[OF int] ce_sub by auto
      have integral {a..e} f = integral {a..c} f + integral {c..e} f
        by (simp add: Henstock_Kurzweil_Integration.integral_combine ce_sub(1) fint_ae ke(2))
      then have integral {a..e} f - integral {a..c} f = integral {c..e} f
        by simp
      then show norm (integral k f) = norm (integral {a..Sup k} f - integral {a..Inf k} f)
        using Inf k = c Sup k = e ke by auto
    qed
    also have   B using B[OF ddiv] by auto
    finally show (kd. norm (integral k f))  B .
  qed
qed

section ‹Basic properties›

lemma rectifiable_path_imp_path:
  "rectifiable_path g  path g"
  unfolding rectifiable_path_def by simp

lemma path_length_pos_le:
  "rectifiable_path g  0  path_length g"
  unfolding rectifiable_path_def path_length_def
  by (auto intro: vector_variation_pos_le)

lemma path_length_eq_0:
  "rectifiable_path g 
    (path_length g = 0  (c. t  {0..1}. g t = c))"
  unfolding rectifiable_path_def path_length_def
  by (rule vector_variation_const_eq) auto

lemma simple_path_length_pos_lt:
  "rectifiable_path g  simple_path g  0 < path_length g"
 proof -
  assume rect: "rectifiable_path g" and sp: "simple_path g"
  have "path_length g  0"
  proof
    assume "path_length g = 0"
    then obtain c where c: "t. t  {0..1}  g t = c"
      using path_length_eq_0[OF rect] by auto
    hence "g (1/4) = g (3/4)" by auto
    moreover from sp have "inj_on g {0<..<1}" by (rule simple_path_inj_on)
    ultimately have "(1/4::real) = 3/4"
      by (auto dest: inj_onD)
    thus False by simp
  qed
  with path_length_pos_le[OF rect] show "0 < path_length g"
    by linarith
 qed

section ‹Invariance under transformations›

lemma rectifiable_path_translation_eq:
  "rectifiable_path ((λx. a + x)  g)  rectifiable_path g"
proof -
  have "path g"
    if "path (λx. a + g x)"
      and "has_bounded_variation_on (λx. a + g x) {0..1}"
    using that path_translation_eq[of a g] by (simp add: o_def)
  moreover have "has_bounded_variation_on g {0..1}"
    if "path (λx. a + g x)"
      and "has_bounded_variation_on (λx. a + g x) {0..1}"
  proof -
    have "has_bounded_variation_on (λx. a + g x + (- a)) {0..1}"
      using that(2) has_bounded_variation_on_const[of "-a" "{0..1}"]
      by (rule has_bounded_variation_on_add)
    then show ?thesis by simp
  qed
  moreover have "path (λx. a + g x)"
    if "path g"
      and "has_bounded_variation_on g {0..1}"
    using that path_translation_eq[of a g] by (simp add: o_def)
  moreover have "has_bounded_variation_on (λx. a + g x) {0..1}"
    if "path g"
      and "has_bounded_variation_on g {0..1}"
    using that(2) has_bounded_variation_on_const[of a "{0..1}"]
    by (auto intro: has_bounded_variation_on_add)
  ultimately show ?thesis
    by (auto simp: o_def rectifiable_path_def)
qed

lemma path_length_translation:
  "path_length ((λx. a + x)  g) = path_length g"
  unfolding path_length_def vector_variation_def comp_def
  by (simp add: algebra_simps)

lemma has_bounded_variation_on_linear_image:
  assumes "linear f" "has_bounded_variation_on g {0..1}"
  shows "has_bounded_variation_on (f  g) {0..1}"
proof -
  have bl: "bounded_linear f" using assms(1) linear_conv_bounded_linear by auto
  have bound: "d. d division_of {0..1} 
    (kd. norm ((f  g) (Sup k) - (f  g) (Inf k)))
     onorm f * vector_variation {0..1} g"
  proof -
    fix d :: "real set set" assume div: "d division_of {0..1}"
    have "(kd. norm ((f  g) (Sup k) - (f  g) (Inf k)))
      = (kd. norm (f (g (Sup k) - g (Inf k))))" 
      using assms(1) by (simp add: o_def linear_diff)
    also have "  (kd. onorm f * norm (g (Sup k) - g (Inf k)))" 
      by (intro sum_mono onorm[OF bl])
    also have " = onorm f * (kd. norm (g (Sup k) - g (Inf k)))" 
      by (simp add: sum_distrib_left)
    also have "  onorm f * vector_variation {0..1} g" 
      by (intro mult_left_mono has_bounded_variation_works(1)[OF assms(2) div order_refl]
          onorm_pos_le[OF bl])
    finally show "(kd. norm ((f  g) (Sup k) - (f  g) (Inf k)))
       onorm f * vector_variation {0..1} g" .
  qed
  then show ?thesis
    unfolding has_bounded_variation_on_interval by blast
qed

lemma rectifiable_path_linear_image_eq:
  assumes "linear f" "inj f"
  shows "rectifiable_path (f  g)  rectifiable_path g"
proof
  assume "rectifiable_path g"
  then show "rectifiable_path (f  g)"
    unfolding rectifiable_path_def
    using path_linear_image_eq[OF assms] has_bounded_variation_on_linear_image[OF assms(1)]
    by auto
next
  assume fg: "rectifiable_path (f  g)"
  have invf: "has_bounded_variation_on g {0..1}"
  proof -
    obtain B where "B > 0" and Bbound: "x. B * norm x  norm (f x)"
      using linear_inj_bounded_below_pos[OF assms(1) assms(2)] by auto
    have bv_fg: "has_bounded_variation_on (f  g) {0..1}"
      using fg unfolding rectifiable_path_def by auto
    show ?thesis unfolding has_bounded_variation_on_interval
    proof -
      obtain C where C: "d. d division_of {0..1} 
        (kd. norm ((f  g) (Sup k) - (f  g) (Inf k)))  C"
        using bv_fg unfolding has_bounded_variation_on_interval by auto
      { fix d :: "real set set" assume div: "d division_of {0..1}"
        have "(kd. B * norm (g (Sup k) - g (Inf k)))
           (kd. norm (f (g (Sup k) - g (Inf k))))" 
          by (intro sum_mono Bbound)
        also have " = (kd. norm ((f  g) (Sup k) - (f  g) (Inf k)))"
          using assms(1) by (simp add: o_def real_vector.linear_diff)
        also have "  C" using C[OF div] .
        finally have "B * (kd. norm (g (Sup k) - g (Inf k)))  C"
          by (simp add: sum_distrib_left)
        then have "(kd. norm (g (Sup k) - g (Inf k)))  C / B"
          using B > 0 by (simp add: field_simps) }
      then show "B. d. d division_of {0..1} 
        (kd. norm (g (Sup k) - g (Inf k)))  B" by blast
    qed
  qed
  moreover have "path g"
    using fg path_linear_image_eq[OF assms(1) assms(2)] unfolding rectifiable_path_def by auto
  ultimately show "rectifiable_path g"
    unfolding rectifiable_path_def by auto
qed


lemma path_length_linear_image:
  assumes "linear f" "x. norm (f x) = norm x"
  shows "path_length (f  g) = path_length g"
proof -
  have eq: "k. norm (f (g (Sup k)) - f (g (Inf k))) = norm (g (Sup k) - g (Inf k))"
    by (metis assms(1) assms(2) real_vector.linear_diff)
  then show ?thesis
    unfolding path_length_def vector_variation_def set_variation_def comp_def by presburger
qed


lemma rectifiable_path_eq:
  assumes eq: "t. t  {0..1}  g t = h t"
    and rect: "rectifiable_path g"
  shows "rectifiable_path h"
proof -
  have "path h"
  proof -
    have "continuous_on {0..1} h = continuous_on {0..1} g"
      by (rule continuous_on_cong_simp[OF refl]) (use eq in simp add: simp_implies_def)
    then show ?thesis using rect unfolding rectifiable_path_def path_def by auto
  qed
  moreover have "has_bounded_variation_on h {0..1}"
  proof -
    from rect have bv: "has_bounded_variation_on g {0..1}"
      unfolding rectifiable_path_def by auto
    have sup_inf_in: "Sup k  {0..1}  Inf k  {0..1}"
      if "d division_of {(0::real)..1}" "k  d" for d k
    proof -
      from division_ofD(2)[OF that] have ks: "k  {0..1}" .
      from division_ofD(3)[OF that] have kne: "k  {}" .
      from division_ofD(4)[OF that] obtain a b where kab: "k = cbox a b" by auto
      with kne have "a  b" by auto
      then have "Sup k = b" "Inf k = a"
        using kab by (auto simp: cSup_atLeastAtMost cInf_atLeastAtMost)
      then show ?thesis using ks kab a  b by auto
    qed
    have sums_eq: "(kd. norm (h (Sup k) - h (Inf k))) = (kd. norm (g (Sup k) - g (Inf k)))"
      if "d division_of {(0::real)..1}" for d
      using sup_inf_in[OF that] by (intro sum.cong refl) (auto simp: eq)
    then show ?thesis
      using bv unfolding has_bounded_variation_on_interval by auto
  qed
  ultimately show ?thesis unfolding rectifiable_path_def by auto
qed

lemma path_length_eq:
  assumes eq: "t. t  {0..1}  g t = h t"
    and rect: "rectifiable_path g"
  shows "path_length g = path_length h"
proof -
  have sup_inf_in: "Sup k  {0..1}  Inf k  {0..1}"
    if "d division_of t" "t  {(0::real)..1}" "k  d" for d t k
  proof -
    from division_ofD(2)[OF that(1) that(3)] that(2) have ks: "k  {0..1}" by auto
    from division_ofD(3)[OF that(1) that(3)] have kne: "k  {}" .
    from division_ofD(4)[OF that(1) that(3)] obtain a b where kab: "k = cbox a b" by auto
    with kne have "a  b" by auto
    then have "Sup k = b" "Inf k = a"
      using kab by (auto simp: cSup_atLeastAtMost cInf_atLeastAtMost)
    then show ?thesis using ks kab a  b by auto
  qed
  have sums_eq: "(kd. norm (h (Sup k) - h (Inf k))) = (kd. norm (g (Sup k) - g (Inf k)))"
    if "d division_of t" "t  {(0::real)..1}" for d t
    using sup_inf_in[OF that] by (intro sum.cong refl) (auto simp: eq)
  have "{kd. norm (h (Sup k) - h (Inf k)) |d. t. d division_of t  t  {0..1}}
      = {kd. norm (g (Sup k) - g (Inf k)) |d. t. d division_of t  t  {0..1}}"
    by (metis (lifting) sums_eq)
  then show ?thesis
    unfolding path_length_def vector_variation_def set_variation_def by auto
qed


lemma path_length_reversepath:
  "rectifiable_path g  path_length (reversepath g) = path_length g"
  unfolding path_length_def reversepath_def comp_def[symmetric]
  using vector_variation_reflect[of 0 1 g 1] by simp

lemma rectifiable_path_subpath:
  "rectifiable_path g; u  {0..1}; v  {0..1} 
    rectifiable_path (subpath u v g)"
  unfolding rectifiable_path_def subpath_def
proof (intro conjI)
  assume rect: "path g  has_bounded_variation_on g {0..1}" and u: "u  {0..1}" and v: "v  {0..1}"
  show "path (λx. g ((v - u) * x + u))"
    using rect u v path_subpath unfolding subpath_def by auto
  have bv: "has_bounded_variation_on g {0..1}" using rect by auto
  have seg: "closed_segment u v  {0..1}" using u v
    by (auto simp: closed_segment_eq_real_ivl split: if_splits)
  show "has_bounded_variation_on (λx. g ((v - u) * x + u)) {0..1}"
  proof (cases "u  v")
    case True
    have mono: "mono_on {0..1} (λx. (v - u) * x + u)"
      using True by (auto intro!: mono_onI mult_left_mono)
    have "has_bounded_variation_on g {u..v}"
      using bv seg True by (auto simp: closed_segment_eq_real_ivl
        intro: has_bounded_variation_on_subset)
    then show ?thesis
      using has_bounded_variation_compose_monotone(1)[of g "λx. (v-u)*x+u" 0 1]
        mono True by (simp add: comp_def)
  next
    case False
    then have vu: "v  u" by auto
    have mono: "mono_on {0..1} (λx. (u - v) * x + v)"
      using vu by (auto intro!: mono_onI mult_left_mono)
    have bvvu: "has_bounded_variation_on g {v..u}"
      using bv seg vu
      by (auto simp: closed_segment_eq_real_ivl split: if_splits
        intro: has_bounded_variation_on_subset)
    have "(λx. g ((v - u) * x + u)) = (λx. g ((u - v) * (1 - x) + v))"
      by (auto simp: algebra_simps)
    also have " = (g  (λx. (u-v)*x + v))  (λx. 1 - x)"
      by (auto simp: comp_def)
    finally have eq: "(λx. g ((v - u) * x + u)) = (g  (λx. (u-v)*x + v))  (-) 1"
      by (auto simp: comp_def)
    have "has_bounded_variation_on (g  (λx. (u-v)*x + v)) {0..1}"
      using has_bounded_variation_compose_monotone(1)[of g "λx. (u-v)*x+v" 0 1]
        mono bvvu by (simp add: comp_def)
    then have "has_bounded_variation_on (g  (λx. (u-v)*x + v)) {1 - 1..1 - 0}"
      by simp
    then have "has_bounded_variation_on ((g  (λx. (u-v)*x + v))  (-) 1) {0..1}"
      by (rule has_bounded_variation_on_reflect)
    then show ?thesis
      using eq by simp
  qed
qed

lemma division_of_affine_image:
  fixes c d :: real
  assumes cpos: "c > 0" and div: "D division_of T" and sub: "T  {a..b}"
  shows "((`) (λx. c * x + d)) ` D division_of ((λx. c * x + d) ` T)"
    and "(λx. c * x + d) ` T  {c*a+d..c*b+d}"
proof -
  let  = "λx::real. c * x + d"
  have inj: "inj " using cpos by (intro injI) simp
  have mono: "mono " using cpos by (intro monoI) auto
  show sub': " ` T  {c*a+d..c*b+d}"
    using sub cpos by (auto simp: mult_left_mono)
  show "((`) ) ` D division_of ( ` T)"
    unfolding division_of_def
  proof (intro conjI ballI impI)
    show "finite (((`) ) ` D)"
      using division_ofD(1)[OF div] by auto
  next
    fix K assume "K  ((`) ) ` D"
    then obtain K0 where K0: "K0  D" "K =  ` K0" by auto
    from division_ofD(2)[OF div K0(1)] have K0sub: "K0  T" .
    from division_ofD(3)[OF div K0(1)] have K0ne: "K0  {}" .
    then show "K   ` T" "K  {}" using K0(2) K0sub by auto
    from division_ofD(4)[OF div K0(1)] obtain α β where ab: "K0 = cbox α β" by auto
    then have "K0 = {α..β}" by auto
    with K0ne have αβ: "α  β" by auto
    have "K =  ` {α..β}" using K0(2) K0 = {α..β} by auto
    also have " = {c*α+d..c*β+d}"
    proof -
      have " ` {α..β} = {y. x. α  x  x  β  y = c*x+d}"
        by (auto simp: image_def)
      also have " = {c*α+d..c*β+d}"
      proof (auto simp: mult_left_mono[OF _ less_imp_le[OF cpos]])
        fix y assume "c * α + d  y" "y  c * β + d"
        then have "α  (y - d) / c" "((y - d) / c)  β"
          using cpos by (auto simp: field_simps)
        moreover have "y = c * ((y - d) / c) + d" using cpos by auto
        ultimately show "xα. x  β  y = c * x + d" by auto
      qed
      finally show ?thesis .
    qed
    finally show "α β. K = cbox α β" by (auto simp: cbox_interval)
  next
    fix K1 K2
    assume "K1  ((`) ) ` D" "K2  ((`) ) ` D" "K1  K2"
    then obtain K1' K2' where K1': "K1'  D" "K1 =  ` K1'"
      and K2': "K2'  D" "K2 =  ` K2'" by auto
    have "K1'  K2'" using K1  K2 K1'(2) K2'(2) inj_image_eq_iff[OF inj] by auto
    then have disj: "interior K1'  interior K2' = {}"
      using division_ofD(5)[OF div K1'(1) K2'(1)] by auto
    show "interior K1  interior K2 = {}"
    proof (rule ccontr)
      assume "interior K1  interior K2  {}"
      then obtain y where "y  interior K1" "y  interior K2" by auto
      from division_ofD(4)[OF div K1'(1)] obtain a1 b1 where "K1' = cbox a1 b1" by auto
      from division_ofD(4)[OF div K2'(1)] obtain a2 b2 where "K2' = cbox a2 b2" by auto
      then have K1eq: "K1' = {a1..b1}" and K2eq: "K2' = {a2..b2}"
        using K1' = cbox a1 b1 by auto
      from division_ofD(3)[OF div K1'(1)] K1eq have "a1  b1" by (auto split: if_splits)
      from division_ofD(3)[OF div K2'(1)] K2eq have "a2  b2" by (auto split: if_splits)
      have K1img: "K1 = {c*a1+d..c*b1+d}" 
      proof -
        have "K1 =  ` {a1..b1}" using K1'(2) K1eq by auto
        also have " = {c*a1+d..c*b1+d}"
        proof safe
          fix x assume "x  {a1..b1}"
          then show " x  {c*a1+d..c*b1+d}" using cpos
            by (auto intro: mult_left_mono)
        next
          fix y assume "y  {c*a1+d..c*b1+d}"
          then have mem: "(y-d)/c  {a1..b1}" using cpos by (auto simp: field_simps)
          moreover have " ((y-d)/c) = y" using cpos by (simp add: field_simps)
          ultimately show "y   ` {a1..b1}" by force
        qed
        finally show ?thesis .
      qed
      have K2img: "K2 = {c*a2+d..c*b2+d}"
      proof -
        have "K2 =  ` {a2..b2}" using K2'(2) K2eq by auto
        also have " = {c*a2+d..c*b2+d}"
        proof safe
          fix x assume "x  {a2..b2}"
          then show " x  {c*a2+d..c*b2+d}" using cpos
            by (auto intro: mult_left_mono)
        next
          fix y assume "y  {c*a2+d..c*b2+d}"
          then have "(y-d)/c  {a2..b2}" using cpos by (auto simp: field_simps)
          moreover have " ((y-d)/c) = y" using cpos by (simp add: field_simps)
          ultimately show "y   ` {a2..b2}" by force
        qed
        finally show ?thesis .
      qed
      from y  interior K1 K1img have "c*a1+d < y" "y < c*b1+d"
        using a1  b1 interior_atLeastAtMost_real by auto
      then have "a1 < (y-d)/c" "(y-d)/c < b1" using cpos by (auto simp: field_simps)
      then have "(y-d)/c  interior K1'"
        using K1eq interior_atLeastAtMost_real by auto
      from y  interior K2 K2img have "c*a2+d < y" "y < c*b2+d"
        using a2  b2 interior_atLeastAtMost_real by auto
      then have "a2 < (y-d)/c" "(y-d)/c < b2" using cpos by (auto simp: field_simps)
      then have "(y-d)/c  interior K2'"
        using K2eq interior_atLeastAtMost_real by auto
      with (y-d)/c  interior K1' disj show False by auto
    qed
  next
    have " (((`) ) ` D) =  ` ( D)" by auto
    also have " D = T" using division_ofD(6)[OF div] by auto
    finally show " (((`) ) ` D) =  ` T" .
  qed
qed

lemma vector_variation_affine_eq:
  fixes g :: "real  'a::euclidean_space" and c d :: real
  assumes "c > 0" "a  b"
  shows "vector_variation {a..b} (g  (λx. c * x + d)) = vector_variation {c*a+d..c*b+d} g"
proof -
  let  = "λx::real. c * x + d"
  let  = "λx::real. (x - d) / c"
  have cne: "c  0" using assms(1) by auto
  have cpos: "0 < c" using assms(1) .
  have inj_φ: "inj " using cne by (intro injI) simp
  have φψ: "x.  ( x) = x" using cne by (simp add: field_simps)
  have ψφ: "x.  ( x) = x" using cne by (simp add: field_simps)
  have ab': "c*a+d  c*b+d" using assms by (auto intro: mult_left_mono)
  have img_ivl: "α β. α  β   ` {α..β} = {c*α+d..c*β+d}"
  proof safe
    fix α β x :: real assume "α  β" "x  {α..β}"
    then show " x  {c*α+d..c*β+d}" using cpos by (auto intro: mult_left_mono)
  next
    fix α β y :: real assume "α  β" "y  {c*α+d..c*β+d}"
    then have "(y-d)/c  {α..β}" using cpos by (auto simp: field_simps)
    moreover have " ((y-d)/c) = y" using cne by (simp add: field_simps)
    ultimately show "y   ` {α..β}" by force
  qed
  ― ‹Key: the variation sums over divisions of any @{term T} equal those over @{term φ(T)}
  have sum_transform: "(kD. norm ((g  ) (Sup k) - (g  ) (Inf k)))
    = (k((`) ) ` D. norm (g (Sup k) - g (Inf k)))"
    if "D division_of T" for D :: "real set set" and T :: "real set"
  proof -
    have div: "D division_of T" using that .
    have inj_on_img: "inj_on ((`) ) D"
      using inj_image_eq_iff[OF inj_φ] by (auto intro!: inj_onI)
    have "(kD. norm ((g  ) (Sup k) - (g  ) (Inf k)))
      = (kD. norm (g ( (Sup k)) - g ( (Inf k))))" by (simp add: o_def)
    also have " = (kD. norm (g (Sup ( ` k)) - g (Inf ( ` k))))"
    proof (intro sum.cong refl arg_cong[where f=norm] arg_cong2[where f="(-)"])
      fix k assume "k  D"
      from division_ofD(4)[OF div this] obtain α β where kab: "k = cbox α β" by auto
      from division_ofD(3)[OF div k  D] have kne: "k  {}" .
      with kab have le: "α  β" by auto
      have k_ivl: "k = {α..β}" using kab by auto
      have img: " ` k = {c*α+d..c*β+d}" using img_ivl[OF le] k_ivl by simp
      have le': "c*α+d  c*β+d" using le cpos by (auto intro: mult_left_mono)
      show "g ( (Sup k)) = g (Sup ( ` k))"
        using k_ivl le img le' by (simp add: cSup_atLeastAtMost)
      show "g ( (Inf k)) = g (Inf ( ` k))"
        using k_ivl le img le' by (simp add: cInf_atLeastAtMost)
    qed
    also have " = (k((`) ) ` D. norm (g (Sup k) - g (Inf k)))"
      by (metis (no_types, lifting) inj_on_img sum.reindex_cong)
    finally show "(kD. norm ((g  ) (Sup k) - (g  ) (Inf k)))
      = (k((`) ) ` D. norm (g (Sup k) - g (Inf k)))" .
  qed
  ― ‹Now show the Sup sets in the vector variation definition are equal›
  have sets_eq: "{kD. norm ((g  ) (Sup k) - (g  ) (Inf k)) |D.
      T. D division_of T  T  {a..b}}
    = {kD. norm (g (Sup k) - g (Inf k)) |D.
      T. D division_of T  T  {c*a+d..c*b+d}}"
  proof safe
    fix D T assume div: "D division_of T" and sub: "T  {a..b}"
    let ?D' = "((`) ) ` D"
    have div': "?D' division_of ( ` T)"
      using division_of_affine_image(1)[OF cpos div sub] .
    have sub': " ` T  {c*a+d..c*b+d}"
      using division_of_affine_image(2)[OF cpos div sub] .
    have sum_eq: "(kD. norm ((g  ) (Sup k) - (g  ) (Inf k)))
      = (k?D'. norm (g (Sup k) - g (Inf k)))"
      using sum_transform[OF div] .
    show "Da. (kD. norm ((g  ) (Sup k) - (g  ) (Inf k)))
      = (kDa. norm (g (Sup k) - g (Inf k)))
       (T. Da division_of T  T  {c*a+d..c*b+d})"
      using sum_eq div' sub' by blast
  next
    fix D T assume div: "D division_of T" and sub: "T  {c*a+d..c*b+d}"
    ― ‹Map back via the inverse affine map @{term (1/c)*x + (-d/c)}
    let ?c' = "1/c" and ?d' = "-d/c"
    have cpos': "?c' > 0" using cpos by auto
    have div': "((`) (λx. ?c' * x + ?d')) ` D division_of ((λx. ?c' * x + ?d') ` T)"
      using division_of_affine_image(1)[OF cpos' div sub] .
    have sub': "(λx. ?c' * x + ?d') ` T  {?c'*(c*a+d)+?d'..?c'*(c*b+d)+?d'}"
      using division_of_affine_image(2)[OF cpos' div sub] .
    have endpoints: "?c'*(c*a+d)+?d' = a" "?c'*(c*b+d)+?d' = b"
      using cne by (auto simp: field_simps)
    ― ‹The inverse map equals @{termψ}
    have inv_eq: "(λx::real. ?c' * x + ?d') = "
      by (rule ext) (simp add: diff_divide_distrib)
    have div'': "((`) ) ` D division_of ( ` T)"
      using div' unfolding inv_eq .
    have sub'': " ` T  {a..b}"
    proof -
      have "(λx::real. ?c' * x + ?d') ` T  {a..b}"
        using sub' endpoints by auto
      then show ?thesis unfolding inv_eq .
    qed
    have sum_eq: "(k((`) ) ` D. norm ((g  ) (Sup k) - (g  ) (Inf k)))
      = (k((`) ) ` ((`) ) ` D. norm (g (Sup k) - g (Inf k)))"
      using sum_transform[OF div''] .
    have φψ_img: " `  ` S = S" for S :: "real set"
    proof -
      have " `  ` S = (  ) ` S" by (simp add: image_image)
      also have "(  ) = id"
        using cne by (auto simp: o_def field_simps)
      also have "id ` S = S" by simp
      finally show ?thesis .
    qed
    have img_back: "((`) ) ` ((`) ) ` D = D"
    proof -
      have "((`) ) ` ((`) ) ` D = ((`)   (`) ) ` D"
        by (simp add: image_comp)
      also have "((`)   (`) ) = id"
        by (rule ext) (simp add: φψ_img)
      also have "id ` D = D" by simp
      finally show ?thesis .
    qed
    have sum_eq': "(k((`) ) ` D. norm ((g  ) (Sup k) - (g  ) (Inf k)))
      = (kD. norm (g (Sup k) - g (Inf k)))"
      using sum_eq img_back by simp
    show "E. (kD. norm (g (Sup k) - g (Inf k))) = (kE. norm ((g  ) (Sup k) - (g  ) (Inf k)))
       (T. E division_of T  T  {a..b})"
      using sum_eq' div'' sub'' by (metis (no_types, lifting))
  qed
  show ?thesis
    unfolding vector_variation_def set_variation_def using sets_eq by auto
qed

lemma path_length_subpath_eq:
  assumes "s  {0..1}" "t  {0..1}"
    and rect: "rectifiable_path g"
  shows "path_length (subpath s t g) = vector_variation (closed_segment s t) g"
  using assms
proof (cases "s  t")
  case True
  then have cs: "closed_segment s t = {s..t}"
    by (simp add: closed_segment_eq_real_ivl)
  show ?thesis
  proof (cases "s = t")
    case True
    then show ?thesis
    proof -
      from s = t have cs': "closed_segment s t = {t..t}" using cs by simp
      have "path_length (subpath t t g) = 0"
        by (metis t  {0..1} eq_iff_diff_eq_0 mult_zero_left path_length_eq_0 rect
            rectifiable_path_subpath subpath_def)
      moreover have "vector_variation {t..t} g = 0"
        by (rule vector_variation_on_null) (simp add: content_real_eq_0)
      ultimately show ?thesis using s = t cs' by simp
    qed
  next
    case False
    with s  t have "s < t" by auto
    then have "t - s > 0" by auto
    have "path_length (subpath s t g) = vector_variation {0..1} (g  (λx. (t-s)*x + s))"
      unfolding path_length_def subpath_def by (simp add: comp_def)
    also have " = vector_variation {(t-s)*0+s..(t-s)*1+s} g"
      using vector_variation_affine_eq[OF t - s > 0 zero_le_one, where d=s and g=g] by simp
    also have " = vector_variation {s..t} g"
      by simp
    finally show ?thesis by (simp add: cs)
  qed
next
  case False
  then have ts: "t < s" by auto
  then have cs: "closed_segment s t = {t..s}"
    by (simp add: closed_segment_eq_real_ivl)
  have "s - t > 0" using ts by auto
  have "path_length (subpath s t g) = vector_variation {0..1} (λx. g ((t - s) * x + s))"
    unfolding path_length_def subpath_def by simp
  also have " = vector_variation {0..1} (g  (λx. (s - t) * x + t)  (-) 1)"
    by (simp add: comp_def algebra_simps)
  finally
   show ?thesis
    using vector_variation_affine_eq[OF s - t > 0 zero_le_one, where d=t and g=g]
    by (simp add: cs vector_variation_reflect)
qed

lemma vector_variation_cong:
  assumes "x. x  s  f x = g x"
  shows "vector_variation s f = vector_variation s g"
proof -
  have sum_eq: "(kd. norm (f (Sup k) - f (Inf k))) = (kd. norm (g (Sup k) - g (Inf k)))"
    if "d division_of t" "t  s" for d t
  proof (rule sum.cong[OF refl])
    fix k assume "k  d"
    then have "k  t" "k  {}" "a b. k = cbox a b"
      using division_ofD(2,3,4)[OF that(1)] by auto
    then obtain a b where "k = cbox a b" "a  b" by fastforce
    then have "Inf k  k" "Sup k  k" by auto
    then have "Inf k  s" "Sup k  s" using k  t that(2) by auto
    then show "norm (f (Sup k) - f (Inf k)) = norm (g (Sup k) - g (Inf k))"
      using assms by auto
  qed
  have "{kd. norm (f (Sup k) - f (Inf k)) |d. t. d division_of t  t  s}
      = {kd. norm (g (Sup k) - g (Inf k)) |d. t. d division_of t  t  s}"
    (is "?L = ?R")
  proof (rule set_eqI, rule iffI)
    fix x assume "x  ?L"
    then obtain d t where "x = (kd. norm (f (Sup k) - f (Inf k)))" "d division_of t" "t  s"
      by auto
    then show "x  ?R" using sum_eq by auto
  next
    fix x assume "x  ?R"
    then obtain d t where "x = (kd. norm (g (Sup k) - g (Inf k)))" "d division_of t" "t  s"
      by auto
    then show "x  ?L" using sum_eq
      by (metis (mono_tags, lifting) mem_Collect_eq)
  qed
  then show ?thesis
    unfolding vector_variation_def set_variation_def by simp
qed

lemma has_bounded_variation_on_cong:
  assumes "x. x  s  f x = g x"
  shows "has_bounded_variation_on f s  has_bounded_variation_on g s"
proof -
  have "d t. d division_of t  t  s 
    (kd. norm (f (Sup k) - f (Inf k))) = (kd. norm (g (Sup k) - g (Inf k)))"
  proof -
    fix d t assume dt: "d division_of t" "t  s"
    show "(kd. norm (f (Sup k) - f (Inf k))) = (kd. norm (g (Sup k) - g (Inf k)))"
    proof (rule sum.cong[OF refl])
      fix k assume "k  d"
      then have "k  t" "k  {}" "a b. k = cbox a b"
        using division_ofD(2,3,4)[OF dt(1)] by auto
      then obtain a b where "k = cbox a b" "a  b" by fastforce
      then have "Inf k  k" "Sup k  k" by auto
      then have "Inf k  s" "Sup k  s" using k  t dt(2) by auto
      then show "norm (f (Sup k) - f (Inf k)) = norm (g (Sup k) - g (Inf k))"
        using assms by auto
    qed
  qed
  then show ?thesis
    unfolding has_bounded_variation_on_def has_bounded_setvariation_on_def by (metis (lifting))
qed

lemma has_bounded_variation_on_affine_iff:
  fixes g :: "real  'a::euclidean_space" and c d :: real
  assumes "c > 0" "a  b"
  shows "has_bounded_variation_on (g  (λx. c * x + d)) {a..b} 
    has_bounded_variation_on g {c*a+d..c*b+d}"
proof
  assume "has_bounded_variation_on g {c*a+d..c*b+d}"
  moreover have "mono_on {a..b} (λx. c * x + d)"
    using assms(1) by (auto intro!: mono_onI mult_left_mono)
  ultimately show "has_bounded_variation_on (g  (λx. c * x + d)) {a..b}"
    by (rule has_bounded_variation_compose_monotone(1))
next
  assume bv: "has_bounded_variation_on (g  (λx. c * x + d)) {a..b}"
  let ?inv = "λx. (x - d) / c"
  have inv_mono: "mono_on {c*a+d..c*b+d} ?inv"
    using assms(1) by (smt (verit, ccfv_SIG) divide_less_cancel monotone_on_def)
  have inv_a: "?inv (c*a+d) = a" and inv_b: "?inv (c*b+d) = b"
    using assms(1) by (auto simp: field_simps)
  have comp_eq: "(g  (λx. c * x + d))  ?inv = g"
    using assms(1) by (auto simp: comp_def field_simps)
  have "has_bounded_variation_on ((g  (λx. c * x + d))  ?inv) {c*a+d..c*b+d}"
    by (metis (lifting) bv has_bounded_variation_compose_monotone(1) inv_a inv_b
        inv_mono)
  then show "has_bounded_variation_on g {c*a+d..c*b+d}"
    by (simp add: comp_eq)
qed

lemma rectifiable_path_join:
  assumes "pathfinish g1 = pathstart g2"
  shows "rectifiable_path (g1 +++ g2) 
    rectifiable_path g1  rectifiable_path g2"
proof -
  have half: "(0::real)  1/2" "1/2  (1::real)" by auto
  have eq1: "(g1 +++ g2) x = (g1  (λx. 2 * x)) x" if "x  {0..1/2}" for x
    using that by (auto simp: joinpaths_def)
  have eq2: "(g1 +++ g2) x = (g2  (λx. 2 * x + (-1))) x" if "x  {1/2..1}" for x
  proof -
    from that have "x = 1/2  x > 1/2" by auto
    then show ?thesis
    proof
      assume "x = 1/2"
      then show ?thesis
        using assms by (simp add: joinpaths_def mult.commute pathfinish_def pathstart_def)
    next
      assume "x > 1/2"
      then show ?thesis by (auto simp: joinpaths_def comp_def)
    qed
  qed
  ― ‹Bounded variation equivalences›
  have bv1: "has_bounded_variation_on (g1 +++ g2) {0..1/2} 
    has_bounded_variation_on g1 {0..1}"
  proof -
    have "has_bounded_variation_on (g1 +++ g2) {0..1/2} 
      has_bounded_variation_on (g1  (λx. 2 * x)) {0..1/2}"
      by (rule has_bounded_variation_on_cong[OF eq1])
    also have "  has_bounded_variation_on g1 {2*0+0..2*(1/2)+0}"
      using has_bounded_variation_on_affine_iff [of 2 0 1/2 _ 0] by force
    also have "{2*0+(0::real)..2*(1/2)+0} = {0..1}" by auto
    finally show ?thesis .
  qed
  have bv2: "has_bounded_variation_on (g1 +++ g2) {1/2..1} 
    has_bounded_variation_on g2 {0..1}"
  proof -
    have "has_bounded_variation_on (g1 +++ g2) {1/2..1} 
      has_bounded_variation_on (g2  (λx. 2 * x + (-1))) {1/2..1}"
      by (rule has_bounded_variation_on_cong[OF eq2])
    also have "  has_bounded_variation_on g2 {2*(1/2)+(-1)..2*1+(-1)}"
      by (rule has_bounded_variation_on_affine_iff) auto
    also have "{2*(1/2)+(-1::real)..2*1+(-1)} = {0..1}" by auto
    finally show ?thesis .
  qed
  show ?thesis
    unfolding rectifiable_path_def
    using path_join[OF assms]
      has_bounded_variation_on_combine[OF half(1) half(2), of "g1 +++ g2"]
      bv1 bv2
    by auto
qed

lemma path_length_join:
  assumes "rectifiable_path g1"
    and "rectifiable_path g2"
    and "pathfinish g1 = pathstart g2"
  shows "path_length (g1 +++ g2) = path_length g1 + path_length g2"
proof -
  have half: "(0::real)  1/2" "1/2  (1::real)" by auto
  have bvj: "has_bounded_variation_on (g1 +++ g2) {0..1}"
    using rectifiable_path_def assms rectifiable_path_join by blast
  have eq1: "(g1 +++ g2) x = (g1  (λx. 2 * x)) x" if "x  {0..1/2}" for x
    using that by (auto simp: joinpaths_def)
  have eq2: "(g1 +++ g2) x = (g2  (λx. 2 * x + (-1))) x" if "x  {1/2..1}" for x
  proof -
    from that have "x = 1/2  x > 1/2" by auto
    then show ?thesis
    proof
      assume "x = 1/2"
      then show ?thesis
        using assms by (simp add: joinpaths_def mult.commute pathfinish_def pathstart_def)
    next
      assume "x > 1/2"
      then show ?thesis by (auto simp: joinpaths_def comp_def)
    qed
  qed
  ― ‹Variation on left half›
  have vv1: "vector_variation {0..1/2} (g1 +++ g2) = path_length g1"
  proof -
    have "vector_variation {0..1/2} (g1 +++ g2) =
      vector_variation {0..1/2} (g1  (λx. 2 * x))"
      by (rule vector_variation_cong[OF eq1])
    also have " = vector_variation {2*0+0..2*(1/2)+0} g1"
      using vector_variation_affine_eq
      by (metis (no_types, lifting) ext add.right_neutral half(1) zero_less_numeral)
    also have "{2*0+(0::real)..2*(1/2)+0} = {0..1}" by auto
    finally show ?thesis unfolding path_length_def .
  qed
  ― ‹Variation on right half›
  have vv2: "vector_variation {1/2..1} (g1 +++ g2) = path_length g2"
  proof -
    have "vector_variation {1/2..1} (g1 +++ g2) =
      vector_variation {1/2..1} (g2  (λx. 2 * x + (-1)))"
      by (rule vector_variation_cong[OF eq2])
    also have " = vector_variation {2*(1/2)+(-1)..2*1+(-1)} g2"
      by (rule vector_variation_affine_eq) auto
    also have "{2*(1/2)+(-1::real)..2*1+(-1)} = {0..1}" by auto
    finally show ?thesis unfolding path_length_def .
  qed
  ― ‹Combine›
  show ?thesis
    unfolding path_length_def
    using vector_variation_combine[OF bvj, of "1/2"] half vv1 vv2
    unfolding path_length_def
    by auto
qed

section ‹Shiftpath›

lemma rectifiable_path_shiftpath:
  assumes "rectifiable_path g"
    and "pathfinish g = pathstart g"
    and "t  {0..1}"
  shows "rectifiable_path (shiftpath t g)"
proof -
  note rg = assms(1) and loop = assms(2) and t01 = assms(3)
  from rg have pg: "path g" and bvg: "has_bounded_variation_on g {0..1}"
    unfolding rectifiable_path_def by auto
  from t01 have t0: "0  t" and t1: "t  1" and mt: "0  1 - t" and mt1: "1 - t  1" by auto
  have eq1: "shiftpath t g x = (g  (λx. 1 * x + t)) x" if "x  {0..1-t}" for x
    by (metis add.commute atLeastAtMost_iff comp_def mult_1 shiftpath_alt_def that)
  have eq2: "shiftpath t g x = (g  (λx. 1 * x + (t - 1))) x" if "x  {1-t..1}" for x
  proof -
    from that have "x = 1-t  x > 1-t" by auto
    then show ?thesis
    proof
      assume "x = 1-t"
      then show ?thesis
        using loop t1 by (simp add: shiftpath_def pathfinish_def pathstart_def)
    next
      assume "x > 1-t"
      then have "t + x > 1" by auto
      then show ?thesis
        by (simp add: add.commute add_diff_eq shiftpath_def)
    qed
  qed
  ― ‹Bounded variation on each half›
  have bv1: "has_bounded_variation_on (shiftpath t g) {0..1-t}"
  proof -
    have "has_bounded_variation_on (shiftpath t g) {0..1-t} 
      has_bounded_variation_on (g  (λx. 1 * x + t)) {0..1-t}"
      by (rule has_bounded_variation_on_cong[OF eq1])
    also have "  has_bounded_variation_on g {1*0+t..1*(1-t)+t}"
      using has_bounded_variation_on_affine_iff mt zero_less_one by blast
    also have "{1*0+t..1*(1-t)+t} = {t..1::real}" by auto
    finally show ?thesis
      using has_bounded_variation_on_subset[OF bvg, of "{t..1}"] t0 t1 by auto
  qed
  have bv2: "has_bounded_variation_on (shiftpath t g) {1-t..1}"
  proof -
    have "has_bounded_variation_on (shiftpath t g) {1-t..1} 
      has_bounded_variation_on (g  (λx. 1 * x + (t - 1))) {1-t..1}"
      by (rule has_bounded_variation_on_cong[OF eq2])
    also have "  has_bounded_variation_on g {1*(1-t)+(t-1)..1*1+(t-1)}"
      using has_bounded_variation_on_affine_iff mt1 zero_less_one by blast
    also have "{1*(1-t)+(t-1)..1*1+(t-1)} = {0..t::real}" by auto
    finally show ?thesis
      using has_bounded_variation_on_subset[OF bvg, of "{0..t}"] t0 t1 by auto
  qed
  ― ‹Combine›
  have "has_bounded_variation_on (shiftpath t g) {0..1}"
    using has_bounded_variation_on_combine[of 0 "1-t" 1 "shiftpath t g"] mt mt1 bv1 bv2 by auto
  then show "rectifiable_path (shiftpath t g)"
    unfolding rectifiable_path_def
    using path_shiftpath[OF pg loop t01] by auto
qed

lemma path_length_shiftpath:
  assumes rg: "rectifiable_path g"
    and loop: "pathfinish g = pathstart g"
    and t01: "t  {0..1}"
  shows "path_length (shiftpath t g) = path_length g"
proof -
  from rg have bvg: "has_bounded_variation_on g {0..1}"
    unfolding rectifiable_path_def by auto
  have bvs: "has_bounded_variation_on (shiftpath t g) {0..1}"
    using rectifiable_path_shiftpath[OF rg loop t01]
    unfolding rectifiable_path_def by auto
  from t01 have t0: "0  t" and t1: "t  1" and mt: "0  1 - t" and mt1: "1 - t  1" by auto
  ― ‹Pointwise agreements (reuse from rectifiable path shiftpath proof)›
  have eq1: "shiftpath t g x = (g  (λx. 1 * x + t)) x" if "x  {0..1-t}" for x
    using that t1 by (auto simp: shiftpath_def algebra_simps)
  have eq2: "shiftpath t g x = (g  (λx. 1 * x + (t - 1))) x" if "x  {1-t..1}" for x
    using that loop t1 by (auto simp add: shiftpath_def pathfinish_def pathstart_def algebra_simps)
  have vv1: "vector_variation {0..1-t} (shiftpath t g) = vector_variation {t..1} g"
  proof -
    have "vector_variation {0..1-t} (shiftpath t g) =
      vector_variation {0..1-t} (g  (λx. 1 * x + t))"
      by (rule vector_variation_cong[OF eq1])
    also have " = vector_variation {1*0+t..1*(1-t)+t} g"
      by (rule vector_variation_affine_eq) (use t1 in auto)
    also have "{1*0+t..1*(1-t)+t} = {t..1::real}" by auto
    finally show ?thesis .
  qed
  have vv2: "vector_variation {1-t..1} (shiftpath t g) = vector_variation {0..t} g"
  proof -
    have "vector_variation {1-t..1} (shiftpath t g) =
      vector_variation {1-t..1} (g  (λx. 1 * x + (t - 1)))"
      by (rule vector_variation_cong[OF eq2])
    also have " = vector_variation {1*(1-t)+(t-1)..1*1+(t-1)} g"
      by (rule vector_variation_affine_eq) (use t0 in auto)
    also have "{1*(1-t)+(t-1)..1*1+(t-1)} = {0..t::real}" by auto
    finally show ?thesis .
  qed
  ― ‹Combine›
  have "path_length (shiftpath t g) = vector_variation {0..1} (shiftpath t g)"
    unfolding path_length_def ..
  also have " = vector_variation {0..1-t} (shiftpath t g) +
    vector_variation {1-t..1} (shiftpath t g)"
    using vector_variation_combine[OF bvs, of "1-t"] mt mt1 by auto
  also have " = vector_variation {t..1} g + vector_variation {0..t} g"
    using vv1 vv2 by simp
  also have " = vector_variation {0..t} g + vector_variation {t..1} g"
    by (rule add.commute)
  also have " = vector_variation {0..1} g"
    using vector_variation_combine[OF bvg, of t] t01 by auto
  also have " = path_length g"
    unfolding path_length_def ..
  finally show "path_length (shiftpath t g) = path_length g" .
qed

section ‹Lipschitz and distance bounds›

lemma lipschitz_imp_rectifiable_path:
  assumes "x y. x  {0..1}  y  {0..1} 
    norm (g x - g y)  B * norm (x - y)"
  shows "rectifiable_path g"
  unfolding rectifiable_path_def
proof
  show "path g"
    unfolding path_def
  proof (rule continuous_onI)
    fix x e :: real assume "x  {0..1}" "e > 0"
    define d where "d = (if B  0 then 1 else e / B)"
    have "d > 0" using e > 0 unfolding d_def by (auto simp: field_simps)
    moreover have "x'. x'  {0..1}  dist x' x < d  dist (g x') (g x) < e"
    proof -
      fix x' assume "x'  {0..1}" "dist x' x < d"
      have "dist (g x') (g x) = norm (g x' - g x)" by (simp add: dist_norm)
      also have "  B * norm (x' - x)" using assms[OF x'  {0..1} x  {0..1}] .
      also have "  B * dist x' x" by (simp add: dist_norm)
      also have " < e"
      proof (cases "B  0")
        case True
        then have "B * dist x' x  0" by (simp add: mult_nonpos_nonneg)
        also have "0 < e" using e > 0 .
        finally show ?thesis .
      next
        case False
        then have "B > 0" by auto
        then have "B * dist x' x < B * d"
          using dist x' x < d by auto
        also have " = e" using B > 0 unfolding d_def by auto
        finally show ?thesis .
      qed
      finally show "dist (g x') (g x) < e" .
    qed
    ultimately show "d>0. x'{0..1}. dist x' x < d  dist (g x') (g x)  e"
      using less_le_not_le by blast 
  qed
next
  show "has_bounded_variation_on g {0..1}"
    using Lipschitz_imp_has_bounded_variation[of "{0..1}" g B] assms
    by auto
qed

lemma path_length_lipschitz:
  assumes "x y. x  {0..1}  y  {0..1}  norm (g x - g y)  B * norm (x - y)"
  shows "path_length g  B"
  unfolding path_length_def
proof (rule has_bounded_variation_works(2)[OF Lipschitz_imp_has_bounded_variation[of "{0..1}" g B]])
  show "bounded {0..1::real}" by simp
  show "x y. x  {0..1}  y  {0..1}  norm (g x - g y)  B * norm (x - y)"
    using assms by auto
next
  fix d t assume dt: "d division_of t" "t  {(0::real)..1}"
  have B  0
    using assms [of 0 1] norm_ge_zero by (fastforce elim: order_trans)
  have "(kd. norm (g (Sup k) - g (Inf k)))  (kd. B * content k)"
  proof (rule sum_mono)
    fix k assume kd: "k  d"
    from division_ofD(2,3,4)[OF dt(1) kd] obtain l u where
      k_eq: "k = cbox l u" and ksub: "k  t" and kne: "k  {}" by auto
    then have lu: "l  u" by fastforce
    obtain ls: "l  {0..1}" and us: "u  {0..1}"
      using ksub dt(2) lu k_eq cbox_interval atLeastAtMost_iff by blast
    have "norm (g (Sup k) - g (Inf k)) = norm (g u - g l)"
      using lu k_eq by (simp add: cbox_interval)
    also have "  B * norm (u - l)"
      using assms[OF us ls] by (simp add: norm_minus_commute)
    also have " = B * (u - l)" using lu by (simp add: real_norm_def)
    also have " = B * content k"
      using lu k_eq by (simp add: cbox_interval)
    finally show "norm (g (Sup k) - g (Inf k))  B * content k" .
  qed
  also have " = B * (kd. content k)" by (simp add: sum_distrib_left)
  also have "  B * 1"
  proof (intro mult_left_mono B0)
    have "(kd. content k)  content {0..1::real}"
      using subadditive_content_division[OF dt(1)] dt(2) by force
    then show "(kd. content k)  1" by simp
  qed
  finally show "(kd. norm (g (Sup k) - g (Inf k)))  B" by simp
qed


lemma dist_points_le_path_length:
  "rectifiable_path g; a  {0..1}; b  {0..1} 
    dist (g a) (g b)  path_length g"
  unfolding rectifiable_path_def path_length_def dist_norm
  using vector_variation_ge_norm_function by blast

lemma dist_endpoints_le_path_length:
  "rectifiable_path g  dist (pathstart g) (pathfinish g)  path_length g"
  using dist_points_le_path_length[of g 0 1]
  by (simp add: pathstart_def pathfinish_def)

lemma path_length_eq_line_segment:
  assumes rect: "rectifiable_path g"
    and len: "path_length g = dist (pathstart g) (pathfinish g)"
  shows "path_image g = closed_segment (pathstart g) (pathfinish g)"
proof (rule equalityI)
  have pg: "path g" and bv: "has_bounded_variation_on g {0..1}"
    using rect unfolding rectifiable_path_def by auto
  have vv_eq: "vector_variation {0..1} g = norm (g 1 - g 0)"
    using len unfolding path_length_def pathstart_def pathfinish_def dist_norm
    by (simp add: norm_minus_commute)
  show sub: "path_image g  closed_segment (pathstart g) (pathfinish g)"
  proof
    fix x assume "x  path_image g"
    then obtain t where t: "t  {0..1}" "x = g t"
      unfolding path_image_def by auto
    have t01: "0  t" "t  1" using t(1) by auto
    have bv_0t: "has_bounded_variation_on g {0..t}"
      using has_bounded_variation_on_subset[OF bv] t(1) by auto
    have bv_t1: "has_bounded_variation_on g {t..1}"
      using has_bounded_variation_on_subset[OF bv] t(1) by auto
    have n1: "norm (g t - g 0)  vector_variation {0..t} g"
      using vector_variation_ge_norm_function[OF bv_0t] t01 by auto
    have n2: "norm (g 1 - g t)  vector_variation {t..1} g"
      using vector_variation_ge_norm_function[OF bv_t1] t01 by auto
    have split: "vector_variation {0..t} g + vector_variation {t..1} g =
      vector_variation {0..1} g"
      using vector_variation_combine[OF bv] t(1) by auto
    have tri: "norm (g 1 - g 0)  norm (g t - g 0) + norm (g 1 - g t)"
      using norm_triangle_ineq[of "g t - g 0" "g 1 - g t"] by simp
    have "norm (g t - g 0) + norm (g 1 - g t) = norm (g 1 - g 0)"
      using n1 n2 split vv_eq tri by linarith
    then have "dist (g 0) (g 1) = dist (g 0) (g t) + dist (g t) (g 1)"
      by (simp add: dist_norm norm_minus_commute)
    then have "between (g 0, g 1) (g t)"
      unfolding between by simp
    then show "x  closed_segment (pathstart g) (pathfinish g)"
      unfolding t(2) pathstart_def pathfinish_def between_mem_segment by simp
  qed
  show "closed_segment (pathstart g) (pathfinish g)  path_image g"
  proof -
    have ne: "path_image g  {}"
      unfolding path_image_def by auto
    have compact: "compact (path_image g)"
      using compact_path_image[OF pg] .
    have conn: "connected (path_image g)"
      using connected_path_image[OF pg] .
    have col: "collinear (path_image g)"
    proof -
      from sub have "path_image g  closed_segment (pathstart g) (pathfinish g)" .
      moreover have "collinear (closed_segment (pathstart g) (pathfinish g))"
        by (rule collinear_closed_segment)
      ultimately show ?thesis
        unfolding collinear_def by (meson subsetD)
    qed
    obtain p q where pq: "path_image g = closed_segment p q"
      using compact_convex_collinear_segment_alt[OF ne compact conn col] by auto
    have "pathstart g  path_image g"
      unfolding path_image_def pathstart_def by auto
    moreover have "pathfinish g  path_image g"
      unfolding path_image_def pathfinish_def by auto
    ultimately have "pathstart g  closed_segment p q" "pathfinish g  closed_segment p q"
      using pq by auto
    then have "closed_segment (pathstart g) (pathfinish g)  closed_segment p q"
      using subset_closed_segment by blast
    then show ?thesis using pq by simp
  qed
qed

section ‹Linepath›

lemma rectifiable_path_linepath:
  "rectifiable_path (linepath a b)"
proof (rule lipschitz_imp_rectifiable_path[where B="dist a b"])
  fix x y :: real assume "x  {0..1}" "y  {0..1}"
  have "linepath a b x - linepath a b y = (x - y) *R (b - a)"
    by (simp add: linepath_def algebra_simps)
  then have "norm (linepath a b x - linepath a b y) = ¦x - y¦ * norm (b - a)"
    by simp
  also have " = norm (b - a) * norm (x - y)"
    by (simp add: abs_real_def real_norm_def mult.commute)
  also have " = dist a b * norm (x - y)"
    by (simp add: dist_norm norm_minus_commute)
  finally show "norm (linepath a b x - linepath a b y)  dist a b * norm (x - y)"
    by simp
qed

lemma path_length_linepath:
  "path_length (linepath a b) = dist a b"
proof (rule antisym)
  show "path_length (linepath a b)  dist a b"
  proof (rule path_length_lipschitz)
    fix x y :: real assume "x  {0..1}" "y  {0..1}"
    have "linepath a b x - linepath a b y = (x - y) *R (b - a)"
      by (simp add: linepath_def algebra_simps)
    then have "norm (linepath a b x - linepath a b y) = ¦x - y¦ * norm (b - a)"
      by simp
    also have " = dist a b * norm (x - y)"
      by (simp add: dist_norm norm_minus_commute abs_real_def real_norm_def mult.commute)
    finally show "norm (linepath a b x - linepath a b y)  dist a b * norm (x - y)"
      by simp
  qed
next
  have "dist a b = dist (pathstart (linepath a b)) (pathfinish (linepath a b))"
    by (simp add: pathstart_def pathfinish_def linepath_def dist_norm)
  also have "  path_length (linepath a b)"
    by (rule dist_endpoints_le_path_length[OF rectifiable_path_linepath])
  finally show "dist a b  path_length (linepath a b)" .
qed

section ‹Rectifiable path image bound›

lemma rectifiable_path_image_subset_cball:
  assumes "rectifiable_path g"
  shows "path_image g  cball (pathstart g) (path_length g)"
proof
  fix x assume "x  path_image g"
  then obtain t where t: "t  {0..1}" "x = g t"
    unfolding path_image_def by auto
  have "dist (pathstart g) x = dist (g 0) (g t)"
    by (simp add: t(2) pathstart_def)
  also have "  path_length g"
    using dist_points_le_path_length[OF assms _ t(1)] by simp
  finally show "x  cball (pathstart g) (path_length g)"
    by (simp add: mem_cball)
qed

end