Theory Polyline_Path

(*
  File:     Polyline_Path.thy
  Author:   Manuel Eberl, University of Innsbruck
*)
section ‹Building a path from a list of points›
theory Polyline_Path
  imports "HOL-Library.Sublist" "Path_Automation.Path_Automation"
begin

(* TODO Move *)
lemma weak_wf_pathlist_altdef:
  "weak_wf_pathlist ps  ps  []  successively (λp q. pathfinish p = pathstart q) ps"
  by (induction ps rule: weak_wf_pathlist.induct) auto

(* TODO Move *)
lemma path_image_joinpaths_list_subset:
  "ps  []  path_image (joinpaths_list ps)  (pset ps. path_image p)"
  by (induction ps rule: joinpaths_list.induct) (use path_image_join_subset in auto)

definition polyline_path :: "'a :: real_normed_vector list  real  'a" where
  "polyline_path xs =
     (if length xs = 1 then linepath (hd xs) (hd xs) else joinpaths_list (map2 linepath xs (tl xs)))"

lemma pathstart_polyline_path:
  assumes "xs  []"
  shows   "pathstart (polyline_path xs) = hd xs"
proof (cases "length xs = 1")
  case False
  hence "tl xs  []"
    using assms by (cases xs) auto
  thus ?thesis using assms
    by (auto simp: polyline_path_def pathstart_joinpaths_list hd_map case_prod_unfold hd_zip)
qed (auto simp: polyline_path_def)

lemma pathfinish_polyline_path:
  assumes "xs  []"
  shows   "pathfinish (polyline_path xs) = last xs"
proof (cases "length xs = 1")
  case True
  thus ?thesis
    by (cases xs) (auto simp: polyline_path_def)
next
  case False
  from assms have "length xs  0"
    by auto
  with False have "length xs  2"
    by linarith    
  from False have *: "tl xs  []"
    using assms by (cases xs) auto
  have "last (zip xs (tl xs)) = zip xs (tl xs) ! (length xs - 2)"
    using False * by (subst last_conv_nth) (auto simp: eval_nat_numeral)
  also have "snd  = xs ! (length xs - 1)"
    using length xs  2 by (subst nth_zip) (auto simp: nth_tl simp flip: Suc_diff_le)
  also have " = last xs"
    using length xs  2 by (subst last_conv_nth) auto
  finally show ?thesis using assms False *
    by (auto simp: polyline_path_def pathfinish_joinpaths_list last_map case_prod_unfold)
qed

lemma polyline_path_welldefined:
  assumes "xs  []"
  shows   "successively (λp q. pathfinish p = pathstart q) (map2 linepath xs (tl xs))"
proof (cases "length xs = 1")
  case True
  thus ?thesis
    by (cases xs) auto
next
  case False
  have "length xs  0"
    using assms by auto
  with False have "length xs  2"
    by linarith
  thus "successively (λp q. pathfinish p = pathstart q) (map2 linepath xs (tl xs))"
  proof (induction xs rule: induct_list012)
    case (3 x y zs)
    have IH: 
      "successively (λp q. pathfinish p = pathstart q) (map2 linepath (y # zs) (tl (y # zs)))"
      if "zs  []"
      by (rule "3.IH") (use zs  [] in auto intro!: Suc_leI)
    show ?case using IH
      by (auto simp: successively_Cons hd_map hd_zip)
  qed auto
qed

lemma valid_path_polyline_path [simp, intro]: "valid_path (polyline_path xs)"
proof -
  consider "length xs = 0" | "length xs = 1" | "length xs  2"
    by linarith
  thus ?thesis
  proof cases
    assume "length xs  2"
    hence [simp]: "tl xs  []" "xs  []"
      by (cases xs; force)+
    have "valid_path (joinpaths_list (map2 linepath xs (tl xs)))"
    proof (rule valid_path_joinpaths_list)
      show "valid_path_pathlist (map2 linepath xs (tl xs))"
        unfolding valid_path_pathlist_altdef
        using length xs  2 by (simp add: list.pred_map o_def case_prod_unfold list.pred_True)
    next
      have "successively (λp q. pathfinish p = pathstart q) (map2 linepath xs (tl xs))"
        using length xs  2 by (intro polyline_path_welldefined) auto
      thus "weak_wf_pathlist (map2 linepath xs (tl xs))"
        unfolding weak_wf_pathlist_altdef using length xs  2 by auto
    qed
    thus ?thesis
      using length xs  2 by (simp add: polyline_path_def)
  qed (auto simp: polyline_path_def)
qed

lemma path_polyline_path [simp, intro]: "path (polyline_path xs)"
  by (rule valid_path_imp_path) auto

lemma polyline_path_subset_convex:
  assumes "convex A" "set xs  A" and [simp]: "xs  []"
  shows   "path_image (polyline_path xs)  A"
proof (cases "length xs = 1")
  case True
  thus ?thesis
    using assms by (cases xs) (auto simp: polyline_path_def)
next
  case False
  have "length xs  0"
    by auto
  with False have "length xs  2"
    by linarith
  have [simp]: "tl xs  []"
    using length xs  2 by (cases xs) auto

  have "path_image (polyline_path xs) = path_image (joinpaths_list (map2 linepath xs (tl xs)))"
    using length xs  2 unfolding polyline_path_def by simp
  also have "  (lset (map2 linepath xs (tl xs)). path_image l)"
    by (rule path_image_joinpaths_list_subset) auto
  also have "  (xset xs. yset (tl xs). closed_segment x y)"
    using length xs  2 by (fastforce dest: set_zip_leftD set_zip_rightD)
  also have "  (xset xs. yset xs. closed_segment x y)"
    by (cases xs) auto
  also have "  A"
    by (intro UN_least closed_segment_subset) (use assms in auto)
  finally show ?thesis .
qed

lemma contour_integral_polyline_path:
  assumes "f contour_integrable_on (polyline_path ps)"
  assumes "ps  []"
  shows   "contour_integral (polyline_path ps) f =
             (i<length ps-1. contour_integral (linepath (ps ! i) (ps ! Suc i)) f)"
proof (cases "length ps  2")
  case True
  have [simp]: "ps  []" "tl ps  []"
    using True by (cases ps; force)+
  have "contour_integral (polyline_path ps) f =
          contour_integral (joinpaths_list (map2 linepath ps (tl ps))) f "
    unfolding polyline_path_def using True by simp
  also have " = (pmap2 linepath ps (tl ps). contour_integral p f)"
    using polyline_path_welldefined[of ps] assms True
    by (subst contour_integral_joinpaths_list) 
       (auto simp: valid_path_pathlist_altdef weak_wf_pathlist_altdef 
                   list.pred_set list.pred_True polyline_path_def)
  also have " = (i<length ps-1. contour_integral (linepath (ps ! i) (tl ps ! i)) f)"
    by (subst sum.list_conv_set_nth) (auto simp: atLeast0LessThan)
  also have " = (i<length ps-1. contour_integral (linepath (ps ! i) (ps ! Suc i)) f)"
    by (intro sum.cong) (auto simp: nth_tl)
  finally show ?thesis .
next
  case False
  from ps  [] have "length ps  0"
    by auto
  hence "length ps = 1"
    using False by linarith
  thus ?thesis
    by (auto simp: polyline_path_def)
qed

end