Theory Negation_Type_Matching

theory Negation_Type_Matching
imports  "../Common/Negation_Type" Matching_Ternary "../Datatype_Selectors" Normalized_Matches
begin

section‹Negation Type Matching›


text‹Transform a @{typ "'a negation_type list"} to a @{typ "'a match_expr"} via conjunction.›
fun alist_and :: "'a negation_type list  'a match_expr" where
  "alist_and [] = MatchAny" |
  "alist_and ((Pos e)#es) = MatchAnd (Match e) (alist_and es)" |
  "alist_and ((Neg e)#es) = MatchAnd (MatchNot (Match e)) (alist_and es)"

lemma normalized_nnf_match_alist_and: "normalized_nnf_match (alist_and as)"
  by(induction as rule: alist_and.induct) simp_all

lemma alist_and_append: "matches γ (alist_and (l1 @ l2)) a p  matches γ  (MatchAnd (alist_and l1)  (alist_and l2)) a p"
  proof(induction l1)
  case Nil thus ?case by (simp add: bunch_of_lemmata_about_matches)
  next
  case (Cons l l1) thus ?case by (cases l) (simp_all add: bunch_of_lemmata_about_matches)
  qed

  text‹This version of @{const alist_and} avoids the trailing @{const MatchAny}. Only intended for code.›
  fun alist_and' :: "'a negation_type list  'a match_expr" where
    "alist_and' [] = MatchAny" |
    "alist_and' [Pos e] = Match e" |
    "alist_and' [Neg e] = MatchNot (Match e)"|
    "alist_and' ((Pos e)#es) = MatchAnd (Match e) (alist_and' es)" |
    "alist_and' ((Neg e)#es) = MatchAnd (MatchNot (Match e)) (alist_and' es)"

  lemma alist_and': "matches (γ, α) (alist_and' as) = matches (γ, α) (alist_and as)"
    by(induction as rule: alist_and'.induct) (simp_all add: bunch_of_lemmata_about_matches)
 
  lemma normalized_nnf_match_alist_and': "normalized_nnf_match (alist_and' as)"
    by(induction as rule: alist_and'.induct) simp_all

  lemma matches_alist_and_alist_and':
    "matches γ (alist_and' ls) a p  matches γ (alist_and ls) a p"
    apply(induction ls rule: alist_and'.induct)
    by(simp add: bunch_of_lemmata_about_matches)+

  lemma alist_and'_append: "matches γ (alist_and' (l1 @ l2)) a p  matches γ (MatchAnd (alist_and' l1) (alist_and' l2)) a p"
    proof(induction l1)
    case Nil thus ?case by (simp add: bunch_of_lemmata_about_matches)
    next
    case (Cons l l1) thus ?case
      apply (cases l)
       by(simp_all add: matches_alist_and_alist_and' bunch_of_lemmata_about_matches)
    qed

lemma alist_and_NegPos_map_getNeg_getPos_matches: 
  "(mset (getNeg spts). matches γ (MatchNot (Match (C m))) a p) 
   (mset (getPos spts). matches γ (Match (C m)) a p)
    
    matches γ (alist_and (NegPos_map C spts)) a p"
  proof(induction spts rule: alist_and.induct)
  qed(auto simp add: bunch_of_lemmata_about_matches)


fun negation_type_to_match_expr_f :: "('a  'b)  'a negation_type  'b match_expr" where
  "negation_type_to_match_expr_f f (Pos a) = Match (f a)" |
  "negation_type_to_match_expr_f f (Neg a) = MatchNot (Match (f a))"

lemma alist_and_negation_type_to_match_expr_f_matches:
    "matches γ (alist_and (NegPos_map C spts)) a p 
        (mset spts. matches γ (negation_type_to_match_expr_f C m) a p)"
  proof(induction spts rule: alist_and.induct)
  qed(auto simp add: bunch_of_lemmata_about_matches)

definition negation_type_to_match_expr :: "'a negation_type  'a match_expr" where
  "negation_type_to_match_expr m  negation_type_to_match_expr_f id m"

lemma negation_type_to_match_expr_simps:
  "negation_type_to_match_expr (Pos e) = (Match e)"
  "negation_type_to_match_expr (Neg e) = (MatchNot (Match e))"
by(simp_all add: negation_type_to_match_expr_def)

lemma alist_and_negation_type_to_match_expr: "alist_and (n#es) =  MatchAnd (negation_type_to_match_expr n) (alist_and es)"
  by(cases n, simp_all add: negation_type_to_match_expr_simps)


fun to_negation_type_nnf :: "'a match_expr  'a negation_type list" where
 "to_negation_type_nnf MatchAny = []" |
 "to_negation_type_nnf (Match a) = [Pos a]" |
 "to_negation_type_nnf (MatchNot (Match a)) = [Neg a]" |
 "to_negation_type_nnf (MatchAnd a b) = (to_negation_type_nnf a) @ (to_negation_type_nnf b)" |
 "to_negation_type_nnf _ = undefined"


lemma "normalized_nnf_match m  matches γ (alist_and (to_negation_type_nnf m)) a p  = matches γ m a p"
  proof(induction m rule: to_negation_type_nnf.induct)
  qed(simp_all add: bunch_of_lemmata_about_matches alist_and_append)


text‹Isolating the matching semantics›
fun nt_match_list :: "('a, 'packet) match_tac  action  'packet  'a negation_type list  bool" where
  "nt_match_list _ _ _ [] = True" |
  "nt_match_list γ a p ((Pos x)#xs)  matches γ (Match x) a p  nt_match_list γ a p xs" |
  "nt_match_list γ a p ((Neg x)#xs)  matches γ (MatchNot (Match x)) a p  nt_match_list γ a p xs"

lemma nt_match_list_matches: "nt_match_list γ a p l  matches γ (alist_and l) a p"
  apply(induction l rule: alist_and.induct)
    apply(case_tac [!] γ)
    apply(simp_all add: bunch_of_lemmata_about_matches)
  done


lemma nt_match_list_simp: "nt_match_list γ a p ms  
      (m  set (getPos ms). matches γ (Match m) a p)  (m  set (getNeg ms). matches γ (MatchNot (Match m)) a p)"
  proof(induction γ a p ms rule: nt_match_list.induct)
  case 3 thus ?case by fastforce
  qed(simp_all)

lemma matches_alist_and: "matches γ (alist_and l) a p  (m  set (getPos l). matches γ (Match m) a p)  (m  set (getNeg l). matches γ (MatchNot (Match m)) a p)"
  using nt_match_list_matches nt_match_list_simp by fast




end