Theory Int_Lattice
theory Int_Lattice
imports Sign_Lattice Interval_Lattice Parity_Lattice Congruence_Lattice
begin
section ‹Integer product lattice›
text ‹
The carrier keeps the four scalar abstractions independently. Its
concretization is their intersection; componentwise order and join preserve
the existing domain structures. Cross-domain reduction is separate from
this carrier definition.
›
subsection ‹Carrier›
record int_dom =
int_sign :: sign
int_ivl :: ivl
int_parity :: parity
int_congruence :: congruence
subsection ‹Order, join and meet›
text ‹
The record package represents a closed record through an extensible scheme.
Giving the scheme a componentwise instance makes the closed ‹int_dom›
abbreviation usable at every existing lattice-polymorphic boundary. The
scheme's ‹more› field is Isabelle machinery, not a semantic extension point:
new integer components belong in ‹int_dom› and must participate explicitly
in its lattice, concretization, and exact bottom decision.
›
instantiation int_dom_ext :: (bounded_lattice) bounded_lattice
begin
definition less_eq_int_dom_ext ::
"'a int_dom_scheme => 'a int_dom_scheme => bool" where
"less_eq_int_dom_ext a b ⟷
int_sign a <= int_sign b ∧
int_ivl a <= int_ivl b ∧
int_parity a <= int_parity b ∧
int_congruence a <= int_congruence b ∧
more a <= more b"
definition less_int_dom_ext ::
"'a int_dom_scheme => 'a int_dom_scheme => bool" where
"less_int_dom_ext a b ⟷ a ≤ b ∧ ¬ b ≤ a"
definition sup_int_dom_ext ::
"'a int_dom_scheme => 'a int_dom_scheme => 'a int_dom_scheme" where
"sup_int_dom_ext a b =
int_dom_ext
(sup (int_sign a) (int_sign b))
(sup (int_ivl a) (int_ivl b))
(sup (int_parity a) (int_parity b))
(sup (int_congruence a) (int_congruence b))
(sup (more a) (more b))"
definition inf_int_dom_ext ::
"'a int_dom_scheme => 'a int_dom_scheme => 'a int_dom_scheme" where
"inf_int_dom_ext a b =
int_dom_ext
(inf (int_sign a) (int_sign b))
(inf (int_ivl a) (int_ivl b))
(inf (int_parity a) (int_parity b))
(inf (int_congruence a) (int_congruence b))
(inf (more a) (more b))"
definition bot_int_dom_ext :: "'a int_dom_scheme" where
"bot_int_dom_ext = int_dom_ext bot bot bot bot bot"
definition top_int_dom_ext :: "'a int_dom_scheme" where
"top_int_dom_ext = int_dom_ext top top top top top"
instance
proof intro_classes
fix x y z :: "'a int_dom_scheme"
show "x < y ⟷ x ≤ y ∧ ¬ y ≤ x"
by (simp add: less_int_dom_ext_def)
show "x ≤ x"
by (simp add: less_eq_int_dom_ext_def)
show "x ≤ y ⟹ y ≤ z ⟹ x ≤ z"
by (auto simp: less_eq_int_dom_ext_def intro: order_trans)
show "x ≤ y ⟹ y ≤ x ⟹ x = y"
by (cases x; cases y)
(auto simp: less_eq_int_dom_ext_def intro: antisym)
show "x ≤ sup x y"
by (simp add: less_eq_int_dom_ext_def sup_int_dom_ext_def)
show "y ≤ sup x y"
by (simp add: less_eq_int_dom_ext_def sup_int_dom_ext_def)
show "y ≤ x ⟹ z ≤ x ⟹ sup y z ≤ x"
by (auto simp: less_eq_int_dom_ext_def sup_int_dom_ext_def)
show "inf x y ≤ x"
by (simp add: less_eq_int_dom_ext_def inf_int_dom_ext_def)
show "inf x y ≤ y"
by (simp add: less_eq_int_dom_ext_def inf_int_dom_ext_def)
show "x ≤ y ⟹ x ≤ z ⟹ x ≤ inf y z"
by (auto simp: less_eq_int_dom_ext_def inf_int_dom_ext_def)
show "bot ≤ x"
by (simp add: less_eq_int_dom_ext_def bot_int_dom_ext_def)
show "x ≤ top"
by (simp add: less_eq_int_dom_ext_def top_int_dom_ext_def)
qed
end
definition int_dom_sip :: "sign => ivl => parity => int_dom" where
"int_dom_sip s i p =
(top :: int_dom)⦇int_sign := s, int_ivl := i, int_parity := p⦈"
definition int_dom_sipc ::
"sign => ivl => parity => congruence => int_dom" where
"int_dom_sipc s i p c =
(top :: int_dom)⦇
int_sign := s,
int_ivl := i,
int_parity := p,
int_congruence := c
⦈"
lemma int_congruence_int_dom_sip [simp]:
"int_congruence (int_dom_sip s i p) = top"
by (simp add: int_dom_sip_def top_int_dom_ext_def)
subsection ‹Concretization›
text ‹
A product value denotes the integers every component admits:
‹gamma_int_dom› intersects the sign, interval, parity and congruence
concretizations.
›
definition gamma_int_dom :: "'a int_dom_scheme => int set" where
"gamma_int_dom d =
gamma_sign (int_sign d) ∩
gamma_ivl (int_ivl d) ∩
gamma_parity (int_parity d) ∩
gamma_congruence (int_congruence d)"
text ‹
Every component meet is exact, so the product meet is too: it concretizes to
the intersection of its operands. Query answers from several analyses are
combined by ‹⊓›, which therefore neither loses nor invents values.
›
lemma gamma_inf_int_dom [simp]:
"gamma_int_dom (a ⊓ b) = gamma_int_dom a ∩ gamma_int_dom b"
by (auto simp: gamma_int_dom_def inf_int_dom_ext_def)
lemma gamma_int_dom_update_sign [simp]:
"gamma_int_dom (d⦇int_sign := s⦈) =
gamma_sign s ∩
gamma_ivl (int_ivl d) ∩
gamma_parity (int_parity d) ∩
gamma_congruence (int_congruence d)"
by (simp add: gamma_int_dom_def)
lemma gamma_int_dom_update_ivl [simp]:
"gamma_int_dom (d⦇int_ivl := i⦈) =
gamma_sign (int_sign d) ∩
gamma_ivl i ∩
gamma_parity (int_parity d) ∩
gamma_congruence (int_congruence d)"
by (simp add: gamma_int_dom_def)
lemma gamma_int_dom_update_parity [simp]:
"gamma_int_dom (d⦇int_parity := p⦈) =
gamma_sign (int_sign d) ∩
gamma_ivl (int_ivl d) ∩
gamma_parity p ∩
gamma_congruence (int_congruence d)"
by (simp add: gamma_int_dom_def)
lemma gamma_int_dom_update_congruence [simp]:
"gamma_int_dom (d⦇int_congruence := c⦈) =
gamma_sign (int_sign d) ∩
gamma_ivl (int_ivl d) ∩
gamma_parity (int_parity d) ∩
gamma_congruence c"
by (simp add: gamma_int_dom_def)
fun interval_fact_of_sign :: "sign ⇒ ivl" where
"interval_fact_of_sign SBot = ⊥"
| "interval_fact_of_sign SNeg = Ivl MinInf (Fin (-1))"
| "interval_fact_of_sign SNonPos = Ivl MinInf (Fin 0)"
| "interval_fact_of_sign SZero = Ivl (Fin 0) (Fin 0)"
| "interval_fact_of_sign SNonNeg = Ivl (Fin 0) PlusInf"
| "interval_fact_of_sign SPos = Ivl (Fin 1) PlusInf"
| "interval_fact_of_sign STop = ⊤"
lemma gamma_interval_fact_of_sign [simp]:
"gamma_ivl (interval_fact_of_sign s) = gamma_sign s"
by (cases s) (auto simp: bot_ivl_def top_ivl_def ivl_top_def)
fun congruence_fact_of_parity :: "parity => congruence" where
"congruence_fact_of_parity PBot = bot"
| "congruence_fact_of_parity PEven = mk_congruence 0 2"
| "congruence_fact_of_parity POdd = mk_congruence 1 2"
| "congruence_fact_of_parity PTop = top"
lemma gamma_congruence_fact_of_parity [simp]:
"gamma_congruence (congruence_fact_of_parity p) = gamma_parity p"
by (cases p)
(auto simp: bot_congruence_def)
lemma gamma_intersect_ivl_exact:
"gamma_ivl (intersect_ivl a b) = gamma_ivl a ∩ gamma_ivl b"
using gamma_ivl_mono[OF intersect_ivl_le1]
gamma_ivl_mono[OF intersect_ivl_le2]
intersect_ivl_gamma
by blast
subsection ‹Executable interface›
text ‹
Deciding emptiness of the product needs more than the components' own tests,
since each can be inhabited while their intersection is empty. Interval and
congruence are checked jointly, after restricting the congruence by parity;
‹is_bottom_int_dom_correct› and ‹is_top_int_dom_correct_gamma› tie the tests to ‹gamma_int_dom›.
›
lemma inter_nonempty_iff:
"A ∩ B ≠ {} ⟷ (∃x. x ∈ A ∧ x ∈ B)"
by blast
lemma congruence_between_iff:
assumes normalized: "normalized_congruence_rep (Some (c, m))"
shows
"(∃n::int. l ≤ n ∧ n ≤ u ∧ m dvd n - c) ⟷
(if m = 0 then l ≤ c ∧ c ≤ u
else l ≤ u ∧ l + ((c - l) mod m) ≤ u)"
proof (cases "m = 0")
case True
then show ?thesis by simp
next
case False
from normalized_congruence_rep_nonzero[OF normalized False]
have modulus: "0 < m" by simp
show ?thesis
proof
assume "∃n::int. l ≤ n ∧ n ≤ u ∧ m dvd n - c"
then obtain n where n: "l ≤ n" "n ≤ u" "m dvd n - c"
by blast
have offset: "m dvd c - n"
using n(3) by (metis dvd_minus_iff minus_diff_eq)
have mod_eq: "(c - l) mod m = (n - l) mod m"
using offset
by (simp add:
Euclidean_Rings.euclidean_ring_cancel_class.mod_eq_dvd_iff)
have remainder_le: "(n - l) mod m ≤ n - l"
by (rule Euclidean_Rings.zmod_le_nonneg_dividend) (use n(1) in linarith)
show
"if m = 0 then l ≤ c ∧ c ≤ u
else l ≤ u ∧ l + ((c - l) mod m) ≤ u"
using False mod_eq n(1,2) remainder_le
by simp
next
assume rhs:
"if m = 0 then l ≤ c ∧ c ≤ u
else l ≤ u ∧ l + ((c - l) mod m) ≤ u"
let ?n = "l + ((c - l) mod m)"
have lower: "l ≤ ?n"
using modulus by simp
have congruent: "m dvd ?n - c"
proof -
have base: "m dvd (c - l) - (c - l) mod m"
by (rule dvd_minus_mod)
have "m dvd - ((c - l) - (c - l) mod m)"
using base by (simp only: dvd_minus_iff)
also have
"- ((c - l) - (c - l) mod m) = ?n - c"
by simp
finally show ?thesis .
qed
have upper: "?n ≤ u"
using rhs False by simp
show "∃n::int. l ≤ n ∧ n ≤ u ∧ m dvd n - c"
by (rule exI[of _ ?n]) (use lower upper congruent in blast)
qed
qed
lemma congruence_class_nonempty:
"∃n::int. m dvd n - c"
by (rule exI[of _ c]) simp
lemma exists_congruence_le:
assumes normalized: "normalized_congruence_rep (Some (c, m))"
and nonzero: "m ≠ 0"
shows "∃n::int. n ≤ u ∧ m dvd n - c"
proof -
from normalized_congruence_rep_nonzero[OF normalized nonzero]
have one_le: "1 ≤ m" by simp
let ?q = "abs (c - u) + 1"
have q_nonnegative: "0 ≤ ?q" by simp
have difference_le_q: "c - u ≤ ?q"
using abs_ge_self[of "c - u"] by linarith
have scale: "?q ≤ m * ?q"
using mult_right_mono[OF one_le q_nonnegative] by simp
let ?n = "c - m * ?q"
have upper: "?n ≤ u"
using difference_le_q scale by linarith
have congruent: "m dvd ?n - c"
by simp
show ?thesis
by (rule exI[of _ ?n]) (use upper congruent in blast)
qed
lemma exists_congruence_ge:
assumes normalized: "normalized_congruence_rep (Some (c, m))"
and nonzero: "m ≠ 0"
shows "∃n::int. l ≤ n ∧ m dvd n - c"
proof -
from normalized_congruence_rep_nonzero[OF normalized nonzero]
have one_le: "1 ≤ m" by simp
let ?q = "abs (l - c) + 1"
have q_nonnegative: "0 ≤ ?q" by simp
have difference_le_q: "l - c ≤ ?q"
using abs_ge_self[of "l - c"] by linarith
have scale: "?q ≤ m * ?q"
using mult_right_mono[OF one_le q_nonnegative] by simp
let ?n = "c + m * ?q"
have lower: "l ≤ ?n"
using difference_le_q scale by linarith
have congruent: "m dvd ?n - c"
by simp
show ?thesis
by (rule exI[of _ ?n]) (use lower congruent in blast)
qed
fun ivl_congruence_rep_nonempty ::
"ivl => congruence_rep => bool" where
"ivl_congruence_rep_nonempty i None = False"
| "ivl_congruence_rep_nonempty (Ivl MinInf MinInf) (Some cm) = False"
| "ivl_congruence_rep_nonempty (Ivl MinInf (Fin u)) (Some (c, m)) =
(if m = 0 then c ≤ u else True)"
| "ivl_congruence_rep_nonempty (Ivl MinInf PlusInf) (Some cm) = True"
| "ivl_congruence_rep_nonempty (Ivl (Fin l) MinInf) (Some cm) = False"
| "ivl_congruence_rep_nonempty (Ivl (Fin l) (Fin u)) (Some (c, m)) =
(if m = 0 then l ≤ c ∧ c ≤ u
else l ≤ u ∧ l + ((c - l) mod m) ≤ u)"
| "ivl_congruence_rep_nonempty (Ivl (Fin l) PlusInf) (Some (c, m)) =
(if m = 0 then l ≤ c else True)"
| "ivl_congruence_rep_nonempty (Ivl PlusInf u) (Some cm) = False"
lemma ivl_congruence_rep_nonempty_correct:
assumes normalized: "normalized_congruence_rep r"
shows
"ivl_congruence_rep_nonempty i r ⟷
gamma_ivl i ∩ gamma_congruence_rep r ≠ {}"
proof (cases r)
case None
then show ?thesis by simp
next
case (Some cm)
obtain c m where cm: "cm = (c, m)"
by (cases cm)
have rep: "r = Some (c, m)"
using Some cm by simp
have normalized': "normalized_congruence_rep (Some (c, m))"
using normalized unfolding rep .
show ?thesis
proof (cases i)
case (Ivl l u)
show ?thesis
unfolding rep Ivl
by (cases l; cases u; cases "m = 0")
(auto simp: inter_nonempty_iff
congruence_between_iff[OF normalized']
congruence_class_nonempty
exists_congruence_le[OF normalized']
exists_congruence_ge[OF normalized'])
qed
qed
fun parity_accepts :: "parity => int => bool" where
"parity_accepts PBot n = False"
| "parity_accepts PEven n = even n"
| "parity_accepts POdd n = odd n"
| "parity_accepts PTop n = True"
lemma parity_accepts_gamma [simp]:
"parity_accepts p n ⟷ n ∈ gamma_parity p"
by (cases p) simp_all
lemma parity_accepts_difference:
assumes concrete: "p = PEven ∨ p = POdd"
and accepts: "parity_accepts p r"
shows "2 dvd n - r ⟷ parity_accepts p n"
using concrete accepts
by (cases p) auto
lemma dvd_shift_modulus:
fixes m n c :: int
shows "m dvd n - (c + m) ⟷ m dvd n - c"
proof
assume shifted: "m dvd n - (c + m)"
have "m dvd (n - (c + m)) + m"
by (rule dvd_add[OF shifted dvd_refl[of m]])
then show "m dvd n - c" by simp
next
assume original: "m dvd n - c"
have "m dvd (n - c) - m"
by (rule dvd_diff[OF original dvd_refl[of m]])
also have "(n - c) - m = n - (c + m)"
by simp
finally show "m dvd n - (c + m)" .
qed
lemma gamma_normalized_lcm_two:
"gamma_congruence_rep
(normalize_congruence_rep (Some (r, lcm m 2))) =
{n. m dvd n - r ∧ 2 dvd n - r}"
by (simp only: gamma_normalize_congruence_rep
gamma_congruence_rep.simps
GCD.semiring_gcd_class.lcm_least_iff)
lemma congruent_even_modulus:
fixes m n c :: int
assumes modulus: "even m"
and congruent: "m dvd n - c"
shows "even n ⟷ even c"
proof -
obtain k where difference: "n - c = m * k"
using congruent unfolding dvd_def by blast
have difference_even: "even (n - c)"
using modulus difference by simp
have parity_eq: "even (n - c) = even (n + c)"
by (rule even_diff_iff)
have sum_even: "even (n + c)"
using parity_eq difference_even by blast
show ?thesis
using sum_even
by (simp only: Parity.semiring_parity_class.even_add)
qed
lemma normalized_lcm_two_inter_parity:
assumes concrete: "p = PEven ∨ p = POdd"
and accepts: "parity_accepts p r"
shows
"gamma_congruence_rep
(normalize_congruence_rep (Some (r, lcm m 2))) =
gamma_parity p ∩ {n. m dvd n - r}"
proof -
have difference:
"⋀n. 2 dvd n - r ⟷ parity_accepts p n"
by (rule parity_accepts_difference[OF concrete accepts])
show ?thesis
unfolding gamma_normalized_lcm_two
using difference by auto
qed
lemma even_modulus_disjoint_parity:
assumes concrete: "p = PEven ∨ p = POdd"
and modulus: "even m"
and rejects: "¬ parity_accepts p c"
shows "gamma_parity p ∩ {n. m dvd n - c} = {}"
proof (rule equals0I)
fix n
assume member:
"n ∈ gamma_parity p ∩ {n. m dvd n - c}"
from member have accepts: "parity_accepts p n"
by simp
from member have congruent: "m dvd n - c"
by simp
have same: "even n ⟷ even c"
by (rule congruent_even_modulus[OF modulus congruent])
from concrete rejects accepts same show False
by (cases p) auto
qed
lemma parity_accepts_add_odd:
assumes concrete: "p = PEven ∨ p = POdd"
and rejects: "¬ parity_accepts p c"
and modulus: "odd m"
shows "parity_accepts p (c + m)"
using concrete rejects modulus by (cases p) auto
fun restrict_congruence_rep_by_parity ::
"parity => congruence_rep => congruence_rep" where
"restrict_congruence_rep_by_parity PBot r = None"
| "restrict_congruence_rep_by_parity PTop r = r"
| "restrict_congruence_rep_by_parity p None = None"
| "restrict_congruence_rep_by_parity p (Some (c, m)) =
(if m = 0 then
if parity_accepts p c then Some (c, 0) else None
else if even m ∧ ¬ parity_accepts p c then None
else
normalize_congruence_rep
(Some
(c + (if parity_accepts p c then 0 else m),
lcm m 2)))"
lemma normalized_restrict_congruence_rep_by_parity:
assumes "normalized_congruence_rep r"
shows
"normalized_congruence_rep
(restrict_congruence_rep_by_parity p r)"
using assms
by (cases p; cases r)
(auto simp only: restrict_congruence_rep_by_parity.simps
normalized_congruence_rep.simps
normalized_normalize_congruence_rep
option.simps
split: prod.splits if_splits)
lemma restrict_concrete_parity_correct:
assumes concrete: "p = PEven ∨ p = POdd"
shows
"gamma_congruence_rep
(restrict_congruence_rep_by_parity p (Some (c, m))) =
gamma_parity p ∩ gamma_congruence_rep (Some (c, m))"
proof (cases "m = 0")
case True
with concrete show ?thesis
by (cases p) auto
next
case nonzero: False
show ?thesis
proof (cases "even m")
case modulus: True
show ?thesis
proof (cases "parity_accepts p c")
case accepts: True
have reduced:
"restrict_congruence_rep_by_parity p (Some (c, m)) =
normalize_congruence_rep (Some (c, lcm m 2))"
using concrete nonzero modulus accepts
by (cases p) simp_all
have exact:
"gamma_congruence_rep
(normalize_congruence_rep (Some (c, lcm m 2))) =
gamma_parity p ∩ {n. m dvd n - c}"
by (rule normalized_lcm_two_inter_parity[OF concrete accepts])
show ?thesis
unfolding reduced
using exact by simp
next
case rejects: False
have reduced:
"restrict_congruence_rep_by_parity p (Some (c, m)) = None"
using concrete nonzero modulus rejects
by (cases p) simp_all
have disjoint:
"gamma_parity p ∩ {n. m dvd n - c} = {}"
by (rule even_modulus_disjoint_parity[OF concrete modulus rejects])
show ?thesis
unfolding reduced
using disjoint by simp
qed
next
case modulus: False
show ?thesis
proof (cases "parity_accepts p c")
case accepts: True
have reduced:
"restrict_congruence_rep_by_parity p (Some (c, m)) =
normalize_congruence_rep (Some (c, lcm m 2))"
using concrete nonzero modulus accepts
by (cases p) simp_all
have exact:
"gamma_congruence_rep
(normalize_congruence_rep (Some (c, lcm m 2))) =
gamma_parity p ∩ {n. m dvd n - c}"
by (rule normalized_lcm_two_inter_parity[OF concrete accepts])
show ?thesis
unfolding reduced
using exact by simp
next
case rejects: False
have odd_modulus: "odd m"
using modulus by simp
have shifted_accepts: "parity_accepts p (c + m)"
by (rule parity_accepts_add_odd[OF concrete rejects odd_modulus])
have reduced:
"restrict_congruence_rep_by_parity p (Some (c, m)) =
normalize_congruence_rep (Some (c + m, lcm m 2))"
using concrete nonzero modulus rejects
by (cases p) simp_all
have exact:
"gamma_congruence_rep
(normalize_congruence_rep (Some (c + m, lcm m 2))) =
gamma_parity p ∩ {n. m dvd n - (c + m)}"
by (rule normalized_lcm_two_inter_parity[
OF concrete shifted_accepts])
show ?thesis
unfolding reduced
using exact by (simp only: gamma_congruence_rep.simps
dvd_shift_modulus)
qed
qed
qed
lemma restrict_congruence_rep_by_parity_correct:
assumes normalized: "normalized_congruence_rep r"
shows
"gamma_congruence_rep
(restrict_congruence_rep_by_parity p r) =
gamma_parity p ∩ gamma_congruence_rep r"
proof (cases p)
case PBot
then show ?thesis by simp
next
case PTop
then show ?thesis by simp
next
case destination: PEven
show ?thesis
proof (cases r)
case None
with destination show ?thesis by simp
next
case (Some cm)
obtain c m where cm: "cm = (c, m)"
by (cases cm)
have rep: "r = Some (c, m)"
using Some cm by simp
show ?thesis
unfolding destination rep
by (rule restrict_concrete_parity_correct) simp
qed
next
case destination: POdd
show ?thesis
proof (cases r)
case None
with destination show ?thesis by simp
next
case (Some cm)
obtain c m where cm: "cm = (c, m)"
by (cases cm)
have rep: "r = Some (c, m)"
using Some cm by simp
show ?thesis
unfolding destination rep
by (rule restrict_concrete_parity_correct) simp
qed
qed
lift_definition restrict_congruence_by_parity ::
"parity => congruence => congruence"
is restrict_congruence_rep_by_parity
by (rule normalized_restrict_congruence_rep_by_parity)
declare restrict_congruence_by_parity.rep_eq [simp]
lemma gamma_restrict_congruence_by_parity [simp]:
"gamma_congruence (restrict_congruence_by_parity p c) =
gamma_parity p ∩ gamma_congruence c"
proof -
have normalized:
"normalized_congruence_rep (Rep_congruence c)"
by simp
have raw:
"gamma_congruence_rep
(restrict_congruence_rep_by_parity p (Rep_congruence c)) =
gamma_parity p ∩
gamma_congruence_rep (Rep_congruence c)"
by (rule restrict_congruence_rep_by_parity_correct[OF normalized])
show ?thesis
unfolding gamma_congruence_def
using raw by simp
qed
definition ivl_congruence_nonempty ::
"ivl => congruence => bool" where
"ivl_congruence_nonempty i c =
ivl_congruence_rep_nonempty i (Rep_congruence c)"
lemma ivl_congruence_nonempty_correct:
"ivl_congruence_nonempty i c ⟷
gamma_ivl i ∩ gamma_congruence c ≠ {}"
proof -
have normalized:
"normalized_congruence_rep (Rep_congruence c)"
by simp
show ?thesis
unfolding ivl_congruence_nonempty_def gamma_congruence_def
by (rule ivl_congruence_rep_nonempty_correct[OF normalized])
qed
definition is_bottom_int_dom :: "'a int_dom_scheme => bool" where
"is_bottom_int_dom d =
(¬ ivl_congruence_nonempty
(intersect_ivl
(interval_fact_of_sign (int_sign d))
(int_ivl d))
(restrict_congruence_by_parity
(int_parity d)
(int_congruence d)))"
lemma is_bottom_int_dom_correct:
"is_bottom_int_dom d ⟷ gamma_int_dom d = {}"
proof -
let ?i =
"intersect_ivl
(interval_fact_of_sign (int_sign d))
(int_ivl d)"
let ?c =
"restrict_congruence_by_parity
(int_parity d)
(int_congruence d)"
have nonempty:
"ivl_congruence_nonempty ?i ?c ⟷
gamma_ivl ?i ∩ gamma_congruence ?c ≠ {}"
by (rule ivl_congruence_nonempty_correct)
have restricted:
"gamma_congruence ?c =
gamma_parity (int_parity d) ∩
gamma_congruence (int_congruence d)"
by simp
have interval:
"gamma_ivl ?i =
gamma_sign (int_sign d) ∩ gamma_ivl (int_ivl d)"
by (simp only: gamma_intersect_ivl_exact
gamma_interval_fact_of_sign)
show ?thesis
unfolding is_bottom_int_dom_def gamma_int_dom_def
using nonempty restricted interval by blast
qed
text ‹
Semantic fullness, symmetric to ‹is_bottom_int_dom› above: ‹d = top›
additionally pins the record's own ‹more› extension field to its top,
which ‹gamma_int_dom› never inspects, so it is strictly stronger than
‹gamma_int_dom d = UNIV› at this instance's actual, extension-polymorphic
‹'a int_dom_scheme› type. Testing each of the four concrete components'
own exact fullness instead reads off ‹gamma_int_dom›'s own definition
directly, the same move ‹is_bottom_int_dom› already makes for emptiness.
›
definition is_top_int_dom :: "'a int_dom_scheme => bool" where
"is_top_int_dom d ⟷
is_top_sign (int_sign d) ∧ is_top_ivl (int_ivl d) ∧
is_top_parity (int_parity d) ∧ is_top_congruence (int_congruence d)"
lemma is_top_int_dom_correct_gamma: "is_top_int_dom d ⟷ gamma_int_dom d = UNIV"
unfolding is_top_int_dom_def gamma_int_dom_def
using is_top_sign_correct_gamma is_top_ivl_correct_gamma
is_top_parity_correct_gamma is_top_congruence_correct_gamma
by auto
lemma gamma_int_dom_mono:
assumes ab: "a ≤ b"
shows "gamma_int_dom a ⊆ gamma_int_dom b"
proof -
from ab have le:
"int_sign a ≤ int_sign b"
"int_ivl a ≤ int_ivl b"
"int_parity a ≤ int_parity b"
"int_congruence a ≤ int_congruence b"
by (simp_all add: less_eq_int_dom_ext_def)
have S: "gamma_sign (int_sign a) ⊆ gamma_sign (int_sign b)"
using le(1) unfolding less_eq_sign_def by (rule gamma_sign_mono)
have I: "gamma_ivl (int_ivl a) ⊆ gamma_ivl (int_ivl b)"
using le(2) by (rule gamma_ivl_mono)
have P: "gamma_parity (int_parity a) ⊆ gamma_parity (int_parity b)"
using le(3) unfolding less_eq_parity_def by (rule gamma_parity_mono)
have C:
"gamma_congruence (int_congruence a) ⊆
gamma_congruence (int_congruence b)"
using le(4)
unfolding less_eq_congruence_iff_gamma .
show ?thesis
unfolding gamma_int_dom_def using S I P C by auto
qed
subsection ‹Constants and printing›
text ‹
‹int_dom_of_int› pins every component to one integer, so it concretizes
to exactly that singleton; the printer follows Goblint's tuple format.
›
definition int_dom_of_int :: "int => int_dom" where
"int_dom_of_int n =
(top :: int_dom)⦇
int_sign := sign_of_int n,
int_ivl := Ivl (Fin n) (Fin n),
int_parity := parity_of_int n,
int_congruence := congruence_of_int n
⦈"
lemma gamma_int_dom_of_int [simp]:
"gamma_int_dom (int_dom_of_int n) = {n}"
by (auto simp: int_dom_of_int_def gamma_int_dom_def
sign_of_int_gamma parity_of_int_gamma)
text ‹
Goblint's integer-domain tuple prints a value one of its components pins to a
single integer as that integer, a value no component constrains as ‹⊤›,
and anything else as its components, each named and separated by ‹;›. The
bottom test runs first, so a component that concretizes to one integer pins a
live product to exactly that integer.
›
fun ivl_constant :: "ivl ⇒ int option" where
"ivl_constant (Ivl (Fin l) (Fin u)) = (if l = u then Some l else None)"
| "ivl_constant _ = None"
definition congruence_constant :: "congruence ⇒ int option" where
"congruence_constant c =
(case Rep_congruence c of
Some (r, m) ⇒ if m = 0 then Some r else None
| None ⇒ None)"
definition int_dom_constant :: "'a int_dom_scheme ⇒ int option" where
"int_dom_constant d =
(if int_sign d = SZero then Some 0
else case ivl_constant (int_ivl d) of
Some n ⇒ Some n
| None ⇒ congruence_constant (int_congruence d))"
lemma gamma_ivl_constant:
"ivl_constant i = Some n ⟹ gamma_ivl i = {n}"
by (induction i rule: ivl_constant.induct) (auto split: if_splits)
lemma gamma_congruence_constant:
"congruence_constant c = Some n ⟹ gamma_congruence c = {n}"
unfolding congruence_constant_def gamma_congruence_def
by (auto split: option.splits if_splits)
text ‹Printing a live product as the integer \<^const>‹int_dom_constant› names
loses nothing: that integer is all the product denotes.›
lemma gamma_int_dom_constant_subset:
"int_dom_constant d = Some n ⟹ gamma_int_dom d ⊆ {n}"
using gamma_ivl_constant gamma_congruence_constant
unfolding int_dom_constant_def gamma_int_dom_def
by (auto split: if_splits option.splits)
definition string_of_int_dom :: "'a int_dom_scheme ⇒ String.literal" where
"string_of_int_dom d =
(if is_bottom_int_dom d then sym_bottom
else if is_top_int_dom d then sym_top
else case int_dom_constant d of
Some n ⇒ string_of_int n
| None ⇒
STR ''signs:'' + string_of_sign (int_sign d)
+ STR ''; intervals:'' + string_of_ivl (int_ivl d)
+ STR ''; parities:'' + string_of_parity (int_parity d)
+ STR ''; congruences:'' + string_of_congruence (int_congruence d))"
end