section \<open> NFA by RBTs \<close>
theory RBT_NFAImpl
imports "../../NFAByLTS" "../../NFAGA" RBT_LTS_DLTS_LTSImpl
        (* "HOL-Library.Efficient_Nat" *)
begin

subsection \<open> NFAs \<close>

interpretation rs_nfa_defs: nfa_by_lts_defs "rs_ops :: (nat, (nat, unit) RBT.rbt) oset_ops"
  rs_ops rs_lts_dlts_ops
  unfolding nfa_by_lts_defs_def
  apply (simp add: rs.StdSet_axioms rs_lts_dlts_impl)
done

type_synonym 'b rs_nfa =
   "(nat, unit) RBT.rbt \<times>
    ('b, unit) RBT.rbt \<times>
    ((nat, ('b, (nat, unit) RBT.rbt) RBT.rbt) RBT.rbt,
     (nat, ('b, nat) RBT.rbt) RBT.rbt) LTS_choice \<times>
    (nat, unit) RBT.rbt \<times> (nat, unit) RBT.rbt \<times> nfa_props"

definition rs_nfa_\<alpha> :: "('a::linorder) rs_nfa \<Rightarrow> (nat, 'a) NFA_rec"
  where "rs_nfa_\<alpha> \<equiv> rs_nfa_defs.nfa_\<alpha>"
definition "rs_nfa_invar \<equiv> rs_nfa_defs.nfa_invar"
definition "rs_nfa_states \<equiv> rs_nfa_defs.nfa_states"
definition "rs_nfa_labels \<equiv> rs_nfa_defs.nfa_labels"
definition "rs_nfa_trans \<equiv> rs_nfa_defs.nfa_trans"
definition "rs_nfa_initial \<equiv> rs_nfa_defs.nfa_initial"
definition "rs_nfa_accepting \<equiv> rs_nfa_defs.nfa_accepting"
definition "rs_nfa_props \<equiv> rs_nfa_defs.nfa_props"
definition "rs_nfa_construct_gen \<equiv> rs_nfa_defs.nfa_construct_gen"
definition "rs_nfa_construct \<equiv> rs_nfa_defs.nfa_construct"
definition "rs_dfa_construct \<equiv> rs_nfa_defs.dfa_construct"
definition "rs_nfa_destruct \<equiv> rs_nfa_defs.nfa_destruct"
definition "rs_nfa_destruct_simple \<equiv> rs_nfa_defs.nfa_destruct_simple"
definition "rs_nfa_states_no \<equiv> rs_nfa_defs.nfa_states_no"
definition "rs_nfa_labels_no \<equiv> rs_nfa_defs.nfa_labels_no"
definition "rs_nfa_trans_no \<equiv> rs_nfa_defs.nfa_trans_no rs_lts_dlts_it"
definition "rs_nfa_initial_no \<equiv> rs_nfa_defs.nfa_initial_no"
definition "rs_nfa_final_no \<equiv> rs_nfa_defs.nfa_final_no"
definition "rs_nfa_accept \<equiv> rs_nfa_defs.accept_impl rs_iteratei rs_lts_dlts_succ_it"

definition "rs_nfa_accept_nfa \<equiv> rs_nfa_defs.accept_nfa_impl rs_iteratei rs_lts_dlts_succ_it"
definition "rs_nfa_accept_dfa \<equiv> rs_nfa_defs.accept_dfa_impl"

term "rs_lts_image"

definition "rs_nfa_rename_states \<equiv> rs_nfa_defs.rename_states_impl rs_image rs_lts_dlts_image False"
definition "rs_nfa_rename_states_dfa \<equiv> rs_nfa_defs.rename_states_impl rs_image rs_lts_dlts_image_dlts True"
definition "rs_nfa_rename_labels_gen \<equiv> rs_nfa_defs.rename_labels_impl_gen rs_lts_dlts_image"
definition "rs_nfa_rename_labels \<equiv> rs_nfa_defs.rename_labels_impl rs_lts_dlts_image rs_image"
definition "rs_nfa_dfa_construct_reachable \<equiv> rs_nfa_defs.NFA_construct_reachable_impl_code
  rs_lts_dlts_add_choice rm_ops"
definition "rs_nfa_construct_reachable \<equiv> rs_nfa_dfa_construct_reachable False"
definition "rs_dfa_construct_reachable \<equiv> rs_nfa_dfa_construct_reachable True"
definition "rs_dfa_construct_reachable_fun \<equiv> NFAGA.construct_by_fun rs_dfa_construct_reachable rs_iteratei"
definition "rs_nfa_normalise \<equiv> rs_nfa_defs.nfa_normalise_impl rs_lts_dlts_add_choice rm_ops rs_lts_dlts_succ_label_it"
definition "rs_nfa_reverse \<equiv> rs_nfa_defs.nfa_reverse_impl rs_lts_dlts_reverse"
definition "rs_nfa_complement \<equiv> rs_nfa_defs.nfa_complement_impl"
definition "rs_nfa_bool_comb_gen \<equiv> rs_nfa_defs.bool_comb_gen_impl rs_lts_dlts_add_choice rm_ops
   rs_lts_dlts_succ_label_it rs_lts_dlts_succ_it"
definition "rs_nfa_bool_comb \<equiv> rs_nfa_defs.bool_comb_impl rs_lts_dlts_add_choice rm_ops
   rs_lts_dlts_succ_label_it rs_lts_dlts_succ_it"
definition "rs_nfa_right_quotient_lists \<equiv> rs_nfa_defs.right_quotient_lists_impl
   rm_ops rs_lts_dlts_filter_it"
definition "rs_nfa_determinise \<equiv> rs_nfa_defs.determinise_impl rs_lts_dlts_add_choice rm_ops rm_ops
  rs_iteratei rs_iteratei rs_iteratei rs_iteratei rs_lts_dlts_succ_it"
definition "rs_nfa_Brzozowski \<equiv> NFAGA.Brzozowski_impl rs_nfa_reverse rs_nfa_determinise"

definition "rs_nfa_language_is_empty \<equiv> rs_nfa_defs.language_is_empty_impl rs_nfa_normalise"
definition "rs_nfa_language_is_univ \<equiv> NFAGA.NFAGA_language_is_univ rs_nfa_determinise rs_nfa_complement
  rs_nfa_language_is_empty"
definition "rs_nfa_language_is_subset \<equiv>
  NFAGA.NFAGA_language_is_subset rs_nfa_determinise rs_nfa_complement
   (rs_nfa_bool_comb (\<and>)) rs_nfa_language_is_empty"
definition "rs_nfa_language_is_eq \<equiv> NFAGA.NFAGA_language_is_eq rs_nfa_language_is_subset"

text \<open> Prepare lts for Hopcroft \<close>

definition lsnd_lss_copy where
  "lsnd_lss_copy = mergesort"

lemma lsnd_lss_copy_impl :
  "set_copy ListSetImpl_NotDist.lsnd_\<alpha> ListSetImpl_NotDist.lsnd_invar ListSetImpl_Sorted.lss_\<alpha> ListSetImpl_Sorted.lss_invar lsnd_lss_copy"
unfolding set_copy_def lsnd_lss_copy_def
  apply (intro conjI allI impI)
  apply (unfold lsnd_invar_def lss_invar_def lss_\<alpha>_def lsnd_\<alpha>_def, simp_all)
  unfolding mergesort_def using mergesort_by_rel_permutes[of "(\<le>)"] apply simp
  (* problem: counter-example *)

lemma lss_lss_copy_impl :
  "set_copy lss_\<alpha> lss_invar lss_\<alpha> lss_invar id"
unfolding set_copy_def
by simp

interpretation rs_hop_ltsr :  Hopcroft_lts rm_ops rm_ops iam_ops lss_ops lss_ops
  id rm_iteratei iam_iteratei lss_union_list
  unfolding Hopcroft_lts_def
  by (simp add: lssr.StdSet_axioms rmr.StdMap_axioms lss_ops_unfold lss_union_list_impl
                rm_ops_unfold lsndr.StdSet_axioms rm_iteratei_impl lsnd_ops_unfold
                lss_lss_copy_impl iamr.StdMap_axioms iam_iteratei_impl iam_ops_unfold)

definition "rs_hop_lts_\<alpha> \<equiv> rs_hop_ltsr.hopcroft_lts_\<alpha>"
definition "rs_hop_lts_invar \<equiv> rs_hop_ltsr.hopcroft_lts_invar"
definition "rs_hop_lts_\<alpha>2 \<equiv> rs_hop_ltsr.hopcroft_lts_\<alpha>2"
definition "rs_hop_lts_invar2 \<equiv> rs_hop_ltsr.hopcroft_lts_invar2"

lemma rs_hop_no_copy :
  "rs_hop_lts_\<alpha>2 = rs_hop_lts_\<alpha>"
  "rs_hop_lts_invar2 = rs_hop_lts_invar"
unfolding rs_hop_lts_invar2_def rs_hop_lts_invar_def
          rs_hop_lts_\<alpha>2_def rs_hop_lts_\<alpha>_def
          rs_hop_ltsr.hopcroft_lts_invar_def
          rs_hop_ltsr.hopcroft_lts_invar2_def
          rs_hop_ltsr.hopcroft_lts_\<alpha>_def
          rs_hop_ltsr.hopcroft_lts_\<alpha>2_def
by simp_all

definition "rs_hop_lts_empty \<equiv> rs_hop_ltsr.hopcroft_lts_empty"
definition "rs_hop_lts_add \<equiv> rs_hop_ltsr.hopcroft_lts_add"
definition "rs_hop_lts_copy \<equiv> id"
definition "rs_hop_lts_get_succs \<equiv> rs_hop_ltsr.hopcroft_lts_get_succ_set"

interpretation rs_hop: nfa_by_lts_hop "rs_ops :: (nat, (nat, unit) RBT.rbt) oset_ops"
  rs_ops rs_lts_dlts_ops lss_\<alpha> lss_invar iam_ops iam_ops iam_ops iam_ops rm_ops rs_iteratei rs_iteratei lss_iteratei lss_iteratei rm_iteratei
  by unfold_locales

definition "rs_nfa_sm_update \<equiv> rs_hop.sm_update"
definition "rs_nfa_Hopcroft \<equiv> rs_hop.Hopcroft_minimise_impl rs_hop_lts_empty
   rs_hop_lts_add rs_hop_lts_get_succs rs_hop_lts_copy
   rs_image rs_lts_dlts_it rs_lts_dlts_image_dlts"

definition "rs_nfa_Hopcroft_NFA \<equiv> \<lambda>A. rs_nfa_Hopcroft (rs_nfa_determinise A)"

lemmas rs_nfa_defs =
  rs_nfa_props_def
  rs_nfa_\<alpha>_def
  rs_nfa_invar_def
  rs_nfa_states_def
  rs_nfa_labels_def
  rs_nfa_trans_def
  rs_nfa_initial_def
  rs_nfa_accepting_def
  rs_nfa_construct_gen_def
  rs_nfa_construct_def
  rs_dfa_construct_def
  rs_nfa_destruct_def
  rs_nfa_destruct_simple_def
  rs_nfa_states_no_def
  rs_nfa_labels_no_def
  rs_nfa_trans_no_def
  rs_nfa_initial_no_def
  rs_nfa_final_no_def
  rs_nfa_accept_def
  rs_nfa_accept_nfa_def
  rs_nfa_accept_dfa_def
  rs_nfa_rename_labels_gen_def
  rs_nfa_rename_labels_def
  rs_nfa_rename_states_def
  rs_nfa_rename_states_dfa_def
  rs_nfa_dfa_construct_reachable_def
  rs_nfa_construct_reachable_def
  rs_dfa_construct_reachable_def
  rs_dfa_construct_reachable_fun_def
  rs_nfa_normalise_def
  rs_nfa_reverse_def
  rs_nfa_complement_def
  rs_nfa_bool_comb_gen_def
  rs_nfa_bool_comb_def
  rs_nfa_right_quotient_lists_def
  rs_nfa_determinise_def
  rs_nfa_Brzozowski_def
  rs_hop_lts_\<alpha>_def
  rs_hop_lts_invar_def
  rs_hop_lts_\<alpha>2_def
  rs_hop_lts_invar2_def
  rs_hop_lts_empty_def
  rs_hop_lts_add_def
  rs_hop_lts_get_succs_def
  rs_hop_lts_copy_def
  rs_nfa_Hopcroft_def
  rs_nfa_Hopcroft_NFA_def
  rs_nfa_language_is_empty_def
  rs_nfa_language_is_univ_def
  rs_nfa_language_is_subset_def
  rs_nfa_language_is_eq_def
  rs_nfa_sm_update_def

lemmas rs_nfa_states_code[code] = rs_nfa_defs.nfa_states_def[folded rs_nfa_defs]
lemmas rs_nfa_labels_code[code] = rs_nfa_defs.nfa_labels_def[folded rs_nfa_defs]
lemmas rs_nfa_trans_code[code] = rs_nfa_defs.nfa_trans_def[folded rs_nfa_defs]
lemmas rs_nfa_initial_code[code] = rs_nfa_defs.nfa_initial_def[folded rs_nfa_defs]
lemmas rs_nfa_accepting_code[code] = rs_nfa_defs.nfa_accepting_def[folded rs_nfa_defs]
lemmas rs_nfa_props_code[code] = rs_nfa_defs.nfa_props_simp[folded rs_nfa_defs]

lemmas rs_nfa_impl = rs_nfa_defs.nfa_by_lts_correct [folded rs_nfa_defs]
interpretation rs_nfa!: nfa rs_nfa_\<alpha> rs_nfa_invar
  using rs_nfa_impl .

lemmas rs_nfa_construct_gen_code[code] = rs_nfa_defs.nfa_construct_gen.simps
   [folded rs_nfa_defs, unfolded rs_nfa_defs.nfa_construct_aux_def]

lemmas rs_nfa_construct_code[code] = rs_nfa_defs.nfa_construct_def [folded rs_nfa_defs]
lemmas rs_dfa_construct_code[code] = rs_nfa_defs.dfa_construct_def [folded rs_nfa_defs]
lemmas rs_nfa_construct_impl = rs_nfa_defs.nfa_construct_correct[folded rs_nfa_defs]
interpretation rs_nfa!: nfa_from_list rs_nfa_\<alpha> rs_nfa_invar rs_nfa_construct
  using rs_nfa_construct_impl .
lemmas rs_dfa_construct_impl = rs_nfa_defs.dfa_construct_correct[folded rs_nfa_defs]
interpretation rs_nfa!: dfa_from_list rs_nfa_\<alpha> rs_nfa_invar rs_dfa_construct
  using rs_dfa_construct_impl .

lemmas rs_nfa_destruct_code[code] = rs_nfa_defs.nfa_destruct.simps [folded rs_nfa_defs]
lemmas rs_nfa_destruct_impl = rs_nfa_defs.nfa_destruct_correct[folded rs_nfa_defs]
interpretation rs_nfa!: nfa_to_list rs_nfa_\<alpha> rs_nfa_invar rs_nfa_destruct
  using rs_nfa_destruct_impl .

lemmas rs_nfa_destruct_simple_code[code] = rs_nfa_defs.nfa_destruct_simple.simps [folded rs_nfa_defs]
lemmas rs_nfa_destruct_simple_impl = rs_nfa_defs.nfa_destruct_simple_correct[folded rs_nfa_defs]
interpretation rs_nfa!: nfa_to_list_simple rs_nfa_\<alpha> rs_nfa_invar rs_nfa_destruct_simple
  using rs_nfa_destruct_simple_impl .

lemmas rs_nfa_states_no_code[code] = rs_nfa_defs.nfa_states_no.simps [folded rs_nfa_defs]
lemmas rs_nfa_labels_no_code[code] = rs_nfa_defs.nfa_labels_no.simps [folded rs_nfa_defs]
lemmas rs_nfa_trans_no_code[code] = rs_nfa_defs.nfa_trans_no.simps [of rs_lts_dlts_it, folded rs_nfa_defs]
lemmas rs_nfa_final_no_code[code] = rs_nfa_defs.nfa_final_no.simps [folded rs_nfa_defs]
lemmas rs_nfa_initial_no_code[code] = rs_nfa_defs.nfa_initial_no.simps [folded rs_nfa_defs]

lemmas rs_nfa_stats_impl = rs_nfa_defs.nfa_stats_correct[unfolded rs_lts_dlts_ops_unfold rs_dlts_ops_unfold,
    OF rs_lts_dlts_it_impl, folded rs_nfa_defs]
interpretation rs_nfa!:  nfa_stats rs_nfa_\<alpha> rs_nfa_invar rs_nfa_states_no
  rs_nfa_labels_no rs_nfa_trans_no rs_nfa_initial_no rs_nfa_final_no
  using rs_nfa_stats_impl .

lemmas rs_nfa_accept_nfa_code[code] = rs_nfa_defs.accept_nfa_impl_code [of rs_iteratei rs_lts_dlts_succ_it, folded rs_nfa_defs]
lemmas rs_nfa_accept_dfa_code[code] = rs_nfa_defs.accept_dfa_impl_code [folded rs_nfa_defs]
lemmas rs_nfa_accept_code[code] = rs_nfa_defs.accept_impl_def [of rs_iteratei rs_lts_dlts_succ_it, folded rs_nfa_defs]

lemmas rs_nfa_accept_impl = rs_nfa_defs.accept_impl_correct[unfolded rs_ops_unfold rs_lts_dlts_ops_unfold,
OF rs_iteratei_impl, OF rs_lts_dlts_succ_it_impl, folded rs_nfa_defs]
interpretation rs_nfa!: nfa_accept rs_nfa_\<alpha> rs_nfa_invar rs_nfa_accept
  using rs_nfa_accept_impl .

lemmas rs_nfa_rename_labels_gen_code [code] = rs_nfa_defs.rename_labels_impl_gen_code [of rs_lts_dlts_image, folded rs_nfa_defs, unfolded rs_lts_dlts_ops_unfold]
lemmas rs_nfa_rename_labels_gen_impl = rs_nfa_defs.rename_labels_impl_gen_correct
   [OF rs_nfa_defs.nfa_by_lts_defs_axioms,
    unfolded rs_ops_unfold rs_dlts_ops_unfold rs_lts_dlts_ops_unfold,
    OF rs_lts_dlts_image_impl,
    folded rs_lts_dlts_defs rs_nfa_defs]

lemmas rs_nfa_rename_labels_code [code] = rs_nfa_defs.rename_labels_impl_def
   [of rs_lts_dlts_image rs_image, folded rs_lts_dlts_defs rs_nfa_defs]
lemmas rs_nfa_rename_labels_impl = rs_nfa_defs.rename_labels_impl_correct
   [OF rs_nfa_defs.nfa_by_lts_defs_axioms,
    unfolded rs_ops_unfold rs_dlts_ops_unfold rs_lts_dlts_ops_unfold,
    OF rs_lts_dlts_image_impl rs_image_impl,
    folded rs_lts_dlts_defs rs_nfa_defs]
interpretation rs_nfa!: nfa_rename_labels rs_nfa_\<alpha> rs_nfa_invar rs_nfa_\<alpha> rs_nfa_invar
   "rs_nfa_rename_labels False" using rs_nfa_rename_labels_impl .

lemmas rs_nfa_rename_states_code [code] = rs_nfa_defs.rename_states_impl_code
   [of rs_image rs_lts_dlts_image False, folded rs_lts_dlts_defs rs_nfa_defs]
lemmas rs_nfa_rename_states_impl = rs_nfa_defs.rename_states_impl_correct
   [OF rs_nfa_defs.nfa_by_lts_defs_axioms,
    unfolded rs_ops_unfold rs_dlts_ops_unfold rs_lts_dlts_ops_unfold,
    OF rs_image_impl rs_lts_dlts_image_impl,
    folded rs_lts_dlts_defs rs_nfa_defs]
interpretation rs_nfa!: nfa_rename_states rs_nfa_\<alpha> rs_nfa_invar rs_nfa_\<alpha> rs_nfa_invar
   rs_nfa_rename_states using rs_nfa_rename_states_impl .

lemmas rs_nfa_rename_states_dfa_code [code] = rs_nfa_defs.rename_states_impl_code
   [of rs_image rs_lts_dlts_image_dlts True, folded rs_lts_dlts_defs rs_nfa_defs]
lemmas rs_nfa_rename_states_dfa_impl = rs_nfa_defs.rename_states_impl_correct_dfa
   [OF rs_nfa_defs.nfa_by_lts_defs_axioms,
    unfolded rs_ops_unfold rs_dlts_ops_unfold rs_lts_dlts_ops_unfold,
    OF rs_image_impl rs_lts_dlts_image_dlts_impl,
    folded rs_lts_dlts_defs rs_nfa_defs]
interpretation rs_nfa!: dfa_rename_states rs_nfa_\<alpha> rs_nfa_invar rs_nfa_\<alpha> rs_nfa_invar
   rs_nfa_rename_states_dfa using rs_nfa_rename_states_dfa_impl .

lemmas rs_nfa_dfa_construct_reachable_code [code] = rs_nfa_defs.NFA_construct_reachable_impl_code_def
  [of rs_lts_dlts_add_choice rm_ops, folded rs_nfa_defs]

lemmas rs_nfa_dfa_construct_reachable_impl = rs_nfa_defs.NFA_construct_reachable_impl_code_correct
   [OF rmr.StdMap_axioms, unfolded rs_lts_dlts_ops_unfold, OF rs_lts_dlts_add_choice_impl,
   folded rs_nfa_defs, unfolded rs_ops_unfold]
lemmas rs_nfa_construct_reachable_impl = nfa_dfa_construct_sublocale_nfa [OF rs_nfa_dfa_construct_reachable_impl, folded rs_nfa_defs]
lemmas rs_dfa_construct_reachable_impl = nfa_dfa_construct_sublocale_dfa [OF
   rs_nfa_dfa_construct_reachable_impl, of _ _ True, folded rs_nfa_defs]
lemmas rs_nfa_construct_reachable_no_enc_impl =
   nfa_construct_no_enc_default [OF rs_nfa_construct_reachable_impl]
lemmas rs_dfa_construct_reachable_no_enc_impl =
   dfa_construct_no_enc_default [OF rs_dfa_construct_reachable_impl]

lemmas rs_dfa_construct_reachable_fun_code [code] = construct_by_fun_alt_def
  [of rs_dfa_construct_reachable rs_iteratei, folded rs_nfa_defs]
lemmas rs_dfa_construct_reachable_fun_impl = construct_by_fun_correct [OF rs_dfa_construct_reachable_impl rs_iteratei_impl,
  folded rs_nfa_defs]
lemmas rs_dfa_construct_reachable_no_enc_fun_impl =
   dfa_construct_no_enc_fun_default [OF rs_dfa_construct_reachable_fun_impl]

lemmas rs_nfa_normalise_code [code] = rs_nfa_defs.nfa_normalise_impl_def
  [of rs_lts_dlts_add_choice rm_ops rs_lts_dlts_succ_label_it, unfolded rs_lts_dlts_ops_unfold, folded rs_nfa_defs]

lemmas rs_nfa_normalise_impl = rs_nfa_defs.nfa_normalise_correct
   [unfolded rs_lts_dlts_ops_unfold rs_dlts_ops_unfold rs_ops_unfold,
    OF rmr.StdMap_axioms  rs_lts_dlts_add_choice_impl rs_lts_dlts_succ_label_it_impl, folded rs_nfa_defs]
interpretation rs_nfa!: nfa_normalise rs_nfa_\<alpha> rs_nfa_invar rs_nfa_normalise
  using rs_nfa_normalise_impl .

lemmas rs_nfa_reverse_code [code] = rs_nfa_defs.nfa_reverse_impl_def
  [of rs_lts_dlts_reverse, folded rs_nfa_defs, unfolded rs_lts_dlts_ops_unfold]
lemmas rs_nfa_reverse_impl = rs_nfa_defs.nfa_reverse_impl_correct
   [OF rs_nfa_defs.nfa_by_lts_defs_axioms, unfolded rs_lts_dlts_ops_unfold rs_dlts_ops_unfold rs_ops_unfold,
    OF rs_lts_dlts_reverse_impl,folded rs_nfa_defs]
interpretation rs_nfa!: nfa_reverse rs_nfa_\<alpha> rs_nfa_invar rs_nfa_\<alpha> rs_nfa_invar rs_nfa_reverse
  using rs_nfa_reverse_impl .

lemmas rs_nfa_complement_code [code] = rs_nfa_defs.nfa_complement_impl_def [folded rs_nfa_defs]
lemmas rs_nfa_complement_impl = rs_nfa_defs.nfa_complement_impl_correct
   [folded rs_nfa_defs]
interpretation rs_nfa!: nfa_complement rs_nfa_\<alpha> rs_nfa_invar rs_nfa_complement
  using rs_nfa_complement_impl .

lemmas rs_nfa_bool_comb_gen_code [code] = rs_nfa_defs.bool_comb_gen_impl_code [of  rs_lts_dlts_add_choice rm_ops
rs_lts_dlts_succ_label_it rs_lts_dlts_succ_it, folded rs_nfa_defs]
lemmas rs_nfa_bool_comb_gen_impl = rs_nfa_defs.bool_comb_gen_impl_correct
   [unfolded rs_lts_dlts_ops_unfold rs_dlts_ops_unfold rs_ops_unfold,
    OF rmr.StdMap_axioms rs_lts_dlts_add_choice_impl rs_lts_dlts_succ_label_it_impl rs_lts_dlts_succ_it_impl, folded rs_nfa_defs]

lemmas rs_nfa_bool_comb_code [code] = rs_nfa_defs.bool_comb_impl_code [of rs_lts_dlts_add_choice rm_ops
rs_lts_dlts_succ_label_it rs_lts_dlts_succ_it, folded rs_nfa_defs]

lemmas rs_nfa_bool_comb_impl = rs_nfa_defs.bool_comb_impl_correct
   [unfolded rs_lts_dlts_ops_unfold rs_ops_unfold,
    OF rmr.StdMap_axioms rs_lts_dlts_add_choice_impl rs_lts_dlts_succ_label_it_impl rs_lts_dlts_succ_it_impl, folded rs_nfa_defs]
interpretation rs_nfa!:
 nfa_bool_comb_same rs_nfa_\<alpha> rs_nfa_invar rs_nfa_bool_comb
   using rs_nfa_bool_comb_impl .

lemmas rs_nfa_right_quotient_lists_code [code] = rs_nfa_defs.right_quotient_lists_impl_code [of rm_ops
rs_lts_dlts_filter_it, folded rs_nfa_defs]
lemmas rs_nfa_right_quotient_lists_impl = rs_nfa_defs.right_quotient_lists_impl_correct
   [unfolded rs_lts_dlts_ops_unfold rs_ops_unfold,
    OF rmr.StdMap_axioms rs_lts_dlts_filter_it_impl, folded rs_nfa_defs]
interpretation rs_nfa!:
 nfa_right_quotient_lists rs_nfa_\<alpha> rs_nfa_invar rs_nfa_\<alpha> rs_nfa_invar rs_nfa_right_quotient_lists
   using rs_nfa_right_quotient_lists_impl .

lemmas rs_nfa_determinise_code [code] = rs_nfa_defs.determinise_impl_code [of rs_lts_dlts_add_choice rm_ops rm_ops
  rs_iteratei rs_iteratei rs_iteratei rs_iteratei rs_lts_dlts_succ_it,
  folded rs_nfa_defs, unfolded rs_nfa_defs.NFA_construct_reachable_impl_code_def]
lemmas rs_nfa_determinise_impl = rs_nfa_defs.determinise_impl_correct
   [unfolded rs_lts_dlts_ops_unfold rs_dlts_ops_unfold rs_ops_unfold,
    OF rs_iteratei_impl rs_iteratei_impl rs_iteratei_impl rs_iteratei_impl
       rs_lts_dlts_succ_it_impl rs_lts_dlts_add_choice_impl rmr.StdMap_axioms rmr.StdMap_axioms, folded rs_nfa_defs]
interpretation rs_nfa!:
 nfa_determinise rs_nfa_\<alpha> rs_nfa_invar rs_nfa_\<alpha> rs_nfa_invar rs_nfa_determinise
   using rs_nfa_determinise_impl .

lemmas rs_nfa_Brzozowski_code [code] = NFAGA.Brzozowski_impl_def [of rs_nfa_reverse rs_nfa_determinise, folded rs_nfa_defs]
lemmas rs_nfa_Brzozowski_impl = NFAGA.Brzozowski_impl_correct [OF rs_nfa_reverse_impl rs_nfa_determinise_impl, folded rs_nfa_defs]
interpretation rs_nfa_min_Brzozowski!:
 nfa_minimise rs_nfa_\<alpha> rs_nfa_invar rs_nfa_\<alpha> rs_nfa_invar rs_nfa_Brzozowski
   using rs_nfa_Brzozowski_impl .

lemmas rs_nfa_language_is_empty_code [code] = rs_nfa_defs.language_is_empty_impl_code [of rs_nfa_normalise, folded rs_nfa_defs]
lemmas rs_nfa_language_is_empty_impl = rs_nfa_defs.language_is_empty_impl_correct[folded rs_nfa_defs, OF rs_nfa_normalise_impl,
  folded rs_nfa_defs]
interpretation rs_nfa!: nfa_language_is_empty rs_nfa_\<alpha> rs_nfa_invar rs_nfa_language_is_empty
 using rs_nfa_language_is_empty_impl .

lemmas rs_nfa_language_is_univ_code [code] = NFAGA.NFAGA_language_is_univ_def [of rs_nfa_determinise rs_nfa_complement rs_nfa_language_is_empty, folded rs_nfa_defs]
lemmas rs_nfa_language_is_univ_impl = NFAGA.NFAGA_language_is_univ_correct [folded rs_nfa_defs,
  OF rs_nfa_complement_impl rs_nfa_determinise_impl rs_nfa_language_is_empty_impl,
  folded rs_nfa_defs]
interpretation rs_nfa!: nfa_language_is_univ rs_nfa_\<alpha> rs_nfa_invar rs_nfa_language_is_univ
 using rs_nfa_language_is_univ_impl .

lemmas rs_nfa_language_is_subset_code [code] =  NFAGA.NFAGA_language_is_subset_def [of rs_nfa_determinise rs_nfa_complement
  "rs_nfa_bool_comb (\<and>)" rs_nfa_language_is_empty, folded rs_nfa_defs]
lemmas rs_nfa_language_is_subset_impl = NFAGA.NFAGA_language_is_subset_correct [folded rs_nfa_defs,
  OF rs_nfa_complement_impl rs_nfa_determinise_impl  rs_nfa_bool_comb_impl rs_nfa_language_is_empty_impl,
  folded rs_nfa_defs]
interpretation rs_nfa!: nfa_language_is_subset rs_nfa_\<alpha> rs_nfa_invar rs_nfa_language_is_subset
 using rs_nfa_language_is_subset_impl .

lemmas rs_nfa_language_is_eq_code [code] = NFAGA.NFAGA_language_is_eq_def [of
  rs_nfa_language_is_subset, folded rs_nfa_defs]
lemmas rs_nfa_language_is_eq_impl = NFAGA.NFAGA_language_is_eq_correct [folded rs_nfa_defs,
  OF rs_nfa_language_is_subset_impl, folded rs_nfa_defs]
interpretation rs_nfa!: nfa_language_is_eq rs_nfa_\<alpha> rs_nfa_invar rs_nfa_language_is_eq
 using rs_nfa_language_is_eq_impl .

lemmas rs_hop_lts_empty_code [code_unfold] = rs_hop_lts_empty_def [unfolded rs_hop_ltsr.hopcroft_lts_empty_def]
lemmas rs_hop_lts_empty_impl = rs_hop_ltsr.hopcroft_lts_empty_correct[folded rs_nfa_defs]

lemmas rs_hop_lts_add_code [code] = rs_hop_lts_add_def [unfolded rs_hop_ltsr.hopcroft_lts_add_alt_def]
lemmas rs_hop_lts_add_impl = rs_hop_ltsr.hopcroft_lts_add_correct[folded rs_nfa_defs]

lemma rs_hop_lts_copy_impl : "lts_copy rs_hop_lts_\<alpha> rs_hop_lts_invar rs_hop_lts_\<alpha>2
 rs_hop_lts_invar2 rs_hop_lts_copy"
unfolding lts_copy_def rs_hop_lts_copy_def rs_hop_no_copy by simp

lemmas rs_hop_lts_get_succs_code [code] = rs_hop_lts_get_succs_def [unfolded rs_hop_ltsr.hopcroft_lts_get_succ_set_def[abs_def]]
lemmas rs_hop_lts_get_succs_impl = rs_hop_ltsr.hopcroft_lts_get_succ_set_correct[folded rs_nfa_defs, unfolded lss_ops_unfold]

lemmas rs_nfa_Hopcroft_impl = rs_hop.Hopcroft_minimise_impl_correct [OF rs_nfa_defs.nfa_by_lts_defs_axioms,
  unfolded rs_ops_unfold rm_ops_unfold rs_lts_dlts_ops_unfold rs_dlts_ops_unfold,
  OF rs_image_impl rs_lts_dlts_image_dlts_impl rs_lts_dlts_it_impl
     rs_hop_lts_empty_impl rs_hop_lts_add_impl rs_hop_lts_get_succs_impl rs_hop_lts_copy_impl, folded rs_nfa_defs]

interpretation rs_nfa_min_Hopcroft!:
 dfa_minimise rs_nfa_\<alpha> rs_nfa_invar rs_nfa_\<alpha> rs_nfa_invar rs_nfa_Hopcroft
  using rs_nfa_Hopcroft_impl .

lemmas rs_nfa_sm_update_code [code] = rs_hop.sm_update.simps[folded rs_nfa_sm_update_def]
lemmas rs_nfa_Hopcroft_code [code] = rs_hop.Hopcroft_minimise_impl_code[of rs_hop_lts_empty rs_hop_lts_add rs_hop_lts_get_succs rs_hop_lts_copy rs_image rs_lts_dlts_it
   rs_lts_dlts_image_dlts,
  unfolded rs_hop.Hopcroft_code_def rs_hop.Hopcroft_code_step_def rs_hop.Hopcroft_code_step_compute_iM_swap_check_def rs_hop.class_map_init_pred_code_def,
  folded rs_nfa_defs]

lemmas rs_nfa_Hopcroft_NFA_code [code] = rs_nfa_Hopcroft_NFA_def
lemmas rs_nfa_Hopcroft_NFA_impl = NFAGA_minimisation_with_determinisation [OF rs_nfa_determinise_impl rs_nfa_Hopcroft_impl,
unfolded o_def, folded rs_nfa_defs]
interpretation rs_nfa_min_Hopcroft_NFA!:
 nfa_minimise rs_nfa_\<alpha> rs_nfa_invar rs_nfa_\<alpha> rs_nfa_invar rs_nfa_Hopcroft_NFA
   using rs_nfa_Hopcroft_NFA_impl .

definition rs_nfa_ops :: "(nat,'a::{linorder},'a rs_nfa) nfa_ops" where
   "rs_nfa_ops \<equiv> \<lparr>
    nfa_op_\<alpha> = rs_nfa_\<alpha>,
    nfa_op_invar = rs_nfa_invar,
    nfa_op_nfa_from_list = rs_nfa_construct,
    nfa_op_dfa_from_list = rs_dfa_construct,
    nfa_op_to_list = rs_nfa_destruct,
    nfa_op_to_list_simple = rs_nfa_destruct_simple,
    nfa_op_states_no = rs_nfa_states_no,
    nfa_op_labels_no = rs_nfa_labels_no,
    nfa_op_trans_no = rs_nfa_trans_no,
    nfa_op_initial_no = rs_nfa_initial_no,
    nfa_op_final_no = rs_nfa_final_no,
    nfa_op_accept = rs_nfa_accept,
    nfa_op_rename_labels = rs_nfa_rename_labels False,
    nfa_op_normalise = rs_nfa_normalise,
    nfa_op_reverse = rs_nfa_reverse,
    nfa_op_complement = rs_nfa_complement,
    nfa_op_bool_comb = rs_nfa_bool_comb,
    nfa_op_determinise = rs_nfa_determinise,
    nfa_op_minimise_Brzozowski = rs_nfa_Brzozowski,
    nfa_op_minimise_Hopcroft = rs_nfa_Hopcroft,
    nfa_op_minimise_Hopcroft_NFA = rs_nfa_Hopcroft_NFA,
    nfa_op_right_quotient_lists = rs_nfa_right_quotient_lists,
    nfa_op_language_is_empty = rs_nfa_language_is_empty,
    nfa_op_language_is_univ = rs_nfa_language_is_univ,
    nfa_op_language_is_subset = rs_nfa_language_is_subset,
    nfa_op_language_is_eq = rs_nfa_language_is_eq \<rparr>"

lemma rs_nfa_ops_unfold[code_unfold] :
   "nfa_op_\<alpha> rs_nfa_ops = rs_nfa_\<alpha>"
   "nfa_op_invar rs_nfa_ops = rs_nfa_invar"
   "nfa_op_nfa_from_list rs_nfa_ops = rs_nfa_construct"
   "nfa_op_dfa_from_list rs_nfa_ops = rs_dfa_construct"
   "nfa_op_to_list rs_nfa_ops = rs_nfa_destruct"
   "nfa_op_to_list_simple rs_nfa_ops = rs_nfa_destruct_simple"
   "nfa_op_states_no rs_nfa_ops = rs_nfa_states_no"
   "nfa_op_labels_no rs_nfa_ops = rs_nfa_labels_no"
   "nfa_op_trans_no rs_nfa_ops = rs_nfa_trans_no"
   "nfa_op_initial_no rs_nfa_ops = rs_nfa_initial_no"
   "nfa_op_final_no rs_nfa_ops = rs_nfa_final_no"
   "nfa_op_accept rs_nfa_ops = rs_nfa_accept"
   "nfa_op_rename_labels rs_nfa_ops = rs_nfa_rename_labels False"
   "nfa_op_normalise rs_nfa_ops = rs_nfa_normalise"
   "nfa_op_reverse rs_nfa_ops = rs_nfa_reverse"
   "nfa_op_complement rs_nfa_ops = rs_nfa_complement"
   "nfa_op_bool_comb rs_nfa_ops = rs_nfa_bool_comb"
   "nfa_op_determinise rs_nfa_ops = rs_nfa_determinise"
   "nfa_op_minimise_Brzozowski rs_nfa_ops = rs_nfa_Brzozowski"
   "nfa_op_minimise_Hopcroft rs_nfa_ops = rs_nfa_Hopcroft"
   "nfa_op_minimise_Hopcroft_NFA rs_nfa_ops = rs_nfa_Hopcroft_NFA"
   "nfa_op_right_quotient_lists rs_nfa_ops = rs_nfa_right_quotient_lists"
   "nfa_op_language_is_empty rs_nfa_ops = rs_nfa_language_is_empty"
   "nfa_op_language_is_univ rs_nfa_ops = rs_nfa_language_is_univ"
   "nfa_op_language_is_subset rs_nfa_ops = rs_nfa_language_is_subset"
   "nfa_op_language_is_eq rs_nfa_ops = rs_nfa_language_is_eq"
  by (simp_all add: rs_nfa_ops_def)

lemmas rs_nfa_impls =
  rs_nfa_impl
  rs_nfa_construct_impl
  rs_dfa_construct_impl
  rs_nfa_destruct_impl
  rs_nfa_destruct_simple_impl
  rs_nfa_stats_impl
  rs_nfa_accept_impl
  rs_nfa_rename_labels_impl
  rs_nfa_rename_labels_gen_impl
  rs_nfa_normalise_impl
  rs_nfa_complement_impl
  rs_nfa_bool_comb_gen_impl
  rs_nfa_bool_comb_impl
  rs_nfa_determinise_impl
  rs_nfa_reverse_impl
  rs_nfa_right_quotient_lists_impl
  rs_nfa_Brzozowski_impl
  rs_nfa_Hopcroft_impl
  rs_nfa_Hopcroft_NFA_impl
  rs_nfa_language_is_empty_impl
  rs_nfa_language_is_univ_impl
  rs_nfa_language_is_subset_impl
  rs_nfa_language_is_eq_impl

lemma rs_nfa_StdNFA_impl: "StdNFA rs_nfa_ops"
  apply (rule StdNFA.intro)
  apply (simp_all add: rs_nfa_ops_def rs_nfa_impls nfa_minimise_sublocale)
done

end


(*<*)(*:maxLineLen=68:*)
theory dAutomaton
  imports bundle.SB_fin spf.SPF
begin

(*causes problems in sb.thy*)
lemma prod_contI[cont2cont]: "(\<And>s. cont(\<lambda>f. g (f,s)))
\<Longrightarrow>(\<And>f. cont (\<lambda>s. g (f,s))) \<Longrightarrow> cont g"
  by (simp add: prod_contI)
(*>*)

section\<open>Automatons\<close> text\<open>\label{sec:aut}\<close>

text\<open>The behaviour of a component can be modeled by a I/O automaton.
This section defines deterministic and non-deterministic automaton
types and their semantic mapping to \Gls{spf} and \Gls{sps}.
Furthermore, we take a closer look at causal automatons and use
their properties to introduce a local that is capable of
constructing automaton and is also providing lemmas to ease the
verification process for the input-output behavior.\<close>

subsection \<open>Deterministic Automaton\<close> text\<open>\label{sub:detaut}\<close>

default_sort %invisible "chan"

text\<open>A deterministic I/O Automaton consists of states, a transition
function, a initial state and a initial output. The transition
function for a deterministic automaton maps from a state type with a
@{type sbElem} to another state and a output \gls{sb}. Now we define
deterministic automaton as a tuple. Since we always have the message
type @{type M} it does not explicitly occur in our signature. But of
course it is hidden in our \gls{sb} and @{type sbElem} types.\<close>

record ('state::type, 'in, 'out) dAutomaton  =
  daTransition :: "('state \<Rightarrow> 'in\<^sup>\<surd> \<Rightarrow> ('state \<times> 'out\<^sup>\<Omega>))"
  daInitState :: "'state"
  daInitOut:: "'out\<^sup>\<Omega>"

text\<open>The type parameter of @{type dAutomaton} show the state set and
the input and output domain. We then introduce two definitions to
obtain the next state or the next output of the transition function.
\<close>

definition daNextState::
"('s::type,'in , _) dAutomaton \<Rightarrow> 's \<Rightarrow>  'in\<^sup>\<surd> \<Rightarrow> 's"where
"daNextState aut s m = fst ((daTransition aut) s m)"

definition daNextOut::
"('s::type, 'in,'out) dAutomaton \<Rightarrow> 's \<Rightarrow>  'in\<^sup>\<surd> \<Rightarrow> 'out\<^sup>\<Omega>" where
"daNextOut aut s m = snd ((daTransition aut) s m)"

subsubsection \<open>Semantic\<close> text\<open>\label{subsub:sem}\<close>

text\<open>The semantic of an automaton corresponds to a \gls{spf}. To
obtain a \gls{spf} with an equivalent behaviour we use a semantic
mapping. In simple terms, the semantic mapping iterates through the
automaton and obtain its output for each input bundle element.
This is formulated as a fixed point function for a function from
states to \gls{spf}, because the behaviour of the transition
function depends on the state. Hence, the states are part of the
iteration. The usage of @{const sb_split} allows to directly access
the first stream bundle element of the input. This is the input of
the transition function and allows us formulate a semantic mapping
without splitting the input \gls{sb} with a lot of cases. If the
input \gls{sb} contains no bundle element, @{const sb_split} maps to
the empty output.\<close>

definition daStateSem::"('s::type, 'I::{finite,chan},'O) dAutomaton
\<Rightarrow> ('s \<Rightarrow> ('I\<^sup>\<Omega> \<rightarrow> 'O\<^sup>\<Omega>))" where
"daStateSem da =
 fix\<cdot>(\<Lambda> h. (\<lambda> state. sb_split\<cdot>
        (\<lambda>sbe. \<Lambda> sb.
           let (nextState, output) = daTransition da state sbe in
          output \<bullet>\<^sup>\<Omega> h nextState\<cdot>sb)))"

text\<open>Altogether, @{const daStateSem} maps to the semantic of any
desired state and is independent form the start state or the initial
output of the automaton. Therefore, the semantic mapping of our
complete automaton uses the initial state to obtain the
corresponding semantic from @{const daStateSem} and also first
outputs the initial output of the automaton.\<close>

definition daSem::"('s::type, 'I::{finite,chan},'O) dAutomaton
\<Rightarrow> ('I\<^sup>\<Omega> \<rightarrow> 'O\<^sup>\<Omega>)" where
"daSem da \<equiv> \<Lambda> sb. daInitOut da \<bullet>\<^sup>\<Omega> daStateSem da(daInitState da)\<cdot>sb"

paragraph\<open>Semantic Properties \\\<close>

text\<open>Specific properties like the step wise evaluation of the
semantic and its causality will be discussed and provided in the
following.\<close>

lemma dastatesem_unfolding: "(daStateSem automat s) =
sb_split\<cdot>(\<lambda>sbe. \<Lambda> sb .
           let (nextState, output) = daTransition automat s sbe in
           output \<bullet>\<^sup>\<Omega> ((daStateSem automat) nextState\<cdot>sb))"
  unfolding daStateSem_def
  apply(subst fix_eq)
  apply(subst beta_cfun)
  apply(intro cont2cont; simp)
  by auto

text\<open>If the input domain is not empty and there is no
bundle element in the input \gls{sb}, our state semantic maps to
\<open>\<bottom>\<close>. This also shows, that the input is only processed, if there
exists a complete bundle element. This is the case, because an empty
stream in the input terminates the automaton directly after its
initial output.\<close>

theorem dastatesem_bottom:
  fixes sb::"'cs::{finite,chan}\<^sup>\<Omega>"
  assumes "\<not>sbHdElemWell (sb)"
  and "\<not> chDomEmpty TYPE('cs)"
  shows "(daStateSem automat s)\<cdot>sb = \<bottom>"
  apply (subst dastatesem_unfolding)
  apply (simp add: sb_split_insert)
  by (metis (no_types, lifting) assms fup1 sbHdElem_h_cont.rep_eq
      sbHdElem_h_def)

lemma dastatesem_strict:
  assumes "\<not> chDomEmpty TYPE('b::{finite, chan})"
  shows "(daStateSem automat s)\<cdot>(\<bottom>::'b\<^sup>\<Omega>) = \<bottom>"
  by (simp add: assms dastatesem_bottom sbHdElemWell_def)

lemma dastatesem_step:
  assumes "sbHdElemWell sb"
  shows "(daStateSem da s)\<cdot>sb = snd (daTransition da s (sbHdElem sb))
  \<bullet>\<^sup>\<Omega> daStateSem da (fst (daTransition da s (sbHdElem sb)))\<cdot>(sbRt\<cdot>sb)"
  apply (subst dastatesem_unfolding)
  apply (simp add: sb_split_insert Let_def case_prod_unfold)
  apply (cases "sbHdElem_h_cont\<cdot>sb")
  apply (simp_all add: sbHdElem_h_cont.rep_eq sbHdElem_def)
  apply (simp_all split: u.split)
  apply (metis assms inst_up_pcpo sbHdElem_h_def u.simps(3))
  by (simp add: up_def)

lemma dastatesem_final:
  assumes "sbHdElemWell sb"
  shows "(daStateSem automat s)\<cdot>sb =
  daNextOut automat s (sbHdElem sb) \<bullet>\<^sup>\<Omega>
  daStateSem automat (daNextState automat s (sbHdElem sb))\<cdot>(sbRt\<cdot>sb)"
  by (metis assms daNextOut_def daNextState_def dastatesem_step)

lemma dastatesem_final_h2:
  shows "daStateSem automat s\<cdot>(sbe \<bullet>\<^sup>\<surd> sb) =
  daNextOut automat s sbe \<bullet>\<^sup>\<Omega>
  daStateSem automat (daNextState automat s sbe)\<cdot>sb"
  apply (cases "chDomEmpty(TYPE('b))")
  apply (subst sbtypeepmpty_sbenone[of sbe],simp)+
  apply (subst sbtypeepmpty_sbbot[of sb],simp)+
  apply (subst dastatesem_unfolding, simp add: sb_split_insert)
  apply (subst case_prod_unfold)
  apply (subgoal_tac "sbHdElem_h_cont\<cdot>\<bottom>=up\<cdot>(Abs_sbElem(None)::'b\<^sup>\<surd>)")
  apply (simp add: daNextOut_def daNextState_def)
  apply (simp add: sbHdElem_h_cont.rep_eq sbHdElem_h_def chDom_def
          up_def)
  apply (subst dastatesem_step)
  apply (simp add: sbECons_def sbHdElemWell_def)
  using sbgetch_sbe2sb_nempty strictI apply fastforce
  by (simp only: daNextOut_def daNextState_def sbhdelem_sbecons
      sbrt_sbecons)

text\<open>If there exists a complete input bundle element, is is
processed according to the automaton and the the semantic continues
with the rest of the input. For this it will also use the semantic
of the next state. This also holds for the empty input domain,
because our output then is constant and does not depend on any
input.\<close>

theorem dastatesem_stepI:
  assumes "(daNextOut da s sbe) = out"
  and "(daNextState da s sbe) = nextState"
  shows "daStateSem da s\<cdot>(sbe \<bullet>\<^sup>\<surd> sb) =
         out  \<bullet>\<^sup>\<Omega> daStateSem da nextState\<cdot>sb"
  by (simp add: assms dastatesem_final_h2)

text\<open>If the output of the automaton in every state is always at
least a complete bundle element, the output is then infinitely long,
if the input domain is empty. This follows directly from the last
theorem.\<close>

theorem dastatesem_inempty_len:
  fixes automat::"('state::type, 'in::{chan, finite}, 'out) dAutomaton"
  assumes "\<And>state sbe. 1 \<le> sbLen (daNextOut automat state sbe)"
  and "chDomEmpty TYPE('in)"
  shows "\<forall>s. sbLen (daStateSem automat s\<cdot>\<bottom>) = \<infinity>"
proof(rule contrapos_pp,simp+)
  assume a1: "\<exists>s::'state. sbLen (daStateSem automat s\<cdot>\<bottom>) \<noteq> \<infinity>"
  obtain len_set where len_set_def:
        "len_set = {sbLen (daStateSem automat s\<cdot>\<bottom>) | s. True }"
    by simp
  hence len_set_least: "\<exists>n \<in> len_set. \<forall>i \<in> len_set. n \<le> i"
    by (metis (mono_tags, lifting) exists_least_iff le_less_linear
        len_set_def mem_Collect_eq)
  then obtain state where state_def: "sbLen
    (daStateSem automat state\<cdot>\<bottom>) \<in> len_set"
    and "\<forall>n \<in> len_set. sbLen (daStateSem automat state\<cdot>\<bottom>) \<le> n"
    using len_set_def by blast
  hence state_least: "\<forall>s. sbLen (daStateSem automat state\<cdot>\<bottom>) \<le>
                          sbLen (daStateSem automat s\<cdot>\<bottom>)"
    using len_set_def len_set_least by blast
  then obtain k where k_def: "Fin k =
                              sbLen (daStateSem automat state\<cdot>\<bottom>)"
    by (metis SBv3.lnat.exhaust a1 inf_less_eq)
  hence "Fin k < sbLen (daNextOut automat state (Abs_sbElem None)) +
         sbLen (daStateSem automat
         (daNextState automat state (Abs_sbElem None))\<cdot> \<bottom>)"
    by (metis state_least add.commute assms(1) le2lnle leI
        lessequal_addition lnat_plus_suc notinfI3)
  thus "False"
    by (metis assms(2) dastatesem_final_h2 k_def leD sblen_sbconc
        sbtypeempty_sbecons_bot)
qed

lemma dastatesem_weak_fin:
  assumes "sbLen sb = Fin n"
    and "\<And>state sbe. 1 \<le> sbLen (daNextOut automat state sbe)"
  shows "sbLen sb \<le> sbLen (daStateSem automat s\<cdot>sb)"
  apply (induction sb arbitrary: s rule: sb_finind)
  apply (simp_all add: assms)
  apply (cases "chDomEmpty TYPE('a)")
  using assms(1) apply auto[1]
  using sbleast2sblenempty apply fastforce
  by (metis (no_types, lifting) dual_order.trans sbECons_def
      sbecons_len assms(2) dastatesem_final_h2 lessequal_addition
      lnat_plus_commu lnat_plus_suc sbECons_def sblen_sbconc)

text\<open>This then leads to our first causality conclusion. The semantic
of our automaton is weak, if the output is always at least one
completed bundle element.\<close>

theorem dastatesem_weak:
  fixes automat::"('state::type, 'in::{chan, finite}, 'out) dAutomaton"
  assumes "\<And>state sbe. 1 \<le> sbLen (daNextOut automat state sbe)"
  shows   "weak_well (daStateSem automat s)"
  apply (cases "chDomEmpty TYPE('in)")
  apply (metis (full_types) assms dastatesem_inempty_len fold_inf
        less_lnsuc sblen_empty sbtypeepmpty_sbbot weak_well_def)
  by (metis assms spf_weakI2 dastatesem_weak_fin lnat_well_h2)

lemma dastatesem_least:
  assumes"(\<lambda>state. sb_split\<cdot>
          (\<lambda>sbe. \<Lambda> sb. snd (daTransition X state sbe) \<bullet>\<^sup>\<Omega>
          Z (fst (daTransition X state sbe))\<cdot>sb)) \<sqsubseteq> Z"
  shows"daStateSem X \<sqsubseteq> Z"
  apply (simp add: daStateSem_def)
  apply (rule fix_least_below)
  apply (subst beta_cfun)
  apply (intro cont2cont; simp)
  by (simp add: assms case_prod_unfold)

text\<open>As described before, our semantic for an automaton firstly
outputs its initial output before iterating through the
automaton, starting with its initial state.\<close>

theorem dasem_insert:
  "daSem automat\<cdot>sb = daInitOut automat \<bullet>\<^sup>\<Omega>
                     daStateSem automat (daInitState automat)\<cdot>sb"
  by (simp add: daSem_def)

text\<open>Hence, the semantic is only strict, if the initial output is
\<open>\<bottom>\<close>.\<close>

theorem dasem_bottom:
  assumes "\<not>chDomEmpty TYPE('in::{chan,finite})"
  shows "daSem automat\<cdot>(\<bottom>::'in\<^sup>\<Omega>) = daInitOut automat"
  by (simp add: daSem_def assms dastatesem_strict)

text\<open>Furthermore, this leads to the conclusion, that the semantic of
an automaton is strong causal, if its corresponding state semantic
is weak and its initial output is at least one complete bundle
element.\<close>

theorem dasem_strong:
  assumes "weak_well(daStateSem automat (daInitState automat))"
  and     "1 \<le> sbLen (daInitOut automat)"
  shows "strong_well (daSem automat)"
  apply (subst strong_well_def)
  apply (simp add: daSem_def)
proof
  fix sb
  have h1: "sbLen sb <\<^sup>l lnsuc\<cdot>(sbLen
                      (daStateSem automat (daInitState automat)\<cdot>sb))"
    using assms(1) sblen_mono
    by (simp add: weak_well_def)
  have h4: "lnsuc\<cdot>(sbLen(daStateSem automat(daInitState automat)\<cdot>sb))
             \<le> sbLen (daInitOut automat) +
               sbLen (daStateSem automat (daInitState automat)\<cdot>sb)"
    by (metis add.commute assms(2) lessequal_addition lnat_plus_suc
        order_refl)
  have h2: "sbLen (daInitOut automat) + sbLen (daStateSem automat
       (daInitState automat)\<cdot>sb) \<le> sbLen (daInitOut automat \<bullet>\<^sup>\<Omega>
        daStateSem automat (daInitState automat)\<cdot>sb)"
    using sblen_sbconc by auto
  have h3: "sbLen sb <\<^sup>l sbLen (daInitOut automat \<bullet>\<^sup>\<Omega>
            daStateSem automat (daInitState automat)\<cdot>sb)"
    using h1 h2 h4 dual_order.trans by blast
  then show "\<And>sb. sbLen sb <\<^sup>l sbLen (daInitOut automat \<bullet>\<^sup>\<Omega>
                  daStateSem automat (daInitState automat)\<cdot>sb)"
    by (metis assms(1) assms(2) dual_order.trans lessequal_addition
        lnat_plus_commu lnat_plus_suc sblen_sbconc weak_well_def)
qed

(*<*)
end
(*>*)


theory Prelude_ListNoNumbers__E6
imports "$HETS_ISABELLE_LIB/MainHC"
uses "$HETS_ISABELLE_LIB/prelude"
begin

setup "Header.initialize
       [\"Comp1\", \"IdDef\", \"FlipDef\", \"FstDef\", \"SndDef\",
        \"CurryDef\", \"UncurryDef\", \"NotFalse\", \"NotTrue\",
        \"AndFalse\", \"AndTrue\", \"AndSym\", \"OrDef\", \"OtherwiseDef\",
        \"NotFalse1\", \"NotTrue1\", \"notNot1\", \"notNot2\",
        \"EqualTDef\", \"EqualSymDef\", \"EqualReflex\", \"EqualTransT\",
        \"DiffDef\", \"DiffSymDef\", \"DiffTDef\", \"DiffFDef\", \"TE1\",
        \"TE2\", \"TE3\", \"TE4\", \"IBE1\", \"IBE2\", \"IBE3\", \"IBE4\",
        \"IBE5\", \"IBE6\", \"IBE7\", \"IBE8\", \"IUE1\", \"IUE2\",
        \"IOE01\", \"IOE02\", \"IOE03\", \"IOE04\", \"IOE05\", \"IOE06\",
        \"IOE07\", \"IOE08\", \"IOE09\", \"LeIrreflexivity\",
        \"LeTAsymmetry\", \"LeTTransitive\", \"LeTTotal\", \"GeDef\",
        \"GeIrreflexivity\", \"GeTAsymmetry\", \"GeTTransitive\",
        \"GeTTotal\", \"LeqDef\", \"LeqReflexivity\", \"LeqTTransitive\",
        \"LeqTTotal\", \"GeqDef\", \"GeqReflexivity\", \"GeqTTransitive\",
        \"GeqTTotal\", \"EqTSOrdRel\", \"EqFSOrdRel\", \"EqTOrdRel\",
        \"EqFOrdRel\", \"EqTOrdTSubstE\", \"EqTOrdFSubstE\",
        \"EqTOrdTSubstD\", \"EqTOrdFSubstD\", \"LeTGeFEqFRel\",
        \"LeFGeTEqTRel\", \"LeTGeTRel\", \"LeFGeFRel\", \"LeqTGetTRel\",
        \"LeqFGetFRel\", \"GeTLeTRel\", \"GeFLeFRel\", \"GeqTLeqTRel\",
        \"GeqFLeqFRel\", \"LeqTGeFRel\", \"LeqFGeTRel\", \"GeTLeFEqFRel\",
        \"GeFLeTEqTRel\", \"GeqTLeFRel\", \"GeqFLeTRel\",
        \"LeqTLeTEqTRel\", \"LeqFLeFEqFRel\", \"GeqTGeTEqTRel\",
        \"GeqFGeFEqFRel\", \"LeTGeqFRel\", \"GeTLeqFRel\", \"LeLeqDiff\",
        \"CmpLTDef\", \"CmpEQDef\", \"CmpGTDef\", \"MaxYDef\", \"MaxXDef\",
        \"MinXDef\", \"MinYDef\", \"MaxSym\", \"MinSym\", \"TO1\", \"TO3\",
        \"TO4\", \"TO5\", \"IOO13\", \"IOO14\", \"IOO15\", \"IOO16\",
        \"IOO17\", \"IOO18\", \"IOO19\", \"IOO20\", \"IOO21\", \"IOO22\",
        \"IOO23\", \"IOO24\", \"IOO25\", \"IOO26\", \"IOO27\", \"IOO28\",
        \"IOO29\", \"IOO30\", \"IOO31\", \"IOO32\", \"IOO33\", \"IBO5\",
        \"IBO6\", \"IBO7\", \"IBO8\", \"IBO9\", \"IBO10\", \"IBO11\",
        \"IBO12\", \"IUO01\", \"IUO02\", \"IUO03\", \"IUO04\", \"IUO05\",
        \"IUO06\", \"IUO07\", \"NotDefHead\", \"HeadDef\", \"NotDefTail\",
        \"TailDef\", \"FoldrNil\", \"FoldrCons\", \"FoldlNil\",
        \"FoldlCons\", \"MapNil\", \"MapCons\", \"XPlusXPlusNil\",
        \"XPlusXPlusCons\", \"FilterNil\", \"FilterConsT\",
        \"FilterConsF\", \"ZipNil\", \"ZipConsNil\", \"ZipConsCons\",
        \"UnzipNil\", \"UnzipCons\", \"ILE01\", \"ILE02\", \"ILO01\",
        \"ILO02\", \"ILO03\", \"ILO04\", \"ILO05\", \"ILO06\", \"ILO07\",
        \"ILO08\", \"ILO09\", \"ILO10\", \"ILO11\", \"ILO12\", \"ILO13\",
        \"ILO14\", \"ILO15\", \"ILO16\", \"ILO17\", \"ILO18\", \"ILO19\",
        \"ILO20\", \"ILO21\", \"ILO22\", \"FoldlDecomp\", \"MapDecomp\",
        \"MapFunctor\", \"FilterProm\", \"InitNil\", \"InitConsNil\",
        \"InitConsCons\", \"LastNil\", \"LastConsNil\", \"LastConsCons\",
        \"NullNil\", \"NullCons\", \"ReverseNil\", \"ReverseCons\",
        \"Foldr1Nil\", \"Foldr1ConsNil\", \"Foldr1ConsCons\",
        \"Foldl1Nil\", \"Foldl1ConsNil\", \"Foldl1ConsCons\", \"ScanlNil\",
        \"ScanlCons\", \"Scanl1Nil\", \"Scanl1Cons\", \"ScanrNil\",
        \"ScanrCons\", \"Scanr1Nil\", \"Scanr1ConsNil\",
        \"Scanr1ConsCons\", \"ScanlProperty\", \"ScanrProperty\",
        \"AndLNil\", \"AndLCons\", \"OrLNil\", \"OrLCons\", \"AnyDef\",
        \"AllDef\", \"ConcatDef\", \"ConcatMapDef\", \"MaximunNil\",
        \"MaximumDef\", \"MinimunNil\", \"MinimumDef\", \"TakeWhileNil\",
        \"TakeWhileConsT\", \"TakeWhileConsF\", \"DropWhileNil\",
        \"DropWhileConsT\", \"DropWhileConsF\", \"SpanNil\", \"SpanConsT\",
        \"SpanConsF\", \"BreakDef\", \"SpanThm\", \"BreakThm\"]"

typedecl Unit

datatype Bool = X_False ("False''") | X_True ("True''")
datatype Ordering = EQ | GT | LT
datatype 'a List = X_Cons 'a "'a List" | X_Nil ("Nil''")

consts
X__XAmpXAmp__X :: "Bool => Bool => Bool" ("(_/ &&/ _)" [54,54] 52)
X__XEqXEq__X :: "'a => 'a => Bool" ("(_/ ==''/ _)" [54,54] 52)
X__XGtXEq__X :: "'a => 'a => Bool" ("(_/ >=''/ _)" [54,54] 52)
X__XGt__X :: "'a => 'a => Bool" ("(_/ >''/ _)" [54,54] 52)
X__XLtXEq__X :: "'a => 'a => Bool" ("(_/ <=''/ _)" [54,54] 52)
X__XLt__X :: "'a => 'a => Bool" ("(_/ <''/ _)" [54,54] 52)
X__XPlusXPlus__X :: "'a List => 'a List => 'a List" ("(_/ ++''/ _)" [54,54] 52)
X__XSlashXEq__X :: "'a => 'a => Bool" ("(_/ '/=/ _)" [54,54] 52)
X__XVBarXVBar__X :: "Bool => Bool => Bool" ("(_/ ||/ _)" [54,54] 52)
X__o__X :: "('b => 'c) * ('a => 'b) => 'a => 'c"
X_all :: "('a => Bool) => 'a List => Bool"
X_andL :: "Bool List => Bool" ("andL/'(_')" [3] 999)
X_any :: "('a => Bool) => 'a List => Bool"
X_concat :: "'a List List => 'a List" ("concat''/'(_')" [3] 999)
X_curry :: "('a * 'b => 'c) => 'a => 'b => 'c"
X_dropWhile :: "('a => Bool) => 'a List => 'a List"
X_filter :: "('a => Bool) => 'a List => 'a List"
X_flip :: "('a => 'b => 'c) => 'b => 'a => 'c"
X_foldl :: "('a => 'b => 'a) => 'a => 'b List => 'a partial"
X_foldr :: "('a => 'b => 'b) => 'b => 'a List => 'b partial"
X_fst :: "'a => 'b => 'a" ("fst''/'(_,/ _')" [3,3] 999)
X_head :: "'a List => 'a partial" ("head/'(_')" [3] 999)
X_id :: "'a => 'a" ("id''/'(_')" [3] 999)
X_init :: "'a List => 'a List partial" ("init/'(_')" [3] 999)
X_last :: "'a List => 'a partial" ("last''/'(_')" [3] 999)
X_map :: "('a => 'b) => 'a List => 'b List"
X_max :: "'a => 'a => 'a"
X_maximum :: "'d List => 'd partial" ("maximum/'(_')" [3] 999)
X_min :: "'a => 'a => 'a"
X_minimum :: "'d List => 'd partial" ("minimum/'(_')" [3] 999)
X_null :: "'a List => Bool" ("null''/'(_')" [3] 999)
X_orL :: "Bool List => Bool" ("orL/'(_')" [3] 999)
X_reverse :: "'a List => 'a List" ("reverse/'(_')" [3] 999)
X_snd :: "'a => 'b => 'b" ("snd''/'(_,/ _')" [3,3] 999)
X_tail :: "'a List => 'a List partial" ("tail/'(_')" [3] 999)
X_takeWhile :: "('a => Bool) => 'a List => 'a List"
X_unzip :: "('a * 'b) List => 'a List * 'b List" ("unzip/'(_')" [3] 999)
X_zip :: "'a List => 'b List => ('a * 'b) List"
break :: "('a => Bool) => 'a List => 'a List * 'a List"
compare :: "'a => 'a => Ordering"
concatMap :: "('a => 'b List) => 'a List => 'b List"
foldl1 :: "('a => 'a => 'a) => 'a List => 'a partial"
foldr1 :: "('a => 'a => 'a) => 'a List => 'a partial"
notH__X :: "Bool => Bool" ("(notH/ _)" [56] 56)
otherwiseH :: "Bool"
scanl :: "('a => 'b => 'a) => 'a => 'b List => 'a List"
scanl1 :: "('a => 'a => 'a) => 'a List => 'a List"
scanr :: "('a => 'b => 'b) => 'b => 'a List => 'b List"
scanr1 :: "('a => 'a => 'a) => 'a List => 'a List"
span :: "('a => Bool) => 'a List => 'a List * 'a List"
uncurry :: "('a => 'b => 'c) => 'a * 'b => 'c"

axioms
Comp1 [rule_format] :
"ALL (f :: 'b => 'c).
 ALL (g :: 'a => 'b). ALL (y :: 'a). X__o__X (f, g) y = f (g y)"

IdDef [rule_format] : "ALL (x :: 'a). id'(x) = x"

FlipDef [rule_format] :
"ALL (f :: 'a => 'b => 'c).
 ALL (x :: 'a). ALL (y :: 'b). X_flip f y x = f x y"

FstDef [rule_format] :
"ALL (x :: 'a). ALL (y :: 'b). fst'(x, y) = x"

SndDef [rule_format] :
"ALL (x :: 'a). ALL (y :: 'b). snd'(x, y) = y"

CurryDef [rule_format] :
"ALL (g :: 'a * 'b => 'c).
 ALL (x :: 'a). ALL (y :: 'b). X_curry g x y = g (x, y)"

UncurryDef [rule_format] :
"ALL (f :: 'a => 'b => 'c).
 ALL (x :: 'a). ALL (y :: 'b). uncurry f (x, y) = f x y"

NotFalse [rule_format] : "notH False' = True'"

NotTrue [rule_format] : "notH True' = False'"

AndFalse [rule_format] : "ALL (x :: Bool). False' && x = False'"

AndTrue [rule_format] : "ALL (x :: Bool). True' && x = x"

AndSym [rule_format] :
"ALL (x :: Bool). ALL (y :: Bool). x && y = y && x"

OrDef [rule_format] :
"ALL (x :: Bool).
 ALL (y :: Bool). x || y = notH (notH x && notH y)"

OtherwiseDef [rule_format] : "otherwiseH = True'"

NotFalse1 [rule_format] :
"ALL (x :: Bool). notH x = True' = (x = False')"

NotTrue1 [rule_format] :
"ALL (x :: Bool). notH x = False' = (x = True')"

notNot1 [rule_format] :
"ALL (x :: Bool). (~ x = True') = (notH x = True')"

notNot2 [rule_format] :
"ALL (x :: Bool). (~ x = False') = (notH x = False')"

EqualTDef [rule_format] :
"ALL (x :: 'a). ALL (y :: 'a). x = y --> x ==' y = True'"

EqualSymDef [rule_format] :
"ALL (x :: 'a). ALL (y :: 'a). x ==' y = y ==' x"

EqualReflex [rule_format] : "ALL (x :: 'a). x ==' x = True'"

EqualTransT [rule_format] :
"ALL (x :: 'a).
 ALL (y :: 'a).
 ALL (z :: 'a).
 x ==' y = True' & y ==' z = True' --> x ==' z = True'"

DiffDef [rule_format] :
"ALL (x :: 'a). ALL (y :: 'a). x /= y = notH (x ==' y)"

DiffSymDef [rule_format] :
"ALL (x :: 'a). ALL (y :: 'a). x /= y = y /= x"

DiffTDef [rule_format] :
"ALL (x :: 'a).
 ALL (y :: 'a). x /= y = True' = (notH (x ==' y) = True')"

DiffFDef [rule_format] :
"ALL (x :: 'a). ALL (y :: 'a). x /= y = False' = (x ==' y = True')"

TE1 [rule_format] :
"ALL (x :: 'a). ALL (y :: 'a). x ==' y = False' --> ~ x = y"

TE2 [rule_format] :
"ALL (x :: 'a).
 ALL (y :: 'a). notH (x ==' y) = True' = (x ==' y = False')"

TE3 [rule_format] :
"ALL (x :: 'a).
 ALL (y :: 'a). notH (x ==' y) = False' = (x ==' y = True')"

TE4 [rule_format] :
"ALL (x :: 'a).
 ALL (y :: 'a). (~ x ==' y = True') = (x ==' y = False')"

IBE1 [rule_format] : "True' ==' True' = True'"

IBE2 [rule_format] : "False' ==' False' = True'"

IBE3 [rule_format] : "False' ==' True' = False'"

IBE4 [rule_format] : "True' ==' False' = False'"

IBE5 [rule_format] : "True' /= False' = True'"

IBE6 [rule_format] : "False' /= True' = True'"

IBE7 [rule_format] : "notH (True' ==' False') = True'"

IBE8 [rule_format] : "notH notH (True' ==' False') = False'"

IUE1 [rule_format] : "() ==' () = True'"

IUE2 [rule_format] : "() /= () = False'"

IOE01 [rule_format] : "LT ==' LT = True'"

IOE02 [rule_format] : "EQ ==' EQ = True'"

IOE03 [rule_format] : "GT ==' GT = True'"

IOE04 [rule_format] : "LT ==' EQ = False'"

IOE05 [rule_format] : "LT ==' GT = False'"

IOE06 [rule_format] : "EQ ==' GT = False'"

IOE07 [rule_format] : "LT /= EQ = True'"

IOE08 [rule_format] : "LT /= GT = True'"

IOE09 [rule_format] : "EQ /= GT = True'"

LeIrreflexivity [rule_format] :
"ALL (x :: 'a). ALL (y :: 'a). x ==' y = True' --> x <' y = False'"

LeTAsymmetry [rule_format] :
"ALL (x :: 'a). ALL (y :: 'a). x <' y = True' --> y <' x = False'"

LeTTransitive [rule_format] :
"ALL (x :: 'a).
 ALL (y :: 'a).
 ALL (z :: 'a). x <' y = True' & y <' z = True' --> x <' z = True'"

LeTTotal [rule_format] :
"ALL (x :: 'a).
 ALL (y :: 'a). (x <' y = True' | y <' x = True') | x ==' y = True'"

GeDef [rule_format] :
"ALL (x :: 'a). ALL (y :: 'a). x >' y = y <' x"

GeIrreflexivity [rule_format] :
"ALL (x :: 'a). ALL (y :: 'a). x ==' y = True' --> x >' y = False'"

GeTAsymmetry [rule_format] :
"ALL (x :: 'a). ALL (y :: 'a). x >' y = True' --> y >' x = False'"

GeTTransitive [rule_format] :
"ALL (x :: 'a).
 ALL (y :: 'a).
 ALL (z :: 'a). (x >' y) && (y >' z) = True' --> x >' z = True'"

GeTTotal [rule_format] :
"ALL (x :: 'a).
 ALL (y :: 'a). ((x >' y) || (y >' x)) || (x ==' y) = True'"

LeqDef [rule_format] :
"ALL (x :: 'a). ALL (y :: 'a). x <=' y = (x <' y) || (x ==' y)"

LeqReflexivity [rule_format] : "ALL (x :: 'a). x <=' x = True'"

LeqTTransitive [rule_format] :
"ALL (x :: 'a).
 ALL (y :: 'a).
 ALL (z :: 'a). (x <=' y) && (y <=' z) = True' --> x <=' z = True'"

LeqTTotal [rule_format] :
"ALL (x :: 'a). ALL (y :: 'a). (x <=' y) && (y <=' x) = x ==' y"

GeqDef [rule_format] :
"ALL (x :: 'a). ALL (y :: 'a). x >=' y = (x >' y) || (x ==' y)"

GeqReflexivity [rule_format] : "ALL (x :: 'a). x >=' x = True'"

GeqTTransitive [rule_format] :
"ALL (x :: 'a).
 ALL (y :: 'a).
 ALL (z :: 'a). (x >=' y) && (y >=' z) = True' --> x >=' z = True'"

GeqTTotal [rule_format] :
"ALL (x :: 'a). ALL (y :: 'a). (x >=' y) && (y >=' x) = x ==' y"

EqTSOrdRel [rule_format] :
"ALL (x :: 'a).
 ALL (y :: 'a).
 x ==' y = True' = (x <' y = False' & x >' y = False')"

EqFSOrdRel [rule_format] :
"ALL (x :: 'a).
 ALL (y :: 'a).
 x ==' y = False' = (x <' y = True' | x >' y = True')"

EqTOrdRel [rule_format] :
"ALL (x :: 'a).
 ALL (y :: 'a).
 x ==' y = True' = (x <=' y = True' & x >=' y = True')"

EqFOrdRel [rule_format] :
"ALL (x :: 'a).
 ALL (y :: 'a).
 x ==' y = False' = (x <=' y = True' | x >=' y = True')"

EqTOrdTSubstE [rule_format] :
"ALL (x :: 'a).
 ALL (y :: 'a).
 ALL (z :: 'a). x ==' y = True' & y <' z = True' --> x <' z = True'"

EqTOrdFSubstE [rule_format] :
"ALL (x :: 'a).
 ALL (y :: 'a).
 ALL (z :: 'a).
 x ==' y = True' & y <' z = False' --> x <' z = False'"

EqTOrdTSubstD [rule_format] :
"ALL (x :: 'a).
 ALL (y :: 'a).
 ALL (z :: 'a). x ==' y = True' & z <' y = True' --> z <' x = True'"

EqTOrdFSubstD [rule_format] :
"ALL (x :: 'a).
 ALL (y :: 'a).
 ALL (z :: 'a).
 x ==' y = True' & z <' y = False' --> z <' x = False'"

LeTGeFEqFRel [rule_format] :
"ALL (x :: 'a).
 ALL (y :: 'a).
 x <' y = True' = (x >' y = False' & x ==' y = False')"

LeFGeTEqTRel [rule_format] :
"ALL (x :: 'a).
 ALL (y :: 'a).
 x <' y = False' = (x >' y = True' | x ==' y = True')"

LeTGeTRel [rule_format] :
"ALL (x :: 'a). ALL (y :: 'a). x <' y = True' = (y >' x = True')"

LeFGeFRel [rule_format] :
"ALL (x :: 'a). ALL (y :: 'a). x <' y = False' = (y >' x = False')"

LeqTGetTRel [rule_format] :
"ALL (x :: 'a). ALL (y :: 'a). x <=' y = True' = (y >=' x = True')"

LeqFGetFRel [rule_format] :
"ALL (x :: 'a).
 ALL (y :: 'a). x <=' y = False' = (y >=' x = False')"

GeTLeTRel [rule_format] :
"ALL (x :: 'a). ALL (y :: 'a). x >' y = True' = (y <' x = True')"

GeFLeFRel [rule_format] :
"ALL (x :: 'a). ALL (y :: 'a). x >' y = False' = (y <' x = False')"

GeqTLeqTRel [rule_format] :
"ALL (x :: 'a). ALL (y :: 'a). x >=' y = True' = (y <=' x = True')"

GeqFLeqFRel [rule_format] :
"ALL (x :: 'a).
 ALL (y :: 'a). x >=' y = False' = (y <=' x = False')"

LeqTGeFRel [rule_format] :
"ALL (x :: 'a). ALL (y :: 'a). x <=' y = True' = (x >' y = False')"

LeqFGeTRel [rule_format] :
"ALL (x :: 'a). ALL (y :: 'a). x <=' y = False' = (x >' y = True')"

GeTLeFEqFRel [rule_format] :
"ALL (x :: 'a).
 ALL (y :: 'a).
 x >' y = True' = (x <' y = False' & x ==' y = False')"

GeFLeTEqTRel [rule_format] :
"ALL (x :: 'a).
 ALL (y :: 'a).
 x >' y = False' = (x <' y = True' | x ==' y = True')"

GeqTLeFRel [rule_format] :
"ALL (x :: 'a). ALL (y :: 'a). x >=' y = True' = (x <' y = False')"

GeqFLeTRel [rule_format] :
"ALL (x :: 'a). ALL (y :: 'a). x >=' y = False' = (x <' y = True')"

LeqTLeTEqTRel [rule_format] :
"ALL (x :: 'a).
 ALL (y :: 'a).
 x <=' y = True' = (x <' y = True' | x ==' y = True')"

LeqFLeFEqFRel [rule_format] :
"ALL (x :: 'a).
 ALL (y :: 'a).
 x <=' y = False' = (x <' y = False' & x ==' y = False')"

GeqTGeTEqTRel [rule_format] :
"ALL (x :: 'a).
 ALL (y :: 'a).
 x >=' y = True' = (x >' y = True' | x ==' y = True')"

GeqFGeFEqFRel [rule_format] :
"ALL (x :: 'a).
 ALL (y :: 'a).
 x >=' y = False' = (x >' y = False' & x ==' y = False')"

LeTGeqFRel [rule_format] :
"ALL (x :: 'a). ALL (y :: 'a). x <' y = True' = (x >=' y = False')"

GeTLeqFRel [rule_format] :
"ALL (x :: 'a). ALL (y :: 'a). x >' y = True' = (x <=' y = False')"

LeLeqDiff [rule_format] :
"ALL (x :: 'a). ALL (y :: 'a). x <' y = (x <=' y) && (x /= y)"

CmpLTDef [rule_format] :
"ALL (x :: 'a). ALL (y :: 'a). compare x y ==' LT = x <' y"

CmpEQDef [rule_format] :
"ALL (x :: 'a). ALL (y :: 'a). compare x y ==' EQ = x ==' y"

CmpGTDef [rule_format] :
"ALL (x :: 'a). ALL (y :: 'a). compare x y ==' GT = x >' y"

MaxYDef [rule_format] :
"ALL (x :: 'a). ALL (y :: 'a). X_max x y ==' y = x <=' y"

MaxXDef [rule_format] :
"ALL (x :: 'a). ALL (y :: 'a). X_max x y ==' x = y <=' x"

MinXDef [rule_format] :
"ALL (x :: 'a). ALL (y :: 'a). X_min x y ==' x = x <=' y"

MinYDef [rule_format] :
"ALL (x :: 'a). ALL (y :: 'a). X_min x y ==' y = y <=' x"

MaxSym [rule_format] :
"ALL (x :: 'a). ALL (y :: 'a). X_max x y ==' y = X_max y x ==' y"

MinSym [rule_format] :
"ALL (x :: 'a). ALL (y :: 'a). X_min x y ==' y = X_min y x ==' y"

TO1 [rule_format] :
"ALL (x :: 'a).
 ALL (y :: 'a).
 (x ==' y = True' | x <' y = True') = (x <=' y = True')"

TO3 [rule_format] :
"ALL (x :: 'a).
 ALL (y :: 'a). notH notH (x <' y) = True' | notH (x <' y) = True'"

TO4 [rule_format] :
"ALL (x :: 'a).
 ALL (y :: 'a). x <' y = True' --> notH (x ==' y) = True'"

TO5 [rule_format] :
"ALL (w :: 'a).
 ALL (x :: 'a).
 ALL (y :: 'a).
 ALL (z :: 'a).
 (x <' y = True' & y <' z = True') & z <' w = True' -->
 x <' w = True'"

IOO13 [rule_format] : "LT <' EQ = True'"

IOO14 [rule_format] : "EQ <' GT = True'"

IOO15 [rule_format] : "LT <' GT = True'"

IOO16 [rule_format] : "LT <=' EQ = True'"

IOO17 [rule_format] : "EQ <=' GT = True'"

IOO18 [rule_format] : "LT <=' GT = True'"

IOO19 [rule_format] : "EQ >=' LT = True'"

IOO20 [rule_format] : "GT >=' EQ = True'"

IOO21 [rule_format] : "GT >=' LT = True'"

IOO22 [rule_format] : "EQ >' LT = True'"

IOO23 [rule_format] : "GT >' EQ = True'"

IOO24 [rule_format] : "GT >' LT = True'"

IOO25 [rule_format] : "X_max LT EQ ==' EQ = True'"

IOO26 [rule_format] : "X_max EQ GT ==' GT = True'"

IOO27 [rule_format] : "X_max LT GT ==' GT = True'"

IOO28 [rule_format] : "X_min LT EQ ==' LT = True'"

IOO29 [rule_format] : "X_min EQ GT ==' EQ = True'"

IOO30 [rule_format] : "X_min LT GT ==' LT = True'"

IOO31 [rule_format] : "compare LT LT ==' EQ = True'"

IOO32 [rule_format] : "compare EQ EQ ==' EQ = True'"

IOO33 [rule_format] : "compare GT GT ==' EQ = True'"

IBO5 [rule_format] : "False' <' True' = True'"

IBO6 [rule_format] : "False' >=' True' = False'"

IBO7 [rule_format] : "True' >=' False' = True'"

IBO8 [rule_format] : "True' <' False' = False'"

IBO9 [rule_format] : "X_max False' True' ==' True' = True'"

IBO10 [rule_format] : "X_min False' True' ==' False' = True'"

IBO11 [rule_format] : "compare True' True' ==' EQ = True'"

IBO12 [rule_format] : "compare False' False' ==' EQ = True'"

IUO01 [rule_format] : "() <=' () = True'"

IUO02 [rule_format] : "() <' () = False'"

IUO03 [rule_format] : "() >=' () = True'"

IUO04 [rule_format] : "() >' () = False'"

IUO05 [rule_format] : "X_max () () ==' () = True'"

IUO06 [rule_format] : "X_min () () ==' () = True'"

IUO07 [rule_format] : "compare () () ==' EQ = True'"

NotDefHead [rule_format] : "~ defOp (head(Nil'))"

HeadDef [rule_format] :
"ALL (x :: 'a).
 ALL (xs :: 'a List). head(X_Cons x xs) = makePartial x"

NotDefTail [rule_format] : "~ defOp (tail(Nil'))"

TailDef [rule_format] :
"ALL (x :: 'a).
 ALL (xs :: 'a List). tail(X_Cons x xs) = makePartial xs"

FoldrNil [rule_format] :
"ALL (f :: 'a => 'b => 'b).
 ALL (s :: 'b). X_foldr f s Nil' = makePartial s"

FoldrCons [rule_format] :
"ALL (f :: 'a => 'b => 'b).
 ALL (s :: 'b).
 ALL (x :: 'a).
 ALL (xs :: 'a List).
 X_foldr f s (X_Cons x xs) =
 restrictOp (makePartial (f x (makeTotal (X_foldr f s xs))))
 (defOp (X_foldr f s xs))"

FoldlNil [rule_format] :
"ALL (g :: 'a => 'b => 'a).
 ALL (t :: 'a). X_foldl g t Nil' = makePartial t"

FoldlCons [rule_format] :
"ALL (g :: 'a => 'b => 'a).
 ALL (t :: 'a).
 ALL (z :: 'b).
 ALL (zs :: 'b List).
 X_foldl g t (X_Cons z zs) = X_foldl g (g t z) zs"

MapNil [rule_format] : "ALL (h :: 'a => 'b). X_map h Nil' = Nil'"

MapCons [rule_format] :
"ALL (h :: 'a => 'b).
 ALL (x :: 'a).
 ALL (xs :: 'a List).
 X_map h (X_Cons x xs) = X_Cons (h x) (X_map h xs)"

XPlusXPlusNil [rule_format] : "ALL (l :: 'a List). Nil' ++' l = l"

XPlusXPlusCons [rule_format] :
"ALL (l :: 'a List).
 ALL (x :: 'a).
 ALL (xs :: 'a List). X_Cons x xs ++' l = X_Cons x (xs ++' l)"

FilterNil [rule_format] :
"ALL (p :: 'a => Bool). X_filter p Nil' = Nil'"

FilterConsT [rule_format] :
"ALL (p :: 'a => Bool).
 ALL (x :: 'a).
 ALL (xs :: 'a List).
 p x = True' -->
 X_filter p (X_Cons x xs) = X_Cons x (X_filter p xs)"

FilterConsF [rule_format] :
"ALL (p :: 'a => Bool).
 ALL (x :: 'a).
 ALL (xs :: 'a List).
 p x = False' --> X_filter p (X_Cons x xs) = X_filter p xs"

ZipNil [rule_format] : "ALL (l :: 'a List). X_zip Nil' l = Nil'"

ZipConsNil [rule_format] :
"ALL (l :: 'a List).
 ALL (x :: 'a).
 ALL (xs :: 'a List). l = Nil' --> X_zip (X_Cons x xs) l = Nil'"

ZipConsCons [rule_format] :
"ALL (l :: 'a List).
 ALL (x :: 'a).
 ALL (xs :: 'a List).
 ALL (y :: 'a).
 ALL (ys :: 'a List).
 l = X_Cons y ys -->
 X_zip (X_Cons x xs) l = X_Cons (x, y) (X_zip xs ys)"

UnzipNil [rule_format] : "unzip(Nil') = (Nil', Nil')"

UnzipCons [rule_format] :
"ALL (ps :: ('a * 'b) List).
 ALL (x :: 'a).
 ALL (z :: 'b).
 unzip(X_Cons (x, z) ps) =
 (let (ys, zs) = unzip(ps) in (X_Cons x ys, X_Cons z zs))"

ILE01 [rule_format] : "Nil' ==' Nil' = True'"

ILE02 [rule_format] :
"ALL (x :: 'a).
 ALL (xs :: 'a List).
 ALL (y :: 'a).
 ALL (ys :: 'a List).
 X_Cons x xs ==' X_Cons y ys = (x ==' y) && (xs ==' ys)"

ILO01 [rule_format] : "Nil' <' Nil' = False'"

ILO02 [rule_format] : "Nil' <=' Nil' = True'"

ILO03 [rule_format] : "Nil' >' Nil' = False'"

ILO04 [rule_format] : "Nil' >=' Nil' = True'"

ILO05 [rule_format] :
"ALL (w :: 'b).
 ALL (ws :: 'b List).
 ALL (z :: 'b).
 ALL (zs :: 'b List).
 z <' w = True' --> X_Cons z zs <' X_Cons w ws = True'"

ILO06 [rule_format] :
"ALL (w :: 'b).
 ALL (ws :: 'b List).
 ALL (z :: 'b).
 ALL (zs :: 'b List).
 z ==' w = True' --> X_Cons z zs <' X_Cons w ws = zs <' ws"

ILO07 [rule_format] :
"ALL (w :: 'b).
 ALL (ws :: 'b List).
 ALL (z :: 'b).
 ALL (zs :: 'b List).
 z <' w = False' & z ==' w = False' -->
 X_Cons z zs <' X_Cons w ws = False'"

ILO08 [rule_format] :
"ALL (w :: 'b).
 ALL (ws :: 'b List).
 ALL (z :: 'b).
 ALL (zs :: 'b List).
 X_Cons z zs <=' X_Cons w ws =
 (X_Cons z zs <' X_Cons w ws) || (X_Cons z zs ==' X_Cons w ws)"

ILO09 [rule_format] :
"ALL (w :: 'b).
 ALL (ws :: 'b List).
 ALL (z :: 'b).
 ALL (zs :: 'b List).
 X_Cons z zs >' X_Cons w ws = X_Cons w ws <' X_Cons z zs"

ILO10 [rule_format] :
"ALL (w :: 'b).
 ALL (ws :: 'b List).
 ALL (z :: 'b).
 ALL (zs :: 'b List).
 X_Cons z zs >=' X_Cons w ws =
 (X_Cons z zs >' X_Cons w ws) || (X_Cons z zs ==' X_Cons w ws)"

ILO11 [rule_format] : "compare Nil' Nil' ==' EQ = Nil' ==' Nil'"

ILO12 [rule_format] : "compare Nil' Nil' ==' LT = Nil' <' Nil'"

ILO13 [rule_format] : "compare Nil' Nil' ==' GT = Nil' >' Nil'"

ILO14 [rule_format] :
"ALL (w :: 'b).
 ALL (ws :: 'b List).
 ALL (z :: 'b).
 ALL (zs :: 'b List).
 compare (X_Cons z zs) (X_Cons w ws) ==' EQ =
 X_Cons z zs ==' X_Cons w ws"

ILO15 [rule_format] :
"ALL (w :: 'b).
 ALL (ws :: 'b List).
 ALL (z :: 'b).
 ALL (zs :: 'b List).
 compare (X_Cons z zs) (X_Cons w ws) ==' LT =
 X_Cons z zs <' X_Cons w ws"

ILO16 [rule_format] :
"ALL (w :: 'b).
 ALL (ws :: 'b List).
 ALL (z :: 'b).
 ALL (zs :: 'b List).
 compare (X_Cons z zs) (X_Cons w ws) ==' GT =
 X_Cons z zs >' X_Cons w ws"

ILO17 [rule_format] : "X_max Nil' Nil' ==' Nil' = Nil' <=' Nil'"

ILO18 [rule_format] : "X_min Nil' Nil' ==' Nil' = Nil' <=' Nil'"

ILO19 [rule_format] :
"ALL (w :: 'b).
 ALL (ws :: 'b List).
 ALL (z :: 'b).
 ALL (zs :: 'b List).
 X_Cons z zs <=' X_Cons w ws =
 X_max (X_Cons z zs) (X_Cons w ws) ==' X_Cons w ws"

ILO20 [rule_format] :
"ALL (w :: 'b).
 ALL (ws :: 'b List).
 ALL (z :: 'b).
 ALL (zs :: 'b List).
 X_Cons w ws <=' X_Cons z zs =
 X_max (X_Cons z zs) (X_Cons w ws) ==' X_Cons z zs"

ILO21 [rule_format] :
"ALL (w :: 'b).
 ALL (ws :: 'b List).
 ALL (z :: 'b).
 ALL (zs :: 'b List).
 X_Cons z zs <=' X_Cons w ws =
 X_min (X_Cons z zs) (X_Cons w ws) ==' X_Cons z zs"

ILO22 [rule_format] :
"ALL (w :: 'b).
 ALL (ws :: 'b List).
 ALL (z :: 'b).
 ALL (zs :: 'b List).
 X_Cons w ws <=' X_Cons z zs =
 X_min (X_Cons z zs) (X_Cons w ws) ==' X_Cons w ws"

FoldlDecomp [rule_format] :
"ALL (e :: 'a).
 ALL (i :: 'a => 'b => 'a).
 ALL (ts :: 'b List).
 ALL (ys :: 'b List).
 X_foldl i e (ys ++' ts) =
 restrictOp (X_foldl i (makeTotal (X_foldl i e ys)) ts)
 (defOp (X_foldl i e ys))"

MapDecomp [rule_format] :
"ALL (f :: 'a => 'b).
 ALL (xs :: 'a List).
 ALL (zs :: 'a List).
 X_map f (xs ++' zs) = X_map f xs ++' X_map f zs"

MapFunctor [rule_format] :
"ALL (f :: 'a => 'b).
 ALL (g :: 'b => 'c).
 ALL (xs :: 'a List).
 X_map (X__o__X (g, f)) xs = X_map g (X_map f xs)"

FilterProm [rule_format] :
"ALL (f :: 'a => 'b).
 ALL (p :: 'b => Bool).
 ALL (xs :: 'a List).
 X_filter p (X_map f xs) = X_map f (X_filter (X__o__X (p, f)) xs)"

InitNil [rule_format] : "~ defOp (init(Nil'))"

InitConsNil [rule_format] :
"ALL (x :: 'a). init(X_Cons x Nil') = makePartial Nil'"

InitConsCons [rule_format] :
"ALL (x :: 'a).
 ALL (xs :: 'a List).
 init(X_Cons x xs) =
 restrictOp (makePartial (X_Cons x (makeTotal (init(xs)))))
 (defOp (init(xs)))"

LastNil [rule_format] : "~ defOp (last'(Nil'))"

LastConsNil [rule_format] :
"ALL (x :: 'a). last'(X_Cons x Nil') = makePartial x"

LastConsCons [rule_format] :
"ALL (x :: 'a).
 ALL (xs :: 'a List). last'(X_Cons x xs) = last'(xs)"

NullNil [rule_format] : "null'(Nil') = True'"

NullCons [rule_format] :
"ALL (x :: 'a). ALL (xs :: 'a List). null'(X_Cons x xs) = False'"

ReverseNil [rule_format] : "reverse(Nil') = Nil'"

ReverseCons [rule_format] :
"ALL (x :: 'a).
 ALL (xs :: 'a List).
 reverse(X_Cons x xs) = reverse(xs) ++' X_Cons x Nil'"

Foldr1Nil [rule_format] :
"ALL (f :: 'a => 'a => 'a). ~ defOp (foldr1 f Nil')"

Foldr1ConsNil [rule_format] :
"ALL (f :: 'a => 'a => 'a).
 ALL (x :: 'a). foldr1 f (X_Cons x Nil') = makePartial x"

Foldr1ConsCons [rule_format] :
"ALL (f :: 'a => 'a => 'a).
 ALL (x :: 'a).
 ALL (xs :: 'a List).
 foldr1 f (X_Cons x xs) =
 restrictOp (makePartial (f x (makeTotal (foldr1 f xs))))
 (defOp (foldr1 f xs))"

Foldl1Nil [rule_format] :
"ALL (f :: 'a => 'a => 'a). ~ defOp (foldl1 f Nil')"

Foldl1ConsNil [rule_format] :
"ALL (f :: 'a => 'a => 'a).
 ALL (x :: 'a). foldl1 f (X_Cons x Nil') = makePartial x"

Foldl1ConsCons [rule_format] :
"ALL (f :: 'a => 'a => 'a).
 ALL (x :: 'a).
 ALL (xs :: 'a List).
 foldl1 f (X_Cons x xs) =
 restrictOp (makePartial (f x (makeTotal (foldr1 f xs))))
 (defOp (foldr1 f xs))"

ScanlNil [rule_format] :
"ALL (g :: 'a => 'b => 'a).
 ALL (q :: 'a).
 ALL (ys :: 'b List). ys = Nil' --> scanl g q ys = X_Cons q Nil'"

ScanlCons [rule_format] :
"ALL (g :: 'a => 'b => 'a).
 ALL (q :: 'a).
 ALL (ys :: 'b List).
 ALL (z :: 'b).
 ALL (zs :: 'b List).
 ys = X_Cons z zs --> scanl g q ys = X_Cons q (scanl g (g q z) zs)"

Scanl1Nil [rule_format] :
"ALL (f :: 'a => 'a => 'a). scanl1 f Nil' = Nil'"

Scanl1Cons [rule_format] :
"ALL (f :: 'a => 'a => 'a).
 ALL (x :: 'a).
 ALL (xs :: 'a List). scanl1 f (X_Cons x xs) = scanl f x xs"

ScanrNil [rule_format] :
"ALL (h :: 'a => 'b => 'b).
 ALL (z :: 'b). scanr h z Nil' = X_Cons z Nil'"

ScanrCons [rule_format] :
"ALL (h :: 'a => 'b => 'b).
 ALL (x :: 'a).
 ALL (xs :: 'a List).
 ALL (y :: 'b).
 ALL (ys :: 'b List).
 ALL (z :: 'b).
 X_Cons y ys = scanr h z xs -->
 scanr h z (X_Cons x xs) = X_Cons (h x y) (X_Cons y ys)"

Scanr1Nil [rule_format] :
"ALL (f :: 'a => 'a => 'a). scanr1 f Nil' = Nil'"

Scanr1ConsNil [rule_format] :
"ALL (f :: 'a => 'a => 'a).
 ALL (x :: 'a). scanr1 f (X_Cons x Nil') = X_Cons x Nil'"

Scanr1ConsCons [rule_format] :
"ALL (f :: 'a => 'a => 'a).
 ALL (q :: 'a).
 ALL (qs :: 'a List).
 ALL (x :: 'a).
 ALL (xs :: 'a List).
 X_Cons q qs = scanr1 f xs -->
 scanr1 f (X_Cons x xs) = X_Cons (f x q) (X_Cons q qs)"

ScanlProperty [rule_format] :
"ALL (g :: 'a => 'b => 'a).
 ALL (x :: 'a).
 ALL (ys :: 'b List). last'(scanl g x ys) = X_foldl g x ys"

ScanrProperty [rule_format] :
"ALL (h :: 'a => 'b => 'b).
 ALL (xs :: 'a List).
 ALL (y :: 'b). head(scanr h y xs) = X_foldr h y xs"

AndLNil [rule_format] : "andL(Nil') = True'"

AndLCons [rule_format] :
"ALL (b1 :: Bool).
 ALL (bs :: Bool List). andL(X_Cons b1 bs) = b1 && andL(bs)"

OrLNil [rule_format] : "orL(Nil') = False'"

OrLCons [rule_format] :
"ALL (b1 :: Bool).
 ALL (bs :: Bool List). orL(X_Cons b1 bs) = b1 || orL(bs)"

AnyDef [rule_format] :
"ALL (p :: 'a => Bool).
 ALL (xs :: 'a List). X_any p xs = orL(X_map p xs)"

AllDef [rule_format] :
"ALL (p :: 'a => Bool).
 ALL (xs :: 'a List). X_all p xs = andL(X_map p xs)"

ConcatDef [rule_format] :
"ALL (xxs :: 'a List List).
 makePartial (concat'(xxs)) =
 X_foldr (X_curry (uncurryOp X__XPlusXPlus__X)) Nil' xxs"

ConcatMapDef [rule_format] :
"ALL (g :: 'a => 'b List).
 ALL (xs :: 'a List). concatMap g xs = concat'(X_map g xs)"

MaximunNil [rule_format] : "~ defOp (maximum(Nil'))"

MaximumDef [rule_format] :
"ALL (ds :: 'd List). maximum(ds) = foldl1 X_max ds"

MinimunNil [rule_format] : "~ defOp (minimum(Nil'))"

MinimumDef [rule_format] :
"ALL (ds :: 'd List). minimum(ds) = foldl1 X_min ds"

TakeWhileNil [rule_format] :
"ALL (p :: 'a => Bool). X_takeWhile p Nil' = Nil'"

TakeWhileConsT [rule_format] :
"ALL (p :: 'a => Bool).
 ALL (x :: 'a).
 ALL (xs :: 'a List).
 p x = True' -->
 X_takeWhile p (X_Cons x xs) = X_Cons x (X_takeWhile p xs)"

TakeWhileConsF [rule_format] :
"ALL (p :: 'a => Bool).
 ALL (x :: 'a).
 ALL (xs :: 'a List).
 p x = False' --> X_takeWhile p (X_Cons x xs) = Nil'"

DropWhileNil [rule_format] :
"ALL (p :: 'a => Bool). X_dropWhile p Nil' = Nil'"

DropWhileConsT [rule_format] :
"ALL (p :: 'a => Bool).
 ALL (x :: 'a).
 ALL (xs :: 'a List).
 p x = True' --> X_dropWhile p (X_Cons x xs) = X_dropWhile p xs"

DropWhileConsF [rule_format] :
"ALL (p :: 'a => Bool).
 ALL (x :: 'a).
 ALL (xs :: 'a List).
 p x = False' --> X_dropWhile p (X_Cons x xs) = X_Cons x xs"

SpanNil [rule_format] :
"ALL (p :: 'a => Bool). span p Nil' = (Nil', Nil')"

SpanConsT [rule_format] :
"ALL (p :: 'a => Bool).
 ALL (x :: 'a).
 ALL (xs :: 'a List).
 p x = True' -->
 span p (X_Cons x xs) =
 (let (ys, zs) = span p xs in (X_Cons x ys, zs))"

SpanConsF [rule_format] :
"ALL (p :: 'a => Bool).
 ALL (x :: 'a).
 ALL (xs :: 'a List).
 p x = False' -->
 span p (X_Cons x xs) =
 (let (ys, zs) = span p xs in (Nil', X_Cons x xs))"

BreakDef [rule_format] :
"ALL (p :: 'a => Bool).
 ALL (xs :: 'a List).
 break p xs = (let q = X__o__X (notH__X, p) in span q xs)"

declare Comp1 [simp]
declare IdDef [simp]
declare FlipDef [simp]
declare FstDef [simp]
declare SndDef [simp]
declare CurryDef [simp]
declare UncurryDef [simp]
declare NotFalse [simp]
declare NotTrue [simp]
declare AndFalse [simp]
declare AndTrue [simp]
declare EqualReflex [simp]
declare IBE1 [simp]
declare IBE2 [simp]
declare IBE3 [simp]
declare IBE4 [simp]
declare IBE5 [simp]
declare IBE6 [simp]
declare IBE7 [simp]
declare IBE8 [simp]
declare IOE01 [simp]
declare IOE02 [simp]
declare IOE03 [simp]
declare IOE04 [simp]
declare IOE05 [simp]
declare IOE06 [simp]
declare IOE07 [simp]
declare IOE08 [simp]
declare IOE09 [simp]
declare LeIrreflexivity [simp]
declare LeTAsymmetry [simp]
declare GeIrreflexivity [simp]
declare GeTAsymmetry [simp]
declare GeTTransitive [simp]
declare GeTTotal [simp]
declare LeqReflexivity [simp]
declare LeqTTransitive [simp]
declare LeqTTotal [simp]
declare GeqReflexivity [simp]
declare GeqTTransitive [simp]
declare GeqTTotal [simp]
declare CmpLTDef [simp]
declare CmpEQDef [simp]
declare CmpGTDef [simp]
declare MaxYDef [simp]
declare MaxXDef [simp]
declare MinXDef [simp]
declare MinYDef [simp]
declare TO4 [simp]
declare IOO13 [simp]
declare IOO14 [simp]
declare IOO15 [simp]
declare IOO16 [simp]
declare IOO17 [simp]
declare IOO18 [simp]
declare IOO19 [simp]
declare IOO20 [simp]
declare IOO21 [simp]
declare IOO22 [simp]
declare IOO23 [simp]
declare IOO24 [simp]
declare IOO25 [simp]
declare IOO26 [simp]
declare IOO27 [simp]
declare IOO28 [simp]
declare IOO29 [simp]
declare IOO30 [simp]
declare IOO31 [simp]
declare IOO32 [simp]
declare IOO33 [simp]
declare IBO5 [simp]
declare IBO6 [simp]
declare IBO7 [simp]
declare IBO8 [simp]
declare IBO9 [simp]
declare IBO10 [simp]
declare IBO11 [simp]
declare IBO12 [simp]
declare IUO05 [simp]
declare IUO06 [simp]
declare IUO07 [simp]
declare NotDefHead [simp]
declare HeadDef [simp]
declare NotDefTail [simp]
declare TailDef [simp]
declare FoldrNil [simp]
declare FoldlNil [simp]
declare MapNil [simp]
declare XPlusXPlusNil [simp]
declare FilterNil [simp]
declare FilterConsF [simp]
declare ZipNil [simp]
declare ILE01 [simp]
declare ILO01 [simp]
declare ILO02 [simp]
declare ILO03 [simp]
declare ILO04 [simp]
declare ILO05 [simp]
declare ILO06 [simp]
declare ILO11 [simp]
declare ILO12 [simp]
declare ILO13 [simp]
declare ILO14 [simp]
declare ILO15 [simp]
declare ILO16 [simp]
declare ILO17 [simp]
declare ILO18 [simp]
declare InitNil [simp]
declare InitConsNil [simp]
declare LastNil [simp]
declare LastConsNil [simp]
declare LastConsCons [simp]
declare NullNil [simp]
declare NullCons [simp]
declare ReverseNil [simp]
declare Foldr1Nil [simp]
declare Foldr1ConsNil [simp]
declare Foldl1Nil [simp]
declare Foldl1ConsNil [simp]
declare Scanl1Nil [simp]
declare Scanl1Cons [simp]
declare ScanrNil [simp]
declare Scanr1Nil [simp]
declare Scanr1ConsNil [simp]
declare ScanlProperty [simp]
declare ScanrProperty [simp]
declare AndLNil [simp]
declare OrLNil [simp]
declare MaximunNil [simp]
declare MinimunNil [simp]
declare TakeWhileNil [simp]
declare TakeWhileConsF [simp]
declare DropWhileNil [simp]
declare DropWhileConsT [simp]
declare DropWhileConsF [simp]
declare SpanNil [simp]

theorem SpanThm :
"ALL (p :: 'a => Bool).
 ALL (xs :: 'a List).
 span p xs = (X_takeWhile p xs, X_dropWhile p xs)"
apply(auto)
apply(case_tac xs)
apply(auto)
apply(induct_tac List)
apply(case_tac "p a")
apply(simp add: TakeWhileConsF DropWhileConsF SpanConsF)
apply(case_tac "p aa")
apply(simp add: TakeWhileConsT DropWhileConsT SpanConsT TakeWhileConsF DropWhileConsF SpanConsF TakeWhileNil DropWhileNil SpanNil)+
apply(simp add: split_def)
apply(case_tac "p a")
apply(simp add: TakeWhileConsT DropWhileConsT SpanConsT TakeWhileConsF DropWhileConsF SpanConsF TakeWhileNil DropWhileNil SpanNil)+
done

setup "Header.record \"SpanThm\""

theorem BreakThm :
"ALL (p :: 'a => Bool).
 ALL (xs :: 'a List). break p xs = span (X__o__X (notH__X, p)) xs"
apply(auto)
apply(case_tac xs)
apply(auto)
apply(simp add: BreakDef)+
done

setup "Header.record \"BreakThm\""

end