Theory Voblint_Domain.Nonrelational_Reachability
theory Nonrelational_Reachability
imports Nonrelational_State Reachability_Lift
begin
section ‹Reachability for pointwise abstract stores›
text ‹
Pointwise stores and structural reachability are independent domain
constructions. This theory composes them: unreachable points denote no
concrete store, and reachable payloads use \<^const>‹gamma_state›.
The logical witness-empty predicate agrees with that composed
concretization; a concrete executable state representation supplies a
finite implementation of it (‹default_st_is_bot_for›, downstream in the
‹Voblint_Exec› session), since ‹is_empty_state_lift› below inherits
\<^const>‹is_empty_state›'s non-executable quantifier over \<^typ>‹vname› on its
‹Lifted› case.
›
subsection ‹Composed concretization›
text ‹A lifted pointwise state is one more kind of state, so ‹γ d› covers it too.
‹γ⇩⊥ _› stays as input syntax that fixes the lifted type where nothing else does.›
abbreviation (input) gamma_state_lift ::
"'a::numeric_domain abs_state lifted ⇒ store set" ("γ⇩⊥") where
"gamma_state_lift ≡ gamma_lift gamma_state"
adhoc_overloading gamma_S == "gamma_lift gamma_state"
fun is_empty_state_lift ::
"'a::executable_domain abs_state lifted ⇒ bool" where
"is_empty_state_lift Bot = True"
| "is_empty_state_lift (Lifted d) = is_empty_state d"
lemma is_empty_state_lift_iff:
"is_empty_state_lift s ⟷ γ⇩⊥ s = {}"
by (cases s) (simp_all add: is_empty_state_iff_gamma_state_empty)
lemma exact_emptiness_is_empty_state_lift:
"exact_emptiness is_empty_state_lift
(gamma_lift gamma_state :: 'a::numeric_domain abs_state lifted ⇒ store set)"
by (rule exact_emptinessI) (rule is_empty_state_lift_iff)
text ‹
‹Reachability_Lift›'s generic ‹gamma_normalize_lift›/‹normalize_lift_mono›/
‹normalized_lift_sup› specialized to ‹is_empty_state›: each generic side
condition (concretization agreement, downward closure) is discharged by
‹is_empty_state_iff_gamma_state_empty›/‹is_empty_state_antimono›. The first
is tagged ‹[simp]›, unlike the generic version, because its side condition
is now a closed fact rather than a further proof obligation.
›
lemma gamma_state_normalize_lift [simp]:
"γ⇩⊥ (normalize_lift is_empty_state d) = γ d"
by (rule gamma_normalize_lift) (rule is_empty_state_iff_gamma_state_empty)
text ‹Collapsing a witness-bottom payload changes what a value says about
itself, never what it represents. Every public result adapter routes its
solved values through \<^const>‹canonicalize_lift› before publishing them, so
this is what lets such an adapter's soundness argument ignore the collapse
entirely.›
lemma gamma_state_canonicalize_lift [simp]:
"γ⇩⊥ (canonicalize_lift is_empty_state d) = γ⇩⊥ d"
by (cases d) simp_all
lemma normalize_state_lift_mono [intro]:
fixes d1 d2 :: "'a::numeric_domain abs_state"
assumes le: "d1 ≤ d2"
shows "normalize_lift is_empty_state d1 ≤ normalize_lift is_empty_state d2"
by (rule normalize_lift_mono[OF le]) (rule is_empty_state_antimono[OF le])
lemma normalized_state_lift_sup [intro]:
fixes s1 s2 :: "'a::numeric_domain abs_state lifted"
assumes n1: "normalized_lift is_empty_state s1" and n2: "normalized_lift is_empty_state s2"
shows "normalized_lift is_empty_state (s1 ⊔ s2)"
by (rule normalized_lift_sup[OF is_empty_state_antimono n1 n2])
subsection ‹The normalization invariant›
text ‹
After normalization, structural and semantic deadness coincide: a
‹normalized_lift›-disciplined value can no longer disagree with its own
‹is_empty_state_lift› reading, because normalization is exactly what rules
out a live-looking ‹Lifted› payload that is secretly witness-bottom.
›
lemma normalized_state_lift_bot_iff [simp]:
"normalized_lift is_empty_state s ⟹ is_empty_state_lift s ⟷ s = Bot"
by (cases s) simp_all
subsection ‹Join›
text ‹
‹gamma_state_supI1›/‹gamma_state_supI2› lifted through \<^const>‹gamma_state_lift›:
a witness on one side of a lifted join survives it, whether the other side
is \<^const>‹Bot› (the join's identity) or a competing \<^const>‹Lifted› payload.
›
lemma gamma_state_lift_supI1 [intro]:
"s ∈ γ⇩⊥ x ⟹ s ∈ γ⇩⊥ (x ⊔ y)"
for x y :: "'a::numeric_domain abs_state lifted"
by (cases x; cases y) auto
lemma gamma_state_lift_supI2 [intro]:
"s ∈ γ⇩⊥ y ⟹ s ∈ γ⇩⊥ (x ⊔ y)"
for x y :: "'a::numeric_domain abs_state lifted"
by (cases x; cases y) auto
subsection ‹Carrying a transfer's soundness through the lift›
text ‹
A pure transfer's soundness fact carries over the \<^const>‹transfer_lift›
wrapper by one case split: \<^const>‹Bot›'s concretization is empty, and a
\<^const>‹normalize_lift› collapse to \<^const>‹Bot› only ever fires when
‹empty_pred› holds, whose concretization is empty by assumption. Three shapes
cover every use --- a collecting inclusion, a membership, and a binary
membership for a combine --- so no consumer repeats the bottom argument.
›
lemma transfer_lift_sound_collect:
assumes step: "⋀d'. C (γ d') ⊆ γ (f d')"
and Cempty: "C {} = {}"
and empty_pred_sound: "⋀d'. empty_pred d' ⟹ γ d' = {}"
shows "C (γ⇩⊥ d) ⊆ γ⇩⊥ (transfer_lift empty_pred f d)"
proof (cases d)
case Bot
then show ?thesis by (simp add: Cempty)
next
case (Lifted d')
have "C (γ d') ⊆ γ (f d')" by (rule step)
then show ?thesis
using Lifted empty_pred_sound[of "f d'"] by (auto simp: normalize_lift_def)
qed
lemma transfer_lift_sound_mem:
assumes step: "⋀d'. s ∈ γ d' ⟹ h s ∈ γ (f d')"
and empty_pred_sound: "⋀d'. empty_pred d' ⟹ γ d' = {}"
and s: "s ∈ γ⇩⊥ d"
shows "h s ∈ γ⇩⊥ (transfer_lift empty_pred f d)"
proof (cases d)
case Bot
then show ?thesis using s by simp
next
case (Lifted d')
with s have "s ∈ γ d'" by simp
then have hs: "h s ∈ γ (f d')" by (rule step)
then have "¬ empty_pred (f d')" using empty_pred_sound by auto
with Lifted hs show ?thesis by simp
qed
lemma transfer_lift2_sound_mem:
assumes step: "⋀d1' d2'. s ∈ γ d1' ⟹ t ∈ γ d2' ⟹ h s t ∈ γ (f d1' d2')"
and empty_pred_sound: "⋀d'. empty_pred d' ⟹ γ d' = {}"
and s: "s ∈ γ⇩⊥ d1"
and t: "t ∈ γ⇩⊥ d2"
shows "h s t ∈ γ⇩⊥ (transfer_lift2 empty_pred f d1 d2)"
proof (cases d1)
case Bot
then show ?thesis using s by simp
next
case (Lifted d1')
show ?thesis
proof (cases d2)
case Bot
then show ?thesis using t by simp
next
case (Lifted d2')
with ‹d1 = Lifted d1'› s t have "s ∈ γ d1'" "t ∈ γ d2'" by simp_all
then have hst: "h s t ∈ γ (f d1' d2')" by (rule step)
then have "¬ empty_pred (f d1' d2')" using empty_pred_sound by auto
with ‹d1 = Lifted d1'› Lifted hst show ?thesis by simp
qed
qed
end