Theory Voblint_Analysis_Sign.Sign_Numeric_Queries

theory Sign_Numeric_Queries
  imports Sign_Backward
begin

section ‹Sign interpretation of the generic numeric-query interface›

text ‹
  ‹sound_numeric_queries› (theory‹Voblint_Domain.Numeric_Queries›) is
  the reusable interface; this theory supplies its Sign instance. None of the
  four query functions is a hand-built table: all four are Sign's instance of
  the generic derivations in locale‹sound_inverse_ops›'s own context ---
  ‹sign_less_true›/‹sign_less_false› read off ‹inv_less_sign›, ‹sign_eq_true›
  reads off ‹sign_less_false› in both directions, and ‹sign_eq_false› reads off
  ‹(⊓)› collapsing to ‹SBot› --- so their soundness is locale‹sound_inverse_ops›'s,
  instantiated by @{thm [source] sign_backward_domain}.
›

text ‹
  ‹sign_less_true_eq›/‹sign_less_false_eq›/‹sign_eq_true_eq›/‹sign_eq_false_eq›
  below restate each derived predicate as an explicit truth table over
  ‹inv_less_sign›/‹(⊓)›. They are the code equations of the four predicates, and
  they guard precision: a future change to
  ‹inv_less_sign›/‹inv_eq_sign›/‹(⊓)› that silently narrows or widens
  what these four predicates classify breaks one of these four proofs, at the
  seven-element lattice, rather than surfacing only as a precision regression
  in a downstream analysis.
›

subsection ‹Comparison judgments›

text ‹
  ‹sign_less_true a b› holds when every concrete pair ‹i ∈ gamma_sign a›,
  ‹j ∈ gamma_sign b› satisfies ‹i < j›; ‹sign_less_false a b› when every such
  pair satisfies ‹¬ i < j›. The two are not complements of each other:
  overlapping abstractions (e.g. ‹SNonPos› against ‹SNonNeg›) make both false,
  meaning unknown. ‹SBot› on either side makes both vacuously true.
›

definition sign_less_true :: "sign ⇒ sign ⇒ bool" where
  "sign_less_true = sound_inverse_ops.less_true inv_less_sign"

lemma sign_less_true_sound:
  assumes "sign_less_true a b" and "i ∈ gamma_sign a" and "j ∈ gamma_sign b"
  shows "i < j"
  using assms sound_inverse_ops.less_true_sound[OF
      sign_backward_domain[THEN mono_refinement.axioms(1), THEN sound_refinement.axioms(4)],
      of a b i j]
  by (simp add: sign_less_true_def)

definition sign_less_false :: "sign ⇒ sign ⇒ bool" where
  "sign_less_false = sound_inverse_ops.less_false inv_less_sign"

lemma sign_less_false_sound:
  assumes "sign_less_false a b" and "i ∈ gamma_sign a" and "j ∈ gamma_sign b"
  shows "¬ i < j"
  using assms sound_inverse_ops.less_false_sound[OF
      sign_backward_domain[THEN mono_refinement.axioms(1), THEN sound_refinement.axioms(4)],
      of a b i j]
  by (simp add: sign_less_false_def)

lemma sign_less_true_eq [code]: "sign_less_true a b ⟷
  (fst (inv_less_sign False a b) = SBot ∨ snd (inv_less_sign False a b) = SBot)"
  by (cases a; cases b;
      simp add: sign_less_true_def sound_inverse_ops.less_true_def[OF
        sign_backward_domain[THEN mono_refinement.axioms(1), THEN sound_refinement.axioms(4)]]
                bot_sign_def is_bottom_sign_def)

lemma sign_less_false_eq [code]: "sign_less_false a b ⟷
  (fst (inv_less_sign True a b) = SBot ∨ snd (inv_less_sign True a b) = SBot)"
  by (cases a; cases b;
      simp add: sign_less_false_def sound_inverse_ops.less_false_def[OF
        sign_backward_domain[THEN mono_refinement.axioms(1), THEN sound_refinement.axioms(4)]]
                bot_sign_def is_bottom_sign_def)

subsection ‹Equality judgments›

text ‹Only ‹SZero› concretizes to a singleton, so equality is provable exactly
  there; two abstractions are provably unequal exactly when their
  concretizations are disjoint. Neither table is hand-built: ‹sign_eq_true›
  is Sign's instance of the ‹eq_true› derivation off ‹less_false› in both
  directions (integer trichotomy), and ‹sign_eq_false› is Sign's instance of
  the ‹eq_false› derivation off ‹(⊓)› collapsing to ‹SBot› (disjoint
  concretizations).›

definition sign_eq_true :: "sign ⇒ sign ⇒ bool" where
  "sign_eq_true = sound_inverse_ops.eq_true inv_less_sign"

text ‹The derived definition unfolds through ‹less_false›'s global constant, so
  the code equation is stated over the Sign-level name directly.›

lemma sign_eq_true_eq [code]:
  "sign_eq_true a b ⟷ (sign_less_false a b ∧ sign_less_false b a)"
  by (simp add: sign_eq_true_def sign_less_false_def
    sound_inverse_ops.eq_true_def[OF
        sign_backward_domain[THEN mono_refinement.axioms(1), THEN sound_refinement.axioms(4)]])

lemma sign_eq_true_sound:
  assumes "sign_eq_true a b" and "i ∈ gamma_sign a" and "j ∈ gamma_sign b"
  shows "i = j"
  using assms sound_inverse_ops.eq_true_sound[OF
      sign_backward_domain[THEN mono_refinement.axioms(1), THEN sound_refinement.axioms(4)],
      of a b i j]
  by (simp add: sign_eq_true_def)

definition sign_eq_false :: "sign ⇒ sign ⇒ bool" where
  "sign_eq_false = sound_inverse_ops.eq_false inf"

lemma sign_eq_false_eq [code]: "sign_eq_false a b ⟷ a ⊓ b = SBot"
  by (cases a; cases b;
      simp add: sign_eq_false_def bot_sign_def sound_inverse_ops.eq_false_def[OF
        sign_backward_domain[THEN mono_refinement.axioms(1), THEN sound_refinement.axioms(4)]]
        is_bottom_sign_def)

lemma sign_eq_false_sound:
  assumes "sign_eq_false a b" and "i ∈ gamma_sign a" and "j ∈ gamma_sign b"
  shows "i ≠ j"
  using assms sound_inverse_ops.eq_false_sound[OF
      sign_backward_domain[THEN mono_refinement.axioms(1), THEN sound_refinement.axioms(4)],
      of a b i j]
  by (simp add: sign_eq_false_def)


subsection ‹Goblint-style optional-Boolean queries›

text ‹
  ‹sign_less›/‹sign_eq› are the generic packaging of the four judgments
  above, so one interpretation both introduces them and discharges the query
  interface. The ⬚‹defines› clause is what keeps them ordinary
  top-level constants, with the code equation the check layer needs.
›

global_interpretation sign_numeric_queries:
  numeric_query_judgments sign_less_true sign_less_false sign_eq_true sign_eq_false
  defines sign_less = sign_numeric_queries.query_less
    and sign_eq = sign_numeric_queries.query_eq
  by unfold_locales
     (auto intro: sign_less_true_sound sign_eq_true_sound
            dest: sign_less_false_sound sign_eq_false_sound)


end