Theory Voblint_Analysis_Congruence.Congruence_Special
theory Congruence_Special
imports Congruence_Arithmetic "Voblint_Nonrelational.Special_Ops"
begin
section ‹What a Min or Max call tells you about a residue class›
text ‹
‹Min a b› and ‹Max a b› each return one of their two operands, never a
newly computed integer, so whatever describes both operands describes the
result. Congruence answers with the join of the two argument classes: sound
for either selection, and the sharpest answer available without knowing
which one is taken. ‹Nondet_Int› constrains nothing and lands at ‹top›.
The reader needs ‹aval_congruence›, Congruence's expression evaluator, from
\<^theory>‹Voblint_Analysis_Congruence.Congruence_Arithmetic›.
›
text ‹
Two known-even operands stay even, exactly as Parity's ‹parity_min› keeps
‹PEven›; a mismatch of moduli falls back on their common coarsening rather
than on ‹top›, which is where the join earns over a constant answer.
›
definition congruence_min :: "congruence => congruence => congruence" where
"congruence_min a b = a ⊔ b"
definition congruence_max :: "congruence => congruence => congruence" where
"congruence_max a b = a ⊔ b"
lemma gamma_congruence_sup_ub1: "gamma_congruence a ⊆ gamma_congruence (a ⊔ b)"
proof -
have "γ (a::congruence) ⊆ γ (a ⊔ b)" by (rule gamma_mono[OF sup_ge1])
then show ?thesis by simp
qed
lemma gamma_congruence_sup_ub2: "gamma_congruence b ⊆ gamma_congruence (a ⊔ b)"
proof -
have "γ (b::congruence) ⊆ γ (a ⊔ b)" by (rule gamma_mono[OF sup_ge2])
then show ?thesis by simp
qed
lemma congruence_min_sound:
assumes "i ∈ gamma_congruence a" and "j ∈ gamma_congruence b"
shows "min i j ∈ gamma_congruence (congruence_min a b)"
using assms gamma_congruence_sup_ub1[of a b] gamma_congruence_sup_ub2[of b a]
unfolding congruence_min_def min_def by auto
lemma congruence_max_sound:
assumes "i ∈ gamma_congruence a" and "j ∈ gamma_congruence b"
shows "max i j ∈ gamma_congruence (congruence_max a b)"
using assms gamma_congruence_sup_ub1[of a b] gamma_congruence_sup_ub2[of b a]
unfolding congruence_max_def max_def by auto
lemma congruence_min_mono:
"a1 ≤ a2 ⟹ b1 ≤ b2 ⟹ congruence_min a1 b1 ≤ congruence_min a2 (b2::congruence)"
unfolding congruence_min_def by (rule sup_mono)
lemma congruence_max_mono:
"a1 ≤ a2 ⟹ b1 ≤ b2 ⟹ congruence_max a1 b1 ≤ congruence_max a2 (b2::congruence)"
unfolding congruence_max_def by (rule sup_mono)
subsection ‹Special-call dispatch›
text ‹
‹congruence_special_ops› pairs ‹congruence_min› and ‹congruence_max›, both the
join of their operands. Interpreting ‹mono_minmax_ops› at this pair makes the
generic special-call transfer sound and monotone for congruences.
›
definition congruence_special_ops :: "congruence special_ops" where
"congruence_special_ops = (| special_min = congruence_min, special_max = congruence_max |)"
lemma congruence_special_ops_min [simp]: "special_min congruence_special_ops = congruence_min"
by (simp add: congruence_special_ops_def)
lemma congruence_special_ops_max [simp]: "special_max congruence_special_ops = congruence_max"
by (simp add: congruence_special_ops_def)
interpretation congruence_special: mono_minmax_ops congruence_special_ops aval_congruence
proof unfold_locales
fix i j :: int and p q :: congruence
assume "i ∈ γ p" and "j ∈ γ q"
then show "min i j ∈ γ (special_min congruence_special_ops p q)"
using congruence_min_sound by simp
next
fix i j :: int and p q :: congruence
assume "i ∈ γ p" and "j ∈ γ q"
then show "max i j ∈ γ (special_max congruence_special_ops p q)"
using congruence_max_sound by simp
next
fix p1 p2 q1 q2 :: congruence
assume "p1 ≤ p2" and "q1 ≤ q2"
then show "special_min congruence_special_ops p1 q1
≤ special_min congruence_special_ops p2 q2"
by (simp add: congruence_min_mono)
next
fix p1 p2 q1 q2 :: congruence
assume "p1 ≤ p2" and "q1 ≤ q2"
then show "special_max congruence_special_ops p1 q1
≤ special_max congruence_special_ops p2 q2"
by (simp add: congruence_max_mono)
qed
fun special_congruence ::
"special_call => vname => (vname => congruence) => (vname => congruence)"
where
"special_congruence Nondet_Int x d = d(x := top)"
| "special_congruence (Min a b) x d =
d(x := congruence_min (aval_congruence a d) (aval_congruence b d))"
| "special_congruence (Max a b) x d =
d(x := congruence_max (aval_congruence a d) (aval_congruence b d))"
lemma special_congruence_eq_transfer:
"special_congruence sc x d = congruence_special.special_transfer sc x d"
by (cases sc) simp_all
end