Theory Dijkstra_Shortest_Path.Weight
section "Weights for Dijkstra's Algorithm"
theory Weight
imports Complex_Main
begin
text ‹
  In this theory, we set up a type class for weights, and
  a typeclass for weights with an infinity element. The latter
  one is used internally in Dijkstra's algorithm.
  Moreover, we provide a datatype that adds an infinity element to a given
  base type.
›
subsection ‹Type Classes Setup›
class weight = ordered_ab_semigroup_add + comm_monoid_add + linorder
begin
lemma add_nonneg_nonneg [simp]:
  assumes "0 ≤ a" and "0 ≤ b" shows "0 ≤ a + b"
proof -
  have "0 + 0 ≤ a + b" 
    using assms by (rule add_mono)
  then show ?thesis by simp
qed
lemma add_nonpos_nonpos[simp]:
  assumes "a ≤ 0" and "b ≤ 0" shows "a + b ≤ 0"
proof -
  have "a + b ≤ 0 + 0"
    using assms by (rule add_mono)
  then show ?thesis by simp
qed
lemma add_nonneg_eq_0_iff:
  assumes x: "0 ≤ x" and y: "0 ≤ y"
  shows "x + y = 0 ⟷ x = 0 ∧ y = 0"
  by (metis local.add_0_left local.add_0_right local.add_left_mono local.antisym_conv x y)
lemma add_incr: "0≤b ⟹ a ≤ a+b"
  by (metis add.comm_neutral add_left_mono)
lemma add_incr_left[simp, intro!]: "0≤b ⟹ a ≤ b + a"
  by (metis add_incr add.commute)
lemma sum_not_less[simp, intro!]: 
  "0≤b ⟹ ¬ (a+b < a)"
  "0≤a ⟹ ¬ (a+b < b)"
  apply (metis add_incr less_le_not_le)
  apply (metis add_incr_left less_le_not_le)
  done
end
instance nat :: weight ..
instance int :: weight ..
instance rat :: weight ..
instance real :: weight ..
term top
class top_weight = order_top + weight +
  assumes inf_add_right[simp]: "a + top = top"
begin
lemma inf_add_left[simp]: "top + a = top"
  by (metis add.commute inf_add_right)
lemmas [simp] = top_unique less_top[symmetric]
  
lemma not_less_inf[simp]:
  "¬ (a < top) ⟷ a=top"
  by simp
  
end
subsection ‹Adding Infinity›
text ‹
  We provide a standard way to add an infinity element to any type.
›