Theory IP_Partition_Preliminaries
section‹Partition a Set by a Specific Constraint›
theory IP_Partition_Preliminaries
imports Main
begin
text‹Will be used for the IP address space partition of a firewall.
However, this file is completely generic in terms of sets, it only imports Main.
It will be used in @{file ‹../Service_Matrix.thy›}.
Core idea: This file partitions @{typ "'a set set"} by some magic condition.
Later, we will show that this magic condition implies that all IPs that have been grouped
by the magic condition show the same behaviour for a simple firewall.›
definition disjoint :: "'a set set ⇒ bool" where
"disjoint ts ≡ ∀A ∈ ts. ∀B ∈ ts. A ≠ B ⟶ A ∩ B = {}"
text_raw‹We will call two partitioned sets \emph{complete} iff @{term "⋃ ss = ⋃ ts"}.›
text‹The condition we use to partition a set. If this holds and
@{term A} is the set of IP addresses in each rule in a firewall,
then @{term B} is a partition of @{term "⋃ A"} where each member has the same behavior
w.r.t the firewall ruleset.›
text‹@{term A} is the carrier set and @{term B}* should be a partition of @{term "⋃ A"}
which fulfills the following condition:›
definition ipPartition :: "'a set set ⇒ 'a set set ⇒ bool" where
"ipPartition A B ≡ ∀a ∈ A. ∀b ∈ B. a ∩ b = {} ∨ b ⊆ a"
definition disjoint_list :: "'a set list ⇒ bool" where
"disjoint_list ls ≡ distinct ls ∧ disjoint (set ls)"
context begin
private fun disjoint_list_rec :: "'a set list ⇒ bool" where
"disjoint_list_rec [] = True" |
"disjoint_list_rec (x#xs) = (x ∩ ⋃(set xs) = {} ∧ disjoint_list_rec xs)"
private lemma disjoint_equi: "disjoint_list_rec ts ⟹ disjoint (set ts)"
apply(induction ts)
apply(simp_all add: disjoint_def)
by fast
private lemma disjoint_list_disjoint_list_rec: "disjoint_list ts ⟹ disjoint_list_rec ts"
apply(induction ts)
apply(simp_all add: disjoint_list_def disjoint_def)
by fast
private definition addSubsetSet :: "'a set ⇒ 'a set set ⇒ 'a set set" where
"addSubsetSet s ts = insert (s - ⋃ts) (((∩) s) ` ts) ∪ ((λx. x - s) ` ts)"
private fun partitioning :: "'a set list ⇒ 'a set set ⇒ 'a set set" where
"partitioning [] ts = ts" |
"partitioning (s#ss) ts = partitioning ss (addSubsetSet s ts)"
text‹simple examples›
lemma "partitioning [{1::nat,2},{3,4},{5,6,7},{6},{10}] {} = {{10}, {6}, {5, 7}, {}, {3, 4}, {1, 2}}" by eval
lemma "⋃ {{1::nat,2},{3,4},{5,6,7},{6},{10}} = ⋃ (partitioning [{1,2},{3,4},{5,6,7},{6},{10}] {})" by eval
lemma "disjoint (partitioning [{1::nat,2},{3,4},{5,6,7},{6},{10}] {})" by eval
lemma "ipPartition {{1::nat,2},{3,4},{5,6,7},{6},{10}} (partitioning [{1::nat,2},{3,4},{5,6,7},{6},{10}] {})" by eval
lemma "ipPartition A {}" by(simp add: ipPartition_def)
lemma ipPartitionUnion: "ipPartition As Cs ∧ ipPartition Bs Cs ⟷ ipPartition (As ∪ Bs) Cs"
unfolding ipPartition_def by fast
private lemma disjointAddSubset: "disjoint ts ⟹ disjoint (addSubsetSet a ts)"
by (auto simp add: disjoint_def addSubsetSet_def)
private lemma coversallAddSubset:"⋃ (insert a ts) = ⋃ (addSubsetSet a ts)"
by (auto simp add: addSubsetSet_def)
private lemma ipPartioningAddSubset0: "disjoint ts ⟹ ipPartition ts (addSubsetSet a ts)"
apply(simp add: addSubsetSet_def ipPartition_def)
apply(safe)
apply blast
apply(simp_all add: disjoint_def)
apply blast+
done
private lemma ipPartitioningAddSubset1: "disjoint ts ⟹ ipPartition (insert a ts) (addSubsetSet a ts)"
apply(simp add: addSubsetSet_def ipPartition_def)
apply(safe)
apply blast
apply(simp_all add: disjoint_def)
apply blast+
done
private lemma addSubsetSetI:
"s - ⋃ts ∈ addSubsetSet s ts"
"t ∈ ts ⟹ s ∩ t ∈ addSubsetSet s ts"
"t ∈ ts ⟹ t - s ∈ addSubsetSet s ts"
unfolding addSubsetSet_def by blast+
private lemma addSubsetSetE:
assumes "A ∈ addSubsetSet s ts"
obtains "A = s - ⋃ts" | T where "T ∈ ts" "A = s ∩ T" | T where "T ∈ ts" "A = T - s"
using assms unfolding addSubsetSet_def by blast
private lemma Union_addSubsetSet: "⋃(addSubsetSet b As) = b ∪ ⋃As"
unfolding addSubsetSet_def by auto
private lemma addSubsetSetCom: "addSubsetSet a (addSubsetSet b As) = addSubsetSet b (addSubsetSet a As)"
proof -
{
fix A a b assume "A ∈ addSubsetSet a (addSubsetSet b As)"
hence "A ∈ addSubsetSet b (addSubsetSet a As)"
apply (rule addSubsetSetE)
proof(goal_cases)
case 1
assume "A = a - ⋃(addSubsetSet b As)"
hence "A = (a - ⋃As) - b" by (auto simp add: Union_addSubsetSet)
thus ?thesis by (auto intro: addSubsetSetI)
next
case (2 T)
have "A = b ∩ (a - ⋃As) ∨ (∃S∈As. A = b ∩ (a ∩ S)) ∨ (∃S∈As. A = (a ∩ S) - b)"
by (rule addSubsetSetE[OF 2(1)]) (auto simp: 2(2))
thus ?thesis by (blast intro: addSubsetSetI)
next
case (3 T)
have "A = b - ⋃(addSubsetSet a As) ∨ (∃S∈As. A = b ∩ (S - a)) ∨ (∃S∈As. A = (S - a) - b)"
by (rule addSubsetSetE[OF 3(1)]) (auto simp: 3(2) Union_addSubsetSet)
thus ?thesis by (blast intro: addSubsetSetI)
qed
}
thus ?thesis by blast
qed
private lemma ipPartitioningAddSubset2: "ipPartition {a} (addSubsetSet a ts)"
apply(simp add: addSubsetSet_def ipPartition_def)
by blast
private lemma disjointPartitioning_helper :"disjoint As ⟹ disjoint (partitioning ss As)"
proof(induction ss arbitrary: As)
case Nil thus ?case by(simp)
next
case (Cons s ss)
from Cons.prems disjointAddSubset have d: "disjoint (addSubsetSet s As)" by fast
from Cons.IH d have "disjoint (partitioning ss (addSubsetSet s As))" .
thus ?case by simp
qed
private lemma disjointPartitioning: "disjoint (partitioning ss {})"
proof -
have "disjoint {}" by(simp add: disjoint_def)
from this disjointPartitioning_helper show ?thesis by fast
qed
private lemma coversallPartitioning:"⋃ (set ts) = ⋃ (partitioning ts {})"
proof -
have "⋃ (set ts ∪ As) = ⋃ (partitioning ts As)" for As
apply(induction ts arbitrary: As)
apply(simp_all)
by (metis Union_addSubsetSet sup_left_commute)
thus ?thesis by (metis sup_bot.right_neutral)
qed
private lemma "⋃ As = ⋃ Bs ⟹ ipPartition As Bs ⟹ ipPartition As (addSubsetSet a Bs)"
by(auto simp add: ipPartition_def addSubsetSet_def)
private lemma ipPartitionSingleSet: "ipPartition {t} (addSubsetSet t Bs)
⟹ ipPartition {t} (partitioning ts (addSubsetSet t Bs))"
apply(induction ts arbitrary: Bs t)
apply(simp_all)
by (metis addSubsetSetCom ipPartitioningAddSubset2)
private lemma ipPartitioning_helper: "disjoint As ⟹ ipPartition (set ts) (partitioning ts As)"
proof(induction ts arbitrary: As)
case Nil thus ?case by(simp add: ipPartition_def)
next
case (Cons t ts)
from Cons.prems ipPartioningAddSubset0 have d: "ipPartition As (addSubsetSet t As)" by blast
from Cons.prems Cons.IH d disjointAddSubset ipPartitioningAddSubset1
have e: "ipPartition (set ts) (partitioning ts (addSubsetSet t As))" by blast
from ipPartitioningAddSubset2 Cons.prems
have "ipPartition {t} (addSubsetSet t As)" by blast
from this Cons.prems ipPartitionSingleSet
have f: "ipPartition {t} (partitioning ts (addSubsetSet t As))" by fast
have "set (t#ts) = insert t (set ts)" by auto
from ipPartitionUnion have "⋀ As Bs Cs. ipPartition As Cs ⟹ ipPartition Bs Cs ⟹ ipPartition (As ∪ Bs) Cs" by fast
with this e f
have "ipPartition (set (t # ts)) (partitioning ts (addSubsetSet t As))" by fastforce
thus ?case by simp
qed
private lemma ipPartitioning: "ipPartition (set ts) (partitioning ts {})"
proof -
have "disjoint {}" by(simp add: disjoint_def)
from this ipPartitioning_helper show ?thesis by fast
qed
private lemma inter_dif_help_lemma: "A ∩ B = {} ⟹ B - S = B - (S - A)"
by blast
private lemma disjoint_list_lem: "disjoint_list ls ⟹ ∀s ∈ set(ls). ∀t ∈ set(ls). s ≠ t ⟶ s ∩ t = {}"
proof(induction ls)
qed(simp_all add: disjoint_list_def disjoint_def)
private lemma disjoint_list_empty: "disjoint_list []"
by (simp add: disjoint_list_def disjoint_def)
private lemma disjoint_sublist: "disjoint_list (t#ts) ⟹ disjoint_list ts"
proof(induction ts arbitrary: t)
qed(simp_all add: disjoint_list_empty disjoint_list_def disjoint_def)
private fun intersection_list :: "'a set ⇒ 'a set list ⇒ 'a set list" where
"intersection_list _ [] = []" |
"intersection_list s (t#ts) = (s ∩ t)#(intersection_list s ts)"
private fun intersection_list_opt :: "'a set ⇒ 'a set list ⇒ 'a set list" where
"intersection_list_opt _ [] = []" |
"intersection_list_opt s (t#ts) = (s ∩ t)#(intersection_list_opt (s - t) ts)"
private lemma disjoint_subset: "disjoint A ⟹ a ∈ A ⟹ b ⊆ a ⟹ disjoint ((A - {a}) ∪ {b})"
apply(simp add: disjoint_def)
by blast
private lemma disjoint_intersection: "disjoint A ⟹ a ∈ A ⟹ disjoint ({a ∩ b} ∪ (A - {a}))"
apply(simp add: disjoint_def)
by(blast)
private lemma intList_equi: "disjoint_list_rec ts ⟹ intersection_list s ts = intersection_list_opt s ts"
proof(induction ts)
case Nil thus ?case by simp
next
case (Cons t ts)
from Cons.prems have "intersection_list_opt s ts = intersection_list_opt (s - t) ts"
proof(induction ts arbitrary: s t)
case Nil thus ?case by simp
next
case Cons
have "∀t ∈ set ts. u ∩ t = {} ⟹ intersection_list_opt s ts = intersection_list_opt (s - u) ts"
for u
apply(induction ts arbitrary: s u)
apply(simp_all)
by (metis Diff_Int_distrib2 Diff_empty Diff_eq Un_Diff_Int sup_bot.right_neutral)
with Cons show ?case
apply(simp)
by (metis Diff_Int_distrib2 Diff_empty Un_empty inf_sup_distrib1)
qed
with Cons show ?case by simp
qed
private fun difference_list :: "'a set ⇒ 'a set list ⇒ 'a set list" where
"difference_list _ [] = []" |
"difference_list s (t#ts) = (t - s)#(difference_list s ts)"
private fun difference_list_opt :: "'a set ⇒ 'a set list ⇒ 'a set list" where
"difference_list_opt _ [] = []" |
"difference_list_opt s (t#ts) = (t - s)#(difference_list_opt (s - t) ts)"
private lemma difList_equi: "disjoint_list_rec ts ⟹ difference_list s ts = difference_list_opt s ts"
proof(induction ts arbitrary: s)
case Nil thus ?case by simp
next
case (Cons t ts)
have difference_list_opt_lem0: "∀t ∈ set(ts). u ∩ t = {} ⟹
difference_list_opt s ts = difference_list_opt (s - u) ts"
for u proof(induction ts arbitrary: s u)
case Cons thus ?case
apply(simp_all add: inter_dif_help_lemma)
by (metis Diff_Int_distrib2 Diff_eq Un_Diff_Int sup_bot.right_neutral)
qed(simp)
have "disjoint_list_rec (t # ts) ⟹ difference_list_opt s ts = difference_list_opt (s - t) ts"
proof(induction ts arbitrary: s t)
case Cons thus ?case
apply(simp_all add: difference_list_opt_lem0)
by (metis Un_empty inf_sup_distrib1 inter_dif_help_lemma)
qed(simp)
with Cons show ?case by simp
qed
private fun partList0 :: "'a set ⇒ 'a set list ⇒ 'a set list" where
"partList0 s [] = []" |
"partList0 s (t#ts) = (s ∩ t)#((t - s)#(partList0 s ts))"
private lemma partList0_set_equi: "set(partList0 s ts) = (((∩) s) ` (set ts)) ∪ ((λx. x - s) ` (set ts))"
by(induction ts arbitrary: s) auto
private lemma partList_sub_equi0: "set(partList0 s ts) =
set(difference_list s ts) ∪ set(intersection_list s ts)"
by(induction ts arbitrary: s) simp+
private fun partList1 :: "'a set ⇒ 'a set list ⇒ 'a set list" where
"partList1 s [] = []" |
"partList1 s (t#ts) = (s ∩ t)#((t - s)#(partList1 (s - t) ts))"
private lemma partList_sub_equi: "set(partList1 s ts) =
set(difference_list_opt s ts) ∪ set(intersection_list_opt s ts)"
by(induction ts arbitrary: s) (simp_all)
private lemma partList0_partList1_equi: "disjoint_list_rec ts ⟹ set (partList0 s ts) = set (partList1 s ts)"
by (simp add: partList_sub_equi partList_sub_equi0 intList_equi difList_equi)
private fun partList2 :: "'a set ⇒ 'a set list ⇒ 'a set list" where
"partList2 s [] = []" |
"partList2 s (t#ts) = (if s ∩ t = {} then (t#(partList2 (s - t) ts))
else (s ∩ t)#((t - s)#(partList2 (s - t) ts)))"
private lemma partList2_empty: "partList2 {} ts = ts"
by(induction ts) (simp_all)
private lemma partList1_partList2_equi: "set(partList1 s ts) - {{}} = set(partList2 s ts) - {{}}"
by(induction ts arbitrary: s) (auto)
private fun partList3 :: "'a set ⇒ 'a set list ⇒ 'a set list" where
"partList3 s [] = []" |
"partList3 s (t#ts) = (if s = {} then (t#ts) else
(if s ∩ t = {} then (t#(partList3 (s - t) ts))
else
(if t - s = {} then (t#(partList3 (s - t) ts))
else (t ∩ s)#((t - s)#(partList3 (s - t) ts)))))"
private lemma partList2_partList3_equi: "set(partList2 s ts) - {{}} = set(partList3 s ts) - {{}}"
apply(induction ts arbitrary: s)
apply(simp; fail)
apply(simp add: partList2_empty)
by blast
fun partList4 :: "'a set ⇒ 'a set list ⇒ 'a set list" where
"partList4 s [] = []" |
"partList4 s (t#ts) = (if s = {} then (t#ts) else
(if s ∩ t = {} then (t#(partList4 s ts))
else
(if t - s = {} then (t#(partList4 (s - t) ts))
else (t ∩ s)#((t - s)#(partList4 (s - t) ts)))))"
private lemma partList4: "partList4 s ts = partList3 s ts"
apply(induction ts arbitrary: s)
apply(simp; fail)
apply (simp add: Diff_triv)
done
private lemma partList0_addSubsetSet_equi: "s ⊆ ⋃(set ts) ⟹
addSubsetSet s (set ts) - {{}} = set(partList0 s ts) - {{}}"
by(simp add: addSubsetSet_def partList0_set_equi)
private fun partitioning_nontail :: "'a set list ⇒ 'a set set ⇒ 'a set set" where
"partitioning_nontail [] ts = ts" |
"partitioning_nontail (s#ss) ts = addSubsetSet s (partitioning_nontail ss ts)"
private lemma partitioningCom: "addSubsetSet a (partitioning ss ts) = partitioning ss (addSubsetSet a ts)"
apply(induction ss arbitrary: a ts)
apply(simp; fail)
apply(simp add: addSubsetSetCom)
done
private lemma partitioning_nottail_equi: "partitioning_nontail ss ts = partitioning ss ts"
apply(induction ss arbitrary: ts)
apply(simp; fail)
apply(simp add: addSubsetSetCom partitioningCom)
done
fun partitioning1 :: "'a set list ⇒ 'a set list ⇒ 'a set list" where
"partitioning1 [] ts = ts" |
"partitioning1 (s#ss) ts = partList4 s (partitioning1 ss ts)"
lemma partList4_empty: "{} ∉ set ts ⟹ {} ∉ set (partList4 s ts)"
apply(induction ts arbitrary: s)
apply(simp; fail)
by auto
lemma partitioning1_empty0: "{} ∉ set ts ⟹ {} ∉ set (partitioning1 ss ts)"
apply(induction ss arbitrary: ts)
apply(simp; fail)
apply(simp add: partList4_empty)
done
lemma partitioning1_empty1: "{} ∉ set ts ⟹
set(partitioning1 ss ts) - {{}} = set(partitioning1 ss ts)"
by(simp add: partitioning1_empty0)
lemma partList4_subset: "a ⊆ ⋃(set ts) ⟹ a ⊆ ⋃(set (partList4 b ts))"
apply(simp add: partList4)
apply(induction ts arbitrary: a b)
apply(simp; fail)
apply(simp)
by fast
private lemma "a ≠ {} ⟹ disjoint_list_rec (a # ts) ⟷ disjoint_list_rec ts ∧ a ∩ ⋃ (set ts) = {}" by auto
lemma partList4_complete0: "s ⊆ ⋃(set ts) ⟹ ⋃(set (partList4 s ts)) = ⋃(set ts)"
unfolding partList4
proof(induction ts arbitrary: s)
case Nil thus ?case by(simp)
next
case Cons thus ?case by (simp add: Diff_subset_conv Un_Diff_Int inf_sup_aci(7) sup.commute)
qed
private lemma partList4_disjoint: "s ⊆ ⋃(set ts) ⟹ disjoint_list_rec ts ⟹
disjoint_list_rec (partList4 s ts)"
apply(induction ts arbitrary: s)
apply(simp; fail)
apply(simp add: Diff_subset_conv)
apply(rule conjI)
apply (metis Diff_subset_conv Int_absorb1 Int_lower2 Un_absorb1 partList4_complete0)
apply(safe)
using partList4_complete0 apply (metis Diff_subset_conv Diff_triv IntI UnionI)
apply (metis Diff_subset_conv Diff_triv)
using partList4_complete0 by (metis Diff_subset_conv IntI UnionI)+
lemma union_set_partList4: "⋃(set (partList4 s ts)) = ⋃(set ts)"
by (induction ts arbitrary: s, auto)
private lemma partList4_distinct_hlp: assumes "a ≠ {}" "a ∉ set ts" "disjoint (insert a (set ts))"
shows "a ∉ set (partList4 s ts)"
proof -
from assms have "¬ a ⊆ ⋃(set ts)" unfolding disjoint_def by fastforce
hence "¬ a ⊆ ⋃(set (partList4 s ts))" using union_set_partList4 by metis
thus ?thesis by blast
qed
private lemma partList4_distinct: "{} ∉ set ts ⟹ disjoint_list ts ⟹ distinct (partList4 s ts)"
proof(induction ts arbitrary: s)
case Nil thus ?case by simp
next
case(Cons t ts)
have x1: "⋀x xa xb xc.
t ∉ set ts ⟹
disjoint (insert t (set ts)) ⟹
xa ∈ t ⟹
xb ∈ s ⟹
xb ∈ t ⟹
xb ∉ {} ⟹
xc ∈ s ⟹
xc ∉ {} ⟹
t ∩ s ∈ set (partList4 (s - t) ts) ⟹
¬ t ∩ s ⊆ ⋃(set (partList4 (s - t) ts))"
by(simp add: union_set_partList4 disjoint_def, force)
have x2: "⋀x xa xb xc.
t ∉ set ts ⟹
disjoint (insert t (set ts)) ⟹
x ∈ t ⟹
xa ∈ t ⟹
xa ∉ s ⟹
xb ∈ s ⟹
xc ∈ s ⟹
¬ t - s ⊆ ⋃(set (partList4 (s - t) ts))"
by(simp add: union_set_partList4 disjoint_def, force)
from Cons have IH: "distinct (partList4 s ts)" for s
using disjoint_sublist list.set_intros(2) by auto
from Cons.prems(1,2) IH show ?case
unfolding disjoint_list_def
apply(simp)
apply(safe)
apply(metis partList4_distinct_hlp)
apply(metis partList4_distinct_hlp)
apply(metis partList4_distinct_hlp)
apply blast
using x1 apply blast
using x2 by blast
qed
lemma partList4_disjoint_list: assumes "s ⊆ ⋃(set ts)" "disjoint_list ts" "{} ∉ set ts"
shows "disjoint_list (partList4 s ts)"
unfolding disjoint_list_def
proof
from assms(2,3) show "distinct (partList4 s ts)"
using partList4_distinct disjoint_list_def by auto
show "disjoint (set (partList4 s ts))"
proof -
have disjoint_list_disjoint_list_rec: "disjoint_list ts ⟹ disjoint_list_rec ts"
proof(induction ts)
case Cons thus ?case by(auto simp add: disjoint_list_def disjoint_def)
qed(simp)
with partList4_disjoint disjoint_equi assms(1,2) show ?thesis by blast
qed
qed
lemma partitioning1_subset: "a ⊆ ⋃ (set ts) ⟹ a ⊆ ⋃ (set (partitioning1 ss ts))"
apply(induction ss arbitrary: ts a)
apply(simp)
apply(simp add: partList4_subset)
done
lemma partitioning1_disjoint_list: "{} ∉ (set ts) ⟹ ⋃ (set ss) ⊆ ⋃ (set ts) ⟹
disjoint_list ts ⟹ disjoint_list (partitioning1 ss ts)"
proof(induction ss)
case Nil thus ?case by simp
next
case(Cons t ts) thus ?case
apply(clarsimp)
apply(rule partList4_disjoint_list)
using partitioning1_subset apply(metis)
apply(blast)
using partitioning1_empty0 apply(metis)
done
qed
private lemma partitioning1_disjoint: "⋃ (set ss) ⊆ ⋃ (set ts) ⟹
disjoint_list_rec ts ⟹ disjoint_list_rec (partitioning1 ss ts)"
proof(induction ss arbitrary: ts)
qed(simp_all add: partList4_disjoint partitioning1_subset)
private lemma partitioning_equi: "{} ∉ set ts ⟹ disjoint_list_rec ts ⟹ ⋃ (set ss) ⊆ ⋃ (set ts) ⟹
set(partitioning1 ss ts) = partitioning_nontail ss (set ts) - {{}}"
proof(induction ss)
case Nil thus ?case by simp
next
case (Cons s ss)
have addSubsetSet_empty: "addSubsetSet s (ts - {{}}) - {{}} = addSubsetSet s ts - {{}}"
for s and ts::"'a set set"
unfolding addSubsetSet_def by blast
have r: "disjoint_list_rec ts ⟹ s ⊆ ⋃(set ts) ⟹
addSubsetSet s (set ts) - {{}} = set (partList4 s ts) - {{}}"
for ts::"'a set list"
unfolding partList4
by(simp add: partList0_addSubsetSet_equi partList0_partList1_equi partList1_partList2_equi
partList2_partList3_equi)
have 1: "disjoint_list_rec (partitioning1 ss ts)"
using partitioning1_disjoint Cons.prems by auto
from Cons.prems have 2: "s ⊆ ⋃(set (partitioning1 ss ts))"
by (meson Sup_upper dual_order.trans list.set_intros(1) partitioning1_subset)
from Cons have IH: "set (partitioning1 ss ts) = partitioning_nontail ss (set ts) - {{}}" by auto
with r[OF 1 2] show ?case by (simp add: partList4_empty addSubsetSet_empty)
qed
lemma ipPartitioning_helper_opt: "{} ∉ set ts ⟹ disjoint_list ts ⟹ ⋃ (set ss) ⊆ ⋃ (set ts)
⟹ ipPartition (set ss) (set (partitioning1 ss ts))"
apply(drule disjoint_list_disjoint_list_rec)
apply(simp add: partitioning_equi partitioning_nottail_equi)
by (meson Diff_subset disjoint_equi ipPartition_def ipPartitioning_helper subsetCE)
lemma complete_helper: "{} ∉ set ts ⟹ ⋃ (set ss) ⊆ ⋃ (set ts)⟹
⋃ (set ts) = ⋃ (set (partitioning1 ss ts))"
apply(induction ss arbitrary: ts)
apply(simp_all)
by (metis partList4_complete0)
lemma "partitioning1 [{1::nat},{2},{}] [{1},{},{2},{3}] = [{1}, {}, {2}, {3}]" by eval
lemma partitioning_foldr: "partitioning X B = foldr addSubsetSet X B"
apply(induction X)
apply(simp; fail)
apply(simp)
by (metis partitioningCom)
lemma "ipPartition (set X) (foldr addSubsetSet X {})"
apply(subst partitioning_foldr[symmetric])
using ipPartitioning by auto
lemma "⋃ (set X) = ⋃ (foldr addSubsetSet X {})"
apply(subst partitioning_foldr[symmetric])
by (simp add: coversallPartitioning)
lemma "partitioning1 X B = foldr partList4 X B"
by(induction X)(simp_all)
lemma "ipPartition (set X) (set (partitioning1 X [UNIV]))"
apply(rule ipPartitioning_helper_opt)
by(simp_all add: disjoint_list_def disjoint_def)
lemma "(⋃(set (partitioning1 X [UNIV]))) = UNIV"
apply(subgoal_tac "UNIV = ⋃ (set (partitioning1 X [UNIV]))")
prefer 2
apply(rule complete_helper[where ts="[UNIV]", simplified])
apply(simp)
done
end
end