Theory Affine_Arithmetic.Counterclockwise
section ‹Counterclockwise›
theory Counterclockwise
imports "HOL-Analysis.Multivariate_Analysis"
begin
text ‹\label{sec:counterclockwise}›
subsection ‹Auxiliary Lemmas›
lemma convex3_alt:
fixes x y z::"'a::real_vector"
assumes "0 ≤ a" "0 ≤ b" "0 ≤ c" "a + b + c = 1"
obtains u v where "a *⇩R x + b *⇩R y + c *⇩R z = x + u *⇩R (y - x) + v *⇩R (z - x)"
and "0 ≤ u" "0 ≤ v" "u + v ≤ 1"
proof -
from convex_hull_3[of x y z] have "a *⇩R x + b *⇩R y + c *⇩R z ∈ convex hull {x, y, z}"
using assms by auto
also note convex_hull_3_alt
finally obtain u v where "a *⇩R x + b *⇩R y + c *⇩R z = x + u *⇩R (y - x) + v *⇩R (z - x)"
and uv: "0 ≤ u" "0 ≤ v" "u + v ≤ 1"
by auto
thus ?thesis ..
qed
lemma (in ordered_ab_group_add) add_nonpos_eq_0_iff:
assumes x: "0 ≥ x" and y: "0 ≥ y"
shows "x + y = 0 ⟷ x = 0 ∧ y = 0"
proof -
from add_nonneg_eq_0_iff[of "-x" "-y"] assms
have "- (x + y) = 0 ⟷ - x = 0 ∧ - y = 0"
by simp
also have "(- (x + y) = 0) = (x + y = 0)" unfolding neg_equal_0_iff_equal ..
finally show ?thesis by simp
qed
lemma sum_nonpos_eq_0_iff:
fixes f :: "'a ⇒ 'b::ordered_ab_group_add"
shows "⟦finite A; ∀x∈A. f x ≤ 0⟧ ⟹ sum f A = 0 ⟷ (∀x∈A. f x = 0)"
by (induct set: finite) (simp_all add: add_nonpos_eq_0_iff sum_nonpos)
lemma fold_if_in_set:
"fold (λx m. if P x m then x else m) xs x ∈ set (x#xs)"
by (induct xs arbitrary: x) auto
subsection ‹Sort Elements of a List›
locale linorder_list0 = fixes le::"'a ⇒ 'a ⇒ bool"
begin
definition "min_for a b = (if le a b then a else b)"
lemma min_for_in[simp]: "x ∈ S ⟹ y ∈ S ⟹ min_for x y ∈ S"
by (auto simp: min_for_def)
lemma fold_min_eqI1: "fold min_for ys y ∉ set ys ⟹ fold min_for ys y = y"
using fold_if_in_set[of _ ys y]
by (auto simp: min_for_def[abs_def])
function selsort where
"selsort [] = []"
| "selsort (y#ys) = (let
xm = fold min_for ys y;
xs' = List.remove1 xm (y#ys)
in (xm#selsort xs'))"
by pat_completeness auto
termination
by (relation "Wellfounded.measure length")
(auto simp: length_remove1 intro!: fold_min_eqI1 dest!: length_pos_if_in_set)
lemma in_set_selsort_eq: "x ∈ set (selsort xs) ⟷ x ∈ (set xs)"
by (induct rule: selsort.induct) (auto simp: Let_def intro!: fold_min_eqI1)
lemma set_selsort[simp]: "set (selsort xs) = set xs"
using in_set_selsort_eq by blast
lemma length_selsort[simp]: "length (selsort xs) = length xs"
proof (induct xs rule: selsort.induct)
case (2 x xs)
from 2[OF refl refl]
show ?case
unfolding selsort.simps
by (auto simp: Let_def length_remove1
simp del: selsort.simps split: if_split_asm
intro!: Suc_pred
dest!: fold_min_eqI1)
qed simp
lemma distinct_selsort[simp]: "distinct (selsort xs) = distinct xs"
by (auto intro!: card_distinct dest!: distinct_card)
lemma selsort_eq_empty_iff[simp]: "selsort xs = [] ⟷ xs = []"
by (cases xs) (auto simp: Let_def)
inductive sortedP :: "'a list ⇒ bool" where
Nil: "sortedP []"
| Cons: "∀y∈set ys. le x y ⟹ sortedP ys ⟹ sortedP (x # ys)"
inductive_cases
sortedP_Nil: "sortedP []" and
sortedP_Cons: "sortedP (x#xs)"
inductive_simps
sortedP_Nil_iff: "sortedP Nil" and
sortedP_Cons_iff: "sortedP (Cons x xs)"
lemma sortedP_append_iff:
"sortedP (xs @ ys) = (sortedP xs & sortedP ys & (∀x ∈ set xs. ∀y ∈ set ys. le x y))"
by (induct xs) (auto intro!: Nil Cons elim!: sortedP_Cons)
lemma sortedP_appendI:
"sortedP xs ⟹ sortedP ys ⟹ (⋀x y. x ∈ set xs ⟹ y ∈ set ys ⟹ le x y) ⟹ sortedP (xs @ ys)"
by (induct xs) (auto intro!: Nil Cons elim!: sortedP_Cons)
lemma sorted_nth_less: "sortedP xs ⟹ i < j ⟹ j < length xs ⟹ le (xs ! i) (xs ! j)"
by (induct xs arbitrary: i j) (auto simp: nth_Cons split: nat.split elim!: sortedP_Cons)
lemma sorted_butlastI[intro, simp]: "sortedP xs ⟹ sortedP (butlast xs)"
by (induct xs) (auto simp: elim!: sortedP_Cons intro!: sortedP.Cons dest!: in_set_butlastD)
lemma sortedP_right_of_append1:
assumes "sortedP (zs@[z])"
assumes "y ∈ set zs"
shows "le y z"
using assms
by (induct zs arbitrary: y z) (auto elim!: sortedP_Cons)
lemma sortedP_right_of_last:
assumes "sortedP zs"
assumes "y ∈ set zs" "y ≠ last zs"
shows "le y (last zs)"
using assms
apply (intro sortedP_right_of_append1[of "butlast zs" "last zs" y])
subgoal by (metis append_is_Nil_conv list.distinct(1) snoc_eq_iff_butlast split_list)
subgoal by (metis List.insert_def append_butlast_last_id insert_Nil list.distinct(1) rotate1.simps(2)
set_ConsD set_rotate1)
done
lemma selsort_singleton_iff: "selsort xs = [x] ⟷ xs = [x]"
by (induct xs) (auto simp: Let_def)
lemma hd_last_sorted:
assumes "sortedP xs" "length xs > 1"
shows "le (hd xs) (last xs)"
proof (cases xs)
case (Cons y ys)
note ys = this
thus ?thesis
using ys assms
by (auto elim!: sortedP_Cons)
qed (insert assms, simp)
end
lemma (in comm_monoid_add) sum_list_distinct_selsort:
assumes "distinct xs"
shows "sum_list (linorder_list0.selsort le xs) = sum_list xs"
using assms
apply (simp add: distinct_sum_list_conv_Sum linorder_list0.distinct_selsort)
apply (rule sum.cong)
subgoal by (simp add: linorder_list0.set_selsort)
subgoal by simp
done
declare linorder_list0.sortedP_Nil_iff[code]
linorder_list0.sortedP_Cons_iff[code]
linorder_list0.selsort.simps[code]
linorder_list0.min_for_def[code]
locale linorder_list = linorder_list0 le for le::"'a::ab_group_add ⇒ _" +
fixes S
assumes order_refl: "a ∈ S ⟹ le a a"
assumes trans': "a ∈ S ⟹ b ∈ S ⟹ c ∈ S ⟹ a ≠ b ⟹ b ≠ c ⟹ a ≠ c ⟹
le a b ⟹ le b c ⟹ le a c"
assumes antisym: "a ∈ S ⟹ b ∈ S ⟹ le a b ⟹ le b a ⟹ a = b"
assumes linear': "a ∈ S ⟹ b ∈ S ⟹ a ≠ b ⟹ le a b ∨ le b a"
begin
lemma trans: "a ∈ S ⟹ b ∈ S ⟹ c ∈ S ⟹ le a b ⟹ le b c ⟹ le a c"
by (cases "a = b" "b = c" "a = c"
rule: bool.exhaust[case_product bool.exhaust[case_product bool.exhaust]])
(auto simp: order_refl intro: trans')
lemma linear: "a ∈ S ⟹ b ∈ S ⟹ le a b ∨ le b a"
by (cases "a = b") (auto simp: linear' order_refl)
lemma min_le1: "w ∈ S ⟹ y ∈ S ⟹ le (min_for w y) y"
and min_le2: "w ∈ S ⟹ y ∈ S ⟹ le (min_for w y) w"
using linear
by (auto simp: min_for_def refl)
lemma fold_min:
assumes "set xs ⊆ S"
shows "list_all (λy. le (fold min_for (tl xs) (hd xs)) y) xs"
proof (cases xs)
case (Cons y ys)
hence subset: "set (y#ys) ⊆ S" using assms
by auto
show ?thesis
unfolding Cons list.sel
using subset
proof (induct ys arbitrary: y)
case (Cons z zs)
hence IH: "⋀y. y ∈ S ⟹ list_all (le (fold min_for zs y)) (y # zs)"
by simp
let ?f = "fold min_for zs (min_for z y)"
have "?f ∈ set ((min_for z y)#zs)"
unfolding min_for_def[abs_def]
by (rule fold_if_in_set)
also have "… ⊆ S" using Cons.prems by auto
finally have "?f ∈ S" .
have "le ?f (min_for z y)"
using IH[of "min_for z y"] Cons.prems
by auto
moreover have "le (min_for z y) y" "le (min_for z y) z" using Cons.prems
by (auto intro!: min_le1 min_le2)
ultimately have "le ?f y" "le ?f z" using Cons.prems ‹?f ∈ S›
by (auto intro!: trans[of ?f "min_for z y"])
thus ?case
using IH[of "min_for z y"]
using Cons.prems
by auto
qed (simp add: order_refl)
qed simp
lemma
sortedP_selsort:
assumes "set xs ⊆ S"
shows "sortedP (selsort xs)"
using assms
proof (induction xs rule: selsort.induct)
case (2 z zs)
from this fold_min[of "z#zs"]
show ?case
by (fastforce simp: list_all_iff Let_def
simp del: remove1.simps
intro: Cons intro!: 2(1)[OF refl refl]
dest!: rev_subsetD[OF _ set_remove1_subset])+
qed (auto intro!: Nil)
end
subsection ‹Abstract CCW Systems›
locale ccw_system0 =
fixes ccw::"'a ⇒ 'a ⇒ 'a ⇒ bool"
and S::"'a set"
begin
abbreviation "indelta t p q r ≡ ccw t q r ∧ ccw p t r ∧ ccw p q t"
abbreviation "insquare p q r s ≡ ccw p q r ∧ ccw q r s ∧ ccw r s p ∧ ccw s p q"
end
abbreviation "distinct3 p q r ≡ ¬(p = q ∨ p = r ∨ q = r)"
abbreviation "distinct4 p q r s ≡ ¬(p = q ∨ p = r ∨ p = s ∨ ¬ distinct3 q r s)"
abbreviation "distinct5 p q r s t ≡ ¬(p = q ∨ p = r ∨ p = s ∨ p = t ∨ ¬ distinct4 q r s t)"
abbreviation "in3 S p q r ≡ p ∈ S ∧ q ∈ S ∧ r ∈ S"
abbreviation "in4 S p q r s ≡ in3 S p q r ∧ s ∈ S"
abbreviation "in5 S p q r s t ≡ in4 S p q r s ∧ t ∈ S"
locale ccw_system12 = ccw_system0 +
assumes cyclic: "ccw p q r ⟹ ccw q r p"
assumes ccw_antisym: "distinct3 p q r ⟹ in3 S p q r ⟹ ccw p q r ⟹ ¬ ccw p r q"
locale ccw_system123 = ccw_system12 +
assumes nondegenerate: "distinct3 p q r ⟹ in3 S p q r ⟹ ccw p q r ∨ ccw p r q"
begin
lemma not_ccw_eq: "distinct3 p q r ⟹ in3 S p q r ⟹ ¬ ccw p q r ⟷ ccw p r q"
using ccw_antisym nondegenerate by blast
end
locale ccw_system4 = ccw_system123 +
assumes interior:
"distinct4 p q r t ⟹ in4 S p q r t ⟹ ccw t q r ⟹ ccw p t r ⟹ ccw p q t ⟹ ccw p q r"
begin
lemma interior':
"distinct4 p q r t ⟹ in4 S p q r t ⟹ ccw p q t ⟹ ccw q r t ⟹ ccw r p t ⟹ ccw p q r"
by (metis ccw_antisym cyclic interior nondegenerate)
end
locale ccw_system1235' = ccw_system123 +
assumes dual_transitive:
"distinct5 p q r s t ⟹ in5 S p q r s t ⟹
ccw s t p ⟹ ccw s t q ⟹ ccw s t r ⟹ ccw t p q ⟹ ccw t q r ⟹ ccw t p r"
locale ccw_system1235 = ccw_system123 +
assumes transitive: "distinct5 p q r s t ⟹ in5 S p q r s t ⟹
ccw t s p ⟹ ccw t s q ⟹ ccw t s r ⟹ ccw t p q ⟹ ccw t q r ⟹ ccw t p r"
begin
lemmas ccw_axioms = cyclic nondegenerate ccw_antisym transitive
sublocale ccw_system1235'
proof (unfold_locales, rule ccontr, goal_cases)
case prems: (1 p q r s t)
hence "ccw s p q ⟹ ccw s r p"
by (metis ccw_axioms prems)
moreover
have "ccw s r p ⟹ ccw s q r"
by (metis ccw_axioms prems)
moreover
have "ccw s q r ⟹ ccw s p q"
by (metis ccw_axioms prems)
ultimately
have "ccw s p q ∧ ccw s r p ∧ ccw s q r ∨ ccw s q p ∧ ccw s p r ∧ ccw s r q"
by (metis ccw_axioms prems)
thus False
by (metis ccw_axioms prems)
qed
end
locale ccw_system = ccw_system1235 + ccw_system4
end