Theory BMSSP_Range_Costed

theory BMSSP_Range_Costed
  imports BMSSP_Complexity
begin

section ‹Range-Synchronised Costed Runs›

text ‹
  The algorithm's time proof charges the recursive calls in one BMSSP loop to
  the disjoint distance ranges cut out by the successive returned bounds.  The
  earlier costed relation keeps enough information for correctness and local
  data-structure costs, but its child-call cost is attached to the raw child
  output.  This theory strengthens the operational run with the range invariant:
  every child output is exactly the next range slice.

  That strengthening is the point at which the informal amortised analysis in
  the paper becomes a reusable Isabelle recurrence.  A child call is not charged
  against the whole parent tree.  It is charged against a slice
  range_tree› between the previous loop bound and the child output
  bound.  The list version range_tree_child_list› records all such
  slices for one parent loop.  Since those slices are disjoint and lie inside
  the final loop output, their vertex and outgoing-edge sums can be bounded by
  the final output itself.

  The exported cost shape is level_range_cost_bound›.  Its first term
  counts completed vertices multiplied by a level factor; its second term counts
  outgoing edges with the range cost coefficient.  The main technical work below
  is to show that the local costs of pulling, batching, and recursive child
  calls close under this shape when moving from level l› to Suc l›.

  There are two related relations.  The first one uses a single batch cost
  parameter for the concatenation of edge relaxations and reinserted source
  labels.  The split relation refines it by charging edge batches and source
  batches separately.  That split form is useful for later progress arguments:
  edge batches are paid for by outgoing edges of the completed ranges, while
  source batches are paid for by the number of child sources exposed by the
  partition pulls.
›

context unique_shortest_digraph
begin

lemma child_costs_le_level_range_child_list_bound:
  assumes mono: "nondecreasing_from a bs"
    and costs: "list_all2 (λc X. c  level_range_cost_bound A R l X) costs
      (range_tree_child_list S a bs)"
  shows "sum_list costs 
    A * l * card (range_tree_chain S a bs B) +
    R * card (outgoing_edges (range_tree_chain S a bs B))"
proof -
  define Xs where "Xs = range_tree_child_list S a bs"
  have cost_sum:
    "sum_list costs  sum_list (map (level_range_cost_bound A R l) Xs)"
    using costs unfolding Xs_def
  proof (induction rule: list_all2_induct)
    case Nil
    then show ?case by simp
  next
    case (Cons c X costs Xs)
    then show ?case
      unfolding level_range_cost_bound_def by simp
  qed
  have split_sum:
    "sum_list (map (level_range_cost_bound A R l) Xs) =
      A * l * sum_list (map card Xs) +
      R * sum_list (map (λX. card (outgoing_edges X)) Xs)"
  proof (induction Xs)
    case Nil
    then show ?case
      unfolding level_range_cost_bound_def by simp
  next
    case (Cons X Xs)
    then show ?case
      unfolding level_range_cost_bound_def by (simp add: algebra_simps)
  qed
  have card_sum:
    "sum_list (map card Xs)  card (range_tree_chain S a bs B)"
    unfolding Xs_def
    by (rule card_range_tree_child_list_le_chain[OF mono])
  have edge_sum:
    "sum_list (map (λX. card (outgoing_edges X)) Xs) 
      card (outgoing_edges (range_tree_chain S a bs B))"
    unfolding Xs_def
    by (rule card_outgoing_edges_range_tree_child_list_le_chain[OF mono])
  have "sum_list (map (level_range_cost_bound A R l) Xs) 
      A * l * card (range_tree_chain S a bs B) +
      R * card (outgoing_edges (range_tree_chain S a bs B))"
  proof -
    have left:
      "A * l * sum_list (map card Xs) 
        A * l * card (range_tree_chain S a bs B)"
      using card_sum by simp
    have right:
      "R * sum_list (map (λX. card (outgoing_edges X)) Xs) 
        R * card (outgoing_edges (range_tree_chain S a bs B))"
      using edge_sum by simp
    show ?thesis
      using left right split_sum by linarith
  qed
  then show ?thesis
    using cost_sum by linarith
qed

inductive range_costed_partition_loop_state
  and range_costed_bmssp where
  Range_State_Done:
    "keys_of D = {} 
     bound_le (Fin a) B 
     complete_on d' (bound_tree P B) 
     range_costed_partition_loop_state Δ M_of t k cap l d P B d' D a
       [] [] B [range_tree P a B]
       (bound_tree P (Fin a)  (set [range_tree P a B])) 0 []"
| Range_State_Stop:
    "bound_le (Fin a) B 
     complete_on d' (bound_tree P (Fin a)) 
     k * cap  card (bound_tree P (Fin a)) 
     range_costed_partition_loop_state Δ M_of t k cap l d P B d' D a
       [] [] (Fin a) [range_tree P a (Fin a)]
       (bound_tree P (Fin a)  (set [range_tree P a (Fin a)])) 0 []"
| Range_State_Step:
    "pull_separates D (M_of l) Bmax S_pull beta D_pull 
     bound_le (Fin beta) B 
     bmssp_pre_full d S_pull (Fin beta) 
     (xS_pull. reachable s x) 
     a  b 
     bound_le (Fin a) B' 
     complete_on d' (bound_tree P (Fin a)) 
     card (bound_tree P (Fin a)) < k * cap 
     range_costed_bmssp Δ M_of t k cap l d S_pull (Fin beta)
       d_child (Fin b) U_child c_child 
     U_child = range_tree P a (Fin b) 
     complete_preserved d_child d' U_child 
     batch =
       edge_relaxation_pairs_between d_child U_child b beta @
       label_pairs_between d S_pull b beta 
     D_next = batch_min_update D_pull batch 
     partition_pull_cost_bound c_pull S_pull 
     partition_batch_cost_bound c_batch t batch 
     range_costed_partition_loop_state Δ M_of t k cap l d P B d'
       D_next b betas bs B' Us_tail U_tail c_tail child_costs_tail 
     c = c_pull + c_batch + c_child + c_tail 
     range_costed_partition_loop_state Δ M_of t k cap l d P B d' D a
       (beta # betas) (b # bs) B'
       (range_tree P a (Fin b) # Us_tail)
       (bound_tree P (Fin a) 
        (set (range_tree P a (Fin b) # Us_tail))) c
       (c_child # child_costs_tail)"
| Range_Cost_Base:
    "S = {x} 
     range_costed_bmssp Δ M_of t k cap 0 d S B
       (λv. if v  base_case_vertices k x B then dist s v else d v)
       (base_case_bound k x B)
       (base_case_vertices k x B)
       (base_case_scan_cost Δ k x B)"
| Range_Cost_Step:
    "D = label_partition_view
       (find_pivots_label_capped k cap d S B)
       (find_pivots_pivots_capped k cap d S B) 
     partition_initial_insert_cost_bound c_insert t
      (find_pivots_pivots_capped k cap d S B) 
     range_costed_partition_loop_state Δ M_of t k cap l
       (find_pivots_label_capped k cap d S B)
       (find_pivots_pivots_capped k cap d S B) B d' D a betas bs B'
       Us U_loop c_loop child_costs_loop 
     complete_on d'
       {v  bound_tree S B'. find_pivots_label_capped k cap d S B v = dist s v} 
     U = U_loop 
       {v  bound_tree S B'. find_pivots_label_capped k cap d S B v = dist s v} 
     c = fp_iter_capped_scan_cost k cap d S S B + c_insert + c_loop 
     range_costed_bmssp Δ M_of t k cap (Suc l) d S B d' B' U c"

text ‹
  The mutually inductive relation above adds the accounting data that the
  operational theory intentionally omitted.  A loop derivation carries the pull
  bounds betas›, the child output bounds bs›, the concrete range slices
  Us›, a total cost c›, and the list of recursive child costs.  The step
  constructor synchronises these fields by requiring the returned child set to
  be exactly @{const range_tree} for the current interval.

  The BMSSP branch keeps the usual split between the base case and the recursive
  step.  In the recursive step, FindPivots pays the scan and initial insertion
  cost, then the range-synchronised loop pays all pulls, batches, and child
  calls.  The correctness argument later forgets the costs and reuses the
  operational trace theorem; the runtime argument keeps the cost and child-cost
  lists.
›

inductive_cases range_costed_bmssp_zeroE:
  "range_costed_bmssp Δ M_of t k cap 0 d S B d' B' U c"

inductive_cases range_costed_bmssp_SucE:
  "range_costed_bmssp Δ M_of t k cap (Suc l) d S B d' B' U c"

lemma range_costed_partition_loop_state_mono:
  assumes run:
    "range_costed_partition_loop_state Δ M_of t k cap l d P B d' D a
      betas bs B' Us U c child_costs"
  shows "nondecreasing_from a bs"
  using run by (induction) auto

theorem range_costed_partition_loop_state_child_call_ranges:
  assumes run:
    "range_costed_partition_loop_state Δ M_of t k cap l d P B d' D a
      betas bs B' Us U c child_costs"
  shows "length child_costs = length bs"
    and "list_all2
      (λc_child U_child. S_child B_child d_child B_child'.
        range_costed_bmssp Δ M_of t k cap l d S_child B_child
          d_child B_child' U_child c_child 
        bmssp_pre_full d S_child B_child 
        (xS_child. reachable s x) 
        card S_child  M_of l)
      child_costs (range_tree_child_list P a bs)"
  using run
  by (induction) (auto simp: pull_separates_def)

lemma range_costed_pull_cost_le_M:
  assumes pull: "pull_separates D M Bmax S beta D_pull"
    and cost: "partition_pull_cost_bound c S"
  shows "c  M"
proof -
  have "card S  M"
    using pull unfolding pull_separates_def by blast
  then show ?thesis
    using cost unfolding partition_pull_cost_bound_def by linarith
qed

lemma range_costed_batch_cost_le:
  assumes pre: "bmssp_pre_full d S (Fin beta)"
    and batch:
      "batch =
        edge_relaxation_pairs_between d_child U b beta @
        label_pairs_between d S b beta"
    and cost: "partition_batch_cost_bound c t batch"
    and card_S: "card S  M"
  shows "c  t * (card (outgoing_edges U) + M)"
proof -
  have S_subset: "S  V"
    using pre unfolding bmssp_pre_full_def by blast
  have finite_S: "finite S"
    using finite_subset[OF S_subset finite_V] .
  have edge_len:
    "length (edge_relaxation_pairs_between d_child U b beta) 
      card (outgoing_edges U)"
    by (rule edge_relaxation_pairs_between_length_le_outgoing)
  have label_len:
    "length (label_pairs_between d S b beta)  card S"
    by (rule label_pairs_between_length_le_card[OF finite_S])
  have batch_len: "length batch  card (outgoing_edges U) + M"
    using batch edge_len label_len card_S by simp
  have "c  t * length batch"
    using cost unfolding partition_batch_cost_bound_def by simp
  also have "  t * (card (outgoing_edges U) + M)"
    using batch_len by simp
  finally show ?thesis .
qed

lemma range_costed_split_batch_cost_le:
  assumes pre: "bmssp_pre_full d S (Fin beta)"
    and edge_cost:
      "partition_batch_cost_bound c_edges t
        (edge_relaxation_pairs_between d_child U b beta)"
    and source_cost:
      "partition_batch_cost_bound c_sources h
        (label_pairs_between d S b beta)"
    and c_def: "c = c_edges + c_sources"
    and card_S: "card S  M"
  shows "c  t * card (outgoing_edges U) + h * M"
proof -
  have S_subset: "S  V"
    using pre unfolding bmssp_pre_full_def by blast
  have finite_S: "finite S"
    using finite_subset[OF S_subset finite_V] .
  have edge_len:
    "length (edge_relaxation_pairs_between d_child U b beta) 
      card (outgoing_edges U)"
    by (rule edge_relaxation_pairs_between_length_le_outgoing)
  have label_len:
    "length (label_pairs_between d S b beta)  card S"
    by (rule label_pairs_between_length_le_card[OF finite_S])
  have edge_part: "c_edges  t * card (outgoing_edges U)"
  proof -
    have "c_edges  t * length (edge_relaxation_pairs_between d_child U b beta)"
      using edge_cost unfolding partition_batch_cost_bound_def by simp
    also have "  t * card (outgoing_edges U)"
      using edge_len by simp
    finally show ?thesis .
  qed
  have source_part: "c_sources  h * M"
  proof -
    have "c_sources  h * length (label_pairs_between d S b beta)"
      using source_cost unfolding partition_batch_cost_bound_def by simp
    also have "  h * card S"
      using label_len by simp
    also have "  h * M"
      using card_S by simp
    finally show ?thesis .
  qed
  show ?thesis
    using edge_part source_part c_def by linarith
qed

lemma range_costed_split_batch_cost_le_card:
  assumes pre: "bmssp_pre_full d S (Fin beta)"
    and edge_cost:
      "partition_batch_cost_bound c_edges t
        (edge_relaxation_pairs_between d_child U b beta)"
    and source_cost:
      "partition_batch_cost_bound c_sources h
        (label_pairs_between d S b beta)"
    and c_def: "c = c_edges + c_sources"
  shows "c  t * card (outgoing_edges U) + h * card S"
proof -
  have S_subset: "S  V"
    using pre unfolding bmssp_pre_full_def by blast
  have finite_S: "finite S"
    using finite_subset[OF S_subset finite_V] .
  have edge_len:
    "length (edge_relaxation_pairs_between d_child U b beta) 
      card (outgoing_edges U)"
    by (rule edge_relaxation_pairs_between_length_le_outgoing)
  have label_len:
    "length (label_pairs_between d S b beta)  card S"
    by (rule label_pairs_between_length_le_card[OF finite_S])
  have edge_part: "c_edges  t * card (outgoing_edges U)"
  proof -
    have "c_edges  t * length (edge_relaxation_pairs_between d_child U b beta)"
      using edge_cost unfolding partition_batch_cost_bound_def by simp
    also have "  t * card (outgoing_edges U)"
      using edge_len by simp
    finally show ?thesis .
  qed
  have source_part: "c_sources  h * card S"
  proof -
    have "c_sources  h * length (label_pairs_between d S b beta)"
      using source_cost unfolding partition_batch_cost_bound_def by simp
    also have "  h * card S"
      using label_len by simp
    finally show ?thesis .
  qed
  show ?thesis
    using edge_part source_part c_def by linarith
qed

lemma range_costed_split_batch_cost_le_range_card:
  assumes pre: "bmssp_pre_full d S (Fin beta)"
    and edge_cost:
      "partition_batch_cost_bound c_edges t
        (edge_relaxation_pairs_between d_child U b beta)"
    and source_cost:
      "partition_batch_cost_bound c_sources h
        (label_pairs_between d S b beta)"
    and complete: "complete_on d_child U"
    and reaches: "u. u  U  reachable s u"
    and c_def: "c = c_edges + c_sources"
  shows "c  t * card (outgoing_edges_range U b (Fin beta)) + h * card S"
proof -
  have S_subset: "S  V"
    using pre unfolding bmssp_pre_full_def by blast
  have finite_S: "finite S"
    using finite_subset[OF S_subset finite_V] .
  have edge_len:
    "length (edge_relaxation_pairs_between d_child U b beta) 
      card (outgoing_edges_range U b (Fin beta))"
    by (rule edge_relaxation_pairs_between_length_le_outgoing_edges_range
      [OF complete reaches])
  have label_len:
    "length (label_pairs_between d S b beta)  card S"
    by (rule label_pairs_between_length_le_card[OF finite_S])
  have edge_part:
    "c_edges  t * card (outgoing_edges_range U b (Fin beta))"
  proof -
    have "c_edges  t * length (edge_relaxation_pairs_between d_child U b beta)"
      using edge_cost unfolding partition_batch_cost_bound_def by simp
    also have "  t * card (outgoing_edges_range U b (Fin beta))"
      using edge_len by simp
    finally show ?thesis .
  qed
  have source_part: "c_sources  h * card S"
  proof -
    have "c_sources  h * length (label_pairs_between d S b beta)"
      using source_cost unfolding partition_batch_cost_bound_def by simp
    also have "  h * card S"
      using label_len by simp
    finally show ?thesis .
  qed
  show ?thesis
    using edge_part source_part c_def by linarith
qed

text ‹
  The single-batch relation is convenient, but the sharper progress lemmas need
  to distinguish where a batch entry came from.  Edge entries are generated by
  @{const edge_relaxation_pairs_between} and are charged to outgoing edges of
  the just-completed range.  Source entries are generated by
  @{const label_pairs_between} and are charged to the number of pulled child
  sources.  The split relation below records both costs explicitly.

  This is a refinement, not a different algorithm.  Its proof to the
  single-batch relation uses the append rule for @{const partition_batch_cost_bound}
  and the elementary fact that a source-batch coefficient bounded by the edge
  coefficient can be absorbed into the combined batch budget.
›

inductive split_range_costed_partition_loop_state
  and split_range_costed_bmssp where
  Split_Range_State_Done:
    "keys_of D = {} 
     bound_le (Fin a) B 
     complete_on d' (bound_tree P B) 
     split_range_costed_partition_loop_state Δ M_of t h k cap l d P B d' D a
       [] [] B [range_tree P a B]
       (bound_tree P (Fin a)  (set [range_tree P a B])) 0 []"
| Split_Range_State_Stop:
    "bound_le (Fin a) B 
     complete_on d' (bound_tree P (Fin a)) 
     k * cap  card (bound_tree P (Fin a)) 
     split_range_costed_partition_loop_state Δ M_of t h k cap l d P B d' D a
       [] [] (Fin a) [range_tree P a (Fin a)]
       (bound_tree P (Fin a)  (set [range_tree P a (Fin a)])) 0 []"
| Split_Range_State_Step:
    "pull_separates D (M_of l) Bmax S_pull beta D_pull 
     bound_le (Fin beta) B 
     bmssp_pre_full d S_pull (Fin beta) 
     (xS_pull. reachable s x) 
     a  b 
     bound_le (Fin a) B' 
     complete_on d' (bound_tree P (Fin a)) 
     card (bound_tree P (Fin a)) < k * cap 
     split_range_costed_bmssp Δ M_of t h k cap l d S_pull (Fin beta)
       d_child (Fin b) U_child c_child 
     U_child = range_tree P a (Fin b) 
     complete_preserved d_child d' U_child 
     edge_batch = edge_relaxation_pairs_between d_child U_child b beta 
     source_batch = label_pairs_between d S_pull b beta 
     batch = edge_batch @ source_batch 
     D_next = batch_min_update D_pull batch 
     partition_pull_cost_bound c_pull S_pull 
     partition_batch_cost_bound c_edges t edge_batch 
     partition_batch_cost_bound c_sources h source_batch 
     split_range_costed_partition_loop_state Δ M_of t h k cap l d P B d'
       D_next b betas bs B' Us_tail U_tail c_tail child_costs_tail 
     c = c_pull + c_edges + c_sources + c_child + c_tail 
     split_range_costed_partition_loop_state Δ M_of t h k cap l d P B d' D a
       (beta # betas) (b # bs) B'
       (range_tree P a (Fin b) # Us_tail)
       (bound_tree P (Fin a) 
        (set (range_tree P a (Fin b) # Us_tail))) c
       (c_child # child_costs_tail)"
| Split_Range_Cost_Base:
    "S = {x} 
     split_range_costed_bmssp Δ M_of t h k cap 0 d S B
       (λv. if v  base_case_vertices k x B then dist s v else d v)
       (base_case_bound k x B)
       (base_case_vertices k x B)
       (base_case_scan_cost Δ k x B)"
| Split_Range_Cost_Step:
    "D = label_partition_view
       (find_pivots_label_capped k cap d S B)
       (find_pivots_pivots_capped k cap d S B) 
     partition_initial_insert_cost_bound c_insert t
       (find_pivots_pivots_capped k cap d S B) 
     split_range_costed_partition_loop_state Δ M_of t h k cap l
       (find_pivots_label_capped k cap d S B)
       (find_pivots_pivots_capped k cap d S B) B d' D a betas bs B'
       Us U_loop c_loop child_costs_loop 
     complete_on d'
       {v  bound_tree S B'. find_pivots_label_capped k cap d S B v = dist s v} 
     U = U_loop 
       {v  bound_tree S B'. find_pivots_label_capped k cap d S B v = dist s v} 
      c = fp_iter_capped_scan_cost k cap d S S B + c_insert + c_loop 
      split_range_costed_bmssp Δ M_of t h k cap (Suc l) d S B d' B' U c"

inductive_cases split_range_costed_bmssp_zeroE:
  "split_range_costed_bmssp Δ M_of t h k cap 0 d S B d' B' U c"

inductive_cases split_range_costed_bmssp_SucE:
  "split_range_costed_bmssp Δ M_of t h k cap (Suc l) d S B d' B' U c"

theorem split_range_costed_partition_loop_state_refines:
  shows
    "split_range_costed_partition_loop_state Δ M_of t h k cap l d P B d' D a
       betas bs B' Us U c child_costs 
     h  t 
     range_costed_partition_loop_state Δ M_of t k cap l d P B d' D a
       betas bs B' Us U c child_costs"
  and
    "split_range_costed_bmssp Δ M_of t h k cap l d S B d' B' U c 
     h  t 
     range_costed_bmssp Δ M_of t k cap l d S B d' B' U c"
proof (induction rule:
    split_range_costed_partition_loop_state_split_range_costed_bmssp.inducts)
  case (Split_Range_State_Done D a B d' P Δ M_of t h k cap l d)
  show ?case
    using Split_Range_State_Done by (meson Range_State_Done)
next
  case (Split_Range_State_Stop a B d' P k cap Δ M_of t h l d D)
  show ?case
    using Split_Range_State_Stop by (meson Range_State_Stop)
next
  case (Split_Range_State_Step D M_of l Bmax S_pull beta D_pull B d a b B'
      d' P k cap Δ t h d_child U_child c_child edge_batch source_batch
      batch D_next c_pull c_edges c_sources betas bs Us_tail U_tail c_tail
      child_costs_tail c)
  have h_le_t: "h  t"
    using Split_Range_State_Step.prems by simp
  have edge_cost':
    "partition_batch_cost_bound c_edges t
      (edge_relaxation_pairs_between d_child U_child b beta)"
    using Split_Range_State_Step by simp
  have source_cost':
    "partition_batch_cost_bound c_sources h
      (label_pairs_between d S_pull b beta)"
    using Split_Range_State_Step by simp
  have batch_cost:
    "partition_batch_cost_bound
      (c_edges + c_sources) t
      (edge_relaxation_pairs_between d_child U_child b beta @
       label_pairs_between d S_pull b beta)"
    by (rule partition_batch_cost_bound_append[OF edge_cost' source_cost' h_le_t])
  have c_eq:
    "c = c_pull + (c_edges + c_sources) + c_child + c_tail"
    using Split_Range_State_Step by simp
  show ?case
    by (rule Range_State_Step[
        where batch =
          "edge_relaxation_pairs_between d_child U_child b beta @
           label_pairs_between d S_pull b beta"
        and c_batch = "c_edges + c_sources"])
      (use Split_Range_State_Step h_le_t batch_cost c_eq in auto)
next
  case (Split_Range_Cost_Base S x Δ M_of t h k cap d B)
  show ?case
    by (rule Range_Cost_Base[OF Split_Range_Cost_Base.hyps])
next
  case Split_Range_Cost_Step
  show ?case
    by (rule Range_Cost_Step)
      (use Split_Range_Cost_Step in auto)
qed

text ‹
  The refinement theorem @{thm split_range_costed_partition_loop_state_refines}
  is the formal connection between the two presentations.  Once it is proved,
  any semantic theorem established for the single-batch relation can be reused
  for the split relation.  The remaining split-specific lemmas therefore focus
  on costs: extracting child sources, bounding edge and source batches
  separately, and then recombining those bounds into the level recurrence.
›

lemma split_range_costed_partition_loop_state_mono:
  assumes run:
    "split_range_costed_partition_loop_state Δ M_of t h k cap l d P B d' D a
      betas bs B' Us U c child_costs"
  shows "nondecreasing_from a bs"
  using run by (induction) auto

theorem split_range_costed_partition_loop_state_child_call_ranges:
  assumes run:
    "split_range_costed_partition_loop_state Δ M_of t h k cap l d P B d' D a
      betas bs B' Us U c child_costs"
  shows "length child_costs = length bs"
    and "list_all2
      (λc_child U_child. S_child B_child d_child B_child'.
        split_range_costed_bmssp Δ M_of t h k cap l d S_child B_child
          d_child B_child' U_child c_child 
        bmssp_pre_full d S_child B_child 
        (xS_child. reachable s x) 
        card S_child  M_of l)
      child_costs (range_tree_child_list P a bs)"
  using run
  by (induction) (auto simp: pull_separates_def)

theorem split_range_costed_partition_loop_state_cost_bound_by_child_sources:
  "split_range_costed_partition_loop_state Δ M_of t h k cap l d P B d' D a
      betas bs B' Us U c child_costs 
   child_sources.
    length child_sources = length bs 
    list_all2
      (λS_child U_child. c_child B_child d_child B_child'.
        split_range_costed_bmssp Δ M_of t h k cap l d S_child B_child
          d_child B_child' U_child c_child 
        bmssp_pre_full d S_child B_child 
        (xS_child. reachable s x) 
        card S_child  M_of l)
      child_sources (range_tree_child_list P a bs) 
    c  sum_list child_costs + sum_list (map card child_sources) +
      t * sum_list
        (map (λX. card (outgoing_edges X)) (range_tree_child_list P a bs)) +
      h * sum_list (map card child_sources)"
and split_range_costed_bmssp_child_sources_trivial:
  "split_range_costed_bmssp Δ M_of t h k cap l d S B d' B' U c  True"
proof (induction rule:
    split_range_costed_partition_loop_state_split_range_costed_bmssp.inducts)
  case (Split_Range_State_Done D a B d' P Δ M_of t h k cap l d)
  show ?case
    by (intro exI[of _ "[]"]) simp
next
  case (Split_Range_State_Stop a B d' P k cap Δ M_of t h l d D)
  show ?case
    by (intro exI[of _ "[]"]) simp
next
  case (Split_Range_State_Step D M_of l Bmax S_pull beta D_pull B d a b B'
      d' P k cap Δ t h d_child U_child c_child edge_batch source_batch
      batch D_next c_pull c_edges c_sources betas bs Us_tail U_tail c_tail
      child_costs_tail c)
  obtain child_sources_tail where len_tail:
      "length child_sources_tail = length bs"
    and sources_tail:
      "list_all2
        (λS_child U_child. c_child B_child d_child B_child'.
          split_range_costed_bmssp Δ M_of t h k cap l d S_child B_child
            d_child B_child' U_child c_child 
          bmssp_pre_full d S_child B_child 
          (xS_child. reachable s x) 
          card S_child  M_of l)
        child_sources_tail (range_tree_child_list P b bs)"
    and tail_cost:
      "c_tail 
        sum_list child_costs_tail + sum_list (map card child_sources_tail) +
        t * sum_list
          (map (λX. card (outgoing_edges X)) (range_tree_child_list P b bs)) +
        h * sum_list (map card child_sources_tail)"
    using Split_Range_State_Step.IH by blast
  have card_pull: "card S_pull  M_of l"
    using Split_Range_State_Step unfolding pull_separates_def by blast
  have pull_cost: "c_pull  card S_pull"
    using Split_Range_State_Step
    unfolding partition_pull_cost_bound_def by blast
  have batch_cost:
    "c_edges + c_sources 
      t * card (outgoing_edges U_child) + h * card S_pull"
    by (rule range_costed_split_batch_cost_le_card[
        where d = d and S = S_pull and d_child = d_child and b = b
          and beta = beta])
      (use Split_Range_State_Step in auto)
  let ?child_sources = "S_pull # child_sources_tail"
  have len: "length ?child_sources = length (b # bs)"
    using len_tail by simp
  have head_source:
    "c_child' B_child d_child' B_child'.
      split_range_costed_bmssp Δ M_of t h k cap l d S_pull B_child
        d_child' B_child' U_child c_child' 
      bmssp_pre_full d S_pull B_child 
      (xS_pull. reachable s x) 
      card S_pull  M_of l"
    using Split_Range_State_Step card_pull by blast
  have sources:
    "list_all2
      (λS_child U_child. c_child B_child d_child B_child'.
        split_range_costed_bmssp Δ M_of t h k cap l d S_child B_child
          d_child B_child' U_child c_child 
        bmssp_pre_full d S_child B_child 
        (xS_child. reachable s x) 
        card S_child  M_of l)
      ?child_sources (range_tree_child_list P a (b # bs))"
    using head_source sources_tail Split_Range_State_Step by simp
  have cost:
    "c  sum_list (c_child # child_costs_tail) +
      sum_list (map card ?child_sources) +
      t * sum_list
        (map (λX. card (outgoing_edges X))
          (range_tree_child_list P a (b # bs))) +
      h * sum_list (map card ?child_sources)"
  proof -
    have c_eq: "c = c_pull + c_edges + c_sources + c_child + c_tail"
      using Split_Range_State_Step by blast
    have "c_pull + c_edges + c_sources + c_child + c_tail 
        card S_pull +
        (t * card (outgoing_edges U_child) + h * card S_pull) +
        c_child +
        (sum_list child_costs_tail + sum_list (map card child_sources_tail) +
          t * sum_list
            (map (λX. card (outgoing_edges X)) (range_tree_child_list P b bs)) +
          h * sum_list (map card child_sources_tail))"
      using pull_cost batch_cost tail_cost by linarith
    also have " =
        sum_list (c_child # child_costs_tail) +
        sum_list (map card ?child_sources) +
        t * (card (outgoing_edges U_child) +
          sum_list
            (map (λX. card (outgoing_edges X)) (range_tree_child_list P b bs))) +
        h * sum_list (map card ?child_sources)"
      by (simp add: algebra_simps)
    also have " =
        sum_list (c_child # child_costs_tail) +
        sum_list (map card ?child_sources) +
        t * sum_list
          (map (λX. card (outgoing_edges X))
            (range_tree_child_list P a (b # bs))) +
        h * sum_list (map card ?child_sources)"
      using Split_Range_State_Step by simp
    finally show ?thesis
      using c_eq by simp
  qed
  show ?case
    by (intro exI[of _ ?child_sources] conjI)
      (use len sources cost in simp_all)
next
  case (Split_Range_Cost_Base S x Δ M_of t h k cap d B)
  show ?case
    by simp
next
  case (Split_Range_Cost_Step D k cap d S B c_insert t Δ M_of h l d' a
      betas bs B' Us U_loop c_loop child_costs_loop U c)
  show ?case
    by simp
qed

theorem split_range_costed_partition_loop_state_cost_from_child_and_source_bounds:
  assumes run:
    "split_range_costed_partition_loop_state Δ M_of t h k cap l d P B d' D a
      betas bs B' Us U c child_costs"
    and child_cost_bounds:
      "list_all2 (λc_child U_child.
        c_child  level_range_cost_bound A R L U_child)
        child_costs (range_tree_child_list P a bs)"
    and source_progress:
      "S_child B_child d_child B_child' U_child c_child.
        split_range_costed_bmssp Δ M_of t h k cap l d S_child B_child
            d_child B_child' U_child c_child;
          bmssp_pre_full d S_child B_child;
          x. x  S_child  reachable s x;
          card S_child  M_of l
         card S_child  card U_child"
  shows "c 
    A * L * card (range_tree_chain P a bs B') +
    (R + t) * card (outgoing_edges (range_tree_chain P a bs B')) +
    Suc h * card (range_tree_chain P a bs B')"
proof -
  obtain child_sources where len_sources:
      "length child_sources = length bs"
    and sources:
      "list_all2
        (λS_child U_child. c_child B_child d_child B_child'.
          split_range_costed_bmssp Δ M_of t h k cap l d S_child B_child
            d_child B_child' U_child c_child 
          bmssp_pre_full d S_child B_child 
          (xS_child. reachable s x) 
          card S_child  M_of l)
        child_sources (range_tree_child_list P a bs)"
    and cost:
      "c  sum_list child_costs + sum_list (map card child_sources) +
        t * sum_list
          (map (λX. card (outgoing_edges X)) (range_tree_child_list P a bs)) +
        h * sum_list (map card child_sources)"
    using split_range_costed_partition_loop_state_cost_bound_by_child_sources[OF run]
    by blast
  have mono: "nondecreasing_from a bs"
    by (rule split_range_costed_partition_loop_state_mono[OF run])
  have source_dom:
    "list_all2 (λS_child U_child. card S_child  card U_child)
      child_sources (range_tree_child_list P a bs)"
    using sources
  proof (induction rule: list_all2_induct)
    case Nil
    then show ?case by simp
  next
    case (Cons S_child child_sources U_child child_sets)
    obtain c_child B_child d_child B_child' where child:
        "split_range_costed_bmssp Δ M_of t h k cap l d S_child B_child
          d_child B_child' U_child c_child"
      and child_pre: "bmssp_pre_full d S_child B_child"
      and child_reaches: "xS_child. reachable s x"
      and child_card: "card S_child  M_of l"
      using Cons.hyps by blast
    have head: "card S_child  card U_child"
      by (rule source_progress[OF child child_pre _ child_card])
        (use child_reaches in blast)
    show ?case
      using head Cons.IH Cons.hyps by simp
  qed
  have source_sum:
    "sum_list (map card child_sources) 
      card (range_tree_chain P a bs B')"
    by (rule sum_card_dominated_by_range_tree_child_list_le_chain
      [OF mono source_dom])
  have child_sum:
    "sum_list child_costs 
      A * L * card (range_tree_chain P a bs B') +
      R * card (outgoing_edges (range_tree_chain P a bs B'))"
    by (rule child_costs_le_level_range_child_list_bound
      [OF mono child_cost_bounds])
  have edge_sum:
    "sum_list
      (map (λX. card (outgoing_edges X)) (range_tree_child_list P a bs)) 
     card (outgoing_edges (range_tree_chain P a bs B'))"
    by (rule card_outgoing_edges_range_tree_child_list_le_chain[OF mono])
  have "c 
      A * L * card (range_tree_chain P a bs B') +
      R * card (outgoing_edges (range_tree_chain P a bs B')) +
      sum_list (map card child_sources) +
      t * card (outgoing_edges (range_tree_chain P a bs B')) +
      h * sum_list (map card child_sources)"
  proof -
    have edge_part:
      "t * sum_list
          (map (λX. card (outgoing_edges X)) (range_tree_child_list P a bs)) 
       t * card (outgoing_edges (range_tree_chain P a bs B'))"
      using edge_sum by simp
    have "sum_list child_costs + sum_list (map card child_sources) +
        t * sum_list
          (map (λX. card (outgoing_edges X)) (range_tree_child_list P a bs)) +
        h * sum_list (map card child_sources) 
        A * L * card (range_tree_chain P a bs B') +
        R * card (outgoing_edges (range_tree_chain P a bs B')) +
        sum_list (map card child_sources) +
        t * card (outgoing_edges (range_tree_chain P a bs B')) +
        h * sum_list (map card child_sources)"
      using child_sum edge_part by linarith
    then show ?thesis
      using cost by linarith
  qed
  also have " 
      A * L * card (range_tree_chain P a bs B') +
      (R + t) * card (outgoing_edges (range_tree_chain P a bs B')) +
      Suc h * card (range_tree_chain P a bs B')"
  proof -
    have source_part:
      "sum_list (map card child_sources) +
        h * sum_list (map card child_sources) 
       Suc h * card (range_tree_chain P a bs B')"
    proof -
      have h_part:
        "h * sum_list (map card child_sources) 
          h * card (range_tree_chain P a bs B')"
        using source_sum by simp
      have "sum_list (map card child_sources) +
          h * sum_list (map card child_sources) 
        card (range_tree_chain P a bs B') +
          h * card (range_tree_chain P a bs B')"
        using source_sum h_part by linarith
      then show ?thesis
        by (simp add: algebra_simps)
    qed
    show ?thesis
      using source_part by (simp add: algebra_simps)
  qed
  finally show ?thesis .
qed

theorem split_range_costed_partition_loop_state_child_cost_bounds:
  assumes run:
    "split_range_costed_partition_loop_state Δ M_of t h k cap l d P B d' D a
      betas bs B' Us U c child_costs"
    and child_bound:
      "c_child U_child S_child B_child d_child B_child'.
        split_range_costed_bmssp Δ M_of t h k cap l d S_child B_child
            d_child B_child' U_child c_child;
          bmssp_pre_full d S_child B_child;
          x. x  S_child  reachable s x;
          card S_child  M_of l
         c_child  level_range_cost_bound A R L U_child"
  shows "list_all2 (λc_child U_child.
      c_child  level_range_cost_bound A R L U_child)
    child_costs (range_tree_child_list P a bs)"
proof -
  have calls:
    "list_all2
      (λc_child U_child. S_child B_child d_child B_child'.
        split_range_costed_bmssp Δ M_of t h k cap l d S_child B_child
          d_child B_child' U_child c_child 
        bmssp_pre_full d S_child B_child 
        (xS_child. reachable s x) 
        card S_child  M_of l)
      child_costs (range_tree_child_list P a bs)"
    by (rule split_range_costed_partition_loop_state_child_call_ranges(2)[OF run])
  show ?thesis
    using calls
  proof (induction rule: list_all2_induct)
    case Nil
    then show ?case by simp
  next
    case (Cons c_child child_costs U_child child_sets)
    obtain S_child B_child d_child B_child' where child:
        "split_range_costed_bmssp Δ M_of t h k cap l d S_child B_child
          d_child B_child' U_child c_child"
      and child_pre: "bmssp_pre_full d S_child B_child"
      and child_reaches: "xS_child. reachable s x"
      and child_card: "card S_child  M_of l"
      using Cons.hyps by blast
    have head:
      "c_child  level_range_cost_bound A R L U_child"
      by (rule child_bound[OF child child_pre _ child_card])
        (use child_reaches in blast)
    show ?case
      using head Cons.IH Cons.hyps by simp
  qed
qed

theorem split_range_costed_partition_loop_state_cost_from_child_bound:
  assumes run:
    "split_range_costed_partition_loop_state Δ M_of t h k cap l d P B d' D a
      betas bs B' Us U c child_costs"
    and child_bound:
      "c_child U_child S_child B_child d_child B_child'.
        split_range_costed_bmssp Δ M_of t h k cap l d S_child B_child
            d_child B_child' U_child c_child;
          bmssp_pre_full d S_child B_child;
          x. x  S_child  reachable s x;
          card S_child  M_of l
         c_child  level_range_cost_bound A R L U_child"
    and source_progress:
      "S_child B_child d_child B_child' U_child c_child.
        split_range_costed_bmssp Δ M_of t h k cap l d S_child B_child
            d_child B_child' U_child c_child;
          bmssp_pre_full d S_child B_child;
          x. x  S_child  reachable s x;
          card S_child  M_of l
         card S_child  card U_child"
  shows "c 
    A * L * card (range_tree_chain P a bs B') +
    (R + t) * card (outgoing_edges (range_tree_chain P a bs B')) +
    Suc h * card (range_tree_chain P a bs B')"
proof -
  have child_cost_bounds:
    "list_all2 (λc_child U_child.
      c_child  level_range_cost_bound A R L U_child)
      child_costs (range_tree_child_list P a bs)"
    by (rule split_range_costed_partition_loop_state_child_cost_bounds
      [OF run child_bound])
  show ?thesis
    by (rule split_range_costed_partition_loop_state_cost_from_child_and_source_bounds
      [OF run child_cost_bounds source_progress])
qed

theorem split_range_costed_partition_loop_state_trace:
  "split_range_costed_partition_loop_state Δ M_of t h k cap l d P B d' D a
     betas bs B' Us U c child_costs 
   sound_label d 
   bmssp_pre_full d P B 
   (x. x  P  reachable s x) 
   concrete_partition_loop_trace P B a bs d' B' Us U"
and split_range_costed_bmssp_correct:
  "split_range_costed_bmssp Δ M_of t h k cap l d S B d' B' U c 
   sound_label d 
   bmssp_pre_full d S B 
   (x. x  S  reachable s x) 
   bmssp_post_full d S B d' B' U"
proof (induction rule:
    split_range_costed_partition_loop_state_split_range_costed_bmssp.inducts)
  case (Split_Range_State_Done D a B d' P Δ M_of t h k cap l d)
  have a_le: "bound_le (Fin a) B"
    using Split_Range_State_Done by blast
  have complete_B: "complete_on d' (bound_tree P B)"
    using Split_Range_State_Done by blast
  have lower: "complete_on d' (bound_tree P (Fin a))"
    by (rule complete_on_subset[OF complete_B])
      (rule bound_tree_bound_mono[OF a_le])
  have range_complete: "complete_on d' (range_tree P a B)"
    by (rule complete_on_subset[OF complete_B])
      (rule range_tree_subset_bound_tree)
  have B_le: "bound_le B B"
    by (cases B) simp_all
  show ?case
    unfolding concrete_partition_loop_trace_def
    using B_le a_le lower range_complete by simp
next
  case (Split_Range_State_Stop a B d' P k cap Δ M_of t h l d D)
  then show ?case
    unfolding concrete_partition_loop_trace_def complete_on_def by simp
next
  case Split_Range_State_Step
  then show ?case
    unfolding concrete_partition_loop_trace_def bmssp_post_full_def
      complete_preserved_def
    by (auto split: bound.splits)
next
  case (Split_Range_Cost_Base S x Δ M_of t h k cap d B)
  have post:
    "bmssp_post d S B
      (λv. if v  base_case_vertices k x B then dist s v else d v)
      (base_case_bound k x B)
      (base_case_vertices k x B)"
    using base_case_result_bmssp_post[OF Split_Range_Cost_Base.hyps,
        where k = k and B = B and d = d]
    unfolding base_case_result_def by simp
  then show ?case
    by (rule bmssp_post_imp_post_full)
next
  case (Split_Range_Cost_Step D k cap d S B c_insert t Δ M_of h l d' a
      betas bs B' Us U_loop c_loop child_costs_loop U c)
  let ?d_fp = "find_pivots_label_capped k cap d S B"
  let ?P = "find_pivots_pivots_capped k cap d S B"
  let ?W = "{v  bound_tree S B'. ?d_fp v = dist s v}"
  have sound_fp: "sound_label ?d_fp"
    unfolding find_pivots_label_capped_def
    by (rule fp_iter_capped_label_sound[OF Split_Range_Cost_Step.prems(1)
      Split_Range_Cost_Step.prems(3)])
  have pivot_pre: "bmssp_pre_full ?d_fp ?P B"
    using find_pivots_capped_establishes_pivot_pre_concrete
      [OF Split_Range_Cost_Step.prems(1) Split_Range_Cost_Step.prems(2)
        Split_Range_Cost_Step.prems(3)] .
  have P_subset_S: "?P  S"
    unfolding find_pivots_pivots_capped_def by auto
  have P_reaches: "x. x  ?P  reachable s x"
    using P_subset_S Split_Range_Cost_Step.prems(3) by blast
  have trace:
    "concrete_partition_loop_trace ?P B a bs d' B' Us U_loop"
    using Split_Range_Cost_Step.IH sound_fp pivot_pre P_reaches by blast
  have loop_post: "bmssp_post_full ?d_fp ?P B d' B' U_loop"
    by (rule concrete_partition_loop_trace_post[OF trace])
  have le: "bound_le B' B"
    using loop_post unfolding bmssp_post_full_def by blast
  have U_tree: "U = bound_tree S B'"
  proof -
    have "U_loop  ?W = bound_tree S B'"
      by (rule concrete_capped_find_pivots_final_tree_assembly
        [OF Split_Range_Cost_Step.prems(1) Split_Range_Cost_Step.prems(2)
          Split_Range_Cost_Step.prems(3) loop_post])
    then show ?thesis
      using Split_Range_Cost_Step(6) by simp
  qed
  have loop_complete: "complete_on d' U_loop"
    using loop_post unfolding bmssp_post_full_def by blast
  have U_complete: "complete_on d' U"
    using complete_on_Un[OF loop_complete Split_Range_Cost_Step(5)]
      Split_Range_Cost_Step(6) by simp
  show ?case
    using le U_tree U_complete unfolding bmssp_post_full_def by blast
qed

text ‹
  The next block closes the level recurrence for the split relation.  The input
  hypotheses have the same shape as the informal induction in the paper: each
  child call already satisfies a level-L› bound on its own output slice, and
  every pulled child source set makes enough progress to be charged to that
  slice.  The trace theorem supplies the geometric fact needed to sum these
  charges: the range slices form a chain inside the parent output.

  Once the slice sums are bounded by the parent output and its outgoing edges,
  the arithmetic is straightforward.  The child level factor contributes
  A * L›, the source-progress term contributes one more A›, and the edge
  batch cost contributes the extra t› in the range coefficient.  This is why
  the target has level Suc L› and coefficient R + t›.
›

theorem split_range_costed_partition_loop_state_closes_level_bound_from_child_cost_bounds_general:
  assumes run:
    "split_range_costed_partition_loop_state Δ M_of t h k cap l d P B d' D a
      betas bs B' Us U c child_costs"
    and sound: "sound_label d"
    and pre: "bmssp_pre_full d P B"
    and P_reaches: "x. x  P  reachable s x"
    and child_cost_bounds:
      "list_all2 (λc_child U_child.
        c_child  level_range_cost_bound A R L U_child)
        child_costs (range_tree_child_list P a bs)"
    and source_progress:
      "S_child B_child d_child B_child' U_child c_child.
        split_range_costed_bmssp Δ M_of t h k cap l d S_child B_child
            d_child B_child' U_child c_child;
          bmssp_pre_full d S_child B_child;
          x. x  S_child  reachable s x;
          card S_child  M_of l
         card S_child  card U_child"
    and source_factor: "Suc h  A"
  shows "c  A * Suc L * card U + (R + t) * card (outgoing_edges U)"
proof -
  have trace: "concrete_partition_loop_trace P B a bs d' B' Us U"
    by (rule split_range_costed_partition_loop_state_trace
      [OF run sound pre P_reaches])
  have children:
    "list_all2 (λU X. U = X  complete_on d' U) Us
      (range_tree_chain_list P a bs B')"
    using trace unfolding concrete_partition_loop_trace_def by blast
  have U_def: "U = bound_tree P (Fin a)  (set Us)"
    using trace unfolding concrete_partition_loop_trace_def by blast
  have Union_eq:
    "(set Us) = (set (range_tree_chain_list P a bs B'))"
    using children by (induction rule: list_all2_induct) auto
  have U_eq_chain:
    "U = bound_tree P (Fin a)  range_tree_chain P a bs B'"
    using U_def Union_eq Union_range_tree_chain_list[of P a bs B'] by simp
  have finite_U: "finite U"
    using U_eq_chain by simp
  have chain_subset: "range_tree_chain P a bs B'  U"
    using U_eq_chain by blast
  have card_chain_le: "card (range_tree_chain P a bs B')  card U"
    by (rule card_mono[OF finite_U chain_subset])
  have outgoing_subset:
    "outgoing_edges (range_tree_chain P a bs B')  outgoing_edges U"
    by (rule outgoing_edges_mono[OF chain_subset])
  have finite_out_U: "finite (outgoing_edges U)"
    by simp
  have card_out_le:
    "card (outgoing_edges (range_tree_chain P a bs B')) 
      card (outgoing_edges U)"
    by (rule card_mono[OF finite_out_U outgoing_subset])
  have loop:
    "c 
      A * L * card (range_tree_chain P a bs B') +
      (R + t) * card (outgoing_edges (range_tree_chain P a bs B')) +
      Suc h * card (range_tree_chain P a bs B')"
    by (rule split_range_costed_partition_loop_state_cost_from_child_and_source_bounds
      [OF run child_cost_bounds source_progress])
  have source_term:
    "Suc h * card (range_tree_chain P a bs B')  A * card U"
  proof -
    have "Suc h * card (range_tree_chain P a bs B') 
        A * card (range_tree_chain P a bs B')"
      using source_factor by (rule mult_right_mono) simp
    also have "  A * card U"
      using card_chain_le by simp
    finally show ?thesis .
  qed
  have "c 
      A * L * card U + (R + t) * card (outgoing_edges U) + A * card U"
  proof -
    have vterm:
      "A * L * card (range_tree_chain P a bs B')  A * L * card U"
      using card_chain_le by simp
    have eterm:
      "(R + t) * card (outgoing_edges (range_tree_chain P a bs B')) 
       (R + t) * card (outgoing_edges U)"
      using card_out_le by simp
    have "A * L * card (range_tree_chain P a bs B') +
        (R + t) * card (outgoing_edges (range_tree_chain P a bs B')) +
        Suc h * card (range_tree_chain P a bs B') 
        A * L * card U + (R + t) * card (outgoing_edges U) + A * card U"
      using vterm eterm source_term by linarith
    then show ?thesis
      using loop by linarith
  qed
  also have " =
      A * Suc L * card U + (R + t) * card (outgoing_edges U)"
    by (simp add: algebra_simps)
  finally show ?thesis .
qed

theorem split_range_costed_partition_loop_state_closes_level_bound_from_source_progress_general:
  assumes run:
    "split_range_costed_partition_loop_state Δ M_of t h k cap l d P B d' D a
      betas bs B' Us U c child_costs"
    and sound: "sound_label d"
    and pre: "bmssp_pre_full d P B"
    and P_reaches: "x. x  P  reachable s x"
    and child_bound:
      "c_child U_child S_child B_child d_child B_child'.
        split_range_costed_bmssp Δ M_of t h k cap l d S_child B_child
            d_child B_child' U_child c_child;
          bmssp_pre_full d S_child B_child;
          x. x  S_child  reachable s x;
          card S_child  M_of l
         c_child  level_range_cost_bound A R L U_child"
    and source_progress:
      "S_child B_child d_child B_child' U_child c_child.
        split_range_costed_bmssp Δ M_of t h k cap l d S_child B_child
            d_child B_child' U_child c_child;
          bmssp_pre_full d S_child B_child;
          x. x  S_child  reachable s x;
          card S_child  M_of l
         card S_child  card U_child"
    and source_factor: "Suc h  A"
  shows "c  A * Suc L * card U + (R + t) * card (outgoing_edges U)"
proof -
  have child_cost_bounds:
    "list_all2 (λc_child U_child.
      c_child  level_range_cost_bound A R L U_child)
      child_costs (range_tree_child_list P a bs)"
    by (rule split_range_costed_partition_loop_state_child_cost_bounds
      [OF run child_bound])
  show ?thesis
    by (rule
      split_range_costed_partition_loop_state_closes_level_bound_from_child_cost_bounds_general
      [OF run sound pre P_reaches child_cost_bounds source_progress
        source_factor])
qed

theorem split_range_costed_nonbase_step_closes_level_bound_from_source_progress_general:
  assumes loop:
    "split_range_costed_partition_loop_state Δ M_of t h k cap l d P B d' D a
      betas bs B' Us U_loop c_loop child_costs"
    and sound: "sound_label d"
    and pre: "bmssp_pre_full d P B"
    and P_reaches: "x. x  P  reachable s x"
    and child_bound:
      "c_child U_child S_child B_child d_child B_child'.
        split_range_costed_bmssp Δ M_of t h k cap l d S_child B_child
            d_child B_child' U_child c_child;
          bmssp_pre_full d S_child B_child;
          x. x  S_child  reachable s x;
          card S_child  M_of l
         c_child  level_range_cost_bound A R L U_child"
    and source_progress:
      "S_child B_child d_child B_child' U_child c_child.
        split_range_costed_bmssp Δ M_of t h k cap l d S_child B_child
            d_child B_child' U_child c_child;
          bmssp_pre_full d S_child B_child;
          x. x  S_child  reachable s x;
          card S_child  M_of l
         card S_child  card U_child"
    and source_factor: "Suc h  A"
    and U_def: "U = U_loop  W"
    and finite_U: "finite U"
    and scan_insert: "c_scan_insert  A * card U"
    and c_def: "c = c_scan_insert + c_loop"
  shows "c  A * Suc (Suc L) * card U +
    (R + t) * card (outgoing_edges U)"
proof -
  have loop_bound:
    "c_loop  A * Suc L * card U_loop +
      (R + t) * card (outgoing_edges U_loop)"
    by (rule split_range_costed_partition_loop_state_closes_level_bound_from_source_progress_general
      [OF loop sound pre P_reaches child_bound source_progress source_factor])
  have U_loop_subset: "U_loop  U"
    using U_def by blast
  have card_loop_le: "card U_loop  card U"
    by (rule card_mono[OF finite_U U_loop_subset])
  have outgoing_subset: "outgoing_edges U_loop  outgoing_edges U"
    by (rule outgoing_edges_mono[OF U_loop_subset])
  have finite_out_U: "finite (outgoing_edges U)"
    by simp
  have card_out_le: "card (outgoing_edges U_loop)  card (outgoing_edges U)"
    by (rule card_mono[OF finite_out_U outgoing_subset])
  have "c 
      A * card U +
      (A * Suc L * card U + (R + t) * card (outgoing_edges U))"
  proof -
    have loop_to_U:
      "c_loop  A * Suc L * card U +
        (R + t) * card (outgoing_edges U)"
    proof -
      have "A * Suc L * card U_loop  A * Suc L * card U"
        using card_loop_le by simp
      moreover have "(R + t) * card (outgoing_edges U_loop) 
          (R + t) * card (outgoing_edges U)"
        using card_out_le by simp
      ultimately show ?thesis
        using loop_bound by linarith
    qed
    show ?thesis
      using scan_insert loop_to_U c_def by linarith
  qed
  also have " =
      A * Suc (Suc L) * card U + (R + t) * card (outgoing_edges U)"
    by (simp add: algebra_simps)
  finally show ?thesis .
qed

lemma split_range_costed_base_level_bound:
  assumes R_pos: "0 < R"
  shows "base_case_scan_cost Δ k x B 
    level_range_cost_bound A R (Suc 0) (base_case_vertices k x B)"
proof -
  have "base_case_scan_cost Δ k x B 
      R * card (outgoing_edges (base_case_vertices k x B))"
    using R_pos unfolding base_case_scan_cost_def by simp
  then show ?thesis
    unfolding level_range_cost_bound_def by linarith
qed

theorem split_range_costed_bmssp_level_bound_from_source_progress_and_local_budgets:
  assumes base_budget: "Δ  A"
    and R_pos: "0 < R"
    and source_factor: "Suc h  A"
    and source_progress:
      "l d S B d' B' U c.
        split_range_costed_bmssp Δ M_of t h k cap l d S B d' B' U c 
        bmssp_pre_full d S B 
        (x. x  S  reachable s x) 
        card S  M_of l 
        card S  card U"
    and step_budget:
      "l d S B D c_insert d' a betas bs B' Us U_loop c_loop
          child_costs U.
        D = label_partition_view
          (find_pivots_label_capped k cap d S B)
          (find_pivots_pivots_capped k cap d S B) 
        partition_initial_insert_cost_bound c_insert t
          (find_pivots_pivots_capped k cap d S B) 
        split_range_costed_partition_loop_state Δ M_of t h k cap l
          (find_pivots_label_capped k cap d S B)
          (find_pivots_pivots_capped k cap d S B) B d' D a betas bs B'
          Us U_loop c_loop child_costs 
        complete_on d'
          {v  bound_tree S B'. find_pivots_label_capped k cap d S B v = dist s v} 
        U = U_loop 
          {v  bound_tree S B'. find_pivots_label_capped k cap d S B v = dist s v} 
        sound_label d 
        bmssp_pre_full d S B 
        (x. x  S  reachable s x) 
        fp_iter_capped_scan_cost k cap d S S B + c_insert  A * card U"
    and run:
      "split_range_costed_bmssp Δ M_of t h k cap l d S B d' B' U c"
    and sound: "sound_label d"
    and pre: "bmssp_pre_full d S B"
    and S_reaches: "x. x  S  reachable s x"
  shows "c  level_range_cost_bound A (R + l * t) (2 * l + 1) U"
  using run sound pre S_reaches
proof (induction l arbitrary: d S B d' B' U c rule: less_induct)
  case (less l)
  show ?case
  proof (cases l)
    case 0
    have run0:
      "split_range_costed_bmssp Δ M_of t h k cap 0 d S B d' B' U c"
      using less.prems(1) 0 by simp
    show ?thesis
      using run0 R_pos 0
      by (cases rule: split_range_costed_bmssp.cases)
        (simp_all add: split_range_costed_base_level_bound)
  next
    case (Suc l0)
    have run_suc:
      "split_range_costed_bmssp Δ M_of t h k cap (Suc l0) d S B d' B' U c"
      using less.prems(1) Suc by simp
    show ?thesis
    proof (cases rule: split_range_costed_bmssp_SucE[OF run_suc])
      case (1 c_insert a betas bs Us U_loop c_loop child_costs_loop)
      let ?d_fp = "find_pivots_label_capped k cap d S B"
      let ?P = "find_pivots_pivots_capped k cap d S B"
      let ?W = "{v  bound_tree S B'. ?d_fp v = dist s v}"
      have sound_fp: "sound_label ?d_fp"
        unfolding find_pivots_label_capped_def
        by (rule fp_iter_capped_label_sound[OF less.prems(2) less.prems(4)])
      have pivot_pre: "bmssp_pre_full ?d_fp ?P B"
        using find_pivots_capped_establishes_pivot_pre_concrete
          [OF less.prems(2) less.prems(3) less.prems(4)] .
      have P_subset_S: "?P  S"
        unfolding find_pivots_pivots_capped_def by auto
      have P_reaches: "x. x  ?P  reachable s x"
        using P_subset_S less.prems(4) by blast
      have child_bound:
        "c_child U_child S_child B_child d_child B_child'.
          split_range_costed_bmssp Δ M_of t h k cap l0 ?d_fp S_child B_child
              d_child B_child' U_child c_child;
            bmssp_pre_full ?d_fp S_child B_child;
            x. x  S_child  reachable s x;
            card S_child  M_of l0
           c_child  level_range_cost_bound A (R + l0 * t)
            (2 * l0 + 1) U_child"
      proof -
        fix c_child U_child S_child B_child d_child B_child'
        assume child:
            "split_range_costed_bmssp Δ M_of t h k cap l0 ?d_fp S_child B_child
              d_child B_child' U_child c_child"
          and child_pre: "bmssp_pre_full ?d_fp S_child B_child"
          and child_reaches: "x. x  S_child  reachable s x"
        show "c_child  level_range_cost_bound A (R + l0 * t)
            (2 * l0 + 1) U_child"
          by (rule less.IH[of l0 ?d_fp S_child B_child d_child B_child'
                U_child c_child, OF _ child sound_fp child_pre child_reaches])
            (simp add: Suc)
      qed
      have source_progress_loop:
        "S_child B_child d_child B_child' U_child c_child.
          split_range_costed_bmssp Δ M_of t h k cap l0 ?d_fp S_child B_child
              d_child B_child' U_child c_child;
            bmssp_pre_full ?d_fp S_child B_child;
            x. x  S_child  reachable s x;
            card S_child  M_of l0
           card S_child  card U_child"
        by (rule source_progress)
      have scan_insert:
        "fp_iter_capped_scan_cost k cap d S S B + c_insert 
          A * card U"
        by (rule step_budget[OF refl 1(3) 1(4) 1(5) 1(1)
            less.prems(2) less.prems(3) less.prems(4)])
      have trace:
        "concrete_partition_loop_trace ?P B a bs d' B' Us U_loop"
        by (rule split_range_costed_partition_loop_state_trace
          [OF 1(4) sound_fp pivot_pre P_reaches])
      have loop_post: "bmssp_post_full ?d_fp ?P B d' B' U_loop"
        by (rule concrete_partition_loop_trace_post[OF trace])
      have finite_U_loop: "finite U_loop"
        using loop_post unfolding bmssp_post_full_def by simp
      have finite_W: "finite ?W"
        by simp
      have finite_U: "finite U"
        using 1(1) finite_U_loop finite_W by simp
      have step:
        "c  A * Suc (Suc (2 * l0 + 1)) * card U +
          (R + l0 * t + t) * card (outgoing_edges U)"
        by (rule split_range_costed_nonbase_step_closes_level_bound_from_source_progress_general
          [OF 1(4) sound_fp pivot_pre P_reaches child_bound
            source_progress_loop source_factor 1(1) finite_U scan_insert 1(2)])
      show ?thesis
        using step Suc unfolding level_range_cost_bound_def
        by (simp add: algebra_simps)
    qed
  qed
qed

theorem split_range_costed_bmssp_level_bound_from_source_progress_budgets:
  assumes degree: "edge_outdegree_le Δ"
    and degree_factor: "Δ  A"
    and R_pos: "0 < R"
    and insert_factor: "t  A * k"
    and source_factor: "Suc h  2 * A"
    and source_progress:
      "l d S B d' B' U c.
        split_range_costed_bmssp Δ M_of t h k cap l d S B d' B' U c 
        bmssp_pre_full d S B 
        (x. x  S  reachable s x) 
        card S  M_of l 
        card S  card U"
    and step_progress:
      "l d S B D c_insert d' a betas bs B' Us U_loop c_loop
          child_costs U.
        D = label_partition_view
          (find_pivots_label_capped k cap d S B)
          (find_pivots_pivots_capped k cap d S B) 
        partition_initial_insert_cost_bound c_insert t
          (find_pivots_pivots_capped k cap d S B) 
        split_range_costed_partition_loop_state Δ M_of t h k cap l
          (find_pivots_label_capped k cap d S B)
          (find_pivots_pivots_capped k cap d S B) B d' D a betas bs B'
          Us U_loop c_loop child_costs 
        complete_on d'
          {v  bound_tree S B'. find_pivots_label_capped k cap d S B v = dist s v} 
        U = U_loop 
          {v  bound_tree S B'. find_pivots_label_capped k cap d S B v = dist s v} 
        sound_label d 
        bmssp_pre_full d S B 
        (x. x  S  reachable s x) 
        card S  cap  k * cap  card U"
    and run:
      "split_range_costed_bmssp Δ M_of t h k cap l d S B d' B' U c"
    and sound: "sound_label d"
    and pre: "bmssp_pre_full d S B"
    and S_reaches: "x. x  S  reachable s x"
  shows "c  level_range_cost_bound (2 * A) (R + l * t) (2 * l + 1) U"
proof (rule split_range_costed_bmssp_level_bound_from_source_progress_and_local_budgets
    [where A = "2 * A" and R = R,
      OF _ R_pos source_factor source_progress _ run sound pre S_reaches])
  show "Δ  2 * A"
    using degree_factor by simp
next
  fix l d S B D c_insert d' a betas bs B' Us U_loop c_loop child_costs U
  assume D_def:
      "D = label_partition_view
        (find_pivots_label_capped k cap d S B)
        (find_pivots_pivots_capped k cap d S B)"
    and insert:
      "partition_initial_insert_cost_bound c_insert t
        (find_pivots_pivots_capped k cap d S B)"
    and loop:
      "split_range_costed_partition_loop_state Δ M_of t h k cap l
        (find_pivots_label_capped k cap d S B)
        (find_pivots_pivots_capped k cap d S B) B d' D a betas bs B'
        Us U_loop c_loop child_costs"
    and complete:
      "complete_on d'
        {v  bound_tree S B'. find_pivots_label_capped k cap d S B v = dist s v}"
    and U_def:
      "U = U_loop 
        {v  bound_tree S B'. find_pivots_label_capped k cap d S B v = dist s v}"
    and sound_s: "sound_label d"
    and pre_s: "bmssp_pre_full d S B"
    and reaches_s: "x. x  S  reachable s x"
  have S_subset: "S  V"
    using pre_s unfolding bmssp_pre_full_def by blast
  have progress:
      "card S  cap  k * cap  card U"
    by (rule step_progress[OF D_def insert loop complete U_def sound_s pre_s reaches_s])
  then have S_cap: "card S  cap"
    by blast
  from progress have U_progress: "k * cap  card U"
    by blast
  show "fp_iter_capped_scan_cost k cap d S S B + c_insert 
      2 * A * card U"
    by (rule find_pivots_scan_and_initial_insert_budget_from_progress
      [OF S_subset degree S_cap insert degree_factor insert_factor U_progress])
qed

theorem finite_initial_label_split_range_costed_top_level_correct:
  assumes all_reachable: "v. v  V  reachable s v"
    and run:
      "split_range_costed_bmssp Δ M_of t h k cap l finite_initial_label {s}
        Infinity d' Infinity U c"
  shows "sssp_correct d'"
proof -
  have pre: "bmssp_pre_full finite_initial_label {s} Infinity"
    using all_reachable finite_initial_label_source_complete
    by (rule top_bmssp_pre_full)
  have sound: "sound_label finite_initial_label"
    using finite_initial_label_sound[OF all_reachable] .
  have S_reaches: "x. x  {s}  reachable s x"
    using all_reachable source_in_V by blast
  have post_full:
    "bmssp_post_full finite_initial_label {s} Infinity d' Infinity U"
    by (rule split_range_costed_bmssp_correct[OF run sound pre S_reaches])
  have post: "bmssp_post finite_initial_label {s} Infinity d' Infinity U"
    using bmssp_post_full_imp_post[OF post_full] .
  then have U_V: "U = V"
    using bound_tree_source_infinity[OF all_reachable]
    unfolding bmssp_post_def by auto
  have complete: "complete_on d' U"
    using post unfolding bmssp_post_def by auto
  then show ?thesis
    using U_V unfolding complete_on_def sssp_correct_def by auto
qed

theorem finite_initial_label_split_range_costed_top_level_correct_and_local_budget_bound:
  assumes all_reachable: "v. v  V  reachable s v"
    and base_budget: "Δ  A"
    and R_pos: "0 < R"
    and source_factor: "Suc h  A"
    and source_progress:
      "l d S B d' B' U c.
        split_range_costed_bmssp Δ M_of t h k cap l d S B d' B' U c 
        bmssp_pre_full d S B 
        (x. x  S  reachable s x) 
        card S  M_of l 
        card S  card U"
    and step_budget:
      "l d S B D c_insert d' a betas bs B' Us U_loop c_loop
          child_costs U.
        D = label_partition_view
          (find_pivots_label_capped k cap d S B)
          (find_pivots_pivots_capped k cap d S B) 
        partition_initial_insert_cost_bound c_insert t
          (find_pivots_pivots_capped k cap d S B) 
        split_range_costed_partition_loop_state Δ M_of t h k cap l
          (find_pivots_label_capped k cap d S B)
          (find_pivots_pivots_capped k cap d S B) B d' D a betas bs B'
          Us U_loop c_loop child_costs 
        complete_on d'
          {v  bound_tree S B'. find_pivots_label_capped k cap d S B v = dist s v} 
        U = U_loop 
          {v  bound_tree S B'. find_pivots_label_capped k cap d S B v = dist s v} 
        sound_label d 
        bmssp_pre_full d S B 
        (x. x  S  reachable s x) 
        fp_iter_capped_scan_cost k cap d S S B + c_insert  A * card U"
    and run:
      "split_range_costed_bmssp Δ M_of t h k cap l finite_initial_label {s}
        Infinity d' Infinity U c"
  shows "sssp_correct d' 
    c  level_range_cost_bound A (R + l * t) (2 * l + 1) U"
proof
  show "sssp_correct d'"
    by (rule finite_initial_label_split_range_costed_top_level_correct
      [OF all_reachable run])
next
  have pre: "bmssp_pre_full finite_initial_label {s} Infinity"
    using all_reachable finite_initial_label_source_complete
    by (rule top_bmssp_pre_full)
  have sound: "sound_label finite_initial_label"
    using finite_initial_label_sound[OF all_reachable] .
  have S_reaches: "x. x  {s}  reachable s x"
    using all_reachable source_in_V by blast
  show "c  level_range_cost_bound A (R + l * t) (2 * l + 1) U"
    by (rule split_range_costed_bmssp_level_bound_from_source_progress_and_local_budgets
      [OF base_budget R_pos source_factor source_progress step_budget run sound pre
        S_reaches])
qed

theorem finite_initial_label_split_range_costed_top_level_correct_and_local_budget_graph_bound:
  assumes all_reachable: "v. v  V  reachable s v"
    and base_budget: "Δ  A"
    and R_pos: "0 < R"
    and source_factor: "Suc h  A"
    and source_progress:
      "l d S B d' B' U c.
        split_range_costed_bmssp Δ M_of t h k cap l d S B d' B' U c 
        bmssp_pre_full d S B 
        (x. x  S  reachable s x) 
        card S  M_of l 
        card S  card U"
    and step_budget:
      "l d S B D c_insert d' a betas bs B' Us U_loop c_loop
          child_costs U.
        D = label_partition_view
          (find_pivots_label_capped k cap d S B)
          (find_pivots_pivots_capped k cap d S B) 
        partition_initial_insert_cost_bound c_insert t
          (find_pivots_pivots_capped k cap d S B) 
        split_range_costed_partition_loop_state Δ M_of t h k cap l
          (find_pivots_label_capped k cap d S B)
          (find_pivots_pivots_capped k cap d S B) B d' D a betas bs B'
          Us U_loop c_loop child_costs 
        complete_on d'
          {v  bound_tree S B'. find_pivots_label_capped k cap d S B v = dist s v} 
        U = U_loop 
          {v  bound_tree S B'. find_pivots_label_capped k cap d S B v = dist s v} 
        sound_label d 
        bmssp_pre_full d S B 
        (x. x  S  reachable s x) 
        fp_iter_capped_scan_cost k cap d S S B + c_insert  A * card U"
    and run:
      "split_range_costed_bmssp Δ M_of t h k cap l finite_initial_label {s}
        Infinity d' Infinity U c"
  shows "sssp_correct d' 
    c  A * (2 * l + 1) * vertex_count + (R + l * t) * edge_count"
proof -
  have combined:
    "sssp_correct d' 
      c  level_range_cost_bound A (R + l * t) (2 * l + 1) U"
    by (rule finite_initial_label_split_range_costed_top_level_correct_and_local_budget_bound
      [OF all_reachable base_budget R_pos source_factor source_progress step_budget run])
  then have correct: "sssp_correct d'"
    by blast
  have pre: "bmssp_pre_full finite_initial_label {s} Infinity"
    using all_reachable finite_initial_label_source_complete
    by (rule top_bmssp_pre_full)
  have sound: "sound_label finite_initial_label"
    using finite_initial_label_sound[OF all_reachable] .
  have S_reaches: "x. x  {s}  reachable s x"
    using all_reachable source_in_V by blast
  have post_full:
    "bmssp_post_full finite_initial_label {s} Infinity d' Infinity U"
    by (rule split_range_costed_bmssp_correct[OF run sound pre S_reaches])
  have post: "bmssp_post finite_initial_label {s} Infinity d' Infinity U"
    using bmssp_post_full_imp_post[OF post_full] .
  have U_V: "U = V"
    using post bound_tree_source_infinity[OF all_reachable]
    unfolding bmssp_post_def by auto
  have cost_U:
      "c  level_range_cost_bound A (R + l * t) (2 * l + 1) U"
    using combined by blast
  have graph_bound:
    "level_range_cost_bound A (R + l * t) (2 * l + 1) U
       A * (2 * l + 1) * vertex_count + (R + l * t) * edge_count"
  proof -
    have U_card: "card U = vertex_count"
      unfolding U_V vertex_count_def by simp
    have out_le: "card (outgoing_edges U)  edge_count"
      by (rule edge_count_outgoing_bound)
    have out_term:
      "(R + l * t) * card (outgoing_edges U)  (R + l * t) * edge_count"
      using out_le by simp
    show ?thesis
      unfolding level_range_cost_bound_def
      using U_card out_term by (simp add: algebra_simps)
  qed
  show ?thesis
    using correct cost_U graph_bound by linarith
qed

theorem finite_initial_label_split_range_costed_top_level_correct_and_source_progress_bound:
  assumes all_reachable: "v. v  V  reachable s v"
    and degree: "edge_outdegree_le Δ"
    and degree_factor: "Δ  A"
    and R_pos: "0 < R"
    and insert_factor: "t  A * k"
    and source_factor: "Suc h  2 * A"
    and source_progress:
      "l d S B d' B' U c.
        split_range_costed_bmssp Δ M_of t h k cap l d S B d' B' U c 
        bmssp_pre_full d S B 
        (x. x  S  reachable s x) 
        card S  M_of l 
        card S  card U"
    and step_progress:
      "l d S B D c_insert d' a betas bs B' Us U_loop c_loop
          child_costs U.
        D = label_partition_view
          (find_pivots_label_capped k cap d S B)
          (find_pivots_pivots_capped k cap d S B) 
        partition_initial_insert_cost_bound c_insert t
          (find_pivots_pivots_capped k cap d S B) 
        split_range_costed_partition_loop_state Δ M_of t h k cap l
          (find_pivots_label_capped k cap d S B)
          (find_pivots_pivots_capped k cap d S B) B d' D a betas bs B'
          Us U_loop c_loop child_costs 
        complete_on d'
          {v  bound_tree S B'. find_pivots_label_capped k cap d S B v = dist s v} 
        U = U_loop 
          {v  bound_tree S B'. find_pivots_label_capped k cap d S B v = dist s v} 
        sound_label d 
        bmssp_pre_full d S B 
        (x. x  S  reachable s x) 
        card S  cap  k * cap  card U"
    and run:
      "split_range_costed_bmssp Δ M_of t h k cap l finite_initial_label {s}
        Infinity d' Infinity U c"
  shows "sssp_correct d' 
    c  level_range_cost_bound (2 * A) (R + l * t) (2 * l + 1) U"
proof
  show "sssp_correct d'"
    by (rule finite_initial_label_split_range_costed_top_level_correct
      [OF all_reachable run])
next
  have pre: "bmssp_pre_full finite_initial_label {s} Infinity"
    using all_reachable finite_initial_label_source_complete
    by (rule top_bmssp_pre_full)
  have sound: "sound_label finite_initial_label"
    using finite_initial_label_sound[OF all_reachable] .
  have S_reaches: "x. x  {s}  reachable s x"
    using all_reachable source_in_V by blast
  show "c  level_range_cost_bound (2 * A) (R + l * t) (2 * l + 1) U"
    by (rule split_range_costed_bmssp_level_bound_from_source_progress_budgets
      [OF degree degree_factor R_pos insert_factor source_factor source_progress
        step_progress run sound pre S_reaches])
qed

theorem finite_initial_label_split_range_costed_top_level_correct_and_graph_bound:
  assumes all_reachable: "v. v  V  reachable s v"
    and degree: "edge_outdegree_le Δ"
    and degree_factor: "Δ  A"
    and R_pos: "0 < R"
    and insert_factor: "t  A * k"
    and source_factor: "Suc h  2 * A"
    and source_progress:
      "l d S B d' B' U c.
        split_range_costed_bmssp Δ M_of t h k cap l d S B d' B' U c 
        bmssp_pre_full d S B 
        (x. x  S  reachable s x) 
        card S  M_of l 
        card S  card U"
    and step_progress:
      "l d S B D c_insert d' a betas bs B' Us U_loop c_loop
          child_costs U.
        D = label_partition_view
          (find_pivots_label_capped k cap d S B)
          (find_pivots_pivots_capped k cap d S B) 
        partition_initial_insert_cost_bound c_insert t
          (find_pivots_pivots_capped k cap d S B) 
        split_range_costed_partition_loop_state Δ M_of t h k cap l
          (find_pivots_label_capped k cap d S B)
          (find_pivots_pivots_capped k cap d S B) B d' D a betas bs B'
          Us U_loop c_loop child_costs 
        complete_on d'
          {v  bound_tree S B'. find_pivots_label_capped k cap d S B v = dist s v} 
        U = U_loop 
          {v  bound_tree S B'. find_pivots_label_capped k cap d S B v = dist s v} 
        sound_label d 
        bmssp_pre_full d S B 
        (x. x  S  reachable s x) 
        card S  cap  k * cap  card U"
    and run:
      "split_range_costed_bmssp Δ M_of t h k cap l finite_initial_label {s}
        Infinity d' Infinity U c"
  shows "sssp_correct d' 
    c  2 * A * (2 * l + 1) * vertex_count + (R + l * t) * edge_count"
proof -
  have combined:
    "sssp_correct d' 
      c  level_range_cost_bound (2 * A) (R + l * t) (2 * l + 1) U"
    by (rule finite_initial_label_split_range_costed_top_level_correct_and_source_progress_bound
      [OF all_reachable degree degree_factor R_pos insert_factor source_factor
        source_progress step_progress run])
  then have correct: "sssp_correct d'"
    by blast
  have pre: "bmssp_pre_full finite_initial_label {s} Infinity"
    using all_reachable finite_initial_label_source_complete
    by (rule top_bmssp_pre_full)
  have sound: "sound_label finite_initial_label"
    using finite_initial_label_sound[OF all_reachable] .
  have S_reaches: "x. x  {s}  reachable s x"
    using all_reachable source_in_V by blast
  have post_full:
    "bmssp_post_full finite_initial_label {s} Infinity d' Infinity U"
    by (rule split_range_costed_bmssp_correct[OF run sound pre S_reaches])
  have post: "bmssp_post finite_initial_label {s} Infinity d' Infinity U"
    using bmssp_post_full_imp_post[OF post_full] .
  have U_V: "U = V"
    using post bound_tree_source_infinity[OF all_reachable]
    unfolding bmssp_post_def by auto
  have cost_U:
      "c  level_range_cost_bound (2 * A) (R + l * t) (2 * l + 1) U"
    using combined by blast
  have graph_bound:
    "level_range_cost_bound (2 * A) (R + l * t) (2 * l + 1) U
       2 * A * (2 * l + 1) * vertex_count + (R + l * t) * edge_count"
  proof -
    have U_card: "card U = vertex_count"
      unfolding U_V vertex_count_def by simp
    have out_le: "card (outgoing_edges U)  edge_count"
      by (rule edge_count_outgoing_bound)
    have out_term:
      "(R + l * t) * card (outgoing_edges U)  (R + l * t) * edge_count"
      using out_le by simp
    show ?thesis
      unfolding level_range_cost_bound_def
      using U_card out_term by (simp add: algebra_simps)
  qed
  show ?thesis
    using correct cost_U graph_bound by linarith
qed

theorem split_range_costed_bmssp_source_card_le_if_sound_label_below_output:
  assumes run:
      "split_range_costed_bmssp Δ M_of t h k cap l d S B d' B' U c"
    and sound: "sound_label d"
    and pre: "bmssp_pre_full d S B"
    and S_reaches: "x. x  S  reachable s x"
    and below: "x. x  S  below_bound (d x) B'"
  shows "card S  card U"
proof -
  have post: "bmssp_post_full d S B d' B' U"
    by (rule split_range_costed_bmssp_correct[OF run sound pre S_reaches])
  have U_eq: "U = bound_tree S B'"
    using post unfolding bmssp_post_full_def by blast
  have S_subset_U: "S  U"
  proof
    fix x
    assume xS: "x  S"
    have S_subset: "S  V"
      using pre unfolding bmssp_pre_full_def by blast
    have xV: "x  V"
      using S_subset xS by blast
    have reach_x: "reachable s x"
      by (rule S_reaches[OF xS])
    have dist_le: "dist s x  d x"
      using sound xV reach_x unfolding sound_label_def by blast
    have below_dist: "below_bound (dist s x) B'"
      using below_bound_le_trans[OF dist_le below[OF xS]] .
    show "x  U"
      unfolding U_eq
      by (rule source_in_own_bound_tree[OF xS reach_x below_dist])
  qed
  have finite_U: "finite U"
    unfolding U_eq bound_tree_def using finite_V by auto
  show ?thesis
    by (rule card_mono[OF finite_U S_subset_U])
qed

theorem split_range_costed_partition_loop_state_success_or_threshold:
  "split_range_costed_partition_loop_state Δ M_of t h k cap l d P B d' D a
      betas bs B' Us U c child_costs 
   sound_label d 
   bmssp_pre_full d P B 
   (x. x  P  reachable s x) 
   B' = B  k * cap  card U"
and split_range_costed_bmssp_success_or_threshold_trivial:
  "split_range_costed_bmssp Δ M_of t h k cap l d S B d' B' U c  True"
proof (induction rule: split_range_costed_partition_loop_state_split_range_costed_bmssp.inducts)
  case (Split_Range_State_Done D a B d' P Δ M_of t h k cap l d)
  then show ?case
    by simp
next
  case (Split_Range_State_Stop a B d' P k cap Δ M_of t h l d D)
  then show ?case
    by simp
next
  case (Split_Range_State_Step D M_of l Bmax S_pull beta D_pull B d a b B_out
      d_out P k cap Delta t h d_child U_child c_child edge_batch source_batch
      batch D_next c_pull c_edges c_sources betas bs Us_tail U_tail c_tail
      child_costs_tail c)
  have tail:
    "B_out = B  k * cap  card U_tail"
    using Split_Range_State_Step.IH Split_Range_State_Step.prems by blast
  then show ?case
  proof
    assume "B_out = B"
    then show ?thesis
      by blast
  next
    assume threshold_tail: "k * cap  card U_tail"
    have tail_trace:
      "concrete_partition_loop_trace P B b bs d_out B_out Us_tail U_tail"
      by (rule split_range_costed_partition_loop_state_trace)
        (use Split_Range_State_Step in blast)+
    have U_tail_def:
      "U_tail = bound_tree P (Fin b)  (set Us_tail)"
      using tail_trace unfolding concrete_partition_loop_trace_def by blast
    have split_b:
      "bound_tree P (Fin b) =
        bound_tree P (Fin a)  range_tree P a (Fin b)"
      using bound_tree_split_at[of a "Fin b" P] Split_Range_State_Step
      by simp
    have U_eq_tail:
      "bound_tree P (Fin a) 
          (set (range_tree P a (Fin b) # Us_tail)) =
        U_tail"
      using U_tail_def split_b by auto
    show ?thesis
      using threshold_tail U_eq_tail by simp
  qed
next
  case (Split_Range_Cost_Base S x Δ M_of t h k cap d B)
  then show ?case
    by simp
next
  case (Split_Range_Cost_Step D k cap d S B c_insert t Δ M_of h l d' a
      betas bs B' Us U_loop c_loop child_costs_loop U c)
  then show ?case
    by simp
qed

theorem split_range_costed_bmssp_Suc_success_or_threshold:
  assumes run:
      "split_range_costed_bmssp Δ M_of t h k cap (Suc l) d S B d' B' U c"
    and sound: "sound_label d"
    and pre: "bmssp_pre_full d S B"
    and S_reaches: "x. x  S  reachable s x"
  shows "B' = B  k * cap  card U"
  using run
proof cases
  case (Split_Range_Cost_Step D c_insert a betas bs Us U_loop c_loop child_costs_loop)
  let ?d_fp = "find_pivots_label_capped k cap d S B"
  let ?P = "find_pivots_pivots_capped k cap d S B"
  let ?W = "{v  bound_tree S B'. ?d_fp v = dist s v}"
  have sound_fp: "sound_label ?d_fp"
    unfolding find_pivots_label_capped_def
    by (rule fp_iter_capped_label_sound[OF sound S_reaches])
  have pivot_pre: "bmssp_pre_full ?d_fp ?P B"
    using find_pivots_capped_establishes_pivot_pre_concrete
      [OF sound pre S_reaches] .
  have P_subset_S: "?P  S"
    unfolding find_pivots_pivots_capped_def by auto
  have P_reaches: "x. x  ?P  reachable s x"
    using P_subset_S S_reaches by blast
  have loop_class:
    "B' = B  k * cap  card U_loop"
    by (rule split_range_costed_partition_loop_state_success_or_threshold
      [OF Split_Range_Cost_Step(3) sound_fp pivot_pre P_reaches])
  have loop_trace:
    "concrete_partition_loop_trace ?P B a bs d' B' Us U_loop"
    by (rule split_range_costed_partition_loop_state_trace
      [OF Split_Range_Cost_Step(3) sound_fp pivot_pre P_reaches])
  have loop_post: "bmssp_post_full ?d_fp ?P B d' B' U_loop"
    by (rule concrete_partition_loop_trace_post[OF loop_trace])
  have finite_U_loop: "finite U_loop"
    using loop_post unfolding bmssp_post_full_def by simp
  show ?thesis
    using loop_class
  proof
    assume "B' = B"
    then show ?thesis
      by blast
  next
    assume threshold_loop: "k * cap  card U_loop"
    have U_eq: "U = U_loop  ?W"
      using Split_Range_Cost_Step(5) by simp
    have finite_U: "finite U"
      unfolding U_eq using finite_U_loop by simp
    have U_loop_subset: "U_loop  U"
      unfolding U_eq by blast
    have "card U_loop  card U"
      by (rule card_mono[OF finite_U U_loop_subset])
    then show ?thesis
      using threshold_loop by linarith
  qed
qed

theorem split_range_costed_bmssp_Suc_source_card_le_from_label_below:
  assumes run:
      "split_range_costed_bmssp Δ M_of t h k cap (Suc l) d S B d' B' U c"
    and sound: "sound_label d"
    and pre: "bmssp_pre_full d S B"
    and S_reaches: "x. x  S  reachable s x"
    and below: "x. x  S  below_bound (d x) B"
    and S_cap: "card S  cap"
    and k_pos: "0 < k"
  shows "card S  card U"
proof -
  have call_class: "B' = B  k * cap  card U"
    by (rule split_range_costed_bmssp_Suc_success_or_threshold
      [OF run sound pre S_reaches])
  then show ?thesis
  proof
    assume B'_eq: "B' = B"
    show ?thesis
    proof (rule split_range_costed_bmssp_source_card_le_if_sound_label_below_output
        [OF run sound pre S_reaches])
      fix x
      assume "x  S"
      then show "below_bound (d x) B'"
        using below B'_eq by simp
    qed
  next
    assume threshold: "k * cap  card U"
    have "cap  k * cap"
      using k_pos by (cases k) simp_all
    then show ?thesis
      using S_cap threshold by linarith
  qed
qed

theorem split_range_costed_capped_step_threshold_if_not_success:
  assumes loop:
      "split_range_costed_partition_loop_state Δ M_of t h k cap l
        (find_pivots_label_capped k cap d S B)
        (find_pivots_pivots_capped k cap d S B) B d' D a betas bs B'
        Us U_loop c_loop child_costs"
    and U_def:
      "U = U_loop 
        {v  bound_tree S B'. find_pivots_label_capped k cap d S B v = dist s v}"
    and sound: "sound_label d"
    and pre: "bmssp_pre_full d S B"
    and S_reaches: "x. x  S  reachable s x"
    and not_success: "B'  B"
  shows "k * cap  card U"
proof -
  let ?d_fp = "find_pivots_label_capped k cap d S B"
  let ?P = "find_pivots_pivots_capped k cap d S B"
  have sound_fp: "sound_label ?d_fp"
    unfolding find_pivots_label_capped_def
    by (rule fp_iter_capped_label_sound[OF sound S_reaches])
  have pivot_pre: "bmssp_pre_full ?d_fp ?P B"
    using find_pivots_capped_establishes_pivot_pre_concrete
      [OF sound pre S_reaches] .
  have P_subset_S: "?P  S"
    unfolding find_pivots_pivots_capped_def by auto
  have P_reaches: "x. x  ?P  reachable s x"
    using P_subset_S S_reaches by blast
  have loop_class:
    "B' = B  k * cap  card U_loop"
    by (rule split_range_costed_partition_loop_state_success_or_threshold
      [OF loop sound_fp pivot_pre P_reaches])
  have threshold_loop: "k * cap  card U_loop"
    using loop_class not_success by blast
  have trace: "concrete_partition_loop_trace ?P B a bs d' B' Us U_loop"
    by (rule split_range_costed_partition_loop_state_trace
      [OF loop sound_fp pivot_pre P_reaches])
  have loop_post: "bmssp_post_full ?d_fp ?P B d' B' U_loop"
    by (rule concrete_partition_loop_trace_post[OF trace])
  have finite_U_loop: "finite U_loop"
    using loop_post unfolding bmssp_post_full_def by simp
  have finite_U: "finite U"
    unfolding U_def using finite_U_loop by simp
  have U_loop_subset: "U_loop  U"
    unfolding U_def by blast
  have "card U_loop  card U"
    by (rule card_mono[OF finite_U U_loop_subset])
  then show ?thesis
    using threshold_loop by linarith
qed

theorem split_range_costed_capped_step_scan_insert_budget_if_not_success:
  assumes degree: "edge_outdegree_le Δ"
    and degree_factor: "Δ  A"
    and insert_factor: "t  A * k"
    and insert:
      "partition_initial_insert_cost_bound c_insert t
        (find_pivots_pivots_capped k cap d S B)"
    and loop:
      "split_range_costed_partition_loop_state Δ M_of t h k cap l
        (find_pivots_label_capped k cap d S B)
        (find_pivots_pivots_capped k cap d S B) B d' D a betas bs B'
        Us U_loop c_loop child_costs"
    and U_def:
      "U = U_loop 
        {v  bound_tree S B'. find_pivots_label_capped k cap d S B v = dist s v}"
    and sound: "sound_label d"
    and pre: "bmssp_pre_full d S B"
    and S_reaches: "x. x  S  reachable s x"
    and S_cap: "card S  cap"
    and not_success: "B'  B"
  shows "fp_iter_capped_scan_cost k cap d S S B + c_insert 
    2 * A * card U"
proof -
  have S_subset: "S  V"
    using pre unfolding bmssp_pre_full_def by blast
  have progress: "k * cap  card U"
    by (rule split_range_costed_capped_step_threshold_if_not_success
      [OF loop U_def sound pre S_reaches not_success])
  show ?thesis
    by (rule find_pivots_scan_and_initial_insert_budget_from_progress
      [OF S_subset degree S_cap insert degree_factor insert_factor progress])
qed

theorem split_range_costed_capped_step_scan_insert_budget_from_seen_or_threshold:
  assumes degree: "edge_outdegree_le Δ"
    and degree_factor: "Δ  A"
    and insert_factor: "t  A * k"
    and seen_factor: "k * Δ + t  2 * A"
    and insert:
      "partition_initial_insert_cost_bound c_insert t
        (find_pivots_pivots_capped k cap d S B)"
    and loop:
      "split_range_costed_partition_loop_state Δ M_of t h k cap l
        (find_pivots_label_capped k cap d S B)
        (find_pivots_pivots_capped k cap d S B) B d' D a betas bs B'
        Us U_loop c_loop child_costs"
    and U_def:
      "U = U_loop 
        {v  bound_tree S B'. find_pivots_label_capped k cap d S B v = dist s v}"
    and sound: "sound_label d"
    and pre: "bmssp_pre_full d S B"
    and S_reaches: "x. x  S  reachable s x"
    and S_cap: "card S  cap"
    and anti: "tree_antichain S"
    and k_pos: "0 < k"
    and seen_success:
      "B' = B 
       card (find_pivots_seen_capped k cap d S B)  card U"
  shows "fp_iter_capped_scan_cost k cap d S S B + c_insert 
    2 * A * card U"
proof (cases "B' = B")
  case True
  have S_subset: "S  V"
    using pre unfolding bmssp_pre_full_def by blast
  show ?thesis
    by (rule find_pivots_scan_and_initial_insert_budget_from_seen_total
      [OF S_subset degree S_cap anti k_pos insert seen_factor
        seen_success[OF True]])
next
  case False
  show ?thesis
    by (rule split_range_costed_capped_step_scan_insert_budget_if_not_success
      [OF degree degree_factor insert_factor insert loop U_def sound pre
        S_reaches S_cap False])
qed

theorem split_range_costed_capped_step_scan_insert_budget_from_scaled_seen_or_threshold:
  assumes degree: "edge_outdegree_le Δ"
    and degree_factor: "Δ  A"
    and insert_factor: "t  A * k"
    and insert_scaled_factor: "t  A_insert * k"
    and seen_scaled_factor: "k * Δ + A_insert  2 * A"
    and insert:
      "partition_initial_insert_cost_bound c_insert t
        (find_pivots_pivots_capped k cap d S B)"
    and loop:
      "split_range_costed_partition_loop_state Δ M_of t h k cap l
        (find_pivots_label_capped k cap d S B)
        (find_pivots_pivots_capped k cap d S B) B d' D a betas bs B'
        Us U_loop c_loop child_costs"
    and U_def:
      "U = U_loop 
        {v  bound_tree S B'. find_pivots_label_capped k cap d S B v = dist s v}"
    and sound: "sound_label d"
    and pre: "bmssp_pre_full d S B"
    and S_reaches: "x. x  S  reachable s x"
    and S_k_cap: "k * card S  cap"
    and anti: "tree_antichain S"
    and k_pos: "0 < k"
    and seen_success:
      "B' = B 
       card (find_pivots_seen_capped k cap d S B)  card U"
  shows "fp_iter_capped_scan_cost k cap d S S B + c_insert 
    2 * A * card U"
proof (cases "B' = B")
  case True
  have S_subset: "S  V"
    using pre unfolding bmssp_pre_full_def by blast
  show ?thesis
    by (rule find_pivots_scan_and_initial_insert_budget_from_seen_scaled
      [OF S_subset degree anti S_k_cap insert insert_scaled_factor
        seen_scaled_factor seen_success[OF True]])
next
  case False
  have S_cap: "card S  cap"
  proof -
    have "card S  k * card S"
      using k_pos by (cases k) simp_all
    then show ?thesis
      using S_k_cap by linarith
  qed
  show ?thesis
    by (rule split_range_costed_capped_step_scan_insert_budget_if_not_success
      [OF degree degree_factor insert_factor insert loop U_def sound pre
        S_reaches S_cap False])
qed

theorem split_range_costed_bmssp_level_bound_from_seen_progress_budgets:
  assumes degree: "edge_outdegree_le Δ"
    and degree_factor: "Δ  A"
    and R_pos: "0 < R"
    and insert_factor: "t  A * k"
    and seen_factor: "k * Δ + t  2 * A"
    and source_factor: "Suc h  2 * A"
    and k_pos: "0 < k"
    and source_progress:
      "l d S B d' B' U c.
        split_range_costed_bmssp Δ M_of t h k cap l d S B d' B' U c 
        bmssp_pre_full d S B 
        (x. x  S  reachable s x) 
        card S  M_of l 
        card S  card U"
    and step_seen_progress:
      "l d S B D c_insert d' a betas bs B' Us U_loop c_loop
          child_costs U.
        D = label_partition_view
          (find_pivots_label_capped k cap d S B)
          (find_pivots_pivots_capped k cap d S B) 
        partition_initial_insert_cost_bound c_insert t
          (find_pivots_pivots_capped k cap d S B) 
        split_range_costed_partition_loop_state Δ M_of t h k cap l
          (find_pivots_label_capped k cap d S B)
          (find_pivots_pivots_capped k cap d S B) B d' D a betas bs B'
          Us U_loop c_loop child_costs 
        complete_on d'
          {v  bound_tree S B'. find_pivots_label_capped k cap d S B v = dist s v} 
        U = U_loop 
          {v  bound_tree S B'. find_pivots_label_capped k cap d S B v = dist s v} 
        sound_label d 
        bmssp_pre_full d S B 
        (x. x  S  reachable s x) 
        card S  cap  tree_antichain S 
        (B' = B 
          card (find_pivots_seen_capped k cap d S B)  card U)"
    and run:
      "split_range_costed_bmssp Δ M_of t h k cap l d S B d' B' U c"
    and sound: "sound_label d"
    and pre: "bmssp_pre_full d S B"
    and S_reaches: "x. x  S  reachable s x"
  shows "c  level_range_cost_bound (2 * A) (R + l * t) (2 * l + 1) U"
proof (rule split_range_costed_bmssp_level_bound_from_source_progress_and_local_budgets
    [where A = "2 * A" and R = R,
      OF _ R_pos source_factor source_progress _ run sound pre S_reaches])
  show "Δ  2 * A"
    using degree_factor by simp
next
  fix l d S B D c_insert d' a betas bs B' Us U_loop c_loop child_costs U
  assume D_def:
      "D = label_partition_view
        (find_pivots_label_capped k cap d S B)
        (find_pivots_pivots_capped k cap d S B)"
    and insert:
      "partition_initial_insert_cost_bound c_insert t
        (find_pivots_pivots_capped k cap d S B)"
    and loop:
      "split_range_costed_partition_loop_state Δ M_of t h k cap l
        (find_pivots_label_capped k cap d S B)
        (find_pivots_pivots_capped k cap d S B) B d' D a betas bs B'
        Us U_loop c_loop child_costs"
    and complete:
      "complete_on d'
        {v  bound_tree S B'. find_pivots_label_capped k cap d S B v = dist s v}"
    and U_def:
      "U = U_loop 
        {v  bound_tree S B'. find_pivots_label_capped k cap d S B v = dist s v}"
    and sound_s: "sound_label d"
    and pre_s: "bmssp_pre_full d S B"
    and reaches_s: "x. x  S  reachable s x"
  have progress:
      "card S  cap  tree_antichain S 
        (B' = B 
          card (find_pivots_seen_capped k cap d S B)  card U)"
    by (rule step_seen_progress
      [OF D_def insert loop complete U_def sound_s pre_s reaches_s])
  then have S_cap: "card S  cap"
    by blast
  from progress have anti: "tree_antichain S"
    by blast
  from progress have seen_success:
      "B' = B 
        card (find_pivots_seen_capped k cap d S B)  card U"
    by blast
  show "fp_iter_capped_scan_cost k cap d S S B + c_insert 
      2 * A * card U"
    by (rule split_range_costed_capped_step_scan_insert_budget_from_seen_or_threshold
      [OF degree degree_factor insert_factor seen_factor insert loop U_def sound_s
        pre_s reaches_s S_cap anti k_pos seen_success])
qed

theorem split_range_costed_bmssp_level_bound_from_scaled_seen_progress_budgets:
  assumes degree: "edge_outdegree_le Δ"
    and degree_factor: "Δ  A"
    and R_pos: "0 < R"
    and insert_factor: "t  A * k"
    and insert_scaled_factor: "t  A_insert * k"
    and seen_scaled_factor: "k * Δ + A_insert  2 * A"
    and source_factor: "Suc h  2 * A"
    and k_pos: "0 < k"
    and source_progress:
      "l d S B d' B' U c.
        split_range_costed_bmssp Δ M_of t h k cap l d S B d' B' U c 
        bmssp_pre_full d S B 
        (x. x  S  reachable s x) 
        card S  M_of l 
        card S  card U"
    and step_scaled_seen_progress:
      "l d S B D c_insert d' a betas bs B' Us U_loop c_loop
          child_costs U.
        D = label_partition_view
          (find_pivots_label_capped k cap d S B)
          (find_pivots_pivots_capped k cap d S B) 
        partition_initial_insert_cost_bound c_insert t
          (find_pivots_pivots_capped k cap d S B) 
        split_range_costed_partition_loop_state Δ M_of t h k cap l
          (find_pivots_label_capped k cap d S B)
          (find_pivots_pivots_capped k cap d S B) B d' D a betas bs B'
          Us U_loop c_loop child_costs 
        complete_on d'
          {v  bound_tree S B'. find_pivots_label_capped k cap d S B v = dist s v} 
        U = U_loop 
          {v  bound_tree S B'. find_pivots_label_capped k cap d S B v = dist s v} 
        sound_label d 
        bmssp_pre_full d S B 
        (x. x  S  reachable s x) 
        k * card S  cap  tree_antichain S 
        (B' = B 
          card (find_pivots_seen_capped k cap d S B)  card U)"
    and run:
      "split_range_costed_bmssp Δ M_of t h k cap l d S B d' B' U c"
    and sound: "sound_label d"
    and pre: "bmssp_pre_full d S B"
    and S_reaches: "x. x  S  reachable s x"
  shows "c  level_range_cost_bound (2 * A) (R + l * t) (2 * l + 1) U"
proof (rule split_range_costed_bmssp_level_bound_from_source_progress_and_local_budgets
    [where A = "2 * A" and R = R,
      OF _ R_pos source_factor source_progress _ run sound pre S_reaches])
  show "Δ  2 * A"
    using degree_factor by simp
next
  fix l d S B D c_insert d' a betas bs B' Us U_loop c_loop child_costs U
  assume D_def:
      "D = label_partition_view
        (find_pivots_label_capped k cap d S B)
        (find_pivots_pivots_capped k cap d S B)"
    and insert:
      "partition_initial_insert_cost_bound c_insert t
        (find_pivots_pivots_capped k cap d S B)"
    and loop:
      "split_range_costed_partition_loop_state Δ M_of t h k cap l
        (find_pivots_label_capped k cap d S B)
        (find_pivots_pivots_capped k cap d S B) B d' D a betas bs B'
        Us U_loop c_loop child_costs"
    and complete:
      "complete_on d'
        {v  bound_tree S B'. find_pivots_label_capped k cap d S B v = dist s v}"
    and U_def:
      "U = U_loop 
        {v  bound_tree S B'. find_pivots_label_capped k cap d S B v = dist s v}"
    and sound_s: "sound_label d"
    and pre_s: "bmssp_pre_full d S B"
    and reaches_s: "x. x  S  reachable s x"
  have progress:
      "k * card S  cap  tree_antichain S 
        (B' = B 
          card (find_pivots_seen_capped k cap d S B)  card U)"
    by (rule step_scaled_seen_progress
      [OF D_def insert loop complete U_def sound_s pre_s reaches_s])
  then have S_k_cap: "k * card S  cap"
    by blast
  from progress have anti: "tree_antichain S"
    by blast
  from progress have seen_success:
      "B' = B 
        card (find_pivots_seen_capped k cap d S B)  card U"
    by blast
  show "fp_iter_capped_scan_cost k cap d S S B + c_insert 
      2 * A * card U"
    by (rule split_range_costed_capped_step_scan_insert_budget_from_scaled_seen_or_threshold
      [OF degree degree_factor insert_factor insert_scaled_factor
        seen_scaled_factor insert loop U_def sound_s pre_s reaches_s
        S_k_cap anti k_pos seen_success])
qed

theorem finite_initial_label_split_range_costed_top_level_correct_and_seen_progress_bound:
  assumes all_reachable: "v. v  V  reachable s v"
    and degree: "edge_outdegree_le Δ"
    and degree_factor: "Δ  A"
    and R_pos: "0 < R"
    and insert_factor: "t  A * k"
    and seen_factor: "k * Δ + t  2 * A"
    and source_factor: "Suc h  2 * A"
    and k_pos: "0 < k"
    and source_progress:
      "l d S B d' B' U c.
        split_range_costed_bmssp Δ M_of t h k cap l d S B d' B' U c 
        bmssp_pre_full d S B 
        (x. x  S  reachable s x) 
        card S  M_of l 
        card S  card U"
    and step_seen_progress:
      "l d S B D c_insert d' a betas bs B' Us U_loop c_loop
          child_costs U.
        D = label_partition_view
          (find_pivots_label_capped k cap d S B)
          (find_pivots_pivots_capped k cap d S B) 
        partition_initial_insert_cost_bound c_insert t
          (find_pivots_pivots_capped k cap d S B) 
        split_range_costed_partition_loop_state Δ M_of t h k cap l
          (find_pivots_label_capped k cap d S B)
          (find_pivots_pivots_capped k cap d S B) B d' D a betas bs B'
          Us U_loop c_loop child_costs 
        complete_on d'
          {v  bound_tree S B'. find_pivots_label_capped k cap d S B v = dist s v} 
        U = U_loop 
          {v  bound_tree S B'. find_pivots_label_capped k cap d S B v = dist s v} 
        sound_label d 
        bmssp_pre_full d S B 
        (x. x  S  reachable s x) 
        card S  cap  tree_antichain S 
        (B' = B 
          card (find_pivots_seen_capped k cap d S B)  card U)"
    and run:
      "split_range_costed_bmssp Δ M_of t h k cap l finite_initial_label {s}
        Infinity d' Infinity U c"
  shows "sssp_correct d' 
    c  level_range_cost_bound (2 * A) (R + l * t) (2 * l + 1) U"
proof
  show "sssp_correct d'"
    by (rule finite_initial_label_split_range_costed_top_level_correct
      [OF all_reachable run])
next
  have pre: "bmssp_pre_full finite_initial_label {s} Infinity"
    using all_reachable finite_initial_label_source_complete
    by (rule top_bmssp_pre_full)
  have sound: "sound_label finite_initial_label"
    using finite_initial_label_sound[OF all_reachable] .
  have S_reaches: "x. x  {s}  reachable s x"
    using all_reachable source_in_V by blast
  show "c  level_range_cost_bound (2 * A) (R + l * t) (2 * l + 1) U"
    by (rule split_range_costed_bmssp_level_bound_from_seen_progress_budgets
      [OF degree degree_factor R_pos insert_factor seen_factor source_factor k_pos
        source_progress step_seen_progress run sound pre S_reaches])
qed

theorem finite_initial_label_split_range_costed_top_level_correct_and_scaled_seen_progress_bound:
  assumes all_reachable: "v. v  V  reachable s v"
    and degree: "edge_outdegree_le Δ"
    and degree_factor: "Δ  A"
    and R_pos: "0 < R"
    and insert_factor: "t  A * k"
    and insert_scaled_factor: "t  A_insert * k"
    and seen_scaled_factor: "k * Δ + A_insert  2 * A"
    and source_factor: "Suc h  2 * A"
    and k_pos: "0 < k"
    and source_progress:
      "l d S B d' B' U c.
        split_range_costed_bmssp Δ M_of t h k cap l d S B d' B' U c 
        bmssp_pre_full d S B 
        (x. x  S  reachable s x) 
        card S  M_of l 
        card S  card U"
    and step_scaled_seen_progress:
      "l d S B D c_insert d' a betas bs B' Us U_loop c_loop
          child_costs U.
        D = label_partition_view
          (find_pivots_label_capped k cap d S B)
          (find_pivots_pivots_capped k cap d S B) 
        partition_initial_insert_cost_bound c_insert t
          (find_pivots_pivots_capped k cap d S B) 
        split_range_costed_partition_loop_state Δ M_of t h k cap l
          (find_pivots_label_capped k cap d S B)
          (find_pivots_pivots_capped k cap d S B) B d' D a betas bs B'
          Us U_loop c_loop child_costs 
        complete_on d'
          {v  bound_tree S B'. find_pivots_label_capped k cap d S B v = dist s v} 
        U = U_loop 
          {v  bound_tree S B'. find_pivots_label_capped k cap d S B v = dist s v} 
        sound_label d 
        bmssp_pre_full d S B 
        (x. x  S  reachable s x) 
        k * card S  cap  tree_antichain S 
        (B' = B 
          card (find_pivots_seen_capped k cap d S B)  card U)"
    and run:
      "split_range_costed_bmssp Δ M_of t h k cap l finite_initial_label {s}
        Infinity d' Infinity U c"
  shows "sssp_correct d' 
    c  level_range_cost_bound (2 * A) (R + l * t) (2 * l + 1) U"
proof
  show "sssp_correct d'"
    by (rule finite_initial_label_split_range_costed_top_level_correct
      [OF all_reachable run])
next
  have pre: "bmssp_pre_full finite_initial_label {s} Infinity"
    using all_reachable finite_initial_label_source_complete
    by (rule top_bmssp_pre_full)
  have sound: "sound_label finite_initial_label"
    using finite_initial_label_sound[OF all_reachable] .
  have S_reaches: "x. x  {s}  reachable s x"
    using all_reachable source_in_V by blast
  show "c  level_range_cost_bound (2 * A) (R + l * t) (2 * l + 1) U"
    by (rule split_range_costed_bmssp_level_bound_from_scaled_seen_progress_budgets
      [OF degree degree_factor R_pos insert_factor insert_scaled_factor
        seen_scaled_factor source_factor k_pos source_progress
        step_scaled_seen_progress run sound pre S_reaches])
qed

theorem finite_initial_label_split_range_costed_top_level_correct_and_seen_progress_graph_bound:
  assumes all_reachable: "v. v  V  reachable s v"
    and degree: "edge_outdegree_le Δ"
    and degree_factor: "Δ  A"
    and R_pos: "0 < R"
    and insert_factor: "t  A * k"
    and seen_factor: "k * Δ + t  2 * A"
    and source_factor: "Suc h  2 * A"
    and k_pos: "0 < k"
    and source_progress:
      "l d S B d' B' U c.
        split_range_costed_bmssp Δ M_of t h k cap l d S B d' B' U c 
        bmssp_pre_full d S B 
        (x. x  S  reachable s x) 
        card S  M_of l 
        card S  card U"
    and step_seen_progress:
      "l d S B D c_insert d' a betas bs B' Us U_loop c_loop
          child_costs U.
        D = label_partition_view
          (find_pivots_label_capped k cap d S B)
          (find_pivots_pivots_capped k cap d S B) 
        partition_initial_insert_cost_bound c_insert t
          (find_pivots_pivots_capped k cap d S B) 
        split_range_costed_partition_loop_state Δ M_of t h k cap l
          (find_pivots_label_capped k cap d S B)
          (find_pivots_pivots_capped k cap d S B) B d' D a betas bs B'
          Us U_loop c_loop child_costs 
        complete_on d'
          {v  bound_tree S B'. find_pivots_label_capped k cap d S B v = dist s v} 
        U = U_loop 
          {v  bound_tree S B'. find_pivots_label_capped k cap d S B v = dist s v} 
        sound_label d 
        bmssp_pre_full d S B 
        (x. x  S  reachable s x) 
        card S  cap  tree_antichain S 
        (B' = B 
          card (find_pivots_seen_capped k cap d S B)  card U)"
    and run:
      "split_range_costed_bmssp Δ M_of t h k cap l finite_initial_label {s}
        Infinity d' Infinity U c"
  shows "sssp_correct d' 
    c  2 * A * (2 * l + 1) * vertex_count + (R + l * t) * edge_count"
proof -
  have combined:
    "sssp_correct d' 
      c  level_range_cost_bound (2 * A) (R + l * t) (2 * l + 1) U"
    by (rule finite_initial_label_split_range_costed_top_level_correct_and_seen_progress_bound
      [OF all_reachable degree degree_factor R_pos insert_factor seen_factor
        source_factor k_pos source_progress step_seen_progress run])
  then have correct: "sssp_correct d'"
    by blast
  have pre: "bmssp_pre_full finite_initial_label {s} Infinity"
    using all_reachable finite_initial_label_source_complete
    by (rule top_bmssp_pre_full)
  have sound: "sound_label finite_initial_label"
    using finite_initial_label_sound[OF all_reachable] .
  have S_reaches: "x. x  {s}  reachable s x"
    using all_reachable source_in_V by blast
  have post_full:
    "bmssp_post_full finite_initial_label {s} Infinity d' Infinity U"
    by (rule split_range_costed_bmssp_correct[OF run sound pre S_reaches])
  have post: "bmssp_post finite_initial_label {s} Infinity d' Infinity U"
    using bmssp_post_full_imp_post[OF post_full] .
  have U_V: "U = V"
    using post bound_tree_source_infinity[OF all_reachable]
    unfolding bmssp_post_def by auto
  have cost_U:
      "c  level_range_cost_bound (2 * A) (R + l * t) (2 * l + 1) U"
    using combined by blast
  have graph_bound:
    "level_range_cost_bound (2 * A) (R + l * t) (2 * l + 1) U
       2 * A * (2 * l + 1) * vertex_count + (R + l * t) * edge_count"
  proof -
    have U_card: "card U = vertex_count"
      unfolding U_V vertex_count_def by simp
    have out_le: "card (outgoing_edges U)  edge_count"
      by (rule edge_count_outgoing_bound)
    have out_term:
      "(R + l * t) * card (outgoing_edges U)  (R + l * t) * edge_count"
      using out_le by simp
    show ?thesis
      unfolding level_range_cost_bound_def
      using U_card out_term by (simp add: algebra_simps)
  qed
  show ?thesis
    using correct cost_U graph_bound by linarith
qed

theorem finite_initial_label_split_range_costed_top_level_correct_and_scaled_seen_progress_graph_bound:
  assumes all_reachable: "v. v  V  reachable s v"
    and degree: "edge_outdegree_le Δ"
    and degree_factor: "Δ  A"
    and R_pos: "0 < R"
    and insert_factor: "t  A * k"
    and insert_scaled_factor: "t  A_insert * k"
    and seen_scaled_factor: "k * Δ + A_insert  2 * A"
    and source_factor: "Suc h  2 * A"
    and k_pos: "0 < k"
    and source_progress:
      "l d S B d' B' U c.
        split_range_costed_bmssp Δ M_of t h k cap l d S B d' B' U c 
        bmssp_pre_full d S B 
        (x. x  S  reachable s x) 
        card S  M_of l 
        card S  card U"
    and step_scaled_seen_progress:
      "l d S B D c_insert d' a betas bs B' Us U_loop c_loop
          child_costs U.
        D = label_partition_view
          (find_pivots_label_capped k cap d S B)
          (find_pivots_pivots_capped k cap d S B) 
        partition_initial_insert_cost_bound c_insert t
          (find_pivots_pivots_capped k cap d S B) 
        split_range_costed_partition_loop_state Δ M_of t h k cap l
          (find_pivots_label_capped k cap d S B)
          (find_pivots_pivots_capped k cap d S B) B d' D a betas bs B'
          Us U_loop c_loop child_costs 
        complete_on d'
          {v  bound_tree S B'. find_pivots_label_capped k cap d S B v = dist s v} 
        U = U_loop 
          {v  bound_tree S B'. find_pivots_label_capped k cap d S B v = dist s v} 
        sound_label d 
        bmssp_pre_full d S B 
        (x. x  S  reachable s x) 
        k * card S  cap  tree_antichain S 
        (B' = B 
          card (find_pivots_seen_capped k cap d S B)  card U)"
    and run:
      "split_range_costed_bmssp Δ M_of t h k cap l finite_initial_label {s}
        Infinity d' Infinity U c"
  shows "sssp_correct d' 
    c  2 * A * (2 * l + 1) * vertex_count + (R + l * t) * edge_count"
proof -
  have combined:
    "sssp_correct d' 
      c  level_range_cost_bound (2 * A) (R + l * t) (2 * l + 1) U"
    by (rule finite_initial_label_split_range_costed_top_level_correct_and_scaled_seen_progress_bound
      [OF all_reachable degree degree_factor R_pos insert_factor insert_scaled_factor
        seen_scaled_factor source_factor k_pos source_progress
        step_scaled_seen_progress run])
  then have correct: "sssp_correct d'"
    by blast
  have pre: "bmssp_pre_full finite_initial_label {s} Infinity"
    using all_reachable finite_initial_label_source_complete
    by (rule top_bmssp_pre_full)
  have sound: "sound_label finite_initial_label"
    using finite_initial_label_sound[OF all_reachable] .
  have S_reaches: "x. x  {s}  reachable s x"
    using all_reachable source_in_V by blast
  have post_full:
    "bmssp_post_full finite_initial_label {s} Infinity d' Infinity U"
    by (rule split_range_costed_bmssp_correct[OF run sound pre S_reaches])
  have post: "bmssp_post finite_initial_label {s} Infinity d' Infinity U"
    using bmssp_post_full_imp_post[OF post_full] .
  have U_V: "U = V"
    using post bound_tree_source_infinity[OF all_reachable]
    unfolding bmssp_post_def by auto
  have cost_U:
      "c  level_range_cost_bound (2 * A) (R + l * t) (2 * l + 1) U"
    using combined by blast
  have graph_bound:
    "level_range_cost_bound (2 * A) (R + l * t) (2 * l + 1) U
       2 * A * (2 * l + 1) * vertex_count + (R + l * t) * edge_count"
  proof -
    have U_card: "card U = vertex_count"
      unfolding U_V vertex_count_def by simp
    have out_le: "card (outgoing_edges U)  edge_count"
      by (rule edge_count_outgoing_bound)
    have out_term:
      "(R + l * t) * card (outgoing_edges U)  (R + l * t) * edge_count"
      using out_le by simp
    show ?thesis
      unfolding level_range_cost_bound_def
      using U_card out_term by (simp add: algebra_simps)
  qed
  show ?thesis
    using correct cost_U graph_bound by linarith
qed

theorem range_costed_partition_loop_state_cost_bound:
  assumes run:
    "range_costed_partition_loop_state Δ M_of t k cap l d P B d' D a
      betas bs B' Us U c child_costs"
  shows "c  sum_list child_costs + (M_of l) * length child_costs +
    t * (sum_list
      (map (λX. card (outgoing_edges X)) (range_tree_child_list P a bs)) +
      (M_of l) * length child_costs)"
  using run
  by (induction)
    (auto simp: pull_separates_def partition_pull_cost_bound_def
      partition_batch_cost_bound_def algebra_simps
      dest: range_costed_pull_cost_le_M range_costed_batch_cost_le)

theorem range_costed_partition_loop_state_cost_bound_by_child_sources:
  "range_costed_partition_loop_state Δ M_of t k cap l d P B d' D a
      betas bs B' Us U c child_costs 
   child_sources.
    length child_sources = length bs 
    list_all2
      (λS_child U_child. c_child B_child d_child B_child'.
        range_costed_bmssp Δ M_of t k cap l d S_child B_child
          d_child B_child' U_child c_child 
        bmssp_pre_full d S_child B_child 
        (xS_child. reachable s x) 
        card S_child  M_of l)
      child_sources (range_tree_child_list P a bs) 
    c  sum_list child_costs + sum_list (map card child_sources) +
      t * (sum_list
        (map (λX. card (outgoing_edges X)) (range_tree_child_list P a bs)) +
        sum_list (map card child_sources))"
and range_costed_bmssp_child_sources_trivial:
  "range_costed_bmssp Δ M_of t k cap l d S B d' B' U c  True"
proof (induction rule:
    range_costed_partition_loop_state_range_costed_bmssp.inducts)
  case (Range_State_Done D a B d' P Δ M_of t k cap l d)
  show ?case
    by (intro exI[of _ "[]"]) simp
next
  case (Range_State_Stop a B d' P k cap Δ M_of t l d D)
  show ?case
    by (intro exI[of _ "[]"]) simp
next
  case (Range_State_Step D M_of l Bmax S_pull beta D_pull B d a b B'
      d' P k cap Δ t d_child U_child c_child batch D_next c_pull
      c_batch betas bs Us_tail U_tail c_tail child_costs_tail c)
  obtain child_sources_tail where len_tail:
      "length child_sources_tail = length bs"
    and sources_tail:
      "list_all2
        (λS_child U_child. c_child B_child d_child B_child'.
          range_costed_bmssp Δ M_of t k cap l d S_child B_child
            d_child B_child' U_child c_child 
          bmssp_pre_full d S_child B_child 
          (xS_child. reachable s x) 
          card S_child  M_of l)
        child_sources_tail (range_tree_child_list P b bs)"
    and tail_cost:
      "c_tail 
        sum_list child_costs_tail + sum_list (map card child_sources_tail) +
        t * (sum_list
          (map (λX. card (outgoing_edges X)) (range_tree_child_list P b bs)) +
          sum_list (map card child_sources_tail))"
    using Range_State_Step.IH(11) by blast
  have card_pull: "card S_pull  M_of l"
    using Range_State_Step unfolding pull_separates_def by blast
  have pull_cost: "c_pull  card S_pull"
    using Range_State_Step
    unfolding partition_pull_cost_bound_def by blast
  have batch_cost:
    "c_batch  t * (card (outgoing_edges U_child) + card S_pull)"
    by (rule range_costed_batch_cost_le
      [where d = d and S = S_pull and d_child = d_child and b = b
        and beta = beta and batch = batch and M = "card S_pull"])
      (use Range_State_Step in auto)
  let ?child_sources = "S_pull # child_sources_tail"
  have len: "length ?child_sources = length (b # bs)"
    using len_tail by simp
  have head_source:
    "c_child' B_child d_child' B_child'.
      range_costed_bmssp Δ M_of t k cap l d S_pull B_child
        d_child' B_child' U_child c_child' 
      bmssp_pre_full d S_pull B_child 
      (xS_pull. reachable s x) 
      card S_pull  M_of l"
    using Range_State_Step card_pull by blast
  have sources:
    "list_all2
      (λS_child U_child. c_child B_child d_child B_child'.
        range_costed_bmssp Δ M_of t k cap l d S_child B_child
          d_child B_child' U_child c_child 
        bmssp_pre_full d S_child B_child 
        (xS_child. reachable s x) 
        card S_child  M_of l)
      ?child_sources (range_tree_child_list P a (b # bs))"
    using head_source sources_tail Range_State_Step by simp
  have cost:
    "c  sum_list (c_child # child_costs_tail) +
      sum_list (map card ?child_sources) +
      t * (sum_list
        (map (λX. card (outgoing_edges X))
          (range_tree_child_list P a (b # bs))) +
        sum_list (map card ?child_sources))"
  proof -
    have c_eq: "c = c_pull + c_batch + c_child + c_tail"
      using Range_State_Step by blast
    have "c_pull + c_batch + c_child + c_tail 
        card S_pull + t * (card (outgoing_edges U_child) + card S_pull) +
        c_child +
        (sum_list child_costs_tail + sum_list (map card child_sources_tail) +
          t * (sum_list
            (map (λX. card (outgoing_edges X)) (range_tree_child_list P b bs)) +
            sum_list (map card child_sources_tail)))"
      using pull_cost batch_cost tail_cost by simp
    also have " =
        sum_list (c_child # child_costs_tail) +
        sum_list (map card ?child_sources) +
        t * (card (outgoing_edges U_child) +
          sum_list
            (map (λX. card (outgoing_edges X)) (range_tree_child_list P b bs)) +
          sum_list (map card ?child_sources))"
      by (simp add: algebra_simps)
    also have " =
        sum_list (c_child # child_costs_tail) +
        sum_list (map card ?child_sources) +
        t * (sum_list
          (map (λX. card (outgoing_edges X))
            (range_tree_child_list P a (b # bs))) +
          sum_list (map card ?child_sources))"
      using Range_State_Step by simp
    finally show ?thesis
      using c_eq by simp
  qed
  show ?case
    by (intro exI[of _ ?child_sources] conjI)
      (use len sources cost in simp_all)
next
  case (Range_Cost_Base S x Δ M_of t k cap d B)
  show ?case
    by simp
next
  case (Range_Cost_Step D k cap d S B c_insert t Δ M_of l d' a betas bs B'
      Us U_loop c_loop child_costs_loop U c)
  show ?case
    by simp
qed

theorem range_costed_partition_loop_state_cost_from_child_and_source_bounds:
  assumes run:
    "range_costed_partition_loop_state Δ M_of t k cap l d P B d' D a
      betas bs B' Us U c child_costs"
    and child_cost_bounds:
      "list_all2 (λc_child U_child.
        c_child  level_range_cost_bound A R L U_child)
        child_costs (range_tree_child_list P a bs)"
    and source_progress:
      "S_child B_child d_child B_child' U_child c_child.
        range_costed_bmssp Δ M_of t k cap l d S_child B_child
            d_child B_child' U_child c_child;
          bmssp_pre_full d S_child B_child;
          x. x  S_child  reachable s x;
          card S_child  M_of l
         card S_child  card U_child"
  shows "c 
    A * L * card (range_tree_chain P a bs B') +
    (R + t) * card (outgoing_edges (range_tree_chain P a bs B')) +
    Suc t * card (range_tree_chain P a bs B')"
proof -
  obtain child_sources where len_sources:
      "length child_sources = length bs"
    and sources:
      "list_all2
        (λS_child U_child. c_child B_child d_child B_child'.
          range_costed_bmssp Δ M_of t k cap l d S_child B_child
            d_child B_child' U_child c_child 
          bmssp_pre_full d S_child B_child 
          (xS_child. reachable s x) 
          card S_child  M_of l)
        child_sources (range_tree_child_list P a bs)"
    and cost:
      "c  sum_list child_costs + sum_list (map card child_sources) +
        t * (sum_list
          (map (λX. card (outgoing_edges X)) (range_tree_child_list P a bs)) +
          sum_list (map card child_sources))"
    using range_costed_partition_loop_state_cost_bound_by_child_sources[OF run]
    by blast
  have mono: "nondecreasing_from a bs"
    by (rule range_costed_partition_loop_state_mono[OF run])
  have source_dom:
    "list_all2 (λS_child U_child. card S_child  card U_child)
      child_sources (range_tree_child_list P a bs)"
    using sources
  proof (induction rule: list_all2_induct)
    case Nil
    then show ?case by simp
  next
    case (Cons S_child child_sources U_child child_sets)
    obtain c_child B_child d_child B_child' where child:
        "range_costed_bmssp Δ M_of t k cap l d S_child B_child
          d_child B_child' U_child c_child"
      and child_pre: "bmssp_pre_full d S_child B_child"
      and child_reaches: "xS_child. reachable s x"
      and child_card: "card S_child  M_of l"
      using Cons.hyps by blast
    have head: "card S_child  card U_child"
      by (rule source_progress[OF child child_pre _ child_card])
        (use child_reaches in blast)
    show ?case
      using head Cons.IH Cons.hyps by simp
  qed
  have source_sum:
    "sum_list (map card child_sources) 
      card (range_tree_chain P a bs B')"
    by (rule sum_card_dominated_by_range_tree_child_list_le_chain
      [OF mono source_dom])
  have child_sum:
    "sum_list child_costs 
      A * L * card (range_tree_chain P a bs B') +
      R * card (outgoing_edges (range_tree_chain P a bs B'))"
    by (rule child_costs_le_level_range_child_list_bound
      [OF mono child_cost_bounds])
  have edge_sum:
    "sum_list
      (map (λX. card (outgoing_edges X)) (range_tree_child_list P a bs)) 
     card (outgoing_edges (range_tree_chain P a bs B'))"
    by (rule card_outgoing_edges_range_tree_child_list_le_chain[OF mono])
  have "c 
      A * L * card (range_tree_chain P a bs B') +
      R * card (outgoing_edges (range_tree_chain P a bs B')) +
      sum_list (map card child_sources) +
      t * (card (outgoing_edges (range_tree_chain P a bs B')) +
        sum_list (map card child_sources))"
  proof -
    have tail:
      "t * (sum_list
          (map (λX. card (outgoing_edges X)) (range_tree_child_list P a bs)) +
          sum_list (map card child_sources)) 
       t * (card (outgoing_edges (range_tree_chain P a bs B')) +
          sum_list (map card child_sources))"
      using edge_sum by simp
    have "sum_list child_costs + sum_list (map card child_sources) +
        t * (sum_list
          (map (λX. card (outgoing_edges X)) (range_tree_child_list P a bs)) +
          sum_list (map card child_sources)) 
        A * L * card (range_tree_chain P a bs B') +
        R * card (outgoing_edges (range_tree_chain P a bs B')) +
        sum_list (map card child_sources) +
        t * (card (outgoing_edges (range_tree_chain P a bs B')) +
          sum_list (map card child_sources))"
      using child_sum tail by linarith
    then show ?thesis
      using cost by linarith
  qed
  also have " 
      A * L * card (range_tree_chain P a bs B') +
      (R + t) * card (outgoing_edges (range_tree_chain P a bs B')) +
      Suc t * card (range_tree_chain P a bs B')"
  proof -
    have source_part:
      "sum_list (map card child_sources) +
        t * sum_list (map card child_sources) 
       Suc t * card (range_tree_chain P a bs B')"
    proof -
      have t_part:
        "t * sum_list (map card child_sources) 
          t * card (range_tree_chain P a bs B')"
        using source_sum by simp
      have "sum_list (map card child_sources) +
          t * sum_list (map card child_sources) 
        card (range_tree_chain P a bs B') +
          t * card (range_tree_chain P a bs B')"
        using source_sum t_part by linarith
      then show ?thesis
        by (simp add: algebra_simps)
    qed
    show ?thesis
      using source_part by (simp add: algebra_simps)
  qed
  finally show ?thesis .
qed

theorem range_costed_partition_loop_state_cost_from_child_cost_bounds:
  assumes run:
    "range_costed_partition_loop_state Δ M_of t k cap l d P B d' D a
      betas bs B' Us U c child_costs"
    and child_cost_bounds:
      "list_all2 (λc_child U_child.
        c_child  level_range_cost_bound A R L U_child)
        child_costs (range_tree_child_list P a bs)"
  shows "c 
    A * L * card (range_tree_chain P a bs B') +
    (R + t) * card (outgoing_edges (range_tree_chain P a bs B')) +
    (Suc t) * (M_of l) * length bs"
proof -
  have child_len: "length child_costs = length bs"
    by (rule range_costed_partition_loop_state_child_call_ranges(1)[OF run])
  have cost:
    "c  sum_list child_costs + (M_of l) * length child_costs +
      t * (sum_list
        (map (λX. card (outgoing_edges X)) (range_tree_child_list P a bs)) +
        (M_of l) * length child_costs)"
    by (rule range_costed_partition_loop_state_cost_bound[OF run])
  have mono: "nondecreasing_from a bs"
    by (rule range_costed_partition_loop_state_mono[OF run])
  have child_sum:
    "sum_list child_costs 
      A * L * card (range_tree_chain P a bs B') +
      R * card (outgoing_edges (range_tree_chain P a bs B'))"
    by (rule child_costs_le_level_range_child_list_bound
      [OF mono child_cost_bounds])
  have edge_sum:
    "sum_list
      (map (λX. card (outgoing_edges X)) (range_tree_child_list P a bs)) 
     card (outgoing_edges (range_tree_chain P a bs B'))"
    by (rule card_outgoing_edges_range_tree_child_list_le_chain[OF mono])
  have "c 
      A * L * card (range_tree_chain P a bs B') +
      R * card (outgoing_edges (range_tree_chain P a bs B')) +
      (M_of l) * length bs +
      t * (card (outgoing_edges (range_tree_chain P a bs B')) +
        (M_of l) * length bs)"
  proof -
    have middle:
      "(M_of l) * length child_costs = (M_of l) * length bs"
      using child_len by simp
    have tail:
      "t * (sum_list
          (map (λX. card (outgoing_edges X)) (range_tree_child_list P a bs)) +
          (M_of l) * length child_costs) 
       t * (card (outgoing_edges (range_tree_chain P a bs B')) +
          (M_of l) * length bs)"
    proof -
      have "sum_list
          (map (λX. card (outgoing_edges X)) (range_tree_child_list P a bs)) +
          (M_of l) * length child_costs 
        card (outgoing_edges (range_tree_chain P a bs B')) +
          (M_of l) * length bs"
        using edge_sum middle by linarith
      then show ?thesis
        by simp
    qed
    have "sum_list child_costs + (M_of l) * length child_costs +
        t * (sum_list
          (map (λX. card (outgoing_edges X)) (range_tree_child_list P a bs)) +
          (M_of l) * length child_costs) 
        A * L * card (range_tree_chain P a bs B') +
        R * card (outgoing_edges (range_tree_chain P a bs B')) +
        (M_of l) * length bs +
        t * (card (outgoing_edges (range_tree_chain P a bs B')) +
          (M_of l) * length bs)"
      using child_sum middle tail by linarith
    then show ?thesis
      using cost by linarith
  qed
  also have " =
      A * L * card (range_tree_chain P a bs B') +
      (R + t) * card (outgoing_edges (range_tree_chain P a bs B')) +
      (Suc t) * (M_of l) * length bs"
    by (simp add: algebra_simps)
  finally show ?thesis .
qed

theorem range_costed_partition_loop_state_child_cost_bounds:
  assumes run:
    "range_costed_partition_loop_state Δ M_of t k cap l d P B d' D a
      betas bs B' Us U c child_costs"
    and child_bound:
      "c_child U_child S_child B_child d_child B_child'.
        range_costed_bmssp Δ M_of t k cap l d S_child B_child
            d_child B_child' U_child c_child;
          bmssp_pre_full d S_child B_child;
          x. x  S_child  reachable s x;
          card S_child  M_of l
         c_child  level_range_cost_bound A R L U_child"
  shows "list_all2 (λc_child U_child.
      c_child  level_range_cost_bound A R L U_child)
    child_costs (range_tree_child_list P a bs)"
proof -
  have calls:
    "list_all2
      (λc_child U_child. S_child B_child d_child B_child'.
        range_costed_bmssp Δ M_of t k cap l d S_child B_child
          d_child B_child' U_child c_child 
        bmssp_pre_full d S_child B_child 
        (xS_child. reachable s x) 
        card S_child  M_of l)
      child_costs (range_tree_child_list P a bs)"
    by (rule range_costed_partition_loop_state_child_call_ranges(2)[OF run])
  show ?thesis
    using calls
  proof (induction rule: list_all2_induct)
    case Nil
    then show ?case by simp
  next
    case (Cons c_child child_costs U_child child_sets)
    obtain S_child B_child d_child B_child' where child:
        "range_costed_bmssp Δ M_of t k cap l d S_child B_child
          d_child B_child' U_child c_child"
      and child_pre: "bmssp_pre_full d S_child B_child"
      and child_reaches: "xS_child. reachable s x"
      and child_card: "card S_child  M_of l"
      using Cons.hyps by blast
    have head:
      "c_child  level_range_cost_bound A R L U_child"
      by (rule child_bound[OF child child_pre _ child_card])
        (use child_reaches in blast)
    show ?case
      using head Cons.IH Cons.hyps by simp
  qed
qed

theorem range_costed_partition_loop_state_cost_from_child_bound:
  assumes run:
    "range_costed_partition_loop_state Δ M_of t k cap l d P B d' D a
      betas bs B' Us U c child_costs"
    and child_bound:
      "c_child U_child S_child B_child d_child B_child'.
        range_costed_bmssp Δ M_of t k cap l d S_child B_child
            d_child B_child' U_child c_child;
          bmssp_pre_full d S_child B_child;
          x. x  S_child  reachable s x;
          card S_child  M_of l
         c_child  level_range_cost_bound A R L U_child"
  shows "c 
    A * L * card (range_tree_chain P a bs B') +
    (R + t) * card (outgoing_edges (range_tree_chain P a bs B')) +
    (Suc t) * (M_of l) * length bs"
proof -
  have child_cost_bounds:
    "list_all2 (λc_child U_child.
      c_child  level_range_cost_bound A R L U_child)
      child_costs (range_tree_child_list P a bs)"
    by (rule range_costed_partition_loop_state_child_cost_bounds
      [OF run child_bound])
  show ?thesis
    by (rule range_costed_partition_loop_state_cost_from_child_cost_bounds
      [OF run child_cost_bounds])
qed

theorem range_costed_partition_loop_state_trace:
  "range_costed_partition_loop_state Δ M_of t k cap l d P B d' D a
     betas bs B' Us U c child_costs 
   sound_label d 
   bmssp_pre_full d P B 
   (x. x  P  reachable s x) 
   concrete_partition_loop_trace P B a bs d' B' Us U"
and range_costed_bmssp_correct:
  "range_costed_bmssp Δ M_of t k cap l d S B d' B' U c 
   sound_label d 
   bmssp_pre_full d S B 
   (x. x  S  reachable s x) 
   bmssp_post_full d S B d' B' U"
proof (induction rule:
    range_costed_partition_loop_state_range_costed_bmssp.inducts)
  case (Range_State_Done D a B d' P Δ M_of t k cap l d)
  have a_le: "bound_le (Fin a) B"
    using Range_State_Done by blast
  have complete_B: "complete_on d' (bound_tree P B)"
    using Range_State_Done by blast
  have lower: "complete_on d' (bound_tree P (Fin a))"
    by (rule complete_on_subset[OF complete_B])
      (rule bound_tree_bound_mono[OF a_le])
  have range_complete: "complete_on d' (range_tree P a B)"
    by (rule complete_on_subset[OF complete_B])
      (rule range_tree_subset_bound_tree)
  have B_le: "bound_le B B"
    by (cases B) simp_all
  show ?case
    unfolding concrete_partition_loop_trace_def
    using B_le a_le lower range_complete by simp
next
  case (Range_State_Stop a B d' P k cap Δ M_of t l d D)
  then show ?case
    unfolding concrete_partition_loop_trace_def complete_on_def by simp
next
  case Range_State_Step
  then show ?case
    unfolding concrete_partition_loop_trace_def bmssp_post_full_def
      complete_preserved_def
    by (auto split: bound.splits)
next
  case (Range_Cost_Base S x Δ M_of t k cap d B)
  have post:
    "bmssp_post d S B
      (λv. if v  base_case_vertices k x B then dist s v else d v)
      (base_case_bound k x B)
      (base_case_vertices k x B)"
    using base_case_result_bmssp_post[OF Range_Cost_Base.hyps,
        where k = k and B = B and d = d]
    unfolding base_case_result_def by simp
  then show ?case
    by (rule bmssp_post_imp_post_full)
next
  case (Range_Cost_Step D k cap d S B c_insert t Δ M_of l d' a
      betas bs B' Us U_loop c_loop child_costs_loop U c)
  let ?d_fp = "find_pivots_label_capped k cap d S B"
  let ?P = "find_pivots_pivots_capped k cap d S B"
  let ?W = "{v  bound_tree S B'. ?d_fp v = dist s v}"
  have sound_fp: "sound_label ?d_fp"
    unfolding find_pivots_label_capped_def
    by (rule fp_iter_capped_label_sound[OF Range_Cost_Step.prems(1)
      Range_Cost_Step.prems(3)])
  have pivot_pre: "bmssp_pre_full ?d_fp ?P B"
    using find_pivots_capped_establishes_pivot_pre_concrete
      [OF Range_Cost_Step.prems(1) Range_Cost_Step.prems(2)
        Range_Cost_Step.prems(3)] .
  have P_subset_S: "?P  S"
    unfolding find_pivots_pivots_capped_def by auto
  have P_reaches: "x. x  ?P  reachable s x"
    using P_subset_S Range_Cost_Step.prems(3) by blast
  have trace:
    "concrete_partition_loop_trace ?P B a bs d' B' Us U_loop"
    using Range_Cost_Step.IH sound_fp pivot_pre P_reaches by blast
  have loop_post: "bmssp_post_full ?d_fp ?P B d' B' U_loop"
    by (rule concrete_partition_loop_trace_post[OF trace])
  have le: "bound_le B' B"
    using loop_post unfolding bmssp_post_full_def by blast
  have U_tree: "U = bound_tree S B'"
  proof -
    have "U_loop  ?W = bound_tree S B'"
      by (rule concrete_capped_find_pivots_final_tree_assembly
        [OF Range_Cost_Step.prems(1) Range_Cost_Step.prems(2)
          Range_Cost_Step.prems(3) loop_post])
    then show ?thesis
      using Range_Cost_Step(6) by simp
  qed
  have loop_complete: "complete_on d' U_loop"
    using loop_post unfolding bmssp_post_full_def by blast
  have U_complete: "complete_on d' U"
    using complete_on_Un[OF loop_complete Range_Cost_Step(5)]
      Range_Cost_Step(6) by simp
  show ?case
    using le U_tree U_complete unfolding bmssp_post_full_def by blast
qed

theorem range_costed_bmssp_source_card_le_if_label_below_output:
  assumes run:
      "range_costed_bmssp Δ M_of t k cap l d S B d' B' U c"
    and sound: "sound_label d"
    and pre: "bmssp_pre_full d S B"
    and S_reaches: "x. x  S  reachable s x"
    and complete: "complete_on d S"
    and below: "x. x  S  below_bound (d x) B'"
  shows "card S  card U"
proof -
  have post: "bmssp_post_full d S B d' B' U"
    by (rule range_costed_bmssp_correct[OF run sound pre S_reaches])
  show ?thesis
    by (rule bmssp_post_full_source_card_le_if_label_below_output
      [OF post complete S_reaches below])
qed

theorem range_costed_bmssp_source_card_le_if_sound_label_below_output:
  assumes run:
      "range_costed_bmssp Δ M_of t k cap l d S B d' B' U c"
    and sound: "sound_label d"
    and pre: "bmssp_pre_full d S B"
    and S_reaches: "x. x  S  reachable s x"
    and below: "x. x  S  below_bound (d x) B'"
  shows "card S  card U"
proof -
  have post: "bmssp_post_full d S B d' B' U"
    by (rule range_costed_bmssp_correct[OF run sound pre S_reaches])
  have U_eq: "U = bound_tree S B'"
    using post unfolding bmssp_post_full_def by blast
  have S_subset_U: "S  U"
  proof
    fix x
    assume xS: "x  S"
    have S_subset: "S  V"
      using pre unfolding bmssp_pre_full_def by blast
    have xV: "x  V"
      using S_subset xS by blast
    have reach_x: "reachable s x"
      by (rule S_reaches[OF xS])
    have dist_le: "dist s x  d x"
      using sound xV reach_x unfolding sound_label_def by blast
    have below_dist: "below_bound (dist s x) B'"
      using below_bound_le_trans[OF dist_le below[OF xS]] .
    show "x  U"
      unfolding U_eq
      by (rule source_in_own_bound_tree[OF xS reach_x below_dist])
  qed
  have finite_U: "finite U"
    unfolding U_eq bound_tree_def using finite_V by auto
  show ?thesis
    by (rule card_mono[OF finite_U S_subset_U])
qed

theorem range_costed_partition_loop_state_success_or_threshold:
  "range_costed_partition_loop_state Δ M_of t k cap l d P B d' D a
      betas bs B' Us U c child_costs 
   sound_label d 
   bmssp_pre_full d P B 
   (x. x  P  reachable s x) 
   B' = B  k * cap  card U"
and range_costed_bmssp_success_or_threshold_trivial:
  "range_costed_bmssp Δ M_of t k cap l d S B d' B' U c  True"
proof (induction rule: range_costed_partition_loop_state_range_costed_bmssp.inducts)
  case (Range_State_Done D a B d' P Δ M_of t k cap l d)
  then show ?case
    by simp
next
  case (Range_State_Stop a B d' P k cap Δ M_of t l d D)
  then show ?case
    by simp
next
  case (Range_State_Step D M_of l Bmax S_pull beta D_pull B d a b B_out
      d_out P k cap Delta t d_child U_child c_child batch D_next c_pull
      c_batch betas bs Us_tail U_tail c_tail child_costs_tail c)
  have tail:
    "B_out = B  k * cap  card U_tail"
    using Range_State_Step.IH Range_State_Step.prems by blast
  then show ?case
  proof
    assume "B_out = B"
    then show ?thesis
      by blast
  next
    assume threshold_tail: "k * cap  card U_tail"
    have tail_trace:
      "concrete_partition_loop_trace P B b bs d_out B_out Us_tail U_tail"
      by (rule range_costed_partition_loop_state_trace)
        (use Range_State_Step in blast)+
    have U_tail_def:
      "U_tail = bound_tree P (Fin b)  (set Us_tail)"
      using tail_trace unfolding concrete_partition_loop_trace_def by blast
    have split_b:
      "bound_tree P (Fin b) =
        bound_tree P (Fin a)  range_tree P a (Fin b)"
      using bound_tree_split_at[of a "Fin b" P] Range_State_Step
      by simp
    have U_eq_tail:
      "bound_tree P (Fin a) 
          (set (range_tree P a (Fin b) # Us_tail)) =
        U_tail"
      using U_tail_def split_b by auto
    show ?thesis
      using threshold_tail U_eq_tail by simp
  qed
next
  case (Range_Cost_Base S x Δ M_of t k cap d B)
  then show ?case
    by simp
next
  case (Range_Cost_Step D k cap d S B c_insert t Δ M_of l d' a betas bs B'
      Us U_loop c_loop child_costs_loop U c)
  then show ?case
    by simp
qed

theorem range_costed_bmssp_Suc_success_or_threshold:
  assumes run:
      "range_costed_bmssp Δ M_of t k cap (Suc l) d S B d' B' U c"
    and sound: "sound_label d"
    and pre: "bmssp_pre_full d S B"
    and S_reaches: "x. x  S  reachable s x"
  shows "B' = B  k * cap  card U"
  using run
proof cases
  case (Range_Cost_Step D c_insert a betas bs Us U_loop c_loop child_costs_loop)
  let ?d_fp = "find_pivots_label_capped k cap d S B"
  let ?P = "find_pivots_pivots_capped k cap d S B"
  let ?W = "{v  bound_tree S B'. ?d_fp v = dist s v}"
  have sound_fp: "sound_label ?d_fp"
    unfolding find_pivots_label_capped_def
    by (rule fp_iter_capped_label_sound[OF sound S_reaches])
  have pivot_pre: "bmssp_pre_full ?d_fp ?P B"
    using find_pivots_capped_establishes_pivot_pre_concrete
      [OF sound pre S_reaches] .
  have P_subset_S: "?P  S"
    unfolding find_pivots_pivots_capped_def by auto
  have P_reaches: "x. x  ?P  reachable s x"
    using P_subset_S S_reaches by blast
  have loop_class:
    "B' = B  k * cap  card U_loop"
    by (rule range_costed_partition_loop_state_success_or_threshold
      [OF Range_Cost_Step(3) sound_fp pivot_pre P_reaches])
  have loop_trace:
    "concrete_partition_loop_trace ?P B a bs d' B' Us U_loop"
    by (rule range_costed_partition_loop_state_trace
      [OF Range_Cost_Step(3) sound_fp pivot_pre P_reaches])
  have loop_post: "bmssp_post_full ?d_fp ?P B d' B' U_loop"
    by (rule concrete_partition_loop_trace_post[OF loop_trace])
  have finite_U_loop: "finite U_loop"
    using loop_post unfolding bmssp_post_full_def by simp
  show ?thesis
    using loop_class
  proof
    assume "B' = B"
    then show ?thesis
      by blast
  next
    assume threshold_loop: "k * cap  card U_loop"
    have U_eq: "U = U_loop  ?W"
      using Range_Cost_Step(5) by simp
    have finite_U: "finite U"
      unfolding U_eq using finite_U_loop by simp
    have U_loop_subset: "U_loop  U"
      unfolding U_eq by blast
    have "card U_loop  card U"
      by (rule card_mono[OF finite_U U_loop_subset])
    then show ?thesis
      using threshold_loop by linarith
  qed
qed

theorem range_costed_bmssp_Suc_source_card_le_from_complete_sources:
  assumes run:
      "range_costed_bmssp Δ M_of t k cap (Suc l) d S B d' B' U c"
    and sound: "sound_label d"
    and pre: "bmssp_pre_full d S B"
    and S_reaches: "x. x  S  reachable s x"
    and complete: "complete_on d S"
    and below: "x. x  S  below_bound (d x) B"
    and S_cap: "card S  cap"
    and k_pos: "0 < k"
  shows "card S  card U"
proof -
  have call_class: "B' = B  k * cap  card U"
    by (rule range_costed_bmssp_Suc_success_or_threshold
      [OF run sound pre S_reaches])
  then show ?thesis
  proof
    assume B'_eq: "B' = B"
    show ?thesis
    proof (rule range_costed_bmssp_source_card_le_if_label_below_output
        [OF run sound pre S_reaches complete])
      fix x
      assume "x  S"
      then show "below_bound (d x) B'"
        using below B'_eq by simp
    qed
  next
    assume threshold: "k * cap  card U"
    have "cap  k * cap"
      using k_pos by (cases k) simp_all
    then show ?thesis
      using S_cap threshold by linarith
  qed
qed

theorem range_costed_bmssp_Suc_source_card_le_from_label_below:
  assumes run:
      "range_costed_bmssp Δ M_of t k cap (Suc l) d S B d' B' U c"
    and sound: "sound_label d"
    and pre: "bmssp_pre_full d S B"
    and S_reaches: "x. x  S  reachable s x"
    and below: "x. x  S  below_bound (d x) B"
    and S_cap: "card S  cap"
    and k_pos: "0 < k"
  shows "card S  card U"
proof -
  have call_class: "B' = B  k * cap  card U"
    by (rule range_costed_bmssp_Suc_success_or_threshold
      [OF run sound pre S_reaches])
  then show ?thesis
  proof
    assume B'_eq: "B' = B"
    show ?thesis
    proof (rule range_costed_bmssp_source_card_le_if_sound_label_below_output
        [OF run sound pre S_reaches])
      fix x
      assume "x  S"
      then show "below_bound (d x) B'"
        using below B'_eq by simp
    qed
  next
    assume threshold: "k * cap  card U"
    have "cap  k * cap"
      using k_pos by (cases k) simp_all
    then show ?thesis
      using S_cap threshold by linarith
  qed
qed

theorem range_costed_capped_step_threshold_if_not_success:
  assumes loop:
      "range_costed_partition_loop_state Δ M_of t k cap l
        (find_pivots_label_capped k cap d S B)
        (find_pivots_pivots_capped k cap d S B) B d' D a betas bs B'
        Us U_loop c_loop child_costs"
    and U_def:
      "U = U_loop 
        {v  bound_tree S B'. find_pivots_label_capped k cap d S B v = dist s v}"
    and sound: "sound_label d"
    and pre: "bmssp_pre_full d S B"
    and S_reaches: "x. x  S  reachable s x"
    and not_success: "B'  B"
  shows "k * cap  card U"
proof -
  let ?d_fp = "find_pivots_label_capped k cap d S B"
  let ?P = "find_pivots_pivots_capped k cap d S B"
  let ?W = "{v  bound_tree S B'. ?d_fp v = dist s v}"
  have sound_fp: "sound_label ?d_fp"
    unfolding find_pivots_label_capped_def
    by (rule fp_iter_capped_label_sound[OF sound S_reaches])
  have pivot_pre: "bmssp_pre_full ?d_fp ?P B"
    using find_pivots_capped_establishes_pivot_pre_concrete
      [OF sound pre S_reaches] .
  have P_subset_S: "?P  S"
    unfolding find_pivots_pivots_capped_def by auto
  have P_reaches: "x. x  ?P  reachable s x"
    using P_subset_S S_reaches by blast
  have loop_class:
    "B' = B  k * cap  card U_loop"
    by (rule range_costed_partition_loop_state_success_or_threshold
      [OF loop sound_fp pivot_pre P_reaches])
  have threshold_loop: "k * cap  card U_loop"
    using loop_class not_success by blast
  have trace: "concrete_partition_loop_trace ?P B a bs d' B' Us U_loop"
    by (rule range_costed_partition_loop_state_trace
      [OF loop sound_fp pivot_pre P_reaches])
  have loop_post: "bmssp_post_full ?d_fp ?P B d' B' U_loop"
    by (rule concrete_partition_loop_trace_post[OF trace])
  have finite_U_loop: "finite U_loop"
    using loop_post unfolding bmssp_post_full_def by simp
  have finite_U: "finite U"
    unfolding U_def using finite_U_loop by simp
  have U_loop_subset: "U_loop  U"
    unfolding U_def by blast
  have "card U_loop  card U"
    by (rule card_mono[OF finite_U U_loop_subset])
  then show ?thesis
    using threshold_loop by linarith
qed

theorem range_costed_capped_step_scan_insert_budget_if_not_success:
  assumes degree: "edge_outdegree_le Δ"
    and degree_factor: "Δ  A"
    and insert_factor: "t  A * k"
    and insert:
      "partition_initial_insert_cost_bound c_insert t
        (find_pivots_pivots_capped k cap d S B)"
    and loop:
      "range_costed_partition_loop_state Δ M_of t k cap l
        (find_pivots_label_capped k cap d S B)
        (find_pivots_pivots_capped k cap d S B) B d' D a betas bs B'
        Us U_loop c_loop child_costs"
    and U_def:
      "U = U_loop 
        {v  bound_tree S B'. find_pivots_label_capped k cap d S B v = dist s v}"
    and sound: "sound_label d"
    and pre: "bmssp_pre_full d S B"
    and S_reaches: "x. x  S  reachable s x"
    and S_cap: "card S  cap"
    and not_success: "B'  B"
  shows "fp_iter_capped_scan_cost k cap d S S B + c_insert 
    2 * A * card U"
proof -
  have S_subset: "S  V"
    using pre unfolding bmssp_pre_full_def by blast
  have progress: "k * cap  card U"
    by (rule range_costed_capped_step_threshold_if_not_success
      [OF loop U_def sound pre S_reaches not_success])
  show ?thesis
    by (rule find_pivots_scan_and_initial_insert_budget_from_progress
      [OF S_subset degree S_cap insert degree_factor insert_factor progress])
qed

theorem range_costed_partition_loop_state_closes_level_bound_general:
  assumes run:
    "range_costed_partition_loop_state Δ M_of t k cap l d P B d' D a
      betas bs B' Us U c child_costs"
    and sound: "sound_label d"
    and pre: "bmssp_pre_full d P B"
    and P_reaches: "x. x  P  reachable s x"
    and child_bound:
      "c_child U_child S_child B_child d_child B_child'.
        range_costed_bmssp Δ M_of t k cap l d S_child B_child
            d_child B_child' U_child c_child;
          bmssp_pre_full d S_child B_child;
          x. x  S_child  reachable s x;
          card S_child  M_of l
         c_child  level_range_cost_bound A R L U_child"
    and overhead: "(Suc t) * (M_of l) * length bs  A * card U"
  shows "c  A * Suc L * card U + (R + t) * card (outgoing_edges U)"
proof -
  have trace: "concrete_partition_loop_trace P B a bs d' B' Us U"
    by (rule range_costed_partition_loop_state_trace
      [OF run sound pre P_reaches])
  have children:
    "list_all2 (λU X. U = X  complete_on d' U) Us
      (range_tree_chain_list P a bs B')"
    using trace unfolding concrete_partition_loop_trace_def by blast
  have U_def: "U = bound_tree P (Fin a)  (set Us)"
    using trace unfolding concrete_partition_loop_trace_def by blast
  have Union_eq:
    "(set Us) = (set (range_tree_chain_list P a bs B'))"
    using children by (induction rule: list_all2_induct) auto
  have U_eq_chain:
    "U = bound_tree P (Fin a)  range_tree_chain P a bs B'"
    using U_def Union_eq Union_range_tree_chain_list[of P a bs B'] by simp
  have finite_U: "finite U"
    using U_eq_chain by simp
  have chain_subset: "range_tree_chain P a bs B'  U"
    using U_eq_chain by blast
  have card_chain_le: "card (range_tree_chain P a bs B')  card U"
    by (rule card_mono[OF finite_U chain_subset])
  have outgoing_subset:
    "outgoing_edges (range_tree_chain P a bs B')  outgoing_edges U"
    by (rule outgoing_edges_mono[OF chain_subset])
  have finite_out_U: "finite (outgoing_edges U)"
    by simp
  have card_out_le:
    "card (outgoing_edges (range_tree_chain P a bs B')) 
      card (outgoing_edges U)"
    by (rule card_mono[OF finite_out_U outgoing_subset])
  have loop:
    "c 
      A * L * card (range_tree_chain P a bs B') +
      (R + t) * card (outgoing_edges (range_tree_chain P a bs B')) +
      (Suc t) * (M_of l) * length bs"
    by (rule range_costed_partition_loop_state_cost_from_child_bound
      [OF run child_bound])
  have "c 
      A * L * card U + (R + t) * card (outgoing_edges U) + A * card U"
  proof -
    have vterm:
      "A * L * card (range_tree_chain P a bs B')  A * L * card U"
      using card_chain_le by simp
    have eterm:
      "(R + t) * card (outgoing_edges (range_tree_chain P a bs B')) 
       (R + t) * card (outgoing_edges U)"
      using card_out_le by simp
    have "A * L * card (range_tree_chain P a bs B') +
        (R + t) * card (outgoing_edges (range_tree_chain P a bs B')) +
        (Suc t) * (M_of l) * length bs 
        A * L * card U + (R + t) * card (outgoing_edges U) + A * card U"
      using vterm eterm overhead by linarith
    then show ?thesis
      using loop by linarith
  qed
  also have " =
      A * Suc L * card U + (R + t) * card (outgoing_edges U)"
    by (simp add: algebra_simps)
  finally show ?thesis .
qed

theorem range_costed_partition_loop_state_closes_level_bound_from_source_progress_general:
  assumes run:
    "range_costed_partition_loop_state Δ M_of t k cap l d P B d' D a
      betas bs B' Us U c child_costs"
    and sound: "sound_label d"
    and pre: "bmssp_pre_full d P B"
    and P_reaches: "x. x  P  reachable s x"
    and child_bound:
      "c_child U_child S_child B_child d_child B_child'.
        range_costed_bmssp Δ M_of t k cap l d S_child B_child
            d_child B_child' U_child c_child;
          bmssp_pre_full d S_child B_child;
          x. x  S_child  reachable s x;
          card S_child  M_of l
         c_child  level_range_cost_bound A R L U_child"
    and source_progress:
      "S_child B_child d_child B_child' U_child c_child.
        range_costed_bmssp Δ M_of t k cap l d S_child B_child
            d_child B_child' U_child c_child;
          bmssp_pre_full d S_child B_child;
          x. x  S_child  reachable s x;
          card S_child  M_of l
         card S_child  card U_child"
    and source_factor: "Suc t  A"
  shows "c  A * Suc L * card U + (R + t) * card (outgoing_edges U)"
proof -
  have trace: "concrete_partition_loop_trace P B a bs d' B' Us U"
    by (rule range_costed_partition_loop_state_trace
      [OF run sound pre P_reaches])
  have children:
    "list_all2 (λU X. U = X  complete_on d' U) Us
      (range_tree_chain_list P a bs B')"
    using trace unfolding concrete_partition_loop_trace_def by blast
  have U_def: "U = bound_tree P (Fin a)  (set Us)"
    using trace unfolding concrete_partition_loop_trace_def by blast
  have Union_eq:
    "(set Us) = (set (range_tree_chain_list P a bs B'))"
    using children by (induction rule: list_all2_induct) auto
  have U_eq_chain:
    "U = bound_tree P (Fin a)  range_tree_chain P a bs B'"
    using U_def Union_eq Union_range_tree_chain_list[of P a bs B'] by simp
  have finite_U: "finite U"
    using U_eq_chain by simp
  have chain_subset: "range_tree_chain P a bs B'  U"
    using U_eq_chain by blast
  have card_chain_le: "card (range_tree_chain P a bs B')  card U"
    by (rule card_mono[OF finite_U chain_subset])
  have outgoing_subset:
    "outgoing_edges (range_tree_chain P a bs B')  outgoing_edges U"
    by (rule outgoing_edges_mono[OF chain_subset])
  have finite_out_U: "finite (outgoing_edges U)"
    by simp
  have card_out_le:
    "card (outgoing_edges (range_tree_chain P a bs B')) 
      card (outgoing_edges U)"
    by (rule card_mono[OF finite_out_U outgoing_subset])
  have child_cost_bounds:
    "list_all2 (λc_child U_child.
      c_child  level_range_cost_bound A R L U_child)
      child_costs (range_tree_child_list P a bs)"
    by (rule range_costed_partition_loop_state_child_cost_bounds
      [OF run child_bound])
  have loop:
    "c 
      A * L * card (range_tree_chain P a bs B') +
      (R + t) * card (outgoing_edges (range_tree_chain P a bs B')) +
      Suc t * card (range_tree_chain P a bs B')"
    by (rule range_costed_partition_loop_state_cost_from_child_and_source_bounds
      [OF run child_cost_bounds source_progress])
  have "c 
      A * L * card U + (R + t) * card (outgoing_edges U) + A * card U"
  proof -
    have vterm:
      "A * L * card (range_tree_chain P a bs B')  A * L * card U"
      using card_chain_le by simp
    have eterm:
      "(R + t) * card (outgoing_edges (range_tree_chain P a bs B')) 
       (R + t) * card (outgoing_edges U)"
      using card_out_le by simp
    have source_term:
      "Suc t * card (range_tree_chain P a bs B')  A * card U"
    proof -
      have "Suc t * card (range_tree_chain P a bs B') 
          A * card (range_tree_chain P a bs B')"
        by (rule mult_right_mono[OF source_factor]) simp
      also have "  A * card U"
        using card_chain_le by simp
      finally show ?thesis .
    qed
    have "A * L * card (range_tree_chain P a bs B') +
        (R + t) * card (outgoing_edges (range_tree_chain P a bs B')) +
        Suc t * card (range_tree_chain P a bs B') 
        A * L * card U + (R + t) * card (outgoing_edges U) + A * card U"
      using vterm eterm source_term by linarith
    then show ?thesis
      using loop by linarith
  qed
  also have " =
      A * Suc L * card U + (R + t) * card (outgoing_edges U)"
    by (simp add: algebra_simps)
  finally show ?thesis .
qed

theorem range_costed_partition_loop_state_closes_level_bound_from_child_cost_bounds_general:
  assumes run:
    "range_costed_partition_loop_state Δ M_of t k cap l d P B d' D a
      betas bs B' Us U c child_costs"
    and sound: "sound_label d"
    and pre: "bmssp_pre_full d P B"
    and P_reaches: "x. x  P  reachable s x"
    and child_cost_bounds:
      "list_all2 (λc_child U_child.
        c_child  level_range_cost_bound A R L U_child)
        child_costs (range_tree_child_list P a bs)"
    and overhead: "(Suc t) * (M_of l) * length bs  A * card U"
  shows "c  A * Suc L * card U + (R + t) * card (outgoing_edges U)"
proof -
  have trace: "concrete_partition_loop_trace P B a bs d' B' Us U"
    by (rule range_costed_partition_loop_state_trace
      [OF run sound pre P_reaches])
  have children:
    "list_all2 (λU X. U = X  complete_on d' U) Us
      (range_tree_chain_list P a bs B')"
    using trace unfolding concrete_partition_loop_trace_def by blast
  have U_def: "U = bound_tree P (Fin a)  (set Us)"
    using trace unfolding concrete_partition_loop_trace_def by blast
  have Union_eq:
    "(set Us) = (set (range_tree_chain_list P a bs B'))"
    using children by (induction rule: list_all2_induct) auto
  have U_eq_chain:
    "U = bound_tree P (Fin a)  range_tree_chain P a bs B'"
    using U_def Union_eq Union_range_tree_chain_list[of P a bs B'] by simp
  have finite_U: "finite U"
    using U_eq_chain by simp
  have chain_subset: "range_tree_chain P a bs B'  U"
    using U_eq_chain by blast
  have card_chain_le: "card (range_tree_chain P a bs B')  card U"
    by (rule card_mono[OF finite_U chain_subset])
  have outgoing_subset:
    "outgoing_edges (range_tree_chain P a bs B')  outgoing_edges U"
    by (rule outgoing_edges_mono[OF chain_subset])
  have finite_out_U: "finite (outgoing_edges U)"
    by simp
  have card_out_le:
    "card (outgoing_edges (range_tree_chain P a bs B')) 
      card (outgoing_edges U)"
    by (rule card_mono[OF finite_out_U outgoing_subset])
  have loop:
    "c 
      A * L * card (range_tree_chain P a bs B') +
      (R + t) * card (outgoing_edges (range_tree_chain P a bs B')) +
      (Suc t) * (M_of l) * length bs"
    by (rule range_costed_partition_loop_state_cost_from_child_cost_bounds
      [OF run child_cost_bounds])
  have "c 
      A * L * card U + (R + t) * card (outgoing_edges U) + A * card U"
  proof -
    have vterm:
      "A * L * card (range_tree_chain P a bs B')  A * L * card U"
      using card_chain_le by simp
    have eterm:
      "(R + t) * card (outgoing_edges (range_tree_chain P a bs B')) 
       (R + t) * card (outgoing_edges U)"
      using card_out_le by simp
    have "A * L * card (range_tree_chain P a bs B') +
        (R + t) * card (outgoing_edges (range_tree_chain P a bs B')) +
        (Suc t) * (M_of l) * length bs 
        A * L * card U + (R + t) * card (outgoing_edges U) + A * card U"
      using vterm eterm overhead by linarith
    then show ?thesis
      using loop by linarith
  qed
  also have " =
      A * Suc L * card U + (R + t) * card (outgoing_edges U)"
    by (simp add: algebra_simps)
  finally show ?thesis .
qed

theorem range_costed_partition_loop_state_closes_level_bound:
  assumes run:
    "range_costed_partition_loop_state Δ M_of t k cap l d P B d' D a
      betas bs B' Us U c child_costs"
    and sound: "sound_label d"
    and pre: "bmssp_pre_full d P B"
    and P_reaches: "x. x  P  reachable s x"
    and child_bound:
      "c_child U_child S_child B_child d_child B_child'.
        range_costed_bmssp Δ M_of t k cap l d S_child B_child
            d_child B_child' U_child c_child;
          bmssp_pre_full d S_child B_child;
          x. x  S_child  reachable s x;
          card S_child  M_of l
         c_child  level_range_cost_bound A R l U_child"
    and overhead: "(Suc t) * (M_of l) * length bs  A * card U"
  shows "c  A * Suc l * card U + (R + t) * card (outgoing_edges U)"
proof -
  have trace: "concrete_partition_loop_trace P B a bs d' B' Us U"
    by (rule range_costed_partition_loop_state_trace
      [OF run sound pre P_reaches])
  have children:
    "list_all2 (λU X. U = X  complete_on d' U) Us
      (range_tree_chain_list P a bs B')"
    using trace unfolding concrete_partition_loop_trace_def by blast
  have U_def: "U = bound_tree P (Fin a)  (set Us)"
    using trace unfolding concrete_partition_loop_trace_def by blast
  have Union_eq:
    "(set Us) = (set (range_tree_chain_list P a bs B'))"
    using children by (induction rule: list_all2_induct) auto
  have U_eq_chain:
    "U = bound_tree P (Fin a)  range_tree_chain P a bs B'"
    using U_def Union_eq Union_range_tree_chain_list[of P a bs B'] by simp
  have finite_U: "finite U"
    using U_eq_chain by simp
  have chain_subset: "range_tree_chain P a bs B'  U"
    using U_eq_chain by blast
  have card_chain_le: "card (range_tree_chain P a bs B')  card U"
    by (rule card_mono[OF finite_U chain_subset])
  have outgoing_subset:
    "outgoing_edges (range_tree_chain P a bs B')  outgoing_edges U"
    by (rule outgoing_edges_mono[OF chain_subset])
  have finite_out_U: "finite (outgoing_edges U)"
    by simp
  have card_out_le:
    "card (outgoing_edges (range_tree_chain P a bs B')) 
      card (outgoing_edges U)"
    by (rule card_mono[OF finite_out_U outgoing_subset])
  have loop:
    "c 
      A * l * card (range_tree_chain P a bs B') +
      (R + t) * card (outgoing_edges (range_tree_chain P a bs B')) +
      (Suc t) * (M_of l) * length bs"
    by (rule range_costed_partition_loop_state_cost_from_child_bound
      [OF run child_bound])
  have "c 
      A * l * card U + (R + t) * card (outgoing_edges U) + A * card U"
  proof -
    have vterm:
      "A * l * card (range_tree_chain P a bs B')  A * l * card U"
      using card_chain_le by simp
    have eterm:
      "(R + t) * card (outgoing_edges (range_tree_chain P a bs B')) 
       (R + t) * card (outgoing_edges U)"
      using card_out_le by simp
    have "A * l * card (range_tree_chain P a bs B') +
        (R + t) * card (outgoing_edges (range_tree_chain P a bs B')) +
        (Suc t) * (M_of l) * length bs 
        A * l * card U + (R + t) * card (outgoing_edges U) + A * card U"
      using vterm eterm overhead by linarith
    then show ?thesis
      using loop by linarith
  qed
  also have " =
      A * Suc l * card U + (R + t) * card (outgoing_edges U)"
    by (simp add: algebra_simps)
  finally show ?thesis .
qed

theorem range_costed_nonbase_step_closes_level_bound_general:
  assumes loop:
    "range_costed_partition_loop_state Δ M_of t k cap l d P B d' D a
      betas bs B' Us U_loop c_loop child_costs"
    and sound: "sound_label d"
    and pre: "bmssp_pre_full d P B"
    and P_reaches: "x. x  P  reachable s x"
    and child_bound:
      "c_child U_child S_child B_child d_child B_child'.
        range_costed_bmssp Δ M_of t k cap l d S_child B_child
            d_child B_child' U_child c_child;
          bmssp_pre_full d S_child B_child;
          x. x  S_child  reachable s x;
          card S_child  M_of l
         c_child  level_range_cost_bound A R L U_child"
    and overhead: "(Suc t) * (M_of l) * length bs  A * card U_loop"
    and U_def: "U = U_loop  W"
    and finite_U: "finite U"
    and scan_insert: "c_scan_insert  A * card U"
    and c_def: "c = c_scan_insert + c_loop"
  shows "c  A * Suc (Suc L) * card U +
    (R + t) * card (outgoing_edges U)"
proof -
  have loop_bound:
    "c_loop  A * Suc L * card U_loop +
      (R + t) * card (outgoing_edges U_loop)"
    by (rule range_costed_partition_loop_state_closes_level_bound_general
      [OF loop sound pre P_reaches child_bound overhead])
  have U_loop_subset: "U_loop  U"
    using U_def by blast
  have card_loop_le: "card U_loop  card U"
    by (rule card_mono[OF finite_U U_loop_subset])
  have outgoing_subset: "outgoing_edges U_loop  outgoing_edges U"
    by (rule outgoing_edges_mono[OF U_loop_subset])
  have finite_out_U: "finite (outgoing_edges U)"
    by simp
  have card_out_le: "card (outgoing_edges U_loop)  card (outgoing_edges U)"
    by (rule card_mono[OF finite_out_U outgoing_subset])
  have "c 
      A * card U +
      (A * Suc L * card U + (R + t) * card (outgoing_edges U))"
  proof -
    have loop_to_U:
      "c_loop  A * Suc L * card U +
        (R + t) * card (outgoing_edges U)"
    proof -
      have "A * Suc L * card U_loop  A * Suc L * card U"
        using card_loop_le by simp
      moreover have "(R + t) * card (outgoing_edges U_loop) 
          (R + t) * card (outgoing_edges U)"
        using card_out_le by simp
      ultimately show ?thesis
        using loop_bound by linarith
    qed
    show ?thesis
      using scan_insert loop_to_U c_def by linarith
  qed
  also have " =
      A * Suc (Suc L) * card U + (R + t) * card (outgoing_edges U)"
    by (simp add: algebra_simps)
  finally show ?thesis .
qed

theorem range_costed_nonbase_step_closes_level_bound_from_source_progress_general:
  assumes loop:
    "range_costed_partition_loop_state Δ M_of t k cap l d P B d' D a
      betas bs B' Us U_loop c_loop child_costs"
    and sound: "sound_label d"
    and pre: "bmssp_pre_full d P B"
    and P_reaches: "x. x  P  reachable s x"
    and child_bound:
      "c_child U_child S_child B_child d_child B_child'.
        range_costed_bmssp Δ M_of t k cap l d S_child B_child
            d_child B_child' U_child c_child;
          bmssp_pre_full d S_child B_child;
          x. x  S_child  reachable s x;
          card S_child  M_of l
         c_child  level_range_cost_bound A R L U_child"
    and source_progress:
      "S_child B_child d_child B_child' U_child c_child.
        range_costed_bmssp Δ M_of t k cap l d S_child B_child
            d_child B_child' U_child c_child;
          bmssp_pre_full d S_child B_child;
          x. x  S_child  reachable s x;
          card S_child  M_of l
         card S_child  card U_child"
    and source_factor: "Suc t  A"
    and U_def: "U = U_loop  W"
    and finite_U: "finite U"
    and scan_insert: "c_scan_insert  A * card U"
    and c_def: "c = c_scan_insert + c_loop"
  shows "c  A * Suc (Suc L) * card U +
    (R + t) * card (outgoing_edges U)"
proof -
  have loop_bound:
    "c_loop  A * Suc L * card U_loop +
      (R + t) * card (outgoing_edges U_loop)"
    by (rule range_costed_partition_loop_state_closes_level_bound_from_source_progress_general
      [OF loop sound pre P_reaches child_bound source_progress source_factor])
  have U_loop_subset: "U_loop  U"
    using U_def by blast
  have card_loop_le: "card U_loop  card U"
    by (rule card_mono[OF finite_U U_loop_subset])
  have outgoing_subset: "outgoing_edges U_loop  outgoing_edges U"
    by (rule outgoing_edges_mono[OF U_loop_subset])
  have finite_out_U: "finite (outgoing_edges U)"
    by simp
  have card_out_le: "card (outgoing_edges U_loop)  card (outgoing_edges U)"
    by (rule card_mono[OF finite_out_U outgoing_subset])
  have "c 
      A * card U +
      (A * Suc L * card U + (R + t) * card (outgoing_edges U))"
  proof -
    have loop_to_U:
      "c_loop  A * Suc L * card U +
        (R + t) * card (outgoing_edges U)"
    proof -
      have "A * Suc L * card U_loop  A * Suc L * card U"
        using card_loop_le by simp
      moreover have "(R + t) * card (outgoing_edges U_loop) 
          (R + t) * card (outgoing_edges U)"
        using card_out_le by simp
      ultimately show ?thesis
        using loop_bound by linarith
    qed
    show ?thesis
      using scan_insert loop_to_U c_def by linarith
  qed
  also have " =
      A * Suc (Suc L) * card U + (R + t) * card (outgoing_edges U)"
    by (simp add: algebra_simps)
  finally show ?thesis .
qed

theorem range_costed_nonbase_step_closes_level_bound_from_child_cost_bounds_general:
  assumes loop:
    "range_costed_partition_loop_state Δ M_of t k cap l d P B d' D a
      betas bs B' Us U_loop c_loop child_costs"
    and sound: "sound_label d"
    and pre: "bmssp_pre_full d P B"
    and P_reaches: "x. x  P  reachable s x"
    and child_cost_bounds:
      "list_all2 (λc_child U_child.
        c_child  level_range_cost_bound A R L U_child)
        child_costs (range_tree_child_list P a bs)"
    and overhead: "(Suc t) * (M_of l) * length bs  A * card U_loop"
    and U_def: "U = U_loop  W"
    and finite_U: "finite U"
    and scan_insert: "c_scan_insert  A * card U"
    and c_def: "c = c_scan_insert + c_loop"
  shows "c  A * Suc (Suc L) * card U +
    (R + t) * card (outgoing_edges U)"
proof -
  have loop_bound:
    "c_loop  A * Suc L * card U_loop +
      (R + t) * card (outgoing_edges U_loop)"
    by (rule
      range_costed_partition_loop_state_closes_level_bound_from_child_cost_bounds_general
      [OF loop sound pre P_reaches child_cost_bounds overhead])
  have U_loop_subset: "U_loop  U"
    using U_def by blast
  have card_loop_le: "card U_loop  card U"
    by (rule card_mono[OF finite_U U_loop_subset])
  have outgoing_subset: "outgoing_edges U_loop  outgoing_edges U"
    by (rule outgoing_edges_mono[OF U_loop_subset])
  have finite_out_U: "finite (outgoing_edges U)"
    by simp
  have card_out_le: "card (outgoing_edges U_loop)  card (outgoing_edges U)"
    by (rule card_mono[OF finite_out_U outgoing_subset])
  have "c 
      A * card U +
      (A * Suc L * card U + (R + t) * card (outgoing_edges U))"
  proof -
    have loop_to_U:
      "c_loop  A * Suc L * card U +
        (R + t) * card (outgoing_edges U)"
    proof -
      have "A * Suc L * card U_loop  A * Suc L * card U"
        using card_loop_le by simp
      moreover have "(R + t) * card (outgoing_edges U_loop) 
          (R + t) * card (outgoing_edges U)"
        using card_out_le by simp
      ultimately show ?thesis
        using loop_bound by linarith
    qed
    show ?thesis
      using scan_insert loop_to_U c_def by linarith
  qed
  also have " =
      A * Suc (Suc L) * card U + (R + t) * card (outgoing_edges U)"
    by (simp add: algebra_simps)
  finally show ?thesis .
qed

theorem range_costed_nonbase_step_closes_level_bound:
  assumes loop:
    "range_costed_partition_loop_state Δ M_of t k cap l d P B d' D a
      betas bs B' Us U_loop c_loop child_costs"
    and sound: "sound_label d"
    and pre: "bmssp_pre_full d P B"
    and P_reaches: "x. x  P  reachable s x"
    and child_bound:
      "c_child U_child S_child B_child d_child B_child'.
        range_costed_bmssp Δ M_of t k cap l d S_child B_child
            d_child B_child' U_child c_child;
          bmssp_pre_full d S_child B_child;
          x. x  S_child  reachable s x;
          card S_child  M_of l
         c_child  level_range_cost_bound A R l U_child"
    and overhead: "(Suc t) * (M_of l) * length bs  A * card U_loop"
    and U_def: "U = U_loop  W"
    and finite_U: "finite U"
    and scan_insert: "c_scan_insert  A * card U"
    and c_def: "c = c_scan_insert + c_loop"
  shows "c  A * Suc (Suc l) * card U +
    (R + t) * card (outgoing_edges U)"
proof -
  have loop_bound:
    "c_loop  A * Suc l * card U_loop +
      (R + t) * card (outgoing_edges U_loop)"
    by (rule range_costed_partition_loop_state_closes_level_bound
      [OF loop sound pre P_reaches child_bound overhead])
  have U_loop_subset: "U_loop  U"
    using U_def by blast
  have card_loop_le: "card U_loop  card U"
    by (rule card_mono[OF finite_U U_loop_subset])
  have outgoing_subset: "outgoing_edges U_loop  outgoing_edges U"
    by (rule outgoing_edges_mono[OF U_loop_subset])
  have finite_out_U: "finite (outgoing_edges U)"
    by simp
  have card_out_le: "card (outgoing_edges U_loop)  card (outgoing_edges U)"
    by (rule card_mono[OF finite_out_U outgoing_subset])
  have "c 
      A * card U +
      (A * Suc l * card U + (R + t) * card (outgoing_edges U))"
  proof -
    have loop_to_U:
      "c_loop  A * Suc l * card U +
        (R + t) * card (outgoing_edges U)"
    proof -
      have "A * Suc l * card U_loop  A * Suc l * card U"
        using card_loop_le by simp
      moreover have "(R + t) * card (outgoing_edges U_loop) 
          (R + t) * card (outgoing_edges U)"
        using card_out_le by simp
      ultimately show ?thesis
        using loop_bound by linarith
    qed
    show ?thesis
      using scan_insert loop_to_U c_def by linarith
  qed
  also have " =
      A * Suc (Suc l) * card U + (R + t) * card (outgoing_edges U)"
    by (simp add: algebra_simps)
  finally show ?thesis .
qed

theorem range_costed_base_level_bound:
  assumes R_pos: "0 < R"
  shows "base_case_scan_cost Δ k x B 
    level_range_cost_bound A R (Suc 0) (base_case_vertices k x B)"
proof -
  have "base_case_scan_cost Δ k x B 
      R * card (outgoing_edges (base_case_vertices k x B))"
    using R_pos unfolding base_case_scan_cost_def by simp
  then show ?thesis
    unfolding level_range_cost_bound_def by linarith
qed

text ‹
  The unsplit relation repeats the same recurrence in a form that is closer to
  the abstract cost interface.  The base theorem
  @{thm range_costed_base_level_bound} pays for the bounded base scan with the
  outgoing-edge component of @{const level_range_cost_bound}.  The main theorem
  below then performs induction on the recursion level: the induction
  hypothesis bounds each child call, while the supplied local-budget hypotheses
  pay for loop overhead and FindPivots overhead at the current level.

  This theorem is intentionally parameterised by the constants A›, R›,
  t›, and M_of›.  Later theories instantiate those parameters with the
  BMSSP schedule and with the bucketed partition costs, but the recurrence
  itself does not depend on how the partition primitive is implemented.
›

theorem range_costed_bmssp_level_bound_from_local_budgets:
  assumes base_budget: "Δ  A"
    and R_pos: "0 < R"
    and loop_budget:
      "l d P B d' D a betas bs B' Us U c child_costs.
        range_costed_partition_loop_state Δ M_of t k cap l d P B d' D a
          betas bs B' Us U c child_costs 
        sound_label d 
        bmssp_pre_full d P B 
        (x. x  P  reachable s x) 
        (Suc t) * (M_of l) * length bs  A * card U"
    and step_budget:
      "l d S B D c_insert d' a betas bs B' Us U_loop c_loop
          child_costs U.
        D = label_partition_view
          (find_pivots_label_capped k cap d S B)
          (find_pivots_pivots_capped k cap d S B) 
        partition_initial_insert_cost_bound c_insert t
          (find_pivots_pivots_capped k cap d S B) 
        range_costed_partition_loop_state Δ M_of t k cap l
          (find_pivots_label_capped k cap d S B)
          (find_pivots_pivots_capped k cap d S B) B d' D a betas bs B'
          Us U_loop c_loop child_costs 
        complete_on d'
          {v  bound_tree S B'. find_pivots_label_capped k cap d S B v = dist s v} 
        U = U_loop 
          {v  bound_tree S B'. find_pivots_label_capped k cap d S B v = dist s v} 
        sound_label d 
        bmssp_pre_full d S B 
        (x. x  S  reachable s x) 
        fp_iter_capped_scan_cost k cap d S S B + c_insert  A * card U"
    and run:
      "range_costed_bmssp Δ M_of t k cap l d S B d' B' U c"
    and sound: "sound_label d"
    and pre: "bmssp_pre_full d S B"
    and S_reaches: "x. x  S  reachable s x"
  shows "c  level_range_cost_bound A (R + l * t) (2 * l + 1) U"
  using run sound pre S_reaches
proof (induction l arbitrary: d S B d' B' U c rule: less_induct)
  case (less l)
  show ?case
  proof (cases l)
    case 0
    have run0:
      "range_costed_bmssp Δ M_of t k cap 0 d S B d' B' U c"
      using less.prems(1) 0 by simp
    show ?thesis
      using run0 R_pos 0
      by (cases rule: range_costed_bmssp.cases)
        (simp_all add: range_costed_base_level_bound)
  next
    case (Suc l0)
    have run_suc:
      "range_costed_bmssp Δ M_of t k cap (Suc l0) d S B d' B' U c"
      using less.prems(1) Suc by simp
    show ?thesis
    proof (cases rule: range_costed_bmssp_SucE[OF run_suc])
      case (1 c_insert a betas bs Us U_loop c_loop child_costs_loop)
      let ?d_fp = "find_pivots_label_capped k cap d S B"
      let ?P = "find_pivots_pivots_capped k cap d S B"
      let ?W = "{v  bound_tree S B'. ?d_fp v = dist s v}"
      have sound_fp: "sound_label ?d_fp"
        unfolding find_pivots_label_capped_def
        by (rule fp_iter_capped_label_sound[OF less.prems(2) less.prems(4)])
      have pivot_pre: "bmssp_pre_full ?d_fp ?P B"
        using find_pivots_capped_establishes_pivot_pre_concrete
          [OF less.prems(2) less.prems(3) less.prems(4)] .
      have P_subset_S: "?P  S"
        unfolding find_pivots_pivots_capped_def by auto
      have P_reaches: "x. x  ?P  reachable s x"
        using P_subset_S less.prems(4) by blast
      have child_bound:
        "c_child U_child S_child B_child d_child B_child'.
          range_costed_bmssp Δ M_of t k cap l0 ?d_fp S_child B_child
              d_child B_child' U_child c_child;
            bmssp_pre_full ?d_fp S_child B_child;
            x. x  S_child  reachable s x;
            card S_child  M_of l0
           c_child  level_range_cost_bound A (R + l0 * t)
            (2 * l0 + 1) U_child"
      proof -
        fix c_child U_child S_child B_child d_child B_child'
        assume child:
            "range_costed_bmssp Δ M_of t k cap l0 ?d_fp S_child B_child
              d_child B_child' U_child c_child"
          and child_pre: "bmssp_pre_full ?d_fp S_child B_child"
          and child_reaches: "x. x  S_child  reachable s x"
        show "c_child  level_range_cost_bound A (R + l0 * t)
            (2 * l0 + 1) U_child"
          by (rule less.IH[of l0 ?d_fp S_child B_child d_child B_child'
                U_child c_child, OF _ child sound_fp child_pre child_reaches])
            (simp add: Suc)
      qed
      have overhead:
        "(Suc t) * (M_of l0) * length bs  A * card U_loop"
        by (rule loop_budget[OF 1(4) sound_fp pivot_pre P_reaches])
      have scan_insert:
        "fp_iter_capped_scan_cost k cap d S S B + c_insert 
          A * card U"
        by (rule step_budget[OF refl 1(3) 1(4) 1(5) 1(1)
            less.prems(2) less.prems(3) less.prems(4)])
      have trace:
        "concrete_partition_loop_trace ?P B a bs d' B' Us U_loop"
        by (rule range_costed_partition_loop_state_trace
          [OF 1(4) sound_fp pivot_pre P_reaches])
      have loop_post: "bmssp_post_full ?d_fp ?P B d' B' U_loop"
        by (rule concrete_partition_loop_trace_post[OF trace])
      have finite_U_loop: "finite U_loop"
        using loop_post unfolding bmssp_post_full_def by simp
      have finite_W: "finite ?W"
        by simp
      have finite_U: "finite U"
        using 1(1) finite_U_loop finite_W by simp
      have step:
        "c  A * Suc (Suc (2 * l0 + 1)) * card U +
          (R + l0 * t + t) * card (outgoing_edges U)"
        by (rule range_costed_nonbase_step_closes_level_bound_general
          [OF 1(4) sound_fp pivot_pre P_reaches child_bound overhead
            1(1) finite_U scan_insert 1(2)])
      show ?thesis
        using step Suc unfolding level_range_cost_bound_def
        by (simp add: algebra_simps)
    qed
  qed
qed

theorem range_costed_bmssp_level_bound_from_source_progress_and_local_budgets:
  assumes base_budget: "Δ  A"
    and R_pos: "0 < R"
    and source_factor: "Suc t  A"
    and source_progress:
      "l d S B d' B' U c.
        range_costed_bmssp Δ M_of t k cap l d S B d' B' U c 
        bmssp_pre_full d S B 
        (x. x  S  reachable s x) 
        card S  M_of l 
        card S  card U"
    and step_budget:
      "l d S B D c_insert d' a betas bs B' Us U_loop c_loop
          child_costs U.
        D = label_partition_view
          (find_pivots_label_capped k cap d S B)
          (find_pivots_pivots_capped k cap d S B) 
        partition_initial_insert_cost_bound c_insert t
          (find_pivots_pivots_capped k cap d S B) 
        range_costed_partition_loop_state Δ M_of t k cap l
          (find_pivots_label_capped k cap d S B)
          (find_pivots_pivots_capped k cap d S B) B d' D a betas bs B'
          Us U_loop c_loop child_costs 
        complete_on d'
          {v  bound_tree S B'. find_pivots_label_capped k cap d S B v = dist s v} 
        U = U_loop 
          {v  bound_tree S B'. find_pivots_label_capped k cap d S B v = dist s v} 
        sound_label d 
        bmssp_pre_full d S B 
        (x. x  S  reachable s x) 
        fp_iter_capped_scan_cost k cap d S S B + c_insert  A * card U"
    and run:
      "range_costed_bmssp Δ M_of t k cap l d S B d' B' U c"
    and sound: "sound_label d"
    and pre: "bmssp_pre_full d S B"
    and S_reaches: "x. x  S  reachable s x"
  shows "c  level_range_cost_bound A (R + l * t) (2 * l + 1) U"
  using run sound pre S_reaches
proof (induction l arbitrary: d S B d' B' U c rule: less_induct)
  case (less l)
  show ?case
  proof (cases l)
    case 0
    have run0:
      "range_costed_bmssp Δ M_of t k cap 0 d S B d' B' U c"
      using less.prems(1) 0 by simp
    show ?thesis
      using run0 R_pos 0
      by (cases rule: range_costed_bmssp.cases)
        (simp_all add: range_costed_base_level_bound)
  next
    case (Suc l0)
    have run_suc:
      "range_costed_bmssp Δ M_of t k cap (Suc l0) d S B d' B' U c"
      using less.prems(1) Suc by simp
    show ?thesis
    proof (cases rule: range_costed_bmssp_SucE[OF run_suc])
      case (1 c_insert a betas bs Us U_loop c_loop child_costs_loop)
      let ?d_fp = "find_pivots_label_capped k cap d S B"
      let ?P = "find_pivots_pivots_capped k cap d S B"
      let ?W = "{v  bound_tree S B'. ?d_fp v = dist s v}"
      have sound_fp: "sound_label ?d_fp"
        unfolding find_pivots_label_capped_def
        by (rule fp_iter_capped_label_sound[OF less.prems(2) less.prems(4)])
      have pivot_pre: "bmssp_pre_full ?d_fp ?P B"
        using find_pivots_capped_establishes_pivot_pre_concrete
          [OF less.prems(2) less.prems(3) less.prems(4)] .
      have P_subset_S: "?P  S"
        unfolding find_pivots_pivots_capped_def by auto
      have P_reaches: "x. x  ?P  reachable s x"
        using P_subset_S less.prems(4) by blast
      have child_bound:
        "c_child U_child S_child B_child d_child B_child'.
          range_costed_bmssp Δ M_of t k cap l0 ?d_fp S_child B_child
              d_child B_child' U_child c_child;
            bmssp_pre_full ?d_fp S_child B_child;
            x. x  S_child  reachable s x;
            card S_child  M_of l0
           c_child  level_range_cost_bound A (R + l0 * t)
            (2 * l0 + 1) U_child"
      proof -
        fix c_child U_child S_child B_child d_child B_child'
        assume child:
            "range_costed_bmssp Δ M_of t k cap l0 ?d_fp S_child B_child
              d_child B_child' U_child c_child"
          and child_pre: "bmssp_pre_full ?d_fp S_child B_child"
          and child_reaches: "x. x  S_child  reachable s x"
        show "c_child  level_range_cost_bound A (R + l0 * t)
            (2 * l0 + 1) U_child"
          by (rule less.IH[of l0 ?d_fp S_child B_child d_child B_child'
                U_child c_child, OF _ child sound_fp child_pre child_reaches])
            (simp add: Suc)
      qed
      have source_progress_loop:
        "S_child B_child d_child B_child' U_child c_child.
          range_costed_bmssp Δ M_of t k cap l0 ?d_fp S_child B_child
              d_child B_child' U_child c_child;
            bmssp_pre_full ?d_fp S_child B_child;
            x. x  S_child  reachable s x;
            card S_child  M_of l0
           card S_child  card U_child"
        by (rule source_progress)
      have scan_insert:
        "fp_iter_capped_scan_cost k cap d S S B + c_insert 
          A * card U"
        by (rule step_budget[OF refl 1(3) 1(4) 1(5) 1(1)
            less.prems(2) less.prems(3) less.prems(4)])
      have trace:
        "concrete_partition_loop_trace ?P B a bs d' B' Us U_loop"
        by (rule range_costed_partition_loop_state_trace
          [OF 1(4) sound_fp pivot_pre P_reaches])
      have loop_post: "bmssp_post_full ?d_fp ?P B d' B' U_loop"
        by (rule concrete_partition_loop_trace_post[OF trace])
      have finite_U_loop: "finite U_loop"
        using loop_post unfolding bmssp_post_full_def by simp
      have finite_W: "finite ?W"
        by simp
      have finite_U: "finite U"
        using 1(1) finite_U_loop finite_W by simp
      have step:
        "c  A * Suc (Suc (2 * l0 + 1)) * card U +
          (R + l0 * t + t) * card (outgoing_edges U)"
        by (rule range_costed_nonbase_step_closes_level_bound_from_source_progress_general
          [OF 1(4) sound_fp pivot_pre P_reaches child_bound
            source_progress_loop source_factor 1(1) finite_U scan_insert 1(2)])
      show ?thesis
        using step Suc unfolding level_range_cost_bound_def
        by (simp add: algebra_simps)
    qed
  qed
qed

theorem range_costed_bmssp_level_bound_from_source_progress_budgets:
  assumes degree: "edge_outdegree_le Δ"
    and degree_factor: "Δ  A"
    and R_pos: "0 < R"
    and insert_factor: "t  A * k"
    and source_factor: "Suc t  2 * A"
    and source_progress:
      "l d S B d' B' U c.
        range_costed_bmssp Δ M_of t k cap l d S B d' B' U c 
        bmssp_pre_full d S B 
        (x. x  S  reachable s x) 
        card S  M_of l 
        card S  card U"
    and step_progress:
      "l d S B D c_insert d' a betas bs B' Us U_loop c_loop
          child_costs U.
        D = label_partition_view
          (find_pivots_label_capped k cap d S B)
          (find_pivots_pivots_capped k cap d S B) 
        partition_initial_insert_cost_bound c_insert t
          (find_pivots_pivots_capped k cap d S B) 
        range_costed_partition_loop_state Δ M_of t k cap l
          (find_pivots_label_capped k cap d S B)
          (find_pivots_pivots_capped k cap d S B) B d' D a betas bs B'
          Us U_loop c_loop child_costs 
        complete_on d'
          {v  bound_tree S B'. find_pivots_label_capped k cap d S B v = dist s v} 
        U = U_loop 
          {v  bound_tree S B'. find_pivots_label_capped k cap d S B v = dist s v} 
        sound_label d 
        bmssp_pre_full d S B 
        (x. x  S  reachable s x) 
        card S  cap  k * cap  card U"
    and run:
      "range_costed_bmssp Δ M_of t k cap l d S B d' B' U c"
    and sound: "sound_label d"
    and pre: "bmssp_pre_full d S B"
    and S_reaches: "x. x  S  reachable s x"
  shows "c  level_range_cost_bound (2 * A) (R + l * t) (2 * l + 1) U"
proof (rule range_costed_bmssp_level_bound_from_source_progress_and_local_budgets
    [where A = "2 * A" and R = R,
      OF _ R_pos source_factor _ _ run sound pre S_reaches])
  show "Δ  2 * A"
    using degree_factor by simp
next
  fix l d S B d' B' U c
  assume child:
      "range_costed_bmssp Δ M_of t k cap l d S B d' B' U c"
    and child_pre: "bmssp_pre_full d S B"
    and child_reaches: "x. x  S  reachable s x"
    and child_card: "card S  M_of l"
  show "card S  card U"
    by (rule source_progress[OF child child_pre child_reaches child_card])
next
  fix l d S B D c_insert d' a betas bs B' Us U_loop c_loop child_costs U
  assume D_def:
      "D = label_partition_view
        (find_pivots_label_capped k cap d S B)
        (find_pivots_pivots_capped k cap d S B)"
    and insert:
      "partition_initial_insert_cost_bound c_insert t
        (find_pivots_pivots_capped k cap d S B)"
    and loop:
      "range_costed_partition_loop_state Δ M_of t k cap l
        (find_pivots_label_capped k cap d S B)
        (find_pivots_pivots_capped k cap d S B) B d' D a betas bs B'
        Us U_loop c_loop child_costs"
    and complete:
      "complete_on d'
        {v  bound_tree S B'. find_pivots_label_capped k cap d S B v = dist s v}"
    and U_def:
      "U = U_loop 
        {v  bound_tree S B'. find_pivots_label_capped k cap d S B v = dist s v}"
    and sound_s: "sound_label d"
    and pre_s: "bmssp_pre_full d S B"
    and reaches_s: "x. x  S  reachable s x"
  have S_subset: "S  V"
    using pre_s unfolding bmssp_pre_full_def by blast
  have progress:
      "card S  cap  k * cap  card U"
    by (rule step_progress[OF D_def insert loop complete U_def sound_s pre_s reaches_s])
  then have S_cap: "card S  cap"
    by blast
  from progress have U_progress: "k * cap  card U"
    by blast
  show "fp_iter_capped_scan_cost k cap d S S B + c_insert 
      2 * A * card U"
    by (rule find_pivots_scan_and_initial_insert_budget_from_progress
      [OF S_subset degree S_cap insert degree_factor insert_factor U_progress])
qed

theorem range_costed_bmssp_level_bound_from_progress_budgets:
  assumes degree: "edge_outdegree_le Δ"
    and degree_factor: "Δ  A"
    and R_pos: "0 < R"
    and insert_factor: "t  A * k"
    and loop_factor: "Suc t  2 * A"
    and loop_progress:
      "l d P B d' D a betas bs B' Us U c child_costs.
        range_costed_partition_loop_state Δ M_of t k cap l d P B d' D a
          betas bs B' Us U c child_costs 
        sound_label d 
        bmssp_pre_full d P B 
        (x. x  P  reachable s x) 
        (M_of l) * length bs  card U"
    and step_progress:
      "l d S B D c_insert d' a betas bs B' Us U_loop c_loop
          child_costs U.
        D = label_partition_view
          (find_pivots_label_capped k cap d S B)
          (find_pivots_pivots_capped k cap d S B) 
        partition_initial_insert_cost_bound c_insert t
          (find_pivots_pivots_capped k cap d S B) 
        range_costed_partition_loop_state Δ M_of t k cap l
          (find_pivots_label_capped k cap d S B)
          (find_pivots_pivots_capped k cap d S B) B d' D a betas bs B'
          Us U_loop c_loop child_costs 
        complete_on d'
          {v  bound_tree S B'. find_pivots_label_capped k cap d S B v = dist s v} 
        U = U_loop 
          {v  bound_tree S B'. find_pivots_label_capped k cap d S B v = dist s v} 
        sound_label d 
        bmssp_pre_full d S B 
        (x. x  S  reachable s x) 
        card S  cap  k * cap  card U"
    and run:
      "range_costed_bmssp Δ M_of t k cap l d S B d' B' U c"
    and sound: "sound_label d"
    and pre: "bmssp_pre_full d S B"
    and S_reaches: "x. x  S  reachable s x"
  shows "c  level_range_cost_bound (2 * A) (R + l * t) (2 * l + 1) U"
proof (rule range_costed_bmssp_level_bound_from_local_budgets
    [where A = "2 * A" and R = R,
      OF _ R_pos _ _ run sound pre S_reaches])
  show "Δ  2 * A"
    using degree_factor by simp
next
  fix l d P B d' D a betas bs B' Us U c child_costs
  assume loop:
      "range_costed_partition_loop_state Δ M_of t k cap l d P B d' D a
        betas bs B' Us U c child_costs"
    and sound_l: "sound_label d"
    and pre_l: "bmssp_pre_full d P B"
    and reaches_l: "x. x  P  reachable s x"
  have progress: "(M_of l) * length bs  card U"
    by (rule loop_progress[OF loop sound_l pre_l reaches_l])
  show "(Suc t) * (M_of l) * length bs  2 * A * card U"
    by (rule loop_overhead_budget_from_progress[OF loop_factor progress])
next
  fix l d S B D c_insert d' a betas bs B' Us U_loop c_loop child_costs U
  assume D_def:
      "D = label_partition_view
        (find_pivots_label_capped k cap d S B)
        (find_pivots_pivots_capped k cap d S B)"
    and insert:
      "partition_initial_insert_cost_bound c_insert t
        (find_pivots_pivots_capped k cap d S B)"
    and loop:
      "range_costed_partition_loop_state Δ M_of t k cap l
        (find_pivots_label_capped k cap d S B)
        (find_pivots_pivots_capped k cap d S B) B d' D a betas bs B'
        Us U_loop c_loop child_costs"
    and complete:
      "complete_on d'
        {v  bound_tree S B'. find_pivots_label_capped k cap d S B v = dist s v}"
    and U_def:
      "U = U_loop 
        {v  bound_tree S B'. find_pivots_label_capped k cap d S B v = dist s v}"
    and sound_s: "sound_label d"
    and pre_s: "bmssp_pre_full d S B"
    and reaches_s: "x. x  S  reachable s x"
  have S_subset: "S  V"
    using pre_s unfolding bmssp_pre_full_def by blast
  have progress:
      "card S  cap  k * cap  card U"
    by (rule step_progress[OF D_def insert loop complete U_def sound_s pre_s reaches_s])
  then have S_cap: "card S  cap"
    by blast
  from progress have U_progress: "k * cap  card U"
    by blast
  show "fp_iter_capped_scan_cost k cap d S S B + c_insert 
      2 * A * card U"
    by (rule find_pivots_scan_and_initial_insert_budget_from_progress
      [OF S_subset degree S_cap insert degree_factor insert_factor U_progress])
qed

theorem finite_initial_label_range_costed_top_level_correct:
  assumes all_reachable: "v. v  V  reachable s v"
    and run:
      "range_costed_bmssp Δ M_of t k cap l finite_initial_label {s}
        Infinity d' Infinity U c"
  shows "sssp_correct d'"
proof -
  have pre: "bmssp_pre_full finite_initial_label {s} Infinity"
    using all_reachable finite_initial_label_source_complete
    by (rule top_bmssp_pre_full)
  have sound: "sound_label finite_initial_label"
    using finite_initial_label_sound[OF all_reachable] .
  have S_reaches: "x. x  {s}  reachable s x"
    using all_reachable source_in_V by blast
  have post_full:
    "bmssp_post_full finite_initial_label {s} Infinity d' Infinity U"
    by (rule range_costed_bmssp_correct[OF run sound pre S_reaches])
  have post: "bmssp_post finite_initial_label {s} Infinity d' Infinity U"
    using bmssp_post_full_imp_post[OF post_full] .
  then have U_V: "U = V"
    using bound_tree_source_infinity[OF all_reachable]
    unfolding bmssp_post_def by auto
  have complete: "complete_on d' U"
    using post unfolding bmssp_post_def by auto
  then show ?thesis
    using U_V unfolding complete_on_def sssp_correct_def by auto
qed

theorem finite_initial_label_range_costed_top_level_correct_and_bound:
  assumes all_reachable: "v. v  V  reachable s v"
    and degree: "edge_outdegree_le Δ"
    and degree_factor: "Δ  A"
    and R_pos: "0 < R"
    and insert_factor: "t  A * k"
    and loop_factor: "Suc t  2 * A"
    and loop_progress:
      "l d P B d' D a betas bs B' Us U c child_costs.
        range_costed_partition_loop_state Δ M_of t k cap l d P B d' D a
          betas bs B' Us U c child_costs 
        sound_label d 
        bmssp_pre_full d P B 
        (x. x  P  reachable s x) 
        (M_of l) * length bs  card U"
    and step_progress:
      "l d S B D c_insert d' a betas bs B' Us U_loop c_loop
          child_costs U.
        D = label_partition_view
          (find_pivots_label_capped k cap d S B)
          (find_pivots_pivots_capped k cap d S B) 
        partition_initial_insert_cost_bound c_insert t
          (find_pivots_pivots_capped k cap d S B) 
        range_costed_partition_loop_state Δ M_of t k cap l
          (find_pivots_label_capped k cap d S B)
          (find_pivots_pivots_capped k cap d S B) B d' D a betas bs B'
          Us U_loop c_loop child_costs 
        complete_on d'
          {v  bound_tree S B'. find_pivots_label_capped k cap d S B v = dist s v} 
        U = U_loop 
          {v  bound_tree S B'. find_pivots_label_capped k cap d S B v = dist s v} 
        sound_label d 
        bmssp_pre_full d S B 
        (x. x  S  reachable s x) 
        card S  cap  k * cap  card U"
    and run:
      "range_costed_bmssp Δ M_of t k cap l finite_initial_label {s}
        Infinity d' Infinity U c"
  shows "sssp_correct d' 
    c  level_range_cost_bound (2 * A) (R + l * t) (2 * l + 1) U"
proof
  show "sssp_correct d'"
    by (rule finite_initial_label_range_costed_top_level_correct
      [OF all_reachable run])
next
  have pre: "bmssp_pre_full finite_initial_label {s} Infinity"
    using all_reachable finite_initial_label_source_complete
    by (rule top_bmssp_pre_full)
  have sound: "sound_label finite_initial_label"
    using finite_initial_label_sound[OF all_reachable] .
  have S_reaches: "x. x  {s}  reachable s x"
    using all_reachable source_in_V by blast
  show "c  level_range_cost_bound (2 * A) (R + l * t) (2 * l + 1) U"
    by (rule range_costed_bmssp_level_bound_from_progress_budgets
      [OF degree degree_factor R_pos insert_factor loop_factor loop_progress
        step_progress run sound pre S_reaches])
qed

theorem finite_initial_label_range_costed_top_level_correct_and_source_progress_bound:
  assumes all_reachable: "v. v  V  reachable s v"
    and degree: "edge_outdegree_le Δ"
    and degree_factor: "Δ  A"
    and R_pos: "0 < R"
    and insert_factor: "t  A * k"
    and source_factor: "Suc t  2 * A"
    and source_progress:
      "l d S B d' B' U c.
        range_costed_bmssp Δ M_of t k cap l d S B d' B' U c 
        bmssp_pre_full d S B 
        (x. x  S  reachable s x) 
        card S  M_of l 
        card S  card U"
    and step_progress:
      "l d S B D c_insert d' a betas bs B' Us U_loop c_loop
          child_costs U.
        D = label_partition_view
          (find_pivots_label_capped k cap d S B)
          (find_pivots_pivots_capped k cap d S B) 
        partition_initial_insert_cost_bound c_insert t
          (find_pivots_pivots_capped k cap d S B) 
        range_costed_partition_loop_state Δ M_of t k cap l
          (find_pivots_label_capped k cap d S B)
          (find_pivots_pivots_capped k cap d S B) B d' D a betas bs B'
          Us U_loop c_loop child_costs 
        complete_on d'
          {v  bound_tree S B'. find_pivots_label_capped k cap d S B v = dist s v} 
        U = U_loop 
          {v  bound_tree S B'. find_pivots_label_capped k cap d S B v = dist s v} 
        sound_label d 
        bmssp_pre_full d S B 
        (x. x  S  reachable s x) 
        card S  cap  k * cap  card U"
    and run:
      "range_costed_bmssp Δ M_of t k cap l finite_initial_label {s}
        Infinity d' Infinity U c"
  shows "sssp_correct d' 
    c  level_range_cost_bound (2 * A) (R + l * t) (2 * l + 1) U"
proof
  show "sssp_correct d'"
    by (rule finite_initial_label_range_costed_top_level_correct
      [OF all_reachable run])
next
  have pre: "bmssp_pre_full finite_initial_label {s} Infinity"
    using all_reachable finite_initial_label_source_complete
    by (rule top_bmssp_pre_full)
  have sound: "sound_label finite_initial_label"
    using finite_initial_label_sound[OF all_reachable] .
  have S_reaches: "x. x  {s}  reachable s x"
    using all_reachable source_in_V by blast
  show "c  level_range_cost_bound (2 * A) (R + l * t) (2 * l + 1) U"
    by (rule range_costed_bmssp_level_bound_from_source_progress_budgets
      [OF degree degree_factor R_pos insert_factor source_factor source_progress
        step_progress run sound pre S_reaches])
qed

theorem finite_initial_label_range_costed_top_level_correct_and_graph_bound:
  assumes all_reachable: "v. v  V  reachable s v"
    and degree: "edge_outdegree_le Δ"
    and degree_factor: "Δ  A"
    and R_pos: "0 < R"
    and insert_factor: "t  A * k"
    and source_factor: "Suc t  2 * A"
    and source_progress:
      "l d S B d' B' U c.
        range_costed_bmssp Δ M_of t k cap l d S B d' B' U c 
        bmssp_pre_full d S B 
        (x. x  S  reachable s x) 
        card S  M_of l 
        card S  card U"
    and step_progress:
      "l d S B D c_insert d' a betas bs B' Us U_loop c_loop
          child_costs U.
        D = label_partition_view
          (find_pivots_label_capped k cap d S B)
          (find_pivots_pivots_capped k cap d S B) 
        partition_initial_insert_cost_bound c_insert t
          (find_pivots_pivots_capped k cap d S B) 
        range_costed_partition_loop_state Δ M_of t k cap l
          (find_pivots_label_capped k cap d S B)
          (find_pivots_pivots_capped k cap d S B) B d' D a betas bs B'
          Us U_loop c_loop child_costs 
        complete_on d'
          {v  bound_tree S B'. find_pivots_label_capped k cap d S B v = dist s v} 
        U = U_loop 
          {v  bound_tree S B'. find_pivots_label_capped k cap d S B v = dist s v} 
        sound_label d 
        bmssp_pre_full d S B 
        (x. x  S  reachable s x) 
        card S  cap  k * cap  card U"
    and run:
      "range_costed_bmssp Δ M_of t k cap l finite_initial_label {s}
        Infinity d' Infinity U c"
  shows "sssp_correct d' 
    c  2 * A * (2 * l + 1) * vertex_count + (R + l * t) * edge_count"
proof -
  have combined:
    "sssp_correct d' 
      c  level_range_cost_bound (2 * A) (R + l * t) (2 * l + 1) U"
    by (rule finite_initial_label_range_costed_top_level_correct_and_source_progress_bound
      [OF all_reachable degree degree_factor R_pos insert_factor source_factor
        source_progress step_progress run])
  then have correct: "sssp_correct d'"
    by blast
  have pre: "bmssp_pre_full finite_initial_label {s} Infinity"
    using all_reachable finite_initial_label_source_complete
    by (rule top_bmssp_pre_full)
  have sound: "sound_label finite_initial_label"
    using finite_initial_label_sound[OF all_reachable] .
  have S_reaches: "x. x  {s}  reachable s x"
    using all_reachable source_in_V by blast
  have post_full:
    "bmssp_post_full finite_initial_label {s} Infinity d' Infinity U"
    by (rule range_costed_bmssp_correct[OF run sound pre S_reaches])
  have post: "bmssp_post finite_initial_label {s} Infinity d' Infinity U"
    using bmssp_post_full_imp_post[OF post_full] .
  have U_V: "U = V"
    using post bound_tree_source_infinity[OF all_reachable]
    unfolding bmssp_post_def by auto
  have cost_U:
      "c  level_range_cost_bound (2 * A) (R + l * t) (2 * l + 1) U"
    using combined by blast
  have graph_bound:
    "level_range_cost_bound (2 * A) (R + l * t) (2 * l + 1) U
       2 * A * (2 * l + 1) * vertex_count + (R + l * t) * edge_count"
  proof -
    have U_card: "card U = vertex_count"
      unfolding U_V vertex_count_def by simp
    have out_le: "card (outgoing_edges U)  edge_count"
      by (rule edge_count_outgoing_bound)
    have out_term:
      "(R + l * t) * card (outgoing_edges U)  (R + l * t) * edge_count"
      using out_le by simp
    show ?thesis
      unfolding level_range_cost_bound_def
      using U_card out_term by (simp add: algebra_simps)
  qed
  show ?thesis
    using correct cost_U graph_bound by linarith
qed

end

end