Theory TopoS_Stateful_Policy_Algorithm

theory TopoS_Stateful_Policy_Algorithm
imports TopoS_Stateful_Policy TopoS_Composition_Theory
begin

section‹Stateful Policy -- Algorithm›

subsection‹Some unimportant lemmata›
  lemma False_set: "{(r, s). False} = {}" by simp
  lemma valid_reqs_ACS_D: "valid_reqs M  valid_reqs (get_ACS M)"
    by(simp add: valid_reqs_def get_ACS_def)
  lemma valid_reqs_IFS_D: "valid_reqs M  valid_reqs (get_IFS M)"
    by(simp add: valid_reqs_def get_IFS_def)
  lemma all_security_requirements_fulfilled_ACS_D: "all_security_requirements_fulfilled M G 
    all_security_requirements_fulfilled (get_ACS M) G"
    by(simp add: all_security_requirements_fulfilled_def get_ACS_def)
  lemma all_security_requirements_fulfilled_IFS_D: "all_security_requirements_fulfilled M G 
    all_security_requirements_fulfilled (get_IFS M) G"
    by(simp add: all_security_requirements_fulfilled_def get_IFS_def)
  lemma all_security_requirements_fulfilled_mono_stateful_policy_to_network_graph:
      " valid_reqs M; E'  E; wf_graph  nodes = V, edges = Efix  E     
        all_security_requirements_fulfilled M 
          (stateful_policy_to_network_graph  hosts = V, flows_fix = Efix, flows_state = E )
        all_security_requirements_fulfilled M 
          (stateful_policy_to_network_graph  hosts = V, flows_fix = Efix, flows_state = E' )"
    apply(simp add: stateful_policy_to_network_graph_def all_flows_def)
    apply(drule all_security_requirements_fulfilled_mono[where E="Efix  E  backflows E" and E'="Efix  E'  backflows E'" and V="V"])
       apply(thin_tac "wf_graph G" for G)
       apply(thin_tac "all_security_requirements_fulfilled M G" for M G)
       apply(simp add: backflows_def, blast)
      apply(thin_tac "all_security_requirements_fulfilled M G" for M G)
      apply(simp add: wf_graph_def)
      apply(simp add: backflows_def)
      using [[simproc add: finite_Collect]] apply(auto)[1]
     apply(simp_all)
   done


subsection ‹Sketch for generating a stateful policy from a simple directed policy›
  text‹Having no stateful flows, we trivially get a valid stateful policy.›
    lemma trivial_stateful_policy_compliance:
    " wf_graph  nodes = V, edges = E ; valid_reqs M; all_security_requirements_fulfilled M  nodes = V, edges = E    
      stateful_policy_compliance  hosts = V, flows_fix = E, flows_state = {}   nodes = V, edges = E  M"
      apply(unfold_locales)
                   apply(simp_all add: wf_graph_def stateful_policy_to_network_graph_def all_flows_def backflows_def False_set)
       apply(simp add: get_IFS_def get_ACS_def all_security_requirements_fulfilled_def)
      apply(clarify)
      apply(drule valid_reqs_ACS_D) 
      apply(drule all_security_requirements_fulfilled_ACS_D)
      apply(drule(1) all_security_requirements_fulfilled_imp_get_offending_empty)
      by force


  text‹trying better›

    text‹First, filtering flows that cause no IFS violations›
    (*the edges front of the list are more likely to be kept*)
    fun filter_IFS_no_violations_accu :: "'v::vertex graph  'v SecurityInvariant_configured list  ('v × 'v) list  ('v × 'v) list  ('v × 'v) list" where
      "filter_IFS_no_violations_accu G M accu [] = accu" |
      "filter_IFS_no_violations_accu G M accu (e#Es) = (if
        all_security_requirements_fulfilled (get_IFS M) (stateful_policy_to_network_graph  hosts = nodes G, flows_fix = edges G, flows_state = set (e#accu) )
        then filter_IFS_no_violations_accu G M (e#accu) Es
        else filter_IFS_no_violations_accu G M accu Es)"
    definition filter_IFS_no_violations :: "'v::vertex graph  'v SecurityInvariant_configured list  ('v × 'v) list  ('v × 'v) list" where
      "filter_IFS_no_violations G M Es = filter_IFS_no_violations_accu G M [] Es"


    lemma filter_IFS_no_violations_subseteq_input: "set (filter_IFS_no_violations G M Es)  set Es"
    apply(subgoal_tac " accu. set (filter_IFS_no_violations_accu G M accu Es)  set Es  set accu")
     apply(erule_tac x="[]" in allE)
     apply(simp add: filter_IFS_no_violations_def)
    unfolding filter_IFS_no_violations_def
    apply(induct_tac Es)
     apply(simp_all)
    apply force
    done
    lemma filter_IFS_no_violations_accu_correct_induction: "valid_reqs (get_IFS M)  wf_graph  nodes = V, edges = E  
            all_security_requirements_fulfilled (get_IFS M) (stateful_policy_to_network_graph  hosts = V, flows_fix = E, flows_state = set (accu) )  
            (set accu)  (set edgesList)  E  
            all_security_requirements_fulfilled (get_IFS M) (stateful_policy_to_network_graph  hosts = V, flows_fix = E, flows_state = set (filter_IFS_no_violations_accu  nodes = V, edges = E  M accu edgesList) )"
      apply(induction edgesList arbitrary: accu)
       by(simp_all)
    lemma filter_IFS_no_violations_correct: "valid_reqs (get_IFS M); wf_graph G;
            all_security_requirements_fulfilled (get_IFS M) G; 
            (set edgesList)  edges G   
            all_security_requirements_fulfilled (get_IFS M) (stateful_policy_to_network_graph  hosts = nodes G, flows_fix = edges G, flows_state = set (filter_IFS_no_violations G M edgesList) )"
    unfolding filter_IFS_no_violations_def
    apply(case_tac G, simp)
    apply(drule(1) filter_IFS_no_violations_accu_correct_induction[where accu="[]", simplified])
      apply(simp_all)
    by(simp add: stateful_policy_to_network_graph_def all_flows_def backflows_def False_set)
    lemma filter_IFS_no_violations_accu_no_IFS: "valid_reqs (get_IFS M)  wf_graph G  get_IFS M = [] 
            (set accu)  (set edgesList)  edges G  
            filter_IFS_no_violations_accu G M accu edgesList = rev(edgesList)@accu"
      apply(induction edgesList arbitrary: accu)
       by(simp_all add: all_security_requirements_fulfilled_def)


    lemma filter_IFS_no_violations_accu_maximal_induction: "valid_reqs (get_IFS M)  wf_graph  nodes = V, edges = E   
      set accu  E  set edgesList  E 
         e  E - (set accu  set edgesList).
            ¬ all_security_requirements_fulfilled (get_IFS M) (stateful_policy_to_network_graph  hosts = V, flows_fix = E, flows_state = {e}  (set accu) )
         
           let stateful = set (filter_IFS_no_violations_accu  nodes = V, edges = E  M accu edgesList) in
            ( e  E - stateful.
            ¬ all_security_requirements_fulfilled (get_IFS M) (stateful_policy_to_network_graph  hosts = V, flows_fix = E, flows_state = {e}  stateful ))"
      proof(induction edgesList arbitrary: accu)
      case Nil thus ?case by(simp add: Let_def)
      next
      case(Cons e Es)
        from Cons.prems(3) Cons.prems(2) have "fst ` set accu  V" and "snd ` set accu  V"
          by(auto simp add: wf_graph_def)
        ― ‹@{const wf_graph} for some complicated structures›
        from Cons.prems(2) this Cons.prems(4)  have "ea. eaE  wf_graph  nodes = V, edges = insert e (insert ea (set accu)) "
          by(auto simp add: wf_graph_def)
        from backflows_wf[OF this] wf_graph_union_edges[OF Cons.prems(2)]
        have "ea. eaE   wf_graph  nodes = V, edges = E  backflows (insert e (insert ea (set accu))) " by (simp)
        hence "ea. eaE  wf_graph  nodes = V, edges = E  set accu  backflows (insert e (insert ea (set accu))) " 
          by (metis Cons.prems(3) sup.order_iff)
        from this Cons.prems(4)
        have "ea. eaE  wf_graph  nodes = V, edges = insert e (insert ea (E  set accu  backflows (insert e (insert ea (set accu))))) "
          by(simp add: insert_absorb)
        hence validgraph1: "ea. eaE - (set (e # accu)  set Es)  
          wf_graph  nodes = V, edges = insert e (insert ea (E  set accu  backflows (insert e (insert ea (set accu))))) " by(simp)

        have validgraph2: " ea. 
         insert ea (E  set accu  backflows (insert ea (set accu)))  insert e (insert ea (E  set accu  backflows (insert e (insert ea (set accu)))))"
         apply(simp add: backflows_def)
         by blast
        
        from all_security_requirements_fulfilled_mono[OF Cons.prems(1) validgraph2 validgraph1] have neg_mono:
            "ea. ea  E - (set (e # accu)  set Es) 
         ¬ all_security_requirements_fulfilled (get_IFS M) 
            nodes = V, edges = insert ea (E  set accu  backflows (insert ea (set accu)))
         
         ¬ all_security_requirements_fulfilled (get_IFS M) 
            nodes = V, edges = insert e (insert ea (E  set accu  backflows (insert e (insert ea (set accu)))))"
           apply(simp)
           by blast

         from Cons.prems(5) have "ea. eaE - (set (e # accu)  set Es) 
          ¬ all_security_requirements_fulfilled (get_IFS M) (stateful_policy_to_network_graph 
              hosts = V, flows_fix = E, flows_state = {ea}  set (e # accu))"
           apply(erule_tac x="ea" in ballE)
           prefer 2
           apply simp
          apply(simp only: stateful_policy_to_network_graph_def all_flows_def stateful_policy.select_convs)
          apply(simp)
          apply(frule(1) neg_mono[simplified])
          by(simp)
         hence goalTrue:
          " eaE - (set (e # accu)  set Es). 
            ¬ all_security_requirements_fulfilled (get_IFS M) 
                (stateful_policy_to_network_graph hosts = V, flows_fix = E, flows_state = {ea}  set (e # accu))"
         by simp
         
        show ?case
        apply(simp add: Let_def)
        apply(rule conjI)

         apply(rule impI)
         apply(thin_tac "_") (*dont't need it*)
         using Cons.IH[where accu="e # accu", OF Cons.prems(1) Cons.prems(2) _ _ goalTrue, simplified Let_def] Cons.prems(3) Cons.prems(4)
         apply(auto) [1]

        apply(rule impI)
        using Cons.IH[where accu="accu", OF Cons.prems(1) Cons.prems(2), simplified Let_def] Cons.prems(5) Cons.prems(3) Cons.prems(4)
        apply(auto)
        done
     qed
    lemma filter_IFS_no_violations_maximal: "valid_reqs (get_IFS M); wf_graph G;
            (set edgesList) = edges G   
            let stateful = set (filter_IFS_no_violations G M edgesList) in 
             e  edges G - stateful.
              ¬ all_security_requirements_fulfilled (get_IFS M) (stateful_policy_to_network_graph  hosts = nodes G, flows_fix = edges G, flows_state = {e}  stateful )"
    unfolding filter_IFS_no_violations_def
    apply(case_tac G, simp)
    apply(drule(1) filter_IFS_no_violations_accu_maximal_induction[where accu="[]" and edgesList="edgesList"])
       by(simp_all)

    ― ‹It is not only maximal for single flows but all non-empty subsets›
    corollary filter_IFS_no_violations_maximal_allsubsets: 
    assumes a1: "valid_reqs (get_IFS M)"
    and     a2: "wf_graph G"
    and     a4: "(set edgesList) = edges G"
    shows   "let stateful = set (filter_IFS_no_violations G M edgesList) in 
             E  edges G - stateful. E  {} 
              ¬ all_security_requirements_fulfilled (get_IFS M) (stateful_policy_to_network_graph  hosts = nodes G, flows_fix = edges G, flows_state = E  stateful )"
    proof -
      let ?stateful = "set (filter_IFS_no_violations G M edgesList)"
      from filter_IFS_no_violations_maximal[OF a1 a2 a4] have not_fulfilled_single: 
        "eedges G - ?stateful. ¬ all_security_requirements_fulfilled (get_IFS M)
                (stateful_policy_to_network_graph hosts = nodes G, flows_fix = edges G, flows_state = {e}  ?stateful)"
        by(simp add: Let_def)
      have neg_mono:
        " e E. e  E  E  edges G - ?stateful  E  {} 
          ¬ all_security_requirements_fulfilled (get_IFS M) 
              (stateful_policy_to_network_graph hosts = nodes G, flows_fix = edges G, flows_state = {e}  ?stateful)  
          ¬ all_security_requirements_fulfilled (get_IFS M) 
              (stateful_policy_to_network_graph hosts = nodes G, flows_fix = edges G, flows_state = E  ?stateful)"
        proof -
          fix e E
          assume h1: "e  E"
          and    h2: "E  edges G - ?stateful"
          and    h3: "E  {}"
          and    h4: "¬ all_security_requirements_fulfilled (get_IFS M) 
            (stateful_policy_to_network_graph hosts = nodes G, flows_fix = edges G, flows_state = {e}  ?stateful)"
  
          from filter_IFS_no_violations_subseteq_input a4 have "?stateful  edges G" by blast
          hence "edges G  (E  ?stateful) = edges G" using h2 by blast
          from a2 this have validgraph1: "wf_graph nodes = nodes G, edges = edges G  (E  ?stateful)"
          by(case_tac G, simp)
  
          from h1 h2 h3 have subseteq: "({e}  ?stateful)  (E  ?stateful)" by blast

          have revimp: "A B. (A  B)  (¬ B  ¬ A)" by fast
          
          from all_security_requirements_fulfilled_mono_stateful_policy_to_network_graph[OF a1 subseteq validgraph1] h4
          show "¬ all_security_requirements_fulfilled (get_IFS M) 
            (stateful_policy_to_network_graph hosts = nodes G, flows_fix = edges G, flows_state = E  ?stateful)" 
            apply(rule revimp)
            by assumption
        qed
      
      show ?thesis
      proof(simp add: Let_def,rule allI,rule impI, rule impI)
        fix E
        assume h1: "E  edges G - ?stateful"
        and    h2: "E  {}"

        from  h1 h2 obtain e where e_prop1: "e  E" by blast 
        from this h1 have "e  edges G - ?stateful" by blast
        from this not_fulfilled_single have e_prop2: "¬ all_security_requirements_fulfilled (get_IFS M)
          (stateful_policy_to_network_graph hosts = nodes G, flows_fix = edges G, flows_state = {e}  ?stateful)"
          by simp
        
        from neg_mono[OF e_prop1 h1 h2 e_prop2]
        show " ¬ all_security_requirements_fulfilled (get_IFS M)
               (stateful_policy_to_network_graph hosts = nodes G, flows_fix = edges G, flows_state = E  set (filter_IFS_no_violations G M edgesList))"
        .
      qed
    qed
    
    ― ‹soundness and completeness›
    thm filter_IFS_no_violations_correct filter_IFS_no_violations_maximal





  text‹Next›
    (*"∀F ∈ get_offending_flows (get_ACS M) (stateful_policy_to_network_graph 𝒯 ). F ⊆ backflows (filternew_flows_state 𝒯)"*)
    (*first in list are more likely to be kept*)
    fun filter_compliant_stateful_ACS_accu :: "'v::vertex graph  'v SecurityInvariant_configured list  ('v × 'v) list  ('v × 'v) list  ('v × 'v) list" where
      "filter_compliant_stateful_ACS_accu G M accu [] = accu" |
      "filter_compliant_stateful_ACS_accu G M accu (e#Es) = (if
        e  backflows (edges G)  (F  get_offending_flows (get_ACS M) (stateful_policy_to_network_graph  hosts = nodes G, flows_fix = edges G, flows_state = set (e#accu) ). F  backflows (set (e#accu)))
        then filter_compliant_stateful_ACS_accu G M (e#accu) Es
        else filter_compliant_stateful_ACS_accu G M accu Es)"
    definition filter_compliant_stateful_ACS :: "'v::vertex graph  'v SecurityInvariant_configured list  ('v × 'v) list  ('v × 'v) list" where
      "filter_compliant_stateful_ACS G M Es = filter_compliant_stateful_ACS_accu G M [] Es"


    lemma filter_compliant_stateful_ACS_subseteq_input: "set (filter_compliant_stateful_ACS G M Es)  set Es"
      apply(subgoal_tac " accu. set (filter_compliant_stateful_ACS_accu G M accu Es)  set Es  set accu")
       apply(erule_tac x="[]" in allE)
       apply(simp add: filter_compliant_stateful_ACS_def)
      apply(induct_tac Es)
       apply(simp_all)
      apply (metis Un_insert_right set_simps(2) set_subset_Cons set_union subset_trans)
      done
    lemma filter_compliant_stateful_ACS_accu_correct_induction: "valid_reqs (get_ACS M)  wf_graph  nodes = V, edges = E  
            (set accu)  (set edgesList)  E  
            F  get_offending_flows (get_ACS M) (stateful_policy_to_network_graph  hosts = V, flows_fix = E, flows_state = set (accu) ). F  backflows (set accu)  
            (a  set accu. a  (backflows E)) 
            𝒯 =  hosts = V, flows_fix = E, flows_state = set (filter_compliant_stateful_ACS_accu  nodes = V, edges = E  M accu edgesList)  
            F  get_offending_flows (get_ACS M) (stateful_policy_to_network_graph 𝒯). F  backflows (filternew_flows_state 𝒯)"
      proof(induction edgesList arbitrary: accu)
        case Nil
          from Nil(5) have "backflows (set accu) = backflows {e  set accu. e  backflows E}" by (metis (lifting) Collect_cong Collect_mem_eq)
          from this Nil(4) have "Fget_offending_flows (get_ACS M) (stateful_policy_to_network_graph hosts = V, flows_fix = E, flows_state = set accu). F  backflows {e  set accu. e  backflows E}" by simp
          from this Nil(6) show ?case by(simp add: filternew_flows_state_alt2)
        next
        case (Cons e Es)
          from Cons.IH[OF Cons.prems(1) Cons.prems(2)] Cons.prems(3) Cons.prems(4) Cons.prems(5) Cons.prems(6)
          show ?case by(simp add: filternew_flows_state_alt2 split: if_split_asm)
      qed

    
    lemma filter_compliant_stateful_ACS_accu_no_side_effects: "valid_reqs (get_ACS M)  wf_graph G 
            F  get_offending_flows (get_ACS M) nodes = nodes G, edges = edges G  backflows (edges G). F  (backflows (edges G)) - (edges G) 
            (set accu)  (set edgesList)  edges G  
            (a  set accu. a  (backflows (edges G))) 
            filter_compliant_stateful_ACS_accu G M accu edgesList = rev([ e  edgesList. e  backflows (edges G)])@accu"
      apply(simp add: backflows_minus_backflows)
      apply(induction edgesList arbitrary: accu)
       apply(simp)
      apply(simp add: stateful_policy_to_network_graph_def all_flows_def)
      apply(rule impI)
      apply(case_tac G, simp, rename_tac V E)
      thm Un_set_offending_flows_bound_minus_subseteq'[where X="backflows E - E" and E="E  backflows E"]
      apply(drule_tac X="backflows E - E" and E="E  backflows E" and E'="(E  backflows E) - (insert a (E  set accu  backflows (insert a (set accu))))" in Un_set_offending_flows_bound_minus_subseteq')
         defer
         prefer 2
         apply blast
        apply auto[1]
       apply(subgoal_tac "E  backflows E - (E  backflows E - insert a (E  set accu  backflows (insert a (set accu)))) = insert a (E  set accu  backflows (insert a (set accu)))")
        apply(simp)
        prefer 2
        apply (metis Un_assoc Un_least Un_mono backflows_subseteq double_diff insert_def insert_subset subset_refl)
       apply(subgoal_tac "backflows (insert a (set accu))  backflows E - E - (E  backflows E - insert a (E  set accu  backflows (insert a (set accu))))")
        apply(blast)
       apply(simp add: backflows_def)
       apply fast
      using FiniteGraph.backflows_wf FiniteGraph.wf_graph_union_edges by metis



    lemma filter_compliant_stateful_ACS_correct: 
      assumes a1: "valid_reqs (get_ACS M)"
      and     a2: "wf_graph G"
      and     a3: "set edgesList  edges G"  
      and     a4: "all_security_requirements_fulfilled (get_ACS M) G"
      and     a5: "𝒯 =  hosts = nodes G, flows_fix = edges G, flows_state = set (filter_compliant_stateful_ACS G M edgesList) "
      shows   "F  get_offending_flows (get_ACS M) (stateful_policy_to_network_graph 𝒯). F  backflows (filternew_flows_state 𝒯)"
      proof -
        obtain V E where VE: "G =  nodes = V, edges = E " by(case_tac G, blast)
        from VE a2 have wfVE: "wf_graph  nodes = V, edges = E " by simp
        from VE a3 have "set edgesList  E" by simp

        from a5 VE have a5': "𝒯 = hosts = V, flows_fix = E, flows_state = set (filter_compliant_stateful_ACS_accu nodes = V, edges = E M [] edgesList)"
          unfolding filter_compliant_stateful_ACS_def
          by(simp)

        from all_security_requirements_fulfilled_imp_get_offending_empty[OF a1 a4] VE
        have "Fget_offending_flows (get_ACS M) (stateful_policy_to_network_graph hosts = V, flows_fix = E, flows_state = {}). F  backflows {}"
          by(simp add: stateful_policy_to_network_graph_def all_flows_def backflows_def False_set)

        from filter_compliant_stateful_ACS_accu_correct_induction[where accu="[]" and edgesList="edgesList", simplified, OF a1 wfVE set edgesList  E this a5']
        show ?thesis .
     qed


    lemma filter_compliant_stateful_ACS_accu_induction_maximal:" valid_reqs (get_ACS M);  wf_graph  nodes = V, edges = E ;
            (set edgesList)  E;
            (set accu)  E; 
            stateful = set (filter_compliant_stateful_ACS_accu  nodes = V, edges = E  M accu edgesList);
            e  E - (set edgesList  set accu  {e  E. e  backflows E}).
            ¬ (get_offending_flows (get_ACS M) (stateful_policy_to_network_graph  hosts = V, flows_fix = E, flows_state = set accu  {e} ))
                 backflows (filternew_flows_state  hosts = V, flows_fix = E, flows_state = set accu  {e} )
             
            e  E - (stateful  {e  E. e  backflows E}). ⌦‹E - {computed stateful flows plus trivial stateful flows}›
            ¬ (get_offending_flows (get_ACS M) (stateful_policy_to_network_graph  hosts = V, flows_fix = E, flows_state = stateful  {e} ))
                 backflows (filternew_flows_state  hosts = V, flows_fix = E, flows_state = stateful  {e} )"
   proof(induction edgesList arbitrary: accu E)
   case Nil from Nil(5)[simplified] Nil(6) show ?case by(simp)
   next
   case (Cons a Es)
     ― ‹case distinction›
     let ?caseDistinction="a  backflows (E)   (Fget_offending_flows (get_ACS M)
                 (stateful_policy_to_network_graph hosts = V, flows_fix = E, flows_state = set (a # accu)).
                    F  backflows (set (a # accu)))"
     from Cons.prems(3) have "set Es  E" by simp

     show ?case
      proof(cases ?caseDistinction)
        assume CaseTrue: ?caseDistinction
        from CaseTrue have 
          "set (filter_compliant_stateful_ACS_accu nodes = V, edges = E M accu (a # Es)) = 
           set (filter_compliant_stateful_ACS_accu nodes = V, edges = E M (a # accu) Es)"
           by(simp)
        from this Cons.prems(5) have statefulsimp:
          "stateful = set (filter_compliant_stateful_ACS_accu nodes = V, edges = E M (a # accu) Es)" by simp
        from Cons.prems(3) Cons.prems(4) have "set (a # accu)  E" by simp

        have "eE - (set Es  set (a # accu)  {e  E. e  backflows E}).
     ¬ (get_offending_flows (get_ACS M) (stateful_policy_to_network_graph hosts = V, flows_fix = E, flows_state = set (a # accu)  {e}))
         backflows (filternew_flows_state hosts = V, flows_fix = E, flows_state = set (a # accu)  {e})"
          proof(rule ballI)
            fix e
            assume h1: "e  E - (set Es  set (a # accu)  {e  E. e  backflows E})"

            from conjunct1[OF CaseTrue] have filternew_flows_state_moveout_a:
              "filternew_flows_state hosts = V, flows_fix = E, flows_state = set (a # accu)  {e} = 
              {a}  filternew_flows_state hosts = V, flows_fix = E, flows_state = set accu  {e}"
              apply(simp add: filternew_flows_state_alt) by blast

            have backflowssubseta: "X. backflows X  backflows ({a}  X)" by(simp add: backflows_def, blast)

            from Cons.prems(6) h1 have 
              "¬ (get_offending_flows (get_ACS M) (stateful_policy_to_network_graph hosts = V, flows_fix = E, flows_state = set accu  {e}))
                 backflows (filternew_flows_state hosts = V, flows_fix = E, flows_state = set accu  {e})" by simp
            from this obtain dat_offender where 
              dat_in: "dat_offender  (get_offending_flows (get_ACS M) (stateful_policy_to_network_graph hosts = V, flows_fix = E, flows_state = set accu  {e}))"
              and dat_offends: "dat_offender  backflows (filternew_flows_state hosts = V, flows_fix = E, flows_state = set accu  {e})" by blast

            have wfGraphA: "wf_graph (stateful_policy_to_network_graph hosts = V, flows_fix = E, flows_state = set (a # accu)  {e})"
              proof(simp add: stateful_policy_to_network_graph_def all_flows_def)
              from Cons.prems(2) h1 Cons.prems(3) Cons.prems(4)
              have "wf_graph nodes=V, edges = insert e (insert a (set accu)) " 
              apply(auto simp add: wf_graph_def) by force
              from this backflows_wf
              have vgh1: "wf_graph nodes = V, edges = backflows (insert e (insert a (set accu)))" by auto
              from Cons.prems(2) wf_graph_add_subset_edges h1  Cons.prems(3) Cons.prems(4)
              have vgh2: "wf_graph nodes = V, edges = insert e ((insert a E)  set accu)"
                proof -
                  have f1: "e  E - (set Es  insert a (set accu)  {R  E. R  backflows E})"
                    using h1 by simp
                  have f2: "insert a (set accu)  E"
                    using set (a # accu)  E by simp
                  have f3: "e  E"
                    using f1 by fastforce
                  have "E  insert a (set accu) = E"
                    using f2 by fastforce
                  thus "wf_graph nodes = V, edges = insert e (insert a E  set accu)"
                    using f3 Cons.prems(2) Un_insert_right insert_absorb sup_commute by fastforce
                qed
              from vgh1 vgh2 wf_graph_union_edges
              show "wf_graph nodes = V, edges = insert e (insert a (E  set accu  backflows (insert e (insert a (set accu)))))" by fastforce
           qed
            
            from dat_in have dat_in_simplified: 
              "dat_offender  (get_offending_flows (get_ACS M) nodes = V, edges = insert e (E  set accu  backflows (insert e (set accu))))"
              by(simp add: stateful_policy_to_network_graph_def all_flows_def)

            have subsethlp: "insert e (E  set accu  backflows (insert e (set accu)))  E  (set (a # accu)  {e})  backflows (set (a # accu)  {e})"
              apply(simp)
              apply(rule, blast)
              apply(rule, blast)
              apply(rule)
              apply(simp add: backflows_def, fast)
              done

            from get_offending_flows_union_mono[OF 
                Cons.prems(1) 
                wfGraphA[simplified stateful_policy_to_network_graph_def all_flows_def graph.select_convs stateful_policy.select_convs],
                OF subsethlp]
            dat_in_simplified have dat_in_a: "dat_offender  (get_offending_flows (get_ACS M) 
              (stateful_policy_to_network_graph hosts = V, flows_fix = E, flows_state = set (a # accu)  {e}))"
              by(simp add: stateful_policy_to_network_graph_def all_flows_def, fast)

            have "dat_offender  (snd a, fst a)"
              proof(rule ccontr)
              assume "¬ dat_offender  (snd a, fst a)"
              hence hlpassm: "dat_offender = (snd a, fst a)" by simp
              from this obtain a1 a2 where "dat_offender = (a2, a1)" by blast
              
              
              have "(get_offending_flows (get_ACS M) nodes = V, edges = insert e (E  set accu  backflows (insert e (set accu))))  
                  insert e (E  set accu  backflows (insert e (set accu)))"
                by (metis Cons.prems(1) Sup_le_iff get_offending_flows_subseteq_edges)
              from this h1 have UN_get_subset: 
                    "(get_offending_flows (get_ACS M) nodes = V, edges = insert e (E  set accu  backflows (insert e (set accu))))  
                   (E  set accu  backflows (insert e (set accu)))"
                by blast

            from dat_offends have dat_offends_simplified: 
              "dat_offender  backflows (insert e (set accu)) - E"
                by(simp only: filternew_flows_state_alt stateful_policy.select_convs backflows_minus_backflows, simp)
              
              from conjunct1[OF CaseTrue] hlpassm have "dat_offender  E"
                by(simp add: backflows_def, fastforce)
              from dat_in_simplified UN_get_subset this have "dat_offender  set accu  backflows (insert e (set accu))" by blast
              from this Cons.prems(4) dat_offender  E have "dat_offender  backflows (insert e (set accu))" by blast
              from dat_offends_simplified[simplified] this have "dat_offender  E" by simp
              from dat_offender  E dat_offender  E show False by simp
            qed

            from this dat_offends have 
              "dat_offender  backflows ({a}  filternew_flows_state hosts = V, flows_fix = E, flows_state = set accu  {e})"
              apply(simp add: backflows_def) by force

            from dat_in_a this
            show "¬ (get_offending_flows (get_ACS M) (stateful_policy_to_network_graph hosts = V, flows_fix = E, flows_state = set (a # accu)  {e}))
             backflows (filternew_flows_state hosts = V, flows_fix = E, flows_state = set (a # accu)  {e})"
            apply(subst filternew_flows_state_moveout_a) by blast
          qed

        from Cons.IH[OF Cons.prems(1) Cons.prems(2) set Es  E set (a # accu)  E statefulsimp this ] show "?case" 
          by(simp)
      next
        assume CaseFalse: "¬ ?caseDistinction"

        from CaseFalse have funapplysimp: 
          "set (filter_compliant_stateful_ACS_accu nodes = V, edges = E M accu (a # Es)) = 
           set (filter_compliant_stateful_ACS_accu nodes = V, edges = E M accu Es)"
           by auto
        from this Cons.prems(5) have statefulsimp:
          "stateful = set (filter_compliant_stateful_ACS_accu nodes = V, edges = E M accu Es)" by simp
        from Cons.prems(4) have "set accu  E" .

        have "a  E - (set Es  set accu  {e  E. e  backflows E}) ¬ (get_offending_flows (get_ACS M) (stateful_policy_to_network_graph hosts = V, flows_fix = E, flows_state = set accu  {a}))
           backflows (filternew_flows_state hosts = V, flows_fix = E, flows_state = set accu  {a})"
          proof(rule ccontr)
            assume h1: "a  E - (set Es  set accu  {e  E. e  backflows E})"
            and    "¬ ¬(get_offending_flows (get_ACS M) (stateful_policy_to_network_graph hosts = V, flows_fix = E, flows_state = set accu  {a}))  backflows (filternew_flows_state hosts = V, flows_fix = E, flows_state = set accu  {a})"
            hence hccontr: "(get_offending_flows (get_ACS M) (stateful_policy_to_network_graph hosts = V, flows_fix = E, flows_state = set accu  {a}))  backflows (filternew_flows_state hosts = V, flows_fix = E, flows_state = set accu  {a})" by simp

            moreover from h1 have stateful_to_graph: "stateful_policy_to_network_graph hosts = V, flows_fix = E, flows_state = set accu  {a} =  nodes = V, edges = E  set accu  backflows (insert a (set accu))"
              by(simp add: stateful_policy_to_network_graph_def all_flows_def, blast)
            moreover have "backflows (filternew_flows_state hosts = V, flows_fix = E, flows_state = set accu  {a}) = backflows (insert a (set accu)) - E"
              by(simp add: filternew_flows_state_alt backflows_minus_backflows)
            ultimately have hccontr_simp:
              "(get_offending_flows (get_ACS M) nodes = V, edges = E  set accu  backflows (insert a (set accu)))  backflows (insert a (set accu)) - E" by simp

            from Cons.prems(3) Cons.prems(4) have backaaccusubE: "backflows (set (a # accu))  backflows E" by(simp add: backflows_def, fastforce)
            from h1 have "a  backflows E" by fastforce
            from backaaccusubE a  backflows E have "a  backflows (insert a (set accu))" by auto


            from a  backflows E CaseFalse have "¬ (Fget_offending_flows (get_ACS M) (stateful_policy_to_network_graph hosts = V, flows_fix = E, flows_state = set (a # accu)). F  backflows (set (a # accu)))" by(simp)
            from this stateful_to_graph have "¬ (Fget_offending_flows (get_ACS M) nodes = V, edges = E  set accu  backflows (insert a (set accu)). F  backflows (insert a (set accu)))" by(simp)
            from this hccontr_simp show False by blast
        qed
        from  Cons.prems(6)[simplified funapplysimp statefulsimp] this
        have "eE - (set Es  set accu  {e  E. e  backflows E}).
       ¬ (get_offending_flows (get_ACS M) (stateful_policy_to_network_graph hosts = V, flows_fix = E, flows_state = set accu  {e}))
           backflows (filternew_flows_state hosts = V, flows_fix = E, flows_state = set accu  {e})"
          by auto

        from Cons.IH[OF Cons.prems(1) Cons.prems(2) set Es  E set accu  E statefulsimp this]
        show ?case by simp
      qed
   qed






   

    lemma filter_compliant_stateful_ACS_maximal: " valid_reqs (get_ACS M); wf_graph  nodes = V, edges = E ;
            (set edgesList) = E;
            stateful = set (filter_compliant_stateful_ACS  nodes = V, edges = E  M edgesList)
             
            e  E - (stateful  {e  E. e  backflows E}). ⌦‹E - {computed stateful flows plus trivial stateful flows}›
            ¬  (get_offending_flows (get_ACS M) (stateful_policy_to_network_graph  hosts = V, flows_fix = E, flows_state = stateful  {e} ))
                 backflows (filternew_flows_state  hosts = V, flows_fix = E, flows_state = stateful  {e} )"
    apply(drule(1) filter_compliant_stateful_ACS_accu_induction_maximal[where accu="[]", simplified])
       apply(blast)
      apply(simp add: filter_compliant_stateful_ACS_def)
     apply(simp)
     apply fastforce
    apply(simp add: filter_compliant_stateful_ACS_def)
   done


    lemma filter_compliant_stateful_ACS_maximal_allsubsets:
      assumes a1: "valid_reqs (get_ACS M)" and a2: "wf_graph  nodes = V, edges = E "
      and a3: "(set edgesList) = E"
      and a4: "stateful = set (filter_compliant_stateful_ACS  nodes = V, edges = E  M edgesList)"
      and a5: "X  E - (stateful  backflows E)" and a6: "X  {}"
      shows "
      ¬ (get_offending_flows (get_ACS M) (stateful_policy_to_network_graph  hosts = V, flows_fix = E, flows_state = stateful  X ))
                 backflows (filternew_flows_state  hosts = V, flows_fix = E, flows_state = stateful  X )"
    proof(rule ccontr, simp)
      from a5 have "X  E" by blast
      assume accontr: "(get_offending_flows (get_ACS M) (stateful_policy_to_network_graph hosts = V, flows_fix = E, flows_state = stateful  X))  backflows (filternew_flows_state hosts = V, flows_fix = E, flows_state = stateful  X)"
      hence "(get_offending_flows (get_ACS M) nodes = V, edges = E  (stateful  X)  backflows (stateful  X))  backflows (stateful  X) - E"
      by(simp add: stateful_policy_to_network_graph_def all_flows_def filternew_flows_state_alt backflows_minus_backflows)
      hence "(get_offending_flows (get_ACS M) nodes = V, edges = E  X  backflows (stateful  X))  backflows (stateful  X) - E"
      using a4 a3 filter_compliant_stateful_ACS_subseteq_input by (metis Diff_subset_conv Un_Diff_cancel Un_assoc a3 bot.extremum_unique sup_bot_right)
      hence accontr_simp: "(get_offending_flows (get_ACS M) nodes = V, edges = E  (backflows stateful)  (backflows X))  backflows (stateful  X) - E"
      using Set.Un_absorb2[OF X  E] backflows_un[of "stateful" "X"] by (metis Un_assoc)
      
      from a2 a5 have "finite X" apply(simp add: wf_graph_def) by (metis (full_types) finite_Diff finite_subset)
      from a6 obtain x where "x  X" by blast


      from x  X a5 have xX_simp1: "(backflows X) - (backflows (X - {x}) - E)  = backflows {x}"
        apply(simp add: backflows_def) by fast
      from a5 have "X  stateful = {}" by auto
      from x  X this have xX_simp2: "(backflows stateful) - (backflows (X - {x}) - E) = backflows stateful"
        apply(simp add: backflows_def) by fast
      have xX_simp3:"backflows (stateful  X) - (backflows (X - {x}) - E) = backflows (stateful  {x})"
        apply(simp only: backflows_un)
        using xX_simp1 xX_simp2 by blast

      have xX_simp4: "backflows (stateful  X) - E - (backflows (X - {x}) - E) = backflows (filternew_flows_state hosts = V, flows_fix = E, flows_state = stateful  {x})"
        apply(simp add: filternew_flows_state_alt backflows_minus_backflows)
        using xX_simp3 by auto


      have xX_simp5: "(E  backflows stateful  backflows X) - (backflows (X - {x}) - E) = E  backflows stateful  backflows {x}"
      using xX_simp3[simplified backflows_un] by blast

      have Eexpand: "E  stateful  {x} = E" 
      using a4 a3 filter_compliant_stateful_ACS_subseteq_input a5 xX by blast

      have "backflows (stateful  X) - E - backflows (X - {x}) = (backflows (stateful  X) - E) - backflows (X - {x})" by simp
      from finite X backflows_finite have finite: "finite (backflows (X - {x}) - E)" by auto
      from a2 a4 a3 filter_compliant_stateful_ACS_subseteq_input have "wf_graph nodes = V, edges = stateful" by (metis Diff_partition wf_graph_remove_edges_union)
      from backflows_wf[OF this] have "wf_graph nodes = V, edges = backflows stateful" .
      from a2 X  E have "wf_graph nodes = V, edges = X" by (metis double_diff dual_order.refl wf_graph_remove_edges)
       from backflows_wf[OF this] have "wf_graph nodes = V, edges = backflows X" .
      from this wf_graph_union_edges wf_graph nodes = V, edges = backflows stateful a2 have wfG: 
        "wf_graph nodes = V, edges = E  backflows stateful  backflows X" by metis

      from xX have subset: "backflows (X - {x}) - E  E  backflows stateful  backflows X" apply(simp add: backflows_def) by fast

      from Un_set_offending_flows_bound_minus_subseteq'[OF a1 wfG subset accontr_simp] have
        "(get_offending_flows (get_ACS M) nodes = V, edges = (E  backflows stateful  backflows X) - (backflows (X - {x}) - E))  (backflows (stateful  X) - E) - (backflows (X - {x}) - E)" by simp
      from this xX_simp4 xX_simp5 have trans1:
        "(get_offending_flows (get_ACS M) nodes = V, edges = E  backflows stateful  backflows {x})  backflows (filternew_flows_state hosts = V, flows_fix = E, flows_state = stateful  {x})" by simp

      hence "(get_offending_flows (get_ACS M) nodes = V, edges = E  backflows (stateful  {x}))  backflows (filternew_flows_state hosts = V, flows_fix = E, flows_state = stateful  {x})"
      apply(simp only: backflows_un) by (metis Un_assoc)
      hence contr1: "(get_offending_flows (get_ACS M) (stateful_policy_to_network_graph hosts = V, flows_fix = E, flows_state = stateful  {x}))  backflows (filternew_flows_state hosts = V, flows_fix = E, flows_state = stateful  {x})"
      apply(simp only: stateful_policy_to_network_graph_def all_flows_def stateful_policy.select_convs)
      using Eexpand by (metis Un_assoc)
      

      from filter_compliant_stateful_ACS_maximal[OF a1 a2 a3 a4] have
        "eE - (stateful  {e  E. e  backflows E}). ¬ (get_offending_flows (get_ACS M) (stateful_policy_to_network_graph hosts = V, flows_fix = E, flows_state = stateful  {e}))  backflows (filternew_flows_state hosts = V, flows_fix = E, flows_state = stateful  {e})" .
      from this a5 x  X have contr2: "¬ (get_offending_flows (get_ACS M) (stateful_policy_to_network_graph hosts = V, flows_fix = E, flows_state = stateful  {x}))  backflows (filternew_flows_state hosts = V, flows_fix = E, flows_state = stateful  {x})" by blast

      from contr1 contr2
      show "False" by simp
    qed


    text@{term filter_compliant_stateful_ACS} is correct and maximal›
    thm filter_compliant_stateful_ACS_correct filter_compliant_stateful_ACS_maximal


    text‹Getting those together. We cannot say edgesList = E› here because one filters first. I guess filtering ACS first is easier, ...›










  definition generate_valid_stateful_policy_IFSACS :: "'v::vertex graph  'v SecurityInvariant_configured list  ('v × 'v) list  'v stateful_policy" where
    "generate_valid_stateful_policy_IFSACS G M edgesList  (let filterIFS = filter_IFS_no_violations G M edgesList in
        (let filterACS = filter_compliant_stateful_ACS G M filterIFS in  hosts = nodes G, flows_fix = edges G, flows_state = set filterACS ))"

  lemma generate_valid_stateful_policy_IFSACS_wf_stateful_policy: assumes wfG: "wf_graph G"
          and     edgesList: "(set edgesList) = edges G"
          shows "wf_stateful_policy (generate_valid_stateful_policy_IFSACS G M edgesList)"
   proof -
    from  wfG show ?thesis
     apply(simp add: generate_valid_stateful_policy_IFSACS_def wf_stateful_policy_def)
     apply(auto simp add: wf_graph_def)
     using edgesList filter_IFS_no_violations_subseteq_input filter_compliant_stateful_ACS_subseteq_input by (metis rev_subsetD)
   qed

   lemma generate_valid_stateful_policy_IFSACS_select_simps:
   shows "hosts (generate_valid_stateful_policy_IFSACS G M edgesList) = nodes G"
   and   "flows_fix (generate_valid_stateful_policy_IFSACS G M edgesList) = edges G"
   and   "flows_state (generate_valid_stateful_policy_IFSACS G M edgesList)  set edgesList"
   proof -
   show  "hosts (generate_valid_stateful_policy_IFSACS G M edgesList) = nodes G"
      by(simp add: generate_valid_stateful_policy_IFSACS_def)
    show "flows_fix (generate_valid_stateful_policy_IFSACS G M edgesList) = edges G"
      by(simp add: generate_valid_stateful_policy_IFSACS_def)
    show "flows_state (generate_valid_stateful_policy_IFSACS G M edgesList)  set edgesList"
      apply(simp add: generate_valid_stateful_policy_IFSACS_def)
      using filter_IFS_no_violations_subseteq_input filter_compliant_stateful_ACS_subseteq_input by (metis subset_trans)
    qed

  lemma generate_valid_stateful_policy_IFSACS_all_security_requirements_fulfilled_IFS: assumes validReqs: "valid_reqs M"
          and     wfG: "wf_graph G"
          and     high_level_policy_valid: "all_security_requirements_fulfilled M G"
          and     edgesList: "(set edgesList)  edges G"
          shows "all_security_requirements_fulfilled (get_IFS M) (stateful_policy_to_network_graph (generate_valid_stateful_policy_IFSACS G M edgesList))"
  proof -
   have simp3: "flows_state (generate_valid_stateful_policy_IFSACS G M edgesList)  edges G" using generate_valid_stateful_policy_IFSACS_select_simps(3) edgesList by fast

    have "set (filter_compliant_stateful_ACS G M (filter_IFS_no_violations G M edgesList))  set (filter_IFS_no_violations G M edgesList)"
      using filter_compliant_stateful_ACS_subseteq_input edgesList by (metis)
    from backflows_subseteq this have 
      "backflows (set (filter_compliant_stateful_ACS G M (filter_IFS_no_violations G M edgesList)))  backflows (set (filter_IFS_no_violations G M edgesList))" by metis
    hence subseteqhlp1:
      "edges G  backflows (set (filter_compliant_stateful_ACS G M (filter_IFS_no_violations G M edgesList)))  edges G  backflows (set (filter_IFS_no_violations G M edgesList))" by blast

    from high_level_policy_valid have "all_security_requirements_fulfilled (get_IFS M) G" by(simp add: all_security_requirements_fulfilled_def get_IFS_def)
    from filter_IFS_no_violations_correct[OF valid_reqs_IFS_D[OF validReqs] wfG this edgesList] have 
      "all_security_requirements_fulfilled (get_IFS M) (stateful_policy_to_network_graph hosts = nodes G, flows_fix = edges G, flows_state = set (filter_IFS_no_violations G M edgesList))" .
      from this edgesList have goalIFS:
        "all_security_requirements_fulfilled (get_IFS M) nodes = nodes G, edges = edges G  backflows (set (filter_IFS_no_violations G M edgesList))"
        apply(simp add: stateful_policy_to_network_graph_def all_flows_def)
        by (metis Un_absorb2 filter_IFS_no_violations_subseteq_input order_trans)


      from  wfG filter_IFS_no_violations_subseteq_input[where Es="edgesList" and G="G" and M="M"] edgesList have 
        "wf_graph nodes = nodes G, edges = set (filter_IFS_no_violations G M edgesList)" 
         apply(case_tac G, simp)
         by (metis le_iff_sup wf_graph_remove_edges_union)
      from backflows_wf[OF this] have
        "wf_graph nodes = nodes G, edges = backflows (set (filter_IFS_no_violations G M edgesList))" by(simp)
      from this wf_graph_union_edges wfG have 
        "wf_graph nodes = nodes G, edges = edges G  backflows (set (filter_IFS_no_violations G M edgesList))" 
        by (metis graph.cases graph.select_convs(1) graph.select_convs(2))

      from all_security_requirements_fulfilled_mono[OF valid_reqs_IFS_D[OF validReqs] subseteqhlp1 this goalIFS]
        have "all_security_requirements_fulfilled (get_IFS M) nodes = nodes G, edges = edges G  backflows (set (filter_compliant_stateful_ACS G M (filter_IFS_no_violations G M edgesList)))"
        .
      thus ?thesis
        apply(simp add: stateful_policy_to_network_graph_def all_flows_def generate_valid_stateful_policy_IFSACS_select_simps simp3 Un_absorb2)
        by(simp add: generate_valid_stateful_policy_IFSACS_def)
  qed

  theorem generate_valid_stateful_policy_IFSACS_stateful_policy_compliance:
  assumes validReqs: "valid_reqs M"
        and     wfG: "wf_graph G"
        and     high_level_policy_valid: "all_security_requirements_fulfilled M G"
        and     edgesList: "(set edgesList) = edges G"
        and     Tau: "𝒯 = generate_valid_stateful_policy_IFSACS G M edgesList"
    shows "stateful_policy_compliance 𝒯 G M"
    proof -
      have 1: "wf_stateful_policy 𝒯"
        apply(simp add: Tau)
        by(simp add: generate_valid_stateful_policy_IFSACS_wf_stateful_policy[OF wfG edgesList])
      have 2: "wf_stateful_policy (generate_valid_stateful_policy_IFSACS G M edgesList)"
        by(simp add: generate_valid_stateful_policy_IFSACS_wf_stateful_policy[OF wfG edgesList])
      have 3: "hosts 𝒯 = nodes G"
        apply(simp add: Tau)
        by(simp add: generate_valid_stateful_policy_IFSACS_select_simps(1))
      have 4: "flows_fix 𝒯  edges G"
        apply(simp add: Tau)
        by(simp add: generate_valid_stateful_policy_IFSACS_select_simps(2))
      have 5: " all_security_requirements_fulfilled (get_IFS M) (stateful_policy_to_network_graph 𝒯)"
        apply(simp add: Tau)
        using generate_valid_stateful_policy_IFSACS_all_security_requirements_fulfilled_IFS[OF validReqs wfG high_level_policy_valid] edgesList by blast
      have 6: "Fget_offending_flows (get_ACS M) (stateful_policy_to_network_graph 𝒯). F  backflows (filternew_flows_state 𝒯)"
        using filter_compliant_stateful_ACS_correct[OF valid_reqs_ACS_D[OF validReqs] wfG _ _ Tau[simplified generate_valid_stateful_policy_IFSACS_def Let_def]] all_security_requirements_fulfilled_ACS_D[OF high_level_policy_valid]
        edgesList filter_IFS_no_violations_subseteq_input by metis

    from 1 2 3 4 5 6 validReqs high_level_policy_valid wfG
    show ?thesis
    unfolding stateful_policy_compliance_def by simp
  qed





  definition generate_valid_stateful_policy_IFSACS_2 :: "'v::vertex graph  'v SecurityInvariant_configured list  ('v × 'v) list  'v stateful_policy" where
    "generate_valid_stateful_policy_IFSACS_2 G M edgesList  
     hosts = nodes G, flows_fix = edges G, flows_state = set (filter_IFS_no_violations G M edgesList)  set (filter_compliant_stateful_ACS G M edgesList) "


  lemma generate_valid_stateful_policy_IFSACS_2_wf_stateful_policy: assumes wfG: "wf_graph G"
          and     edgesList: "(set edgesList) = edges G"
          shows "wf_stateful_policy (generate_valid_stateful_policy_IFSACS_2 G M edgesList)"
   proof -
    from  wfG show ?thesis
     apply(simp add: generate_valid_stateful_policy_IFSACS_2_def wf_stateful_policy_def)
     apply(auto simp add: wf_graph_def)
     using edgesList filter_IFS_no_violations_subseteq_input by (metis rev_subsetD)
   qed

   lemma generate_valid_stateful_policy_IFSACS_2_select_simps:
   shows "hosts (generate_valid_stateful_policy_IFSACS_2 G M edgesList) = nodes G"
   and   "flows_fix (generate_valid_stateful_policy_IFSACS_2 G M edgesList) = edges G"
   and   "flows_state (generate_valid_stateful_policy_IFSACS_2 G M edgesList)  set edgesList"
   proof -
   show  "hosts (generate_valid_stateful_policy_IFSACS_2 G M edgesList) = nodes G"
      by(simp add: generate_valid_stateful_policy_IFSACS_2_def)
    show "flows_fix (generate_valid_stateful_policy_IFSACS_2 G M edgesList) = edges G"
      by(simp add: generate_valid_stateful_policy_IFSACS_2_def)
    show "flows_state (generate_valid_stateful_policy_IFSACS_2 G M edgesList)  set edgesList"
      apply(simp add: generate_valid_stateful_policy_IFSACS_2_def)
      using filter_compliant_stateful_ACS_subseteq_input by (metis inf.coboundedI2)
    qed

  lemma generate_valid_stateful_policy_IFSACS_2_all_security_requirements_fulfilled_IFS: assumes validReqs: "valid_reqs M"
          and     wfG: "wf_graph G"
          and     high_level_policy_valid: "all_security_requirements_fulfilled M G"
          and     edgesList: "(set edgesList)  edges G"
          shows "all_security_requirements_fulfilled (get_IFS M) (stateful_policy_to_network_graph (generate_valid_stateful_policy_IFSACS_2 G M edgesList))"
  proof -
    have subseteq: "set (filter_IFS_no_violations G M edgesList)  set (filter_compliant_stateful_ACS G M edgesList)  set (filter_IFS_no_violations G M edgesList)" by blast

    from wfG filter_IFS_no_violations_subseteq_input edgesList
    have wfG': "wf_graph nodes = nodes G, edges = edges G  set (filter_IFS_no_violations G M edgesList)" 
      by (metis graph_eq_intro Un_absorb2 graph.select_convs(1) graph.select_convs(2) order.trans)

    from high_level_policy_valid have "all_security_requirements_fulfilled (get_IFS M) G" by(simp add: all_security_requirements_fulfilled_def get_IFS_def)
    from filter_IFS_no_violations_correct[OF valid_reqs_IFS_D[OF validReqs] wfG this edgesList] have 
      "all_security_requirements_fulfilled (get_IFS M) (stateful_policy_to_network_graph hosts = nodes G, flows_fix = edges G, flows_state = set (filter_IFS_no_violations G M edgesList))" .


    from all_security_requirements_fulfilled_mono_stateful_policy_to_network_graph[OF valid_reqs_IFS_D[OF validReqs] subseteq wfG' this]
    have "all_security_requirements_fulfilled (get_IFS M) (stateful_policy_to_network_graph (generate_valid_stateful_policy_IFSACS_2 G M edgesList))"
      by(simp add: generate_valid_stateful_policy_IFSACS_2_def)
    thus ?thesis .
  qed


  lemma generate_valid_stateful_policy_IFSACS_2_filter_compliant_stateful_ACS:
  assumes validReqs: "valid_reqs M"
        and     wfG: "wf_graph G"
        and     high_level_policy_valid: "all_security_requirements_fulfilled M G"
        and     edgesList: "(set edgesList)  edges G"
        and     Tau: "𝒯 = generate_valid_stateful_policy_IFSACS_2 G M edgesList"
  shows "Fget_offending_flows (get_ACS M) (stateful_policy_to_network_graph 𝒯). F  backflows (filternew_flows_state 𝒯)"
    proof- 
      let ?filterACS = "set (filter_compliant_stateful_ACS G M edgesList)"
      let ?filterIFS = "set (filter_IFS_no_violations G M edgesList)"
      from all_security_requirements_fulfilled_ACS_D[OF high_level_policy_valid] have "all_security_requirements_fulfilled (get_ACS M) G" .

      from filter_compliant_stateful_ACS_correct[OF valid_reqs_ACS_D[OF validReqs] wfG edgesList this] have 
        "Fget_offending_flows (get_ACS M) (stateful_policy_to_network_graph  hosts = nodes G, flows_fix = edges G, flows_state = ?filterACS). 
          F  backflows (?filterACS) - edges G"
        apply(simp)
        apply(simp add: backflows_minus_backflows[symmetric])
        by(simp add: filternew_flows_state_alt)
      hence "Fget_offending_flows (get_ACS M) nodes = nodes G, edges = edges G  backflows (?filterACS). F  backflows (?filterACS) - edges G"
        apply(simp add: stateful_policy_to_network_graph_def all_flows_def)
        using filter_compliant_stateful_ACS_subseteq_input by (metis (lifting, no_types) Un_absorb2 edgesList order_trans)
      from this validReqs have offending_filterACS_upperbound:
        "m. m  set (get_ACS M)  
        (c_offending_flows m nodes = nodes G, edges = edges G  backflows (?filterACS))  
          backflows (?filterACS) - edges G"
        by(simp add: valid_reqs_def get_offending_flows_def, blast)

      from wfG filter_compliant_stateful_ACS_subseteq_input edgesList have "wf_graph nodes = nodes G, edges = ?filterACS"
        by (metis graph.cases graph.select_convs(1) graph.select_convs(2) le_iff_sup wf_graph_remove_edges_union)
      from this backflows_wf have "wf_graph nodes = nodes G, edges = backflows (?filterACS)" by blast
      moreover have "wf_graph nodes = nodes G, edges = edges G" using wfG by(case_tac G, simp)
      ultimately have wfG1: "wf_graph nodes = nodes G, edges = edges G  backflows (?filterACS)"
        using wf_graph_union_edges by blast
        
      from edgesList have edgesUnsimp: "edges G  (?filterACS  ?filterIFS) = edges G"
        using filter_IFS_no_violations_subseteq_input filter_compliant_stateful_ACS_subseteq_input by blast

      ― ‹We set up a ?REM that we use in the @{thm configured_SecurityInvariant.Un_set_offending_flows_bound_minus_subseteq} lemma›
      let ?REM = "(backflows (?filterACS) - backflows (?filterIFS)) - edges G"

      have REM_gives_desired_upper_bound: "(backflows (?filterACS) - edges G) - ?REM = backflows (?filterACS  ?filterIFS) - edges G"
        by(simp add: backflows_def, blast)

      have REM_gives_desired_edges: "(edges G  backflows (?filterACS)) - ?REM = edges G  (backflows (?filterACS  ?filterIFS))"
        by(simp add: backflows_def, blast)

      from wfG have "finite (edges G)" using wf_graph_def by blast
      hence "finite (backflows ?filterACS)" using backflows_finite by (metis List.finite_set)
      hence finite1: "finite (backflows (?filterACS) - backflows (?filterIFS) - edges G)" by fast

      from configured_SecurityInvariant.Un_set_offending_flows_bound_minus_subseteq[where E'="?REM" and X="(backflows (?filterACS) - edges G)",
          OF _ wfG1 offending_filterACS_upperbound, simplified REM_gives_desired_upper_bound REM_gives_desired_edges
          ] valid_reqs_ACS_D[OF validReqs, unfolded valid_reqs_def]
      have "m. m  set (get_ACS M) 
              Fc_offending_flows m nodes = nodes G, edges = edges G  backflows (?filterACS  ?filterIFS).
                  F  backflows (?filterACS  ?filterIFS) - edges G" by blast
      hence "Fget_offending_flows (get_ACS M)
         nodes = nodes G, edges = edges G  (backflows (?filterACS  ?filterIFS)). F  backflows (?filterACS  ?filterIFS) - edges G"
       using get_offending_flows_def by fast
      hence "Fget_offending_flows (get_ACS M)
         nodes = nodes G, edges = edges G  (?filterACS  ?filterIFS)  (backflows (?filterACS  ?filterIFS)).
       F  backflows (?filterACS  ?filterIFS) - edges G"
        by(simp add: edgesUnsimp)
      hence "Fget_offending_flows (get_ACS M) (stateful_policy_to_network_graph hosts = nodes G, flows_fix = edges G, flows_state = ?filterACS  ?filterIFS).
                F  backflows (?filterACS  ?filterIFS) - edges G"
        by(simp add: stateful_policy_to_network_graph_def all_flows_def)

      thus ?thesis
        apply(simp add: Tau generate_valid_stateful_policy_IFSACS_2_def)
        apply(simp add: filternew_flows_state_alt backflows_minus_backflows)
        by (metis inf_commute)
    qed
        




  theorem generate_valid_stateful_policy_IFSACS_2_stateful_policy_compliance:
  assumes validReqs: "valid_reqs M"
        and     wfG: "wf_graph G"
        and     high_level_policy_valid: "all_security_requirements_fulfilled M G"
        and     edgesList: "(set edgesList) = edges G"
        and     Tau: "𝒯 = generate_valid_stateful_policy_IFSACS_2 G M edgesList"
    shows "stateful_policy_compliance 𝒯 G M"
    proof -
      have 1: "wf_stateful_policy 𝒯"
        apply(simp add: Tau)
        by(simp add: generate_valid_stateful_policy_IFSACS_2_wf_stateful_policy[OF wfG edgesList])
      have 2: "wf_stateful_policy (generate_valid_stateful_policy_IFSACS G M edgesList)"
        by(simp add: generate_valid_stateful_policy_IFSACS_wf_stateful_policy[OF wfG edgesList])
      have 3: "hosts 𝒯 = nodes G"
        apply(simp add: Tau)
        by(simp add: generate_valid_stateful_policy_IFSACS_2_select_simps(1))
      have 4: "flows_fix 𝒯  edges G"
        apply(simp add: Tau)
        by(simp add: generate_valid_stateful_policy_IFSACS_2_select_simps(2))
      have 5: "all_security_requirements_fulfilled (get_IFS M) (stateful_policy_to_network_graph 𝒯)"
        apply(simp add: Tau)
        using generate_valid_stateful_policy_IFSACS_2_all_security_requirements_fulfilled_IFS[OF validReqs wfG high_level_policy_valid] edgesList by blast
      have 6: "Fget_offending_flows (get_ACS M) (stateful_policy_to_network_graph 𝒯). F  backflows (filternew_flows_state 𝒯)"
        using generate_valid_stateful_policy_IFSACS_2_filter_compliant_stateful_ACS[OF 
            validReqs wfG high_level_policy_valid]
        Tau edgesList by auto

    from 1 2 3 4 5 6 validReqs high_level_policy_valid wfG
    show ?thesis
    unfolding stateful_policy_compliance_def by simp
  qed





  text‹
    If there are no IFS requirements and the ACS requirements cause no side effects,
    effectively, the graph can be considered as undirected graph! 
›
  lemma generate_valid_stateful_policy_IFSACS_2_noIFS_noACSsideeffects_imp_fullgraph:
  assumes validReqs: "valid_reqs M"
        and     wfG: "wf_graph G"
        and     high_level_policy_valid: "all_security_requirements_fulfilled M G"
        and     edgesList: "(set edgesList) = edges G"
        and     no_ACS_sideeffects: "F  get_offending_flows (get_ACS M) nodes = nodes G, edges = edges G  backflows (edges G). F  (backflows (edges G)) - (edges G)"
        and     no_IFS: "get_IFS M = []"
  shows "stateful_policy_to_network_graph (generate_valid_stateful_policy_IFSACS_2 G M edgesList) = undirected G"
  proof -
    from filter_IFS_no_violations_accu_no_IFS[OF valid_reqs_IFS_D[OF validReqs] wfG no_IFS] edgesList
      have "filter_IFS_no_violations G M edgesList = rev edgesList"
      by(simp add: filter_IFS_no_violations_def)
    from this filter_compliant_stateful_ACS_subseteq_input have flows_state_IFS: "flows_state (generate_valid_stateful_policy_IFSACS_2 G M edgesList) = set (filter_compliant_stateful_ACS G M edgesList)"
      by(auto simp add: generate_valid_stateful_policy_IFSACS_2_def)

    have flowsfix: "flows_fix (generate_valid_stateful_policy_IFSACS_2 G M edgesList) = edges G" by(simp add: generate_valid_stateful_policy_IFSACS_2_def)

    have hosts: "hosts (generate_valid_stateful_policy_IFSACS_2 G M edgesList) = nodes G" by(simp add: generate_valid_stateful_policy_IFSACS_2_def)

    from filter_compliant_stateful_ACS_accu_no_side_effects[OF valid_reqs_ACS_D[OF validReqs] wfG no_ACS_sideeffects] have 
      "filter_compliant_stateful_ACS G M edgesList = rev [eedgesList . e  backflows (edges G)]"
      by(simp add: filter_compliant_stateful_ACS_def edgesList)
    hence filterACS: "set (filter_compliant_stateful_ACS G M edgesList) = edges G - (backflows (edges G))" using edgesList by force

    show ?thesis
      apply(simp add: undirected_backflows stateful_policy_to_network_graph_def all_flows_def)
      apply(simp add: hosts filterACS flows_state_IFS flowsfix)
      apply(simp add: backflows_minus_backflows)
      by fast
    qed
  lemma generate_valid_stateful_policy_IFSACS_noIFS_noACSsideeffects_imp_fullgraph:
  assumes validReqs: "valid_reqs M"
        and     wfG: "wf_graph G"
        and     high_level_policy_valid: "all_security_requirements_fulfilled M G"
        and     edgesList: "(set edgesList) = edges G"
        and     no_ACS_sideeffects: "F  get_offending_flows (get_ACS M) nodes = nodes G, edges = edges G  backflows (edges G). F  (backflows (edges G)) - (edges G)"
        and     no_IFS: "get_IFS M = []"
  shows "stateful_policy_to_network_graph (generate_valid_stateful_policy_IFSACS G M edgesList) = undirected G"
  proof -
    from filter_IFS_no_violations_accu_no_IFS[OF valid_reqs_IFS_D[OF validReqs] wfG no_IFS] edgesList
      have "filter_IFS_no_violations G M edgesList = rev edgesList"
      by(simp add: filter_IFS_no_violations_def)
    from this filter_compliant_stateful_ACS_subseteq_input have flows_state_IFS: "flows_state (generate_valid_stateful_policy_IFSACS G M edgesList) = set (filter_compliant_stateful_ACS G M (rev edgesList))"
      by(simp add: generate_valid_stateful_policy_IFSACS_def)

    have flowsfix: "flows_fix (generate_valid_stateful_policy_IFSACS G M edgesList) = edges G" by(simp add: generate_valid_stateful_policy_IFSACS_def)

    have hosts: "hosts (generate_valid_stateful_policy_IFSACS G M edgesList) = nodes G" by(simp add: generate_valid_stateful_policy_IFSACS_def)

    from filter_compliant_stateful_ACS_accu_no_side_effects[OF valid_reqs_ACS_D[OF validReqs] wfG no_ACS_sideeffects] have 
      "filter_compliant_stateful_ACS G M (rev edgesList) = [eedgesList . e  backflows (edges G)]"
      apply(simp add: filter_compliant_stateful_ACS_def edgesList) by (metis rev_filter rev_swap)
    hence filterACS: "set (filter_compliant_stateful_ACS G M (rev edgesList)) = edges G - (backflows (edges G))" using edgesList by force

    show ?thesis
      apply(simp add: undirected_backflows stateful_policy_to_network_graph_def all_flows_def)
      apply(simp add: hosts filterACS flows_state_IFS flowsfix)
      apply(simp add: backflows_minus_backflows)
      by fast
    qed


(*
text{* In the repo history, we see failed attempts which try to prove that under composition, the IFS and ACS filtering is also maximal.
       I guess this does not hold in general. Needs a counter example. *}

*)
end