Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/Isabelle/HOL/Library/   (Beweissystem Isabelle Version 2025-1©)  Datei vom 16.11.2025 mit Größe 78 kB image not shown  

Quelle  FSet.thy

  Sprache: Isabelle
 

(*  Title:      HOL/Library/FSet.thy
  Author: Ondrej Kuncar, TU Muenchen
  Author: Cezary Kaliszyk and Christian Urban
  Author: Andrei Popescu, TU Muenchen
  Author: Martin Desharnais, MPI-INF Saarbruecken
*)

section Type of finite sets defined as a subtype of sets

theory FSet
imports Main Countable
begin

subsection Definition of the type

typedef 'a fset = "{A :: 'a set. finite A}"  morphisms fset Abs_fset
by auto

setup_lifting type_definition_fset


subsection Basic operations and type class instantiations

(* FIXME transfer and right_total vs. bi_total *)
instantiation fset :: (finite) finite
begin
instance by (standard; transfer; simp)
end

instantiation fset :: (type) "{bounded_lattice_bot, distrib_lattice, minus}"
begin

lift_definition bot_fset :: "'a fset" is "{}" parametric empty_transfer by simp

lift_definition less_eq_fset :: "'a fset ==> 'a fset ==> bool" is subset_eq parametric subset_transfer
  .

definition less_fset :: "'a fset ==> 'a fset ==> bool" where "xs < ys xs ys xs (ys::'a fset)"

lemma less_fset_transfer[transfer_rule]:
  includes lifting_syntax
  assumes [transfer_rule]: "bi_unique A"
  shows "((pcr_fset A) ===> (pcr_fset A) ===> (=)) () (<)"
  unfolding less_fset_def[abs_def] psubset_eq[abs_def] by transfer_prover


lift_definition sup_fset :: "'a fset ==> 'a fset ==> 'a fset" is union parametric union_transfer
  by simp

lift_definition inf_fset :: "'a fset ==> 'a fset ==> 'a fset" is inter parametric inter_transfer
  by simp

lift_definition minus_fset :: "'a fset ==> 'a fset ==> 'a fset" is minus parametric Diff_transfer
  by simp

instance
  by (standard; transfer; auto)+

end

abbreviation fempty :: "'a fset" ({||}where "{||} bot"
abbreviation fsubset_eq :: "'a fset ==> 'a fset ==> bool" (infix || 50) where "xs || ys xs ys"
abbreviation fsubset :: "'a fset ==> 'a fset ==> bool" (infix || 50) where "xs || ys xs < ys"
abbreviation funion :: "'a fset ==> 'a fset ==> 'a fset" (infixl || 65) where "xs || ys sup xs ys"
abbreviation finter :: "'a fset ==> 'a fset ==> 'a fset" (infixl || 65) where "xs || ys inf xs ys"
abbreviation fminus :: "'a fset ==> 'a fset ==> 'a fset" (infixl |-| 65) where "xs |-| ys minus xs ys"

instantiation fset :: (equal) equal
begin
definition "HOL.equal A B A || B B || A"
instance by intro_classes (auto simp add: equal_fset_def)
end

instantiation fset :: (type) conditionally_complete_lattice
begin

context includes lifting_syntax
begin

lemma right_total_Inf_fset_transfer:
  assumes [transfer_rule]: "bi_unique A" and [transfer_rule]: "right_total A"
  shows "(rel_set (rel_set A) ===> rel_set A)
    (λS. if finite (S Collect (Domainp A)) then S Collect (Domainp A) else {})
      (λS. if finite (Inf S) then Inf S else {})"
    by transfer_prover

lemma Inf_fset_transfer:
  assumes [transfer_rule]: "bi_unique A" and [transfer_rule]: "bi_total A"
  shows "(rel_set (rel_set A) ===> rel_set A) (λA. if finite (Inf A) then Inf A else {})
    (λA. if finite (Inf A) then Inf A else {})"
  by transfer_prover

lift_definition Inf_fset :: "'a fset set ==> 'a fset" is "λA. if finite (Inf A) then Inf A else {}"
parametric right_total_Inf_fset_transfer Inf_fset_transfer by simp

lemma Sup_fset_transfer:
  assumes [transfer_rule]: "bi_unique A"
  shows "(rel_set (rel_set A) ===> rel_set A) (λA. if finite (Sup A) then Sup A else {})
  (λA. if finite (Sup A) then Sup A else {})" by transfer_prover

lift_definition Sup_fset :: "'a fset set ==> 'a fset" is "λA. if finite (Sup A) then Sup A else {}"
parametric Sup_fset_transfer by simp

lemma finite_Sup: "z. finite z (a. a X a z) ==> finite (Sup X)"
by (auto intro: finite_subset)

lemma transfer_bdd_below[transfer_rule]: "(rel_set (pcr_fset (=)) ===> (=)) bdd_below bdd_below"
  by auto

end

instance
proof
  fix x z :: "'a fset"
  fix X :: "'a fset set"
  {
    assume "x X" "bdd_below X"
    then show "Inf X || x" by transfer auto
  next
    assume "X {}" "(x. x X ==> z || x)"
    then show "z || Inf X" by transfer (clarsimp, blast)
  next
    assume "x X" "bdd_above X"
    then obtain z where "x X" "(x. x X ==> x || z)"
      by (auto simp: bdd_above_def)
    then show "x || Sup X"
      by transfer (auto intro!: finite_Sup)
  next
    assume "X {}" "(x. x X ==> x || z)"
    then show "Sup X || z" by transfer (clarsimp, blast)
  }
qed
end

instantiation fset :: (finite) complete_lattice
begin

lift_definition top_fset :: "'a fset" is UNIV parametric right_total_UNIV_transfer UNIV_transfer
  by simp

instance
  by (standard; transfer; auto)

end

instantiation fset :: (finite) complete_boolean_algebra
begin

lift_definition uminus_fset :: "'a fset ==> 'a fset" is uminus
  parametric right_total_Compl_transfer Compl_transfer by simp

instance
  by (standard; transfer) (simp_all add: Inf_Sup Diff_eq)
end

abbreviation fUNIV :: "'a::finite fset" where "fUNIV top"
abbreviation fuminus :: "'a::finite fset ==> 'a fset" (|-| _ [81] 80) where "|-| x uminus x"

declare top_fset.rep_eq[simp]


subsection Other operations

lift_definition finsert :: "'a ==> 'a fset ==> 'a fset" is insert parametric Lifting_Set.insert_transfer
  by simp

syntax
  "_fset" :: "args => 'a fset"  ((indent=2 notation=mixfix finite set enumeration\{|_|}))
syntax_consts
  "_fset"  finsert
translations
  "{|x, xs|}" == "CONST finsert x {|xs|}"
  "{|x|}"     == "CONST finsert x {||}"

abbreviation fmember :: "'a ==> 'a fset ==> bool" (infix || 50) where
  "x || X x fset X"

abbreviation not_fmember :: "'a ==> 'a fset ==> bool" (infix || 50) where
  "x || X x fset X"

context
begin

qualified abbreviation Ball :: "'a fset ==> ('a ==> bool) ==> bool" where
  "Ball X Set.Ball (fset X)"

alias fBall = FSet.Ball

qualified abbreviation Bex :: "'a fset ==> ('a ==> bool) ==> bool" where
  "Bex X Set.Bex (fset X)"

alias fBex = FSet.Bex

end

syntax (input)
  "_fBall" :: "pttrn ==> 'a fset ==> bool ==> bool"  ((indent=3 notation=binder finite !\! (_/|:|_)./ _) [0, 0, 10] 10)
  "_fBex"  :: "pttrn ==> 'a fset ==> bool ==> bool"  ((indent=3 notation=binder finite ?\? (_/|:|_)./ _) [0, 0, 10] 10)
  "_fBex1" :: "pttrn ==> 'a fset ==> bool ==> bool"  ((indent=3 notation=binder finite ?!\?! (_/:_)./ _) [0, 0, 10] 10)

syntax
  "_fBall" :: "pttrn ==> 'a fset ==> bool ==> bool"  ((indent=3 notation=binder finite \\∈|_)./ _) [0, 0, 10] 10)
  "_fBex"  :: "pttrn ==> 'a fset ==> bool ==> bool"  ((indent=3 notation=binder finite \\∈|_)./ _) [0, 0, 10] 10)
  "_fBnex" :: "pttrn ==> 'a fset ==> bool ==> bool"  ((indent=3 notation=binder finite \\∈|_)./ _) [0, 0, 10] 10)
  "_fBex1" :: "pttrn ==> 'a fset ==> bool ==> bool"  ((indent=3 notation=binder finite !\\∈|_)./ _) [0, 0, 10] 10)

syntax_consts
  "_fBall" "_fBnex"  fBall and
  "_fBex"  fBex and
  "_fBex1"  Ex1

translations
  "x||A. P"  "CONST FSet.Ball A (λx. P)"
  "x||A. P"  "CONST FSet.Bex A (λx. P)"
  "x||A. P"  "CONST fBall A (λx. ¬ P)"
  "!x||A. P"  "!x. x || A P"

typed_print_translation 
  [(🍋fBall,
  (🍋fBex, Syntax_Trans.preserve_binder_abs2_tr' 🍋_fBex)]
 🍋 to avoid eta-contraction of body

syntax
  "_setlessfAll" :: "[idt, 'a, bool] ==> bool"   ((indent=3 notation=binder finite \\⊂|_./ _)  [0, 0, 10] 10)
  "_setlessfEx"  :: "[idt, 'a, bool] ==> bool"   ((indent=3 notation=binder finite \\⊂|_./ _)  [0, 0, 10] 10)
  "_setlefAll"   :: "[idt, 'a, bool] ==> bool"   ((indent=3 notation=binder finite \\⊆|_./ _) [0, 0, 10] 10)
  "_setlefEx"    :: "[idt, 'a, bool] ==> bool"   ((indent=3 notation=binder finite \\⊆|_./ _) [0, 0, 10] 10)

syntax_consts
  "_setlessfAll" "_setlefAll"  All and
  "_setlessfEx" "_setlefEx"  Ex

translations
 "A||B. P"  "A. A || B P"
 "A||B. P"  "A. A || B P"
 "A||B. P"  "A. A || B P"
 "A||B. P"  "A. A || B P"


context includes lifting_syntax
begin

lemma fmember_transfer0[transfer_rule]:
  assumes [transfer_rule]: "bi_unique A"
  shows "(A ===> pcr_fset A ===> (=)) () (||)"
  by transfer_prover

lemma fBall_transfer0[transfer_rule]:
  assumes [transfer_rule]: "bi_unique A"
  shows "(pcr_fset A ===> (A ===> (=)) ===> (=)) (Ball) (fBall)"
  by transfer_prover

lemma fBex_transfer0[transfer_rule]:
  assumes [transfer_rule]: "bi_unique A"
  shows "(pcr_fset A ===> (A ===> (=)) ===> (=)) (Bex) (fBex)"
  by transfer_prover

lift_definition ffilter :: "('a ==> bool) ==> 'a fset ==> 'a fset" is Set.filter
  parametric Lifting_Set.filter_transfer by simp

lift_definition fPow :: "'a fset ==> 'a fset fset" is Pow parametric Pow_transfer
by (simp add: finite_subset)

lift_definition fcard :: "'a fset ==> nat" is card parametric card_transfer .

lift_definition fimage :: "('a ==> 'b) ==> 'a fset ==> 'b fset" (infixr |`| 90) is image
  parametric image_transfer by simp

lift_definition fthe_elem :: "'a fset ==> 'a" is the_elem .

lift_definition fbind :: "'a fset ==> ('a ==> 'b fset) ==> 'b fset" is Set.bind parametric bind_transfer
by (simp add: Set.bind_def)

lift_definition ffUnion :: "'a fset fset ==> 'a fset" is Union parametric Union_transfeby simp

lift_definition ffold :: "('a ==> 'b ==> 'b) ==> 'b ==> 'a fset ==> 'b" is Finite_Set.fold .

lift_definition fset_of_list :: "'a list ==> 'a fset" is set by (rule finite_set)

lift_definition sorted_list_of_fset :: "'a::linorder fset ==> 'a list" is sorted_list_of_set .


subsection Transferred lemmas from Set.thy

lemma fset_eqI: "(x. (x || A) = (x || B)) ==> A = B"
  by (rule set_eqI[Transfer.transferred])

lemma fset_eq_iff[no_atp]: "(A = B) = (x. (x || A) = (x || B))"
  by (rule set_eq_iff[Transfer.transferred])

lemma fBallI[no_atp]: "(x. x || A ==> P x) ==> fBall A P"
  by (rule ballI[Transfer.transferred])

lemma fbspec[no_atp]: "fBall A P ==> x || A ==> P x"
  by (rule bspec[Transfer.transferred])

lemma fBallE[no_atp]: "fBall A P ==> (P x ==> Q) ==> (x || A ==> Q) ==> Q"
  by (rule ballE[Transfer.transferred])

lemma fBexI[no_atp]: "P x ==> x || A ==> fBex A P"
  by (rule bexI[Transfer.transferred])

lemma rev_fBexI[no_atp]: "x || A ==> P x ==> fBex A P"
  by (rule rev_bexI[Transfer.transferred])

lemma fBexCI[no_atp]: "(fBall A (λx. ¬ P x) ==> P a) ==> a || A ==> fBex A P"
  by (rule bexCI[Transfer.transferred])

lemma fBexE[no_atp]: "fBex A P ==> (x. x || A ==> P x ==> Q) ==> Q"
  by (rule bexE[Transfer.transferred])

lemma fBall_triv[no_atp]: "fBall A (λx. P) = ((x. x || A) P)"
  by (rule ball_triv[Transfer.transferred])

lemma fBex_triv[no_atp]: "fBex A (λx. P) = ((x. x || A) P)"
  by (rule bex_triv[Transfer.transferred])

lemma fBex_triv_one_point1[no_atp]: "fBex A (λx. x = a) = (a || A)"
  by (rule bex_triv_one_point1[Transfer.transferred])

lemma fBex_triv_one_point2[no_atp]: "fBex A ((=) a) = (a || A)"
  by (rule bex_triv_one_point2[Transfer.transferred])

lemma fBex_one_point1[no_atp]: "fBex A (λx. x = a P x) = (a || A P a)"
  by (rule bex_one_point1[Transfer.transferred])

lemma fBex_one_point2[no_atp]: "fBex A (λx. a = x P x) = (a || A P a)"
  by (rule bex_one_point2[Transfer.transferred])

lemma fBall_one_point1[no_atp]: "fBall A (λx. x = a P x) = (a || A P a)"
  by (rule ball_one_point1[Transfer.transferred])

lemma fBall_one_point2[no_atp]: "fBall A (λx. a = x P x) = (a || A P a)"
  by (rule ball_one_point2[Transfer.transferred])

lemma fBall_conj_distrib: "fBall A (λx. P x Q x) = (fBall A P fBall A Q)"
  by (rule ball_conj_distrib[Transfer.transferred])

lemma fBex_disj_distrib: "fBex A (λx. P x Q x) = (fBex A P fBex A Q)"
  by (rule bex_disj_distrib[Transfer.transferred])

lemma fBall_cong[fundef_cong]: "A = B ==> (x. x || B ==> P x = Q x) ==> fBall A P = fBall B Q"
  by (rule ball_cong[Transfer.transferred])

lemma fBex_cong[fundef_cong]: "A = B ==> (x. x || B ==> P x = Q x) ==> fBex A P = fBex B Q"
  by (rule bex_cong[Transfer.transferred])

lemma fsubsetI[intro!]: "(x. x || A ==> x || B) ==> A || B"
  by (rule subsetI[Transfer.transferred])

lemma fsubsetD[elim, intro?]: "A || B ==> c || A ==> c || B"
  by (rule subsetD[Transfer.transferred])

lemma rev_fsubsetD[no_atp,intro?]: "c || A ==> A || B ==> c || B"
  by (rule rev_subsetD[Transfer.transferred])

lemma fsubsetCE[no_atp,elim]: "A || B ==> (c || A ==> P) ==> (c || B ==> P) ==> P"
  by (rule subsetCE[Transfer.transferred])

lemma fsubset_eq[no_atp]: "(A || B) = fBall A (λx. x || B)"
  by (rule subset_eq[Transfer.transferred])

lemma contra_fsubsetD[no_atp]: "A || B ==> c || B ==> c || A"
  by (rule contra_subsetD[Transfer.transferred])

lemma fsubset_refl: "A || A"
  by (rule subset_refl[Transfer.transferred])

lemma fsubset_trans: "A || B ==> B || C ==> A || C"
  by (rule subset_trans[Transfer.transferred])

lemma fset_rev_mp: "c || A ==> A || B ==> c || B"
  by (rule rev_subsetD[Transfer.transferred])

lemma fset_mp: "A || B ==> c || A ==> c || B"
  by (rule subsetD[Transfer.transferred])

lemma fsubset_not_fsubset_eq[code]: "(A || B) = (A || B ¬ B || A)"
  by (rule subset_not_subset_eq[Transfer.transferred])

lemma eq_fmem_trans: "a = b ==> b || A ==> a || A"
  by (rule eq_mem_trans[Transfer.transferred])

lemma fsubset_antisym[intro!]: "A || B ==> B || A ==> A = B"
  by (rule subset_antisym[Transfer.transferred])

lemma fequalityD1: "A = B ==> A || B"
  by (rule equalityD1[Transfer.transferred])

lemma fequalityD2: "A = B ==> B || A"
  by (rule equalityD2[Transfer.transferred])

lemma fequalityE: "A = B ==> (A || B ==> B || A ==> P) ==> P"
  by (rule equalityE[Transfer.transferred])

lemma fequalityCE[elim]:
  "A = B ==> (c || A ==> c || B ==> P) ==> (c || A ==> c || B ==> P) ==> P"
  by (rule equalityCE[Transfer.transferred])

lemma eqfset_imp_iff: "A = B ==> (x || A) = (x || B)"
  by (rule eqset_imp_iff[Transfer.transferred])

lemma eqfelem_imp_iff: "x = y ==> (x || A) = (y || A)"
  by (rule eqelem_imp_iff[Transfer.transferred])

lemma fempty_iff[simp]: "(c || {||}) = False"
  by (rule empty_iff[Transfer.transferred])

lemma fempty_fsubsetI[iff]: "{||} || x"
  by (rule empty_subsetI[Transfer.transferred])

lemma equalsffemptyI: "(y. y || A ==> False) ==> A = {||}"
  by (rule equals0I[Transfer.transferred])

lemma equalsffemptyD: "A = {||} ==> a || A"
  by (rule equals0D[Transfer.transferred])

lemma fBall_fempty[simp]: "fBall {||} P = True"
  by (rule ball_empty[Transfer.transferred])

lemma fBex_fempty[simp]: "fBex {||} P = False"
  by (rule bex_empty[Transfer.transferred])

lemma fPow_iff[iff]: "(A || fPow B) = (A || B)"
  by (rule Pow_iff[Transfer.transferred])

lemma fPowI: "A || B ==> A || fPow B"
  by (rule PowI[Transfer.transferred])

lemma fPowD: "A || fPow B ==> A || B"
  by (rule PowD[Transfer.transferred])

lemma fPow_bottom: "{||} || fPow B"
  by (rule Pow_bottom[Transfer.transferred])

lemma fPow_top: "A || fPow A"
  by (rule Pow_top[Transfer.transferred])

lemma fPow_not_fempty: "fPow A {||}"
  by (rule Pow_not_empty[Transfer.transferred])

lemma finter_iff[simp]: "(c || A || B) = (c || A c || B)"
  by (rule Int_iff[Transfer.transferred])

lemma finterI[intro!]: "c || A ==> c || B ==> c || A || B"
  by (rule IntI[Transfer.transferred])

lemma finterD1: "c || A || B ==> c || A"
  by (rule IntD1[Transfer.transferred])

lemma finterD2: "c || A || B ==> c || B"
  by (rule IntD2[Transfer.transferred])

lemma finterE[elim!]: "c || A || B ==> (c || A ==> c || B ==> P) ==> P"
  by (rule IntE[Transfer.transferred])

lemma funion_iff[simp]: "(c || A || B) = (c || A c || B)"
  by (rule Un_iff[Transfer.transferred])

lemma funionI1[elim?]: "c || A ==> c || A || B"
  by (rule UnI1[Transfer.transferred])

lemma funionI2[elim?]: "c || B ==> c || A || B"
  by (rule UnI2[Transfer.transferred])

lemma funionCI[intro!]: "(c || B ==> c || A) ==> c || A || B"
  by (rule UnCI[Transfer.transferred])

lemma funionE[elim!]: "c || A || B ==> (c || A ==> P) ==> (c || B ==> P) ==> P"
  by (rule UnE[Transfer.transferred])

lemma fminus_iff[simp]: "(c || A |-| B) = (c || A c || B)"
  by (rule Diff_iff[Transfer.transferred])

lemma fminusI[intro!]: "c || A ==> c || B ==> c || A |-| B"
  by (rule DiffI[Transfer.transferred])

lemma fminusD1: "c || A |-| B ==> c || A"
  by (rule DiffD1[Transfer.transferred])

lemma fminusD2: "c || A |-| B ==> c || B ==> P"
  by (rule DiffD2[Transfer.transferred])

lemma fminusE[elim!]: "c || A |-| B ==> (c || A ==> c || B ==> P) ==> P"
  by (rule DiffE[Transfer.transferred])

lemma finsert_iff[simp]: "(a || finsert b A) = (a = b a || A)"
  by (rule insert_iff[Transfer.transferred])

lemma finsertI1: "a || finsert a B"
  by (rule insertI1[Transfer.transferred])

lemma finsertI2: "a || B ==> a || finsert b B"
  by (rule insertI2[Transfer.transferred])

lemma finsertE[elim!]: "a || finsert b A ==> (a = b ==> P) ==> (a || A ==> P) ==> P"
  by (rule insertE[Transfer.transferred])

lemma finsertCI[intro!]: "(a || B ==> a = b) ==> a || finsert b B"
  by (rule insertCI[Transfer.transferred])

lemma fsubset_finsert_iff:
  "(A || finsert x B) = (if x || A then A |-| {|x|} || B else A || B)"
  by (rule subset_insert_iff[Transfer.transferred])

lemma finsert_ident: "x || A ==> x || B ==> (finsert x A = finsert x B) = (A = B)"
  by (rule insert_ident[Transfer.transferred])

lemma fsingletonI[intro!,no_atp]: "a || {|a|}"
  by (rule singletonI[Transfer.transferred])

lemma fsingletonD[dest!,no_atp]: "b || {|a|} ==> b = a"
  by (rule singletonD[Transfer.transferred])

lemma fsingleton_iff: "(b || {|a|}) = (b = a)"
  by (rule singleton_iff[Transfer.transferred])

lemma fsingleton_inject[dest!]: "{|a|} = {|b|} ==> a = b"
  by (rule singleton_inject[Transfer.transferred])

lemma fsingleton_finsert_inj_eq[iff,no_atp]: "({|b|} = finsert a A) = (a = b A || {|b|})"
  by (rule singleton_insert_inj_eq[Transfer.transferred])

lemma fsingleton_finsert_inj_eq'[iff,no_atp]: "(finsert a A = {|b|}) = (a = b A || {|b|})"
  by (rule singleton_insert_inj_eq'[Transfer.transferred])

lemma fsubset_fsingletonD: "A || {|x|} ==> A = {||} A = {|x|}"
  by (rule subset_singletonD[Transfer.transferred])

lemma fminus_single_finsert: "A |-| {|x|} || B ==> A || finsert x B"
  by (rule Diff_single_insert[Transfer.transferred])

lemma fdoubleton_eq_iff: "({|a, b|} = {|c, d|}) = (a = c b = d a = d b = c)"
  by (rule doubleton_eq_iff[Transfer.transferred])

lemma funion_fsingleton_iff:
  "(A || B = {|x|}) = (A = {||} B = {|x|} A = {|x|} B = {||} A = {|x|} B = {|x|})"
  by (rule Un_singleton_iff[Transfer.transferred])

lemma fsingleton_funion_iff:
  "({|x|} = A || B) = (A = {||} B = {|x|} A = {|x|} B = {||} A = {|x|} B = {|x|})"
  by (rule singleton_Un_iff[Transfer.transferred])

lemma fimage_eqI[simp, intro]: "b = f x ==> x || A ==> b || f |`| A"
  by (rule image_eqI[Transfer.transferred])

lemma fimageI: "x || A ==> f x || f |`| A"
  by (rule imageI[Transfer.transferred])

lemma rev_fimage_eqI: "x || A ==> b = f x ==> b || f |`| A"
  by (rule rev_image_eqI[Transfer.transferred])

lemma fimageE[elim!]: "b || f |`| A ==> (x. b = f x ==> x || A ==> thesis) ==> thesis"
  by (rule imageE[Transfer.transferred])

lemma Compr_fimage_eq: "{x. x || f |`| A P x} = f ` {x. x || A P (f x)}"
  by (rule Compr_image_eq[Transfer.transferred])

lemma fimage_funion: "f |`| (A || B) = f |`| A || f |`| B"
  by (rule image_Un[Transfer.transferred])

lemma fimage_iff: "(z || f |`| A) = fBex A (λx. z = f x)"
  by (rule image_iff[Transfer.transferred])

lemma fimage_fsubset_iff[no_atp]: "(f |`| A || B) = fBall A (λx. f x || B)"
  by (rule image_subset_iff[Transfer.transferred])

lemma fimage_fsubsetI: "(x. x || A ==> f x || B) ==> f |`| A || B"
  by (rule image_subsetI[Transfer.transferred])

lemma fimage_ident[simp]: "(λx. x) |`| Y = Y"
  by (rule image_ident[Transfer.transferred])

lemma if_split_fmem1: "((if Q then x else y) || b) = ((Q x || b) (¬ Q y || b))"
  by (rule if_split_mem1[Transfer.transferred])

lemma if_split_fmem2: "(a || (if Q then x else y)) = ((Q a || x) (¬ Q a || y))"
  by (rule if_split_mem2[Transfer.transferred])

lemma pfsubsetI[intro!,no_atp]: "A || B ==> A B ==> A || B"
  by (rule psubsetI[Transfer.transferred])

lemma pfsubsetE[elim!,no_atp]: "A || B ==> (A || B ==> ¬ B || A ==> R) ==> R"
  by (rule psubsetE[Transfer.transferred])

lemma pfsubset_finsert_iff:
  "(A || finsert x B) =
    (if x || B then A || B else if x || A then A |-| {|x|} || B else A || B)"
  by (rule psubset_insert_iff[Transfer.transferred])

lemma pfsubset_eq: "(A || B) = (A || B A B)"
  by (rule psubset_eq[Transfer.transferred])

lemma pfsubset_imp_fsubset: "A || B ==> A || B"
  by (rule psubset_imp_subset[Transfer.transferred])

lemma pfsubset_trans: "A || B ==> B || C ==> A || C"
  by (rule psubset_trans[Transfer.transferred])

lemma pfsubsetD: "A || B ==> c || A ==> c || B"
  by (rule psubsetD[Transfer.transferred])

lemma pfsubset_fsubset_trans: "A || B ==> B || C ==> A || C"
  by (rule psubset_subset_trans[Transfer.transferred])

lemma fsubset_pfsubset_trans: "A || B ==> B || C ==> A || C"
  by (rule subset_psubset_trans[Transfer.transferred])

lemma pfsubset_imp_ex_fmem: "A || B ==> b. b || B |-| A"
  by (rule psubset_imp_ex_mem[Transfer.transferred])

lemma fimage_fPow_mono: "f |`| A || B ==> (|`|) f |`| fPow A || fPow B"
  by (rule image_Pow_mono[Transfer.transferred])

lemma fimage_fPow_surj: "f |`| A = B ==> (|`|) f |`| fPow A = fPow B"
  by (rule image_Pow_surj[Transfer.transferred])

lemma fsubset_finsertI: "B || finsert a B"
  by (rule subset_insertI[Transfer.transferred])

lemma fsubset_finsertI2: "A || B ==> A || finsert b B"
  by (rule subset_insertI2[Transfer.transferred])

lemma fsubset_finsert: "x || A ==> (A || finsert x B) = (A || B)"
  by (rule subset_insert[Transfer.transferred])

lemma funion_upper1: "A || A || B"
  by (rule Un_upper1[Transfer.transferred])

lemma funion_upper2: "B || A || B"
  by (rule Un_upper2[Transfer.transferred])

lemma funion_least: "A || C ==> B || C ==> A || B || C"
  by (rule Un_least[Transfer.transferred])

lemma finter_lower1: "A || B || A"
  by (rule Int_lower1[Transfer.transferred])

lemma finter_lower2: "A || B || B"
  by (rule Int_lower2[Transfer.transferred])

lemma finter_greatest: "C || A ==> C || B ==> C || A || B"
  by (rule Int_greatest[Transfer.transferred])

lemma fminus_fsubset: "A |-| B || A"
  by (rule Diff_subset[Transfer.transferred])

lemma fminus_fsubset_conv: "(A |-| B || C) = (A || B || C)"
  by (rule Diff_subset_conv[Transfer.transferred])

lemma fsubset_fempty[simp]: "(A || {||}) = (A = {||})"
  by (rule subset_empty[Transfer.transferred])

lemma not_pfsubset_fempty[iff]: "¬ A || {||}"
  by (rule not_psubset_empty[Transfer.transferred])

lemma finsert_is_funion: "finsert a A = {|a|} || A"
  by (rule insert_is_Un[Transfer.transferred])

lemma finsert_not_fempty[simp]: "finsert a A {||}"
  by (rule insert_not_empty[Transfer.transferred])

lemma fempty_not_finsert: "{||} finsert a A"
  by (rule empty_not_insert[Transfer.transferred])

lemma finsert_absorb: "a || A ==> finsert a A = A"
  by (rule insert_absorb[Transfer.transferred])

lemma finsert_absorb2[simp]: "finsert x (finsert x A) = finsert x A"
  by (rule insert_absorb2[Transfer.transferred])

lemma finsert_commute: "finsert x (finsert y A) = finsert y (finsert x A)"
  by (rule insert_commute[Transfer.transferred])

lemma finsert_fsubset[simp]: "(finsert x A || B) = (x || B A || B)"
  by (rule insert_subset[Transfer.transferred])

lemma finsert_inter_finsert[simp]: "finsert a A || finsert a B = finsert a (A || B)"
  by (rule insert_inter_insert[Transfer.transferred])

lemma finsert_disjoint[simp,no_atp]:
  "(finsert a A || B = {||}) = (a || B A || B = {||})"
  "({||} = finsert a A || B) = (a || B {||} = A || B)"
  by (rule insert_disjoint[Transfer.transferred])+

lemma disjoint_finsert[simp,no_atp]:
  "(B || finsert a A = {||}) = (a || B B || A = {||})"
  "({||} = A || finsert b B) = (b || A {||} = A || B)"
  by (rule disjoint_insert[Transfer.transferred])+

lemma fimage_fempty[simp]: "f |`| {||} = {||}"
  by (rule image_empty[Transfer.transferred])

lemma fimage_finsert[simp]: "f |`| finsert a B = finsert (f a) (f |`| B)"
  by (rule image_insert[Transfer.transferred])

lemma fimage_constant: "x || A ==> (λx. c) |`| A = {|c|}"
  by (rule image_constant[Transfer.transferred])

lemma fimage_constant_conv: "(λx. c) |`| A = (if A = {||} then {||} else {|c|})"
  by (rule image_constant_conv[Transfer.transferred])

lemma fimage_fimage: "f |`| g |`| A = (λx. f (g x)) |`| A"
  by (rule image_image[Transfer.transferred])

lemma finsert_fimage[simp]: "x || A ==> finsert (f x) (f |`| A) = f |`| A"
  by (rule insert_image[Transfer.transferred])

lemma fimage_is_fempty[iff]: "(f |`| A = {||}) = (A = {||})"
  by (rule image_is_empty[Transfer.transferred])

lemma fempty_is_fimage[iff]: "({||} = f |`| A) = (A = {||})"
  by (rule empty_is_image[Transfer.transferred])

lemma fimage_cong: "M = N ==> (x. x || N ==> f x = g x) ==> f |`| M = g |`| N"
  by (rule image_cong[Transfer.transferred])

lemma fimage_finter_fsubset: "f |`| (A || B) || f |`| A || f |`| B"
  by (rule image_Int_subset[Transfer.transferred])

lemma fimage_fminus_fsubset: "f |`| A |-| f |`| B || f |`| (A |-| B)"
  by (rule image_diff_subset[Transfer.transferred])

lemma finter_absorb: "A || A = A"
  by (rule Int_absorb[Transfer.transferred])

lemma finter_left_absorb: "A || (A || B) = A || B"
  by (rule Int_left_absorb[Transfer.transferred])

lemma finter_commute: "A || B = B || A"
  by (rule Int_commute[Transfer.transferred])

lemma finter_left_commute: "A || (B || C) = B || (A || C)"
  by (rule Int_left_commute[Transfer.transferred])

lemma finter_assoc: "A || B || C = A || (B || C)"
  by (rule Int_assoc[Transfer.transferred])

lemma finter_ac:
  "A || B || C = A || (B || C)"
  "A || (A || B) = A || B"
  "A || B = B || A"
  "A || (B || C) = B || (A || C)"
  by (rule Int_ac[Transfer.transferred])+

lemma finter_absorb1: "B || A ==> A || B = B"
  by (rule Int_absorb1[Transfer.transferred])

lemma finter_absorb2: "A || B ==> A || B = A"
  by (rule Int_absorb2[Transfer.transferred])

lemma finter_fempty_left: "{||} || B = {||}"
  by (rule Int_empty_left[Transfer.transferred])

lemma finter_fempty_right: "A || {||} = {||}"
  by (rule Int_empty_right[Transfer.transferred])

lemma disjoint_iff_fnot_equal: "(A || B = {||}) = fBall A (λx. fBall B (() x))"
  by (rule disjoint_iff_not_equal[Transfer.transferred])

lemma finter_funion_distrib: "A || (B || C) = A || B || (A || C)"
  by (rule Int_Un_distrib[Transfer.transferred])

lemma finter_funion_distrib2: "B || C || A = B || A || (C || A)"
  by (rule Int_Un_distrib2[Transfer.transferred])

lemma finter_fsubset_iff[no_atp, simp]: "(C || A || B) = (C || A C || B)"
  by (rule Int_subset_iff[Transfer.transferred])

lemma funion_absorb: "A || A = A"
  by (rule Un_absorb[Transfer.transferred])

lemma funion_left_absorb: "A || (A || B) = A || B"
  by (rule Un_left_absorb[Transfer.transferred])

lemma funion_commute: "A || B = B || A"
  by (rule Un_commute[Transfer.transferred])

lemma funion_left_commute: "A || (B || C) = B || (A || C)"
  by (rule Un_left_commute[Transfer.transferred])

lemma funion_assoc: "A || B || C = A || (B || C)"
  by (rule Un_assoc[Transfer.transferred])

lemma funion_ac:
  "A || B || C = A || (B || C)"
  "A || (A || B) = A || B"
  "A || B = B || A"
  "A || (B || C) = B || (A || C)"
  by (rule Un_ac[Transfer.transferred])+

lemma funion_absorb1: "A || B ==> A || B = B"
  by (rule Un_absorb1[Transfer.transferred])

lemma funion_absorb2: "B || A ==> A || B = A"
  by (rule Un_absorb2[Transfer.transferred])

lemma funion_fempty_left: "{||} || B = B"
  by (rule Un_empty_left[Transfer.transferred])

lemma funion_fempty_right: "A || {||} = A"
  by (rule Un_empty_right[Transfer.transferred])

lemma funion_finsert_left[simp]: "finsert a B || C = finsert a (B || C)"
  by (rule Un_insert_left[Transfer.transferred])

lemma funion_finsert_right[simp]: "A || finsert a B = finsert a (A || B)"
  by (rule Un_insert_right[Transfer.transferred])

lemma finter_finsert_left: "finsert a B || C = (if a || C then finsert a (B || C) else B || C)"
  by (rule Int_insert_left[Transfer.transferred])

lemma finter_finsert_left_ifffempty[simp]: "a || C ==> finsert a B || C = B || C"
  by (rule Int_insert_left_if0[Transfer.transferred])

lemma finter_finsert_left_if1[simp]: "a || C ==> finsert a B || C = finsert a (B || C)"
  by (rule Int_insert_left_if1[Transfer.transferred])

lemma finter_finsert_right:
  "A || finsert a B = (if a || A then finsert a (A || B) else A || B)"
  by (rule Int_insert_right[Transfer.transferred])

lemma finter_finsert_right_ifffempty[simp]: "a || A ==> A || finsert a B = A || B"
  by (rule Int_insert_right_if0[Transfer.transferred])

lemma finter_finsert_right_if1[simp]: "a || A ==> A || finsert a B = finsert a (A || B)"
  by (rule Int_insert_right_if1[Transfer.transferred])

lemma funion_finter_distrib: "A || (B || C) = A || B || (A || C)"
  by (rule Un_Int_distrib[Transfer.transferred])

lemma funion_finter_distrib2: "B || C || A = B || A || (C || A)"
  by (rule Un_Int_distrib2[Transfer.transferred])

lemma funion_finter_crazy:
  "A || B || (B || C) || (C || A) = A || B || (B || C) || (C || A)"
  by (rule Un_Int_crazy[Transfer.transferred])

lemma fsubset_funion_eq: "(A || B) = (A || B = B)"
  by (rule subset_Un_eq[Transfer.transferred])

lemma funion_fempty[iff]: "(A || B = {||}) = (A = {||} B = {||})"
  by (rule Un_empty[Transfer.transferred])

lemma funion_fsubset_iff[no_atp, simp]: "(A || B || C) = (A || C B || C)"
  by (rule Un_subset_iff[Transfer.transferred])

lemma funion_fminus_finter: "A |-| B || (A || B) = A"
  by (rule Un_Diff_Int[Transfer.transferred])

lemma ffunion_empty[simp]: "ffUnion {||} = {||}"
  by (rule Union_empty[Transfer.transferred])

lemma ffunion_mono: "A || B ==> ffUnion A || ffUnion B"
  by (rule Union_mono[Transfer.transferred])

lemma ffunion_insert[simp]: "ffUnion (finsert a B) = a || ffUnion B"
  by (rule Union_insert[Transfer.transferred])

lemma fminus_finter2: "A || C |-| (B || C) = A || C |-| B"
  by (rule Diff_Int2[Transfer.transferred])

lemma funion_finter_assoc_eq: "(A || B || C = A || (B || C)) = (C || A)"
  by (rule Un_Int_assoc_eq[Transfer.transferred])

lemma fBall_funion: "fBall (A || B) P = (fBall A P fBall B P)"
  by (rule ball_Un[Transfer.transferred])

lemma fBex_funion: "fBex (A || B) P = (fBex A P fBex B P)"
  by (rule bex_Un[Transfer.transferred])

lemma fminus_eq_fempty_iff[simp,no_atp]: "(A |-| B = {||}) = (A || B)"
  by (rule Diff_eq_empty_iff[Transfer.transferred])

lemma fminus_cancel[simp]: "A |-| A = {||}"
  by (rule Diff_cancel[Transfer.transferred])

lemma fminus_idemp[simp]: "A |-| B |-| B = A |-| B"
  by (rule Diff_idemp[Transfer.transferred])

lemma fminus_triv: "A || B = {||} ==> A |-| B = A"
  by (rule Diff_triv[Transfer.transferred])

lemma fempty_fminus[simp]: "{||} |-| A = {||}"
  by (rule empty_Diff[Transfer.transferred])

lemma fminus_fempty[simp]: "A |-| {||} = A"
  by (rule Diff_empty[Transfer.transferred])

lemma fminus_finsertffempty[simp,no_atp]: "x || A ==> A |-| finsert x B = A |-| B"
  by (rule Diff_insert0[Transfer.transferred])

lemma fminus_finsert: "A |-| finsert a B = A |-| B |-| {|a|}"
  by (rule Diff_insert[Transfer.transferred])

lemma fminus_finsert2: "A |-| finsert a B = A |-| {|a|} |-| B"
  by (rule Diff_insert2[Transfer.transferred])

lemma finsert_fminus_if: "finsert x A |-| B = (if x || B then A |-| B else finsert x (A |-| B))"
  by (rule insert_Diff_if[Transfer.transferred])

lemma finsert_fminus1[simp]: "x || B ==> finsert x A |-| B = A |-| B"
  by (rule insert_Diff1[Transfer.transferred])

lemma finsert_fminus_single[simp]: "finsert a (A |-| {|a|}) = finsert a A"
  by (rule insert_Diff_single[Transfer.transferred])

lemma finsert_fminus: "a || A ==> finsert a (A |-| {|a|}) = A"
  by (rule insert_Diff[Transfer.transferred])

lemma fminus_finsert_absorb: "x || A ==> finsert x A |-| {|x|} = A"
  by (rule Diff_insert_absorb[Transfer.transferred])

lemma fminus_disjoint[simp]: "A || (B |-| A) = {||}"
  by (rule Diff_disjoint[Transfer.transferred])

lemma fminus_partition: "A || B ==> A || (B |-| A) = B"
  by (rule Diff_partition[Transfer.transferred])

lemma double_fminus: "A || B ==> B || C ==> B |-| (C |-| A) = A"
  by (rule double_diff[Transfer.transferred])

lemma funion_fminus_cancel[simp]: "A || (B |-| A) = A || B"
  by (rule Un_Diff_cancel[Transfer.transferred])

lemma funion_fminus_cancel2[simp]: "B |-| A || A = B || A"
  by (rule Un_Diff_cancel2[Transfer.transferred])

lemma fminus_funion: "A |-| (B || C) = A |-| B || (A |-| C)"
  by (rule Diff_Un[Transfer.transferred])

lemma fminus_finter: "A |-| (B || C) = A |-| B || (A |-| C)"
  by (rule Diff_Int[Transfer.transferred])

lemma funion_fminus: "A || B |-| C = A |-| C || (B |-| C)"
  by (rule Un_Diff[Transfer.transferred])

lemma finter_fminus: "A || B |-| C = A || (B |-| C)"
  by (rule Int_Diff[Transfer.transferred])

lemma fminus_finter_distrib: "C || (A |-| B) = C || A |-| (C || B)"
  by (rule Diff_Int_distrib[Transfer.transferred])

lemma fminus_finter_distrib2: "A |-| B || C = A || C |-| (B || C)"
  by (rule Diff_Int_distrib2[Transfer.transferred])

lemma fUNIV_bool[no_atp]: "fUNIV = {|False, True|}"
  by (rule UNIV_bool[Transfer.transferred])

lemma fPow_fempty[simp]: "fPow {||} = {|{||}|}"
  by (rule Pow_empty[Transfer.transferred])

lemma fPow_finsert: "fPow (finsert a A) = fPow A || finsert a |`| fPow A"
  by (rule Pow_insert[Transfer.transferred])

lemma funion_fPow_fsubset: "fPow A || fPow B || fPow (A || B)"
  by (rule Un_Pow_subset[Transfer.transferred])

lemma fPow_finter_eq[simp]: "fPow (A || B) = fPow A || fPow B"
  by (rule Pow_Int_eq[Transfer.transferred])

lemma fset_eq_fsubset: "(A = B) = (A || B B || A)"
  by (rule set_eq_subset[Transfer.transferred])

lemma fsubset_iff[no_atp]: "(A || B) = (t. t || A t || B)"
  by (rule subset_iff[Transfer.transferred])

lemma fsubset_iff_pfsubset_eq: "(A || B) = (A || B A = B)"
  by (rule subset_iff_psubset_eq[Transfer.transferred])

lemma all_not_fin_conv[simp]: "(x. x || A) = (A = {||})"
  by (rule all_not_in_conv[Transfer.transferred])

lemma ex_fin_conv: "(x. x || A) = (A {||})"
  by (rule ex_in_conv[Transfer.transferred])

lemma fimage_mono: "A || B ==> f |`| A || f |`| B"
  by (rule image_mono[Transfer.transferred])

lemma fPow_mono: "A || B ==> fPow A || fPow B"
  by (rule Pow_mono[Transfer.transferred])

lemma finsert_mono: "C || D ==> finsert a C || finsert a D"
  by (rule insert_mono[Transfer.transferred])

lemma funion_mono: "A || C ==> B || D ==> A || B || C || D"
  by (rule Un_mono[Transfer.transferred])

lemma finter_mono: "A || C ==> B || D ==> A || B || C || D"
  by (rule Int_mono[Transfer.transferred])

lemma fminus_mono: "A || C ==> D || B ==> A |-| B || C |-| D"
  by (rule Diff_mono[Transfer.transferred])

lemma fin_mono: "A || B ==> x || A x || B"
  by (rule in_mono[Transfer.transferred])

lemma fthe_felem_eq[simp]: "fthe_elem {|x|} = x"
  by (rule the_elem_eq[Transfer.transferred])

lemma fLeast_mono:
  "mono f ==> fBex S (λx. fBall S (() x)) ==> (LEAST y. y || f |`| S) = f (LEAST x. x || S)"
  by (rule Least_mono[Transfer.transferred])

lemma fbind_fbind: "fbind (fbind A B) C = fbind A (λx. fbind (B x) C)"
  by (rule Set.bind_bind[Transfer.transferred])

lemma fempty_fbind[simp]: "fbind {||} f = {||}"
  by (rule empty_bind[Transfer.transferred])

lemma nonfempty_fbind_const: "A {||} ==> fbind A (λ_. B) = B"
  by (rule nonempty_bind_const[Transfer.transferred])

lemma fbind_const: "fbind A (λ_. B) = (if A = {||} then {||} else B)"
  by (rule bind_const[Transfer.transferred])

lemma ffmember_filter[simp]: "(x || ffilter P A) = (x || A P x)"
  by transfer simp

lemma fequalityI: "A || B ==> B || A ==> A = B"
  by (rule equalityI[Transfer.transferred])

lemma fset_of_list_simps[simp]:
  "fset_of_list [] = {||}"
  "fset_of_list (x21 # x22) = finsert x21 (fset_of_list x22)"
  by (rule set_simps[Transfer.transferred])+

lemma fset_of_list_append[simp]: "fset_of_list (xs @ ys) = fset_of_list xs || fset_of_list ys"
  by (rule set_append[Transfer.transferred])

lemma fset_of_list_rev[simp]: "fset_of_list (rev xs) = fset_of_list xs"
  by (rule set_rev[Transfer.transferred])

lemma fset_of_list_map[simp]: "fset_of_list (map f xs) = f |`| fset_of_list xs"
  by (rule set_map[Transfer.transferred])


subsection Additional lemmas

subsubsection ffUnion\
lemma ffUnion_funion_distrib[simp]: "ffUnion (A || B) = ffUnion A || ffUnion B"
  by (rule Union_Un_distrib[Transfer.transferred])


subsubsection fbind\


lemma fbind_cong[fundef_cong]: "A = B ==> (x. x || B ==> f x = g x) ==> fbind A f = fbind B g"
by transfer force


subsubsection fsingleton\

lemma fsingletonE: " b || {|a|} ==> (b = a ==> thesis) ==> thesis"
  by (rule fsingletonD [elim_format])


subsubsection femepty\

lemma fempty_ffilter[simp]: "ffilter (λ_. False) A = {||}"
by transfer auto

(* FIXME, transferred doesn't work here *)
lemma femptyE [elim!]: "a || {||} ==> P"
  by simp


subsubsection fset\
lemma fset_simps[simp]:
  "fset {||} = {}"
  "fset (finsert x X) = insert x (fset X)"
  by (rule bot_fset.rep_eq finsert.rep_eq)+

lemma finite_fset [simp]:
  shows "finite (fset S)"
  by transfer simp

lemmas fset_cong = fset_inject

lemma filter_fset [simp]:
  shows "fset (ffilter P xs) = Collect P fset xs"
  by transfer auto

lemma inter_fset[simp]: "fset (A || B) = fset A fset B"
  by (rule inf_fset.rep_eq)

lemma union_fset[simp]: "fset (A || B) = fset A fset B"
  by (rule sup_fset.rep_eq)

lemma minus_fset[simp]: "fset (A |-| B) = fset A - fset B"
  by (rule minus_fset.rep_eq)


subsubsection ffilter\


lemma subset_ffilter:
  "ffilter P A || ffilter Q A = ( x. x || A P x Q x)"
  by transfer auto

lemma eq_ffilter:
  "(ffilter P A = ffilter Q A) = (x. x || A P x = Q x)"
  by transfer auto

lemma pfsubset_ffilter:
  "(x. x || A ==> P x ==> Q x) ==> (x || A ¬ P x Q x) ==>
    ffilter P A || ffilter Q A"
  unfolding less_fset_def by (auto simp add: subset_ffilter eq_ffilter)


subsubsection fset_of_list\

lemma fset_of_list_filter[simp]:
  "fset_of_list (filter P xs) = ffilter P (fset_of_list xs)"
  by transfer auto

lemma fset_of_list_subset[intro]:
  "set xs set ys ==> fset_of_list xs || fset_of_list ys"
  by transfer simp

lemma fset_of_list_elem: "(x || fset_of_list xs) (x set xs)"
  by transfer simp


subsubsection finsert\

(* FIXME, transferred doesn't work here *)
lemma set_finsert:
  assumes "x || A"
  obtains B where "A = finsert x B" and "x || B"
using assms by transfer (metis Set.set_insert finite_insert)

lemma mk_disjoint_finsert: "a || A ==> B. A = finsert a B a || B"
  by (rule exI [where x = "A |-| {|a|}"]) blast

lemma finsert_eq_iff:
  assumes "a || A" and "b || B"
  shows "(finsert a A = finsert b B) =
    (if a = b then A = B else C. A = finsert b C b || C B = finsert a C a || C)"
  using assms by transfer (force simp: insert_eq_iff)


subsubsection fimage\
lemma subset_fimage_iff: "(B || f|`|A) = ( AA. AA || A B = f|`|AA)"
by transfer (metis mem_Collect_eq rev_finite_subset subset_image_iff)

lemma fimage_strict_mono:
  assumes "inj_on f (fset B)" and "A || B"
  shows "f |`| A || f |`| B"
  🍋 TODO: Configure transfer framework to lift @{thm Fun.image_strict_mono}.
proof (rule pfsubsetI)
  from A || B have "A || B"
    by (rule pfsubset_imp_fsubset)
  thus "f |`| A || f |`| B"
    by (rule fimage_mono)
next
  from A || B have "A || B" and "A B"
    by (simp_all add: pfsubset_eq)

  have "fset A fset B"
    using A B
    by (simp add: fset_cong)
  hence "f ` fset A f ` fset B"
    using A || B
    by (simp add: inj_on_image_eq_iff[OF inj_on f (fset B)] less_eq_fset.rep_eq)
  hence "fset (f |`| A) fset (f |`| B)"
    by (simp add: fimage.rep_eq)
  thus "f |`| A f |`| B"
    by (simp add: fset_cong)
qed


subsubsection bounded quantification

lemma bex_simps [simp, no_atp]:
  "A P Q. fBex A (λx. P x Q) = (fBex A P Q)"
  "A P Q. fBex A (λx. P Q x) = (P fBex A Q)"
  "P. fBex {||} P = False"
  "a B P. fBex (finsert a B) P = (P a fBex B P)"
  "A P f. fBex (f |`| A) P = fBex A (λx. P (f x))"
  "A P. (¬ fBex A P) = fBall A (λx. ¬ P x)"
by auto

lemma ball_simps [simp, no_atp]:
  "A P Q. fBall A (λx. P x Q) = (fBall A P Q)"
  "A P Q. fBall A (λx. P Q x) = (P fBall A Q)"
  "A P Q. fBall A (λx. P Q x) = (P fBall A Q)"
  "A P Q. fBall A (λx. P x Q) = (fBex A P Q)"
  "P. fBall {||} P = True"
  "a B P. fBall (finsert a B) P = (P a fBall B P)"
  "A P f. fBall (f |`| A) P = fBall A (λx. P (f x))"
  "A P. (¬ fBall A P) = fBex A (λx. ¬ P x)"
by auto

lemma atomize_fBall:
    "(x. x || A ==> P x) == Trueprop (fBall A (λx. P x))"
  by (simp add: Set.atomize_ball)

lemma fBall_mono[mono]: "P Q ==> fBall S P fBall S Q"
  by auto

lemma fBex_mono[mono]: "P Q ==> fBex S P fBex S Q"
  by auto

end


subsubsection fcard\


(* FIXME: improve transferred to handle bounded meta quantification *)

lemma fcard_fempty:
  "fcard {||} = 0"
  by transfer (rule card.empty)

lemma fcard_finsert_disjoint:
  "x || A ==> fcard (finsert x A) = Suc (fcard A)"
  by transfer (rule card_insert_disjoint)

lemma fcard_finsert_if:
  "fcard (finsert x A) = (if x || A then fcard A else Suc (fcard A))"
  by transfer (rule card_insert_if)

lemma fcard_0_eq [simp, no_atp]:
  "fcard A = 0 A = {||}"
  by transfer (rule card_0_eq)

lemma fcard_Suc_fminus1:
  "x || A ==> Suc (fcard (A |-| {|x|})) = fcard A"
  by transfer (rule card_Suc_Diff1)

lemma fcard_fminus_fsingleton:
  "x || A ==> fcard (A |-| {|x|}) = fcard A - 1"
  by transfer (rule card_Diff_singleton)

lemma fcard_fminus_fsingleton_if:
  "fcard (A |-| {|x|}) = (if x || A then fcard A - 1 else fcard A)"
  by transfer (rule card_Diff_singleton_if)

lemma fcard_fminus_finsert[simp]:
  assumes "a || A" and "a || B"
  shows "fcard (A |-| finsert a B) = fcard (A |-| B) - 1"
using assms by transfer (rule card_Diff_insert)

lemma fcard_finsert: "fcard (finsert x A) = Suc (fcard (A |-| {|x|}))"
by transfer (rule card.insert_remove)

lemma fcard_finsert_le: "fcard A fcard (finsert x A)"
by transfer (rule card_insert_le)

lemma fcard_mono:
  "A || B ==> fcard A fcard B"
by transfer (rule card_mono)

lemma fcard_seteq: "A || B ==> fcard B fcard A ==> A = B"
by transfer (rule card_seteq)

lemma pfsubset_fcard_mono: "A || B ==> fcard A < fcard B"
by transfer (rule psubset_card_mono)

lemma fcard_funion_finter:
  "fcard A + fcard B = fcard (A || B) + fcard (A || B)"
by transfer (rule card_Un_Int)

lemma fcard_funion_disjoint:
  "A || B = {||} ==> fcard (A || B) = fcard A + fcard B"
by transfer (rule card_Un_disjoint)

lemma fcard_funion_fsubset:
  "B || A ==> fcard (A |-| B) = fcard A - fcard B"
by transfer (rule card_Diff_subset)

lemma diff_fcard_le_fcard_fminus:
  "fcard A - fcard B fcard(A |-| B)"
by transfer (rule diff_card_le_card_Diff)

lemma fcard_fminus1_less: "x || A ==> fcard (A |-| {|x|}) < fcard A"
by transfer (rule card_Diff1_less)

lemma fcard_fminus2_less:
  "x || A ==> y || A ==> fcard (A |-| {|x|} |-| {|y|}) < fcard A"
by transfer (rule card_Diff2_less)

lemma fcard_fminus1_le: "fcard (A |-| {|x|}) fcard A"
by transfer (rule card_Diff1_le)

lemma fcard_pfsubset: "A || B ==> fcard A < fcard B ==> A < B"
by transfer (rule card_psubset)


subsubsection sorted_list_of_fset\
lemma sorted_list_of_fset_simps[simp]:
  "set (sorted_list_of_fset S) = fset S"
  "fset_of_list (sorted_list_of_fset S) = S"
by (transfer, simp)+


subsubsection ffold\


(* FIXME: improve transferred to handle bounded meta quantification *)

context comp_fun_commute
begin
  lemma ffold_empty[simp]: "ffold f z {||} = z"
    by (rule fold_empty[Transfer.transferred])

  lemma ffold_finsert [simp]:
    assumes "x || A"
    shows "ffold f z (finsert x A) = f x (ffold f z A)"
    using assms by (transfer fixing: f) (rule fold_insert)

  lemma ffold_fun_left_comm:
    "f x (ffold f z A) = ffold f (f x z) A"
    by (transfer fixing: f) (rule fold_fun_left_comm)

  lemma ffold_finsert2:
    "x || A ==> ffold f z (finsert x A) = ffold f (f x z) A"
    by (transfer fixing: f) (rule fold_insert2)

  lemma ffold_rec:
    assumes "x || A"
    shows "ffold f z A = f x (ffold f z (A |-| {|x|}))"
    using assms by (transfer fixing: f) (rule fold_rec)

  lemma ffold_finsert_fremove:
    "ffold f z (finsert x A) = f x (ffold f z (A |-| {|x|}))"
     by (transfer fixing: f) (rule fold_insert_remove)
end

lemma ffold_fimage:
  assumes "inj_on g (fset A)"
  shows "ffold f z (g |`| A) = ffold (f g) z A"
using assms by transfer' (rule fold_image)

lemma ffold_cong:
  assumes "comp_fun_commute f" "comp_fun_commute g"
  "x. x || A ==> f x = g x"
    and "s = t" and "A = B"
  shows "ffold f s A = ffold g t B"
  using assms[unfolded comp_fun_commute_def']
  by transfer (meson Finite_Set.fold_cong subset_UNIV)

context comp_fun_idem
begin

  lemma ffold_finsert_idem:
    "ffold f z (finsert x A) = f x (ffold f z A)"
    by (transfer fixing: f) (rule fold_insert_idem)

  declare ffold_finsert [simp del] ffold_finsert_idem [simp]

  lemma ffold_finsert_idem2:
    "ffold f z (finsert x A) = ffold f (f x z) A"
    by (transfer fixing: f) (rule fold_insert_idem2)

end


subsubsection @{term fsubset}

lemma wfP_pfsubset: "wfP (||)"
proof (rule wfp_if_convertible_to_nat)
  show "x y. x || y ==> fcard x < fcard y"
    by (rule pfsubset_fcard_mono)
qed


subsubsection Group operations

locale comm_monoid_fset = comm_monoid
begin

sublocale set: comm_monoid_set ..

lift_definition F :: "('b ==> 'a) ==> 'b fset ==> 'a" is set.F .

lemma cong[fundef_cong]: "A = B ==> (x. x || B ==> g x = h x) ==> F g A = F h B"
  by (rule set.cong[Transfer.transferred])

lemma cong_simp[cong]:
  "[ A = B; x. x || B =simp=> g x = h x ] ==> F g A = F h B"
unfolding simp_implies_def by (auto cong: cong)

end

context comm_monoid_add begin

sublocale fsum: comm_monoid_fset plus 0
  rewrites "comm_monoid_set.F plus 0 = sum"
  defines fsum = fsum.F
proof -
  show "comm_monoid_fset (+) 0" by standard

  show "comm_monoid_set.F (+) 0 = sum" unfolding sum_def ..
qed

end


subsubsection Semilattice operations

locale semilattice_fset = semilattice
begin

sublocale set: semilattice_set ..

lift_definition F :: "'a fset ==> 'a" is set.F .

lemma eq_fold: "F (finsert x A) = ffold f x A"
  by transfer (rule set.eq_fold)

lemma singleton [simp]: "F {|x|} = x"
  by transfer (rule set.singleton)

lemma insert_not_elem: "x || A ==> A {||} ==> F (finsert x A) = x 🪙* F A"
  by transfer (rule set.insert_not_elem)

lemma in_idem: "x || A ==> x 🪙* F A = F A"
  by transfer (rule set.in_idem)

lemma insert [simp]: "A {||} ==> F (finsert x A) = x 🪙* F A"
  by transfer (rule set.insert)

end

locale semilattice_order_fset = binary?: semilattice_order + semilattice_fset
begin

end


context linorder begin

sublocale fMin: semilattice_order_fset min less_eq less
  rewrites "semilattice_set.F min = Min"
  defines fMin = fMin.F
proof -
  show "semilattice_order_fset min () (<)" by standard

  show "semilattice_set.F min = Min" unfolding Min_def ..
qed

sublocale fMax: semilattice_order_fset max greater_eq greater
  rewrites "semilattice_set.F max = Max"
  defines fMax = fMax.F
proof -
  show "semilattice_order_fset max () (>)"
    by standard

  show "semilattice_set.F max = Max"
    unfolding Max_def ..
qed

end

lemma mono_fMax_commute: "mono f ==> A {||} ==> f (fMax A) = fMax (f |`| A)"
  by transfer (rule mono_Max_commute)

lemma mono_fMin_commute: "mono f ==> A {||} ==> f (fMin A) = fMin (f |`| A)"
  by transfer (rule mono_Min_commute)

lemma fMax_in[simp]: "A {||} ==> fMax A || A"
  by transfer (rule Max_in)

lemma fMin_in[simp]: "A {||} ==> fMin A || A"
  by transfer (rule Min_in)

lemma fMax_ge[simp]: "x || A ==> x fMax A"
  by transfer (rule Max_ge)

lemma fMin_le[simp]: "x || A ==> fMin A x"
  by transfer (rule Min_le)

lemma fMax_eqI: "(y. y || A ==> y x) ==> x || A ==> fMax A = x"
  by transfer (rule Max_eqI)

lemma fMin_eqI: "(y. y || A ==> x y) ==> x || A ==> fMin A = x"
  by transfer (rule Min_eqI)

lemma fMax_finsert[simp]: "fMax (finsert x A) = (if A = {||} then x else max x (fMax A))"
  by transfer simp

lemma fMin_finsert[simp]: "fMin (finsert x A) = (if A = {||} then x else min x (fMin A))"
  by transfer simp

context linorder begin

lemma fset_linorder_max_induct[case_names fempty finsert]:
  assumes "P {||}"
  and     "x S. [y. y || S y < x; P S] ==> P (finsert x S)"
  shows "P S"
proof -
  (* FIXME transfer and right_total vs. bi_total *)
  note Domainp_forall_transfer[transfer_rule]
  show ?thesis
  using assms by (transfer fixing: less) (auto intro: finite_linorder_max_induct)
qed

lemma fset_linorder_min_induct[case_names fempty finsert]:
  assumes "P {||}"
  and     "x S. [y. y || S y > x; P S] ==> P (finsert x S)"
  shows "P S"
proof -
  (* FIXME transfer and right_total vs. bi_total *)
  note Domainp_forall_transfer[transfer_rule]
  show ?thesis
  using assms by (transfer fixing: less) (auto intro: finite_linorder_min_induct)
qed

end


subsection Choice in fsets

lemma fset_choice:
  assumes "x. x || A (y. P x y)"
  shows "f. x. x || A P x (f x)"
  using assms by transfer metis


subsection Induction and Cases rules for fsets

lemma fset_exhaust [case_names empty insert, cases type: fset]:
  assumes fempty_case: "S = {||} ==> P"
  and     finsert_case: "x S'. S = finsert x S' ==> P"
  shows "P"
  using assms by transfer blast

lemma fset_induct [case_names empty insert]:
  assumes fempty_case: "P {||}"
  and     finsert_case: "x S. P S ==> P (finsert x S)"
  shows "P S"
proof -
  (* FIXME transfer and right_total vs. bi_total *)
  note Domainp_forall_transfer[transfer_rule]
  show ?thesis
  using assms by transfer (auto intro: finite_induct)
qed

lemma fset_induct_stronger [case_names empty insert, induct type: fset]:
  assumes empty_fset_case: "P {||}"
  and     insert_fset_case: "x S. [x || S; P S] ==> P (finsert x S)"
  shows "P S"
proof -
  (* FIXME transfer and right_total vs. bi_total *)
  note Domainp_forall_transfer[transfer_rule]
  show ?thesis
  using assms by transfer (auto intro: finite_induct)
qed

lemma fset_card_induct:
  assumes empty_fset_case: "P {||}"
  and     card_fset_Suc_case: "S T. Suc (fcard S) = (fcard T) ==> P S ==> P T"
  shows "P S"
proof (induct S)
  case empty
  show "P {||}" by (rule empty_fset_case)
next
  case (insert x S)
  have h: "P S" by fact
  have "x || S" by fact
  then have "Suc (fcard S) = fcard (finsert x S)"
    by transfer auto
  then show "P (finsert x S)"
    using h card_fset_Suc_case by simp
qed

lemma fset_strong_cases:
  obtains "xs = {||}"
    | ys x where "x || ys" and "xs = finsert x ys"
  by auto

lemma fset_induct2:
  "P {||} {||} ==>
  (x xs. x || xs ==> P (finsert x xs) {||}) ==>
  (y ys. y || ys ==> P {||} (finsert y ys)) ==>
  (x xs y ys. [P xs ys; x || xs; y || ys] ==> P (finsert x xs) (finsert y ys)) ==>
  P xsa ysa"
by (induct xsa arbitrary: ysa; metis fset_induct_stronger)


subsection Lemmas depending on induction

lemma ffUnion_fsubset_iff: "ffUnion A || B fBall A (λx. x || B)"
  by (induction A) simp_all


subsection Setup for Lifting/Transfer

subsubsection Relator and predicator properties

lift_definition rel_fset :: "('a ==> 'b ==> bool) ==> 'a fset ==> 'b fset ==> bool" is rel_set
parametric rel_set_transfer .

lemma rel_fset_alt_def: "rel_fset R = (λA B. (x.y. x||A y||B R x y)
   (y. x. y||B x||A R x y))"
  by transfer' (metis (no_types, opaque_lifting) rel_set_def)

lemma finite_rel_set:
  assumes fin: "finite X" "finite Z"
  assumes R_S: "rel_set (R OO S) X Z"
  shows "Y. finite Y rel_set R X Y rel_set S Y Z"
proof -
  obtain f g where f: "xX. R x (f x) (zZ. S (f x) z)"
               and g: "zZ. S (g z) z (xX. R x (g z))"
    using R_S[unfolded rel_set_def OO_def] by metis

  let ?Y = "f ` X g ` Z"
  have "finite ?Y" by (simp add: fin)
  moreover have "rel_set R X ?Y"
    unfolding rel_set_def
    using f g by clarsimp blast
  moreover have "rel_set S ?Y Z"
    unfolding rel_set_def
    using f g by clarsimp blast
  ultimately show ?thesis by metis
qed

subsubsection Transfer rules for the Transfer package

text Unconditional transfer rules

context includes lifting_syntax
begin

lemma fempty_transfer [transfer_rule]:
  "rel_fset A {||} {||}"
  by (rule empty_transfer[Transfer.transferred])

lemma finsert_transfer [transfer_rule]:
  "(A ===> rel_fset A ===> rel_fset A) finsert finsert"
  unfolding rel_fun_def rel_fset_alt_def by blast

lemma funion_transfer [transfer_rule]:
  "(rel_fset A ===> rel_fset A ===> rel_fset A) funion funion"
  unfolding rel_fun_def rel_fset_alt_def by blast

lemma ffUnion_transfer [transfer_rule]:
  "(rel_fset (rel_fset A) ===> rel_fset A) ffUnion ffUnion"
  unfolding rel_fun_def rel_fset_alt_def by transfer (simp, fast)

lemma fimage_transfer [transfer_rule]:
  "((A ===> B) ===> rel_fset A ===> rel_fset B) fimage fimage"
  unfolding rel_fun_def rel_fset_alt_def by simp blast

lemma fBall_transfer [transfer_rule]:
  "(rel_fset A ===> (A ===> (=)) ===> (=)) fBall fBall"
  unfolding rel_fset_alt_def rel_fun_def by blast

lemma fBex_transfer [transfer_rule]:
  "(rel_fset A ===> (A ===> (=)) ===> (=)) fBex fBex"
  unfolding rel_fset_alt_def rel_fun_def by blast

(* FIXME transfer doesn't work here *)
lemma fPow_transfer [transfer_rule]:
  "(rel_fset A ===> rel_fset (rel_fset A)) fPow fPow"
  unfolding rel_fun_def
  using Pow_transfer[unfolded rel_fun_def, rule_format, Transfer.transferred]
  by blast

lemma rel_fset_transfer [transfer_rule]:
  "((A ===> B ===> (=)) ===> rel_fset A ===> rel_fset B ===> (=))
    rel_fset rel_fset"
  unfolding rel_fun_def
  using rel_set_transfer[unfolded rel_fun_def,rule_format, Transfer.transferred, where A = A and B = B]
  by simp

lemma bind_transfer [transfer_rule]:
  "(rel_fset A ===> (A ===> rel_fset B) ===> rel_fset B) fbind fbind"
  unfolding rel_fun_def
  using bind_transfer[unfolded rel_fun_def, rule_format, Transfer.transferred] by blast

text Rules requiring bi-unique, bi-total or right-total relations

lemma fmember_transfer [transfer_rule]:
  assumes "bi_unique A"
  shows "(A ===> rel_fset A ===> (=)) (||) (||)"
  using assms unfolding rel_fun_def rel_fset_alt_def bi_unique_def by metis

lemma finter_transfer [transfer_rule]:
  assumes "bi_unique A"
  shows "(rel_fset A ===> rel_fset A ===> rel_fset A) finter finter"
  using assms unfolding rel_fun_def
  using inter_transfer[unfolded rel_fun_def, rule_format, Transfer.transferred] by blast

lemma fminus_transfer [transfer_rule]:
  assumes "bi_unique A"
  shows "(rel_fset A ===> rel_fset A ===> rel_fset A) (|-|) (|-|)"
  using assms unfolding rel_fun_def
  using Diff_transfer[unfolded rel_fun_def, rule_format, Transfer.transferred] by blast

lemma fsubset_transfer [transfer_rule]:
  assumes "bi_unique A"
  shows "(rel_fset A ===> rel_fset A ===> (=)) (||) (||)"
  using assms unfolding rel_fun_def
  using subset_transfer[unfolded rel_fun_def, rule_format, Transfer.transferred] by blast

lemma fSup_transfer [transfer_rule]:
  "bi_unique A ==> (rel_set (rel_fset A) ===> rel_fset A) Sup Sup"
  unfolding rel_fun_def
  apply clarify
  apply transfer'
  using Sup_fset_transfer[unfolded rel_fun_def] by blast

(* FIXME: add right_total_fInf_transfer *)

lemma fInf_transfer [transfer_rule]:
  assumes "bi_unique A" and "bi_total A"
  shows "(rel_set (rel_fset A) ===> rel_fset A) Inf Inf"
  using assms unfolding rel_fun_def
  apply clarify
  apply transfer'
  using Inf_fset_transfer[unfolded rel_fun_def] by blast

lemma ffilter_transfer [transfer_rule]:
  assumes "bi_unique A"
  shows "((A ===> (=)) ===> rel_fset A ===> rel_fset A) ffilter ffilter"
  using assms Lifting_Set.filter_transfer
  unfolding rel_fun_def by (metis ffilter.rep_eq rel_fset.rep_eq)

lemma card_transfer [transfer_rule]:
  "bi_unique A ==> (rel_fset A ===> (=)) fcard fcard"
  using card_transfer unfolding rel_fun_def
  by (metis fcard.rep_eq rel_fset.rep_eq)

end

lifting_update fset.lifting
lifting_forget fset.lifting


subsection BNF setup

context
includes fset.lifting
begin

lemma rel_fset_alt:
  "rel_fset R a b (t fset a. u fset b. R t u) (t fset b. u fset a. R u t)"
  by transfer (simp add: rel_set_def)

lemma fset_to_fset: "finite A ==> fset (the_inv fset A) = A"
  by (metis CollectI f_the_inv_into_f fset_cases fset_cong inj_onI rangeI)

lemma rel_fset_aux:
"(t fset a. u fset b. R t u) (u fset b. t fset a. R t u)
 ((BNF_Def.Grp {a. fset a {(a, b). R a b}} (fimage fst))-1-1 OO
  BNF_Def.Grp {a. fset a {(a, b). R a b}} (fimage snd)) a b" (is "?L = ?R")
proof
  assume ?L
  define R' where "R' =
    the_inv fset (Collect (case_prod R) (fset a × fset b))" (is "_ = the_inv fset ?L'")
  have "finite ?L'" by (intro finite_Int[OF disjI2] finite_cartesian_product) (transfer, simp)+
  hence *: "fset R' = ?L'" unfolding R'_def by (intro fset_to_fset)
  show ?R unfolding Grp_def relcompp.simps conversep.simps
  proof (intro CollectI case_prodI exI[of _ a] exI[of _ b] exI[of _ R'] conjI refl)
    from * show "a = fimage fst R'" using conjunct1[OF ?L]
      by (transfer, auto simp add: image_def Int_def split: prod.splits)
    from * show "b = fimage snd R'" using conjunct2[OF ?L]
      by (transfer, auto simp add: image_def Int_def split: prod.splits)
  qed (auto simp add: *)
next
  assume ?R thus ?L unfolding Grp_def relcompp.simps conversep.simps
    using Product_Type.Collect_case_prodD by blast
qed

bnf "'a fset"
  map: fimage
  sets: fset
  bd: natLeq
  wits: "{||}"
  rel: rel_fset
apply -
          apply transfer' apply simp
         apply transfer' apply force
        apply transfer apply force
       apply transfer' apply force
      apply (rule natLeq_card_order)
       apply (rule natLeq_cinfinite)
  apply (rule regularCard_natLeq)
    apply transfer apply (metis finite_iff_ordLess_natLeq)
   apply (fastforce simp: rel_fset_alt)
 apply (simp add: Grp_def relcompp.simps conversep.simps fun_eq_iff rel_fset_alt
   rel_fset_aux[unfolded OO_Grp_alt])
apply transfer apply simp
done

lemma rel_fset_fset: "rel_set χ (fset A1) (fset A2) = rel_fset χ A1 A2"
  by (simp add: rel_fset.rep_eq)

end

declare
  fset.map_comp[simp]
  fset.map_id[simp]
  fset.set_map[simp]


subsection Size setup

context includes fset.lifting 
begin
lift_definition size_fset :: "('a ==> nat) ==> 'a fset ==> nat" is "λf. sum (Suc f)" .
end

instantiation fset :: (type) size 
begin
definition size_fset where
  size_fset_overloaded_def: "size_fset = FSet.size_fset (λ_. 0)"
instance ..
end

lemma size_fset_simps[simp]: "size_fset f X = (x fset X. Suc (f x))"
  by (rule size_fset_def[THEN meta_eq_to_obj_eq, THEN fun_cong, THEN fun_cong,
    unfolded map_fun_def comp_def id_apply])

lemma size_fset_overloaded_simps[simp]: "size X = (x fset X. Suc 0)"
  by (rule size_fset_simps[of "λ_. 0", unfolded add_0_left add_0_right,
    folded size_fset_overloaded_def])

lemma fset_size_o_map: "inj f ==> size_fset g fimage f = size_fset (g f)"
  unfolding fun_eq_iff
  by (simp add: inj_def inj_onI sum.reindex)

setup 
 BNF_LFP_Size.register_size_global 🍋fset \
  @{thm size_fset_overloaded_def} @{thms size_fset_simps size_fset_overloaded_simps}
  @{thms fset_size_o_map}


lifting_update fset.lifting
lifting_forget fset.lifting

subsection Advanced relator customization

text Set vs. sum relators:

lemma rel_set_rel_sum[simp]:
"rel_set (rel_sum χ φ) A1 A2
 rel_set χ (Inl -` A1) (Inl -` A2) rel_set φ (Inr -` A1) (Inr -` A2)"
(is "?L ?Rl ?Rr")
proof safe
  assume L: "?L"
  show ?Rl unfolding rel_set_def Bex_def vimage_eq proof safe
    fix l1 assume "Inl l1 A1"
    then obtain a2 where a2: "a2 A2" and "rel_sum χ φ (Inl l1) a2"
    using L unfolding rel_set_def by auto
    then obtain l2 where "a2 = Inl l2 χ l1 l2" by (cases a2, auto)
    thus " l2. Inl l2 A2 χ l1 l2" using a2 by auto
  next
    fix l2 assume "Inl l2 A2"
    then obtain a1 where a1: "a1 A1" and "rel_sum χ φ a1 (Inl l2)"
    using L unfolding rel_set_def by auto
    then obtain l1 where "a1 = Inl l1 χ l1 l2" by (cases a1, auto)
    thus " l1. Inl l1 A1 χ l1 l2" using a1 by auto
  qed
  show ?Rr unfolding rel_set_def Bex_def vimage_eq proof safe
    fix r1 assume "Inr r1 A1"
    then obtain a2 where a2: "a2 A2" and "rel_sum χ φ (Inr r1) a2"
    using L unfolding rel_set_def by auto
    then obtain r2 where "a2 = Inr r2 φ r1 r2" by (cases a2, auto)
    thus " r2. Inr r2 A2 φ r1 r2" using a2 by auto
  next
    fix r2 assume "Inr r2 A2"
    then obtain a1 where a1: "a1 A1" and "rel_sum χ φ a1 (Inr r2)"
    using L unfolding rel_set_def by auto
    then obtain r1 where "a1 = Inr r1 φ r1 r2" by (cases a1, auto)
    thus " r1. Inr r1 A1 φ r1 r2" using a1 by auto
  qed
next
  assume Rl: "?Rl" and Rr: "?Rr"
  show ?L unfolding rel_set_def Bex_def vimage_eq proof safe
    fix a1 assume a1: "a1 A1"
    show " a2. a2 A2 rel_sum χ φ a1 a2"
    proof(cases a1)
      case (Inl l1) then obtain l2 where "Inl l2 A2 χ l1 l2"
      using Rl a1 unfolding rel_set_def by blast
      thus ?thesis unfolding Inl by auto
    next
      case (Inr r1) then obtain r2 where "Inr r2 A2 φ r1 r2"
      using Rr a1 unfolding rel_set_def by blast
      thus ?thesis unfolding Inr by auto
    qed
  next
    fix a2 assume a2: "a2 A2"
    show " a1. a1 A1 rel_sum χ φ a1 a2"
    proof(cases a2)
      case (Inl l2) then obtain l1 where "Inl l1 A1 χ l1 l2"
      using Rl a2 unfolding rel_set_def by blast
      thus ?thesis unfolding Inl by auto
    next
      case (Inr r2) then obtain r1 where "Inr r1 A1 φ r1 r2"
      using Rr a2 unfolding rel_set_def by blast
      thus ?thesis unfolding Inr by auto
    qed
  qed
qed


subsubsection Countability

lemma exists_fset_of_list: "xs. fset_of_list xs = S"
  including fset.lifting
  by transfer (rule finite_list)

lemma fset_of_list_surj[simp, intro]: "surj fset_of_list"
  by (metis exists_fset_of_list surj_def)

instance fset :: (countable) countable
proof
  obtain to_nat :: "'a list ==> nat" where "inj to_nat"
    by (metis ex_inj)
  moreover have "inj (inv fset_of_list)"
    using fset_of_list_surj by (rule surj_imp_inj_inv)
  ultimately have "inj (to_nat inv fset_of_list)"
    by (rule inj_compose)
  thus "to_nat::'a fset ==> nat. inj to_nat"
    by auto
qed


subsection Quickcheck setup

text Setup adapted from sets.

notation Quickcheck_Exhaustive.orelse (infixr orelse 55)

context
  includes term_syntax
begin

definition [code_unfold]:
"valterm_femptyset = Code_Evaluation.valtermify ({||} :: ('a :: typerep) fset)"

definition [code_unfold]:
"valtermify_finsert x s = Code_Evaluation.valtermify finsert {} (x :: ('a :: typerep * _)) {} s"

end

instantiation fset :: (exhaustive) exhaustive
begin

fun exhaustive_fset where
"exhaustive_fset f i = (if i = 0 then None else (f {||} orelse exhaustive_fset (λA. f A orelse Quickcheck_Exhaustive.exhaustive (λx. if x || A then None else f (finsert x A)) (i - 1)) (i - 1)))"

instance ..

end

instantiation fset :: (full_exhaustive) full_exhaustive
begin

fun full_exhaustive_fset where
"full_exhaustive_fset f i = (if i = 0 then None else (f valterm_femptyset orelse full_exhaustive_fset (λA. f A orelse Quickcheck_Exhaustive.full_exhaustive (λx. if fst x || fst A then None else f (valtermify_finsert x A)) (i - 1)) (i - 1)))"

instance ..

end

no_notation Quickcheck_Exhaustive.orelse  (infixr orelse 55)

instantiation fset :: (random) random
begin

context
  includes state_combinator_syntax
begin

fun random_aux_fset :: "natural ==> natural ==> natural × natural ==> ('a fset × (unit ==> term)) × natural × natural" where
"random_aux_fset 0 j = Quickcheck_Random.collapse (Random.select_weight [(1, Pair valterm_femptyset)])" |
"random_aux_fset (Code_Numeral.Suc i) j =
  Quickcheck_Random.collapse (Random.select_weight
    [(1, Pair valterm_femptyset),
     (Code_Numeral.Suc i,
      Quickcheck_Random.random j (λx. random_aux_fset i j (λs. Pair (valtermify_finsert x s))))])"

lemma [code]:
  "random_aux_fset i j =
    Quickcheck_Random.collapse (Random.select_weight [(1, Pair valterm_femptyset),
      (i, Quickcheck_Random.random j (λx. random_aux_fset (i - 1) j (λs. Pair (valtermify_finsert x s))))])"
proof (induct i rule: natural.induct)
  case zero
  show ?case by (subst select_weight_drop_zero[symmetric]) (simp add: less_natural_def)
next
  case (Suc i)
  show ?case by (simp only: random_aux_fset.simps Suc_natural_minus_one)
qed

definition "random_fset i = random_aux_fset i i"

instance ..

end

end


subsection Code Generation Setup

text The following @{attribute code_unfold} lemmas are so the pre-processor of the code generator
 will perform conversions like, e.g.,
 @{lemma "x || fimage f (fset_of_list xs) x f ` set xs"
  by (simp only: fimage.rep_eq fset_of_list.rep_eq)}.

declare
  ffilter.rep_eq[code_unfold]
  fimage.rep_eq[code_unfold]
  finsert.rep_eq[code_unfold]
  fset_of_list.rep_eq[code_unfold]
  inf_fset.rep_eq[code_unfold]
  minus_fset.rep_eq[code_unfold]
  sup_fset.rep_eq[code_unfold]
  uminus_fset.rep_eq[code_unfold]

end

Messung V0.5 in Prozent
C=94 H=99 G=96

¤ Dauer der Verarbeitung: 0.48 Sekunden  (vorverarbeitet am  2026-04-27) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.