(* Title: A simple ROBDD implementation Author:ThomasTuerk<tuerk@in.tum.de> Maintainer:ThomasTuerk<tuerk@in.tum.de>
*) section‹\isaheader{ROBDDs}› theory Robdd imports Main "../ICF/spec/MapSpec""../Iterator/SetIteratorOperations"
begin
text‹Let's first fix some datatypes for BDDs or more specifically
reduced ordered binary decision diagrams (OBDDs).›
lemma robdd_is_leaf_alt_def : "robdd_is_leaf b ⟷ (b = robdd_one ∨ b = robdd_zero)" by (cases b) auto
text‹IDs are just used a convinience for performance reasons. Therefore,
we define two robdds to be equivalent if they are equal up to ids.› primrec robdd_equiv where "robdd_equiv (robdd_leaf f) b = (b = robdd_leaf f)"
| "robdd_equiv (robdd_var i l v r) b = (∃i' l' r'. b = robdd_var i' l' v r' ∧ robdd_equiv l l' ∧ robdd_equiv r r')"
lemma robdd_equiv_simps[simp] : "robdd_equiv b (robdd_leaf f) = (b = robdd_leaf f)" "robdd_equiv b b" by (induct b, auto)
subsection‹subrobdds›
text‹It is for later definitions important to be able to talk about all the
that form a robdd. This leads to the definition of subrobdds.›
primrec subrobdds :: "robdd ==> robdd set"where "subrobdds (robdd_leaf f) = {robdd_leaf f}"
| "subrobdds (robdd_var i l v r) = (insert (robdd_var i l v r) (subrobdds l ∪ subrobdds r))"
definition subrobdds_proper :: "robdd ==> robdd set"where "subrobdds_proper b = (subrobdds b) - {b}"
lemma subrobdds_alt_def : "subrobdds b = insert b (subrobdds_proper b)" by (cases b) (simp_all add: subrobdds_proper_def)
lemma subobbds_proper_size: "b1 ∈ subrobdds_proper b2 ==> size_robdd b1 < size_robdd b2" proof (induct b2 arbitrary: b1) case (robdd_leaf f) thus ?caseby (simp add: subrobdds_proper_def) next case (robdd_var i l v r) note indhyp_l = robdd_var(1) note indhyp_r = robdd_var(2)
from robdd_var(3) have b1_in_cases: "b1 ∈ subrobdds l ∨ b1 ∈ subrobdds r"by (simp add: subrobdds_proper_def) show ?case proof (cases "b1 ∈ subrobdds l") case True with indhyp_l[of b1] show ?thesis apply (cases "b1 = l") apply (simp_all add: subrobdds_proper_def) done next case False with b1_in_cases have"b1 ∈ subrobdds r"by blast with indhyp_r[of b1] show ?thesis apply (cases "b1 = r") apply (simp_all add: subrobdds_proper_def) done qed qed
lemma subrobdds_proper_simps [simp] : "subrobdds_proper (robdd_leaf f) = {}" "subrobdds_proper (robdd_var i l v r) = (insert l (insert r (subrobdds_proper l ∪ subrobdds_proper r)))" proof - show"subrobdds_proper (robdd_leaf f) = {}" by (simp_all add: subrobdds_proper_def) next have"subrobdds_proper (robdd_var i l v r) = subrobdds l ∪ subrobdds r - {robdd_var i l v r}" by (simp add: subrobdds_proper_def) alsohave"... = subrobdds l ∪ subrobdds r" proof - from subrobdds_size [of "robdd_var i l v r" l] subrobdds_size [of "robdd_var i l v r" r] have"robdd_var i l v r ∉ subrobdds l""robdd_var i l v r ∉ subrobdds r"by auto thus ?thesis by auto qed alsohave"... = (insert l (insert r (subrobdds_proper l ∪ subrobdds_proper r)))" by (auto simp add: subrobdds_proper_def) finallyshow"subrobdds_proper (robdd_var i l v r) = (insert l (insert r (subrobdds_proper l ∪ subrobdds_proper r)))" . qed
lemma subrobdds_set_idempot2 [simp] : "subrobdds_set (subrobdds b) = subrobdds b" using subrobdds_set_idempot[of "{b}"] by simp
lemma subrobdds_set_mono : "bs ⊆ subrobdds_set bs" unfolding subrobdds_set_def by auto
lemma subrobdds_set_mono2 : "bs1 ⊆ bs2 ==> (subrobdds_set bs1 ⊆ subrobdds_set bs2)" unfolding subrobdds_set_def by auto
subsection‹Invariants›
subsubsection‹IDs›
text‹Ids are just added for convienience and performance. Two ROBDDs should have
same id if and only if they have the same semantics. This way, the equivalence check
ROBDDs can be reduced to an equality check of ids.›
text‹leafs can often be implicitly added› definition robdd_invar_ids_leafs where "robdd_invar_ids_leafs bs = (∀b f. (b ∈ subrobdds_set bs) ⟶ ((robdd_α b = robdd_α (robdd_leaf f)) ⟷ robdd_get_id b = robdd_get_id (robdd_leaf f)))"
text‹Together with other invariants it can the later be derived that
two robdds have the same id if and only if they are equal.› definition robdd_invar_ids_equal where "robdd_invar_ids_equal bs = (∀b1 b2. (b1 ∈ subrobdds_set bs ∧ b2 ∈ subrobdds_set bs) ⟶ ((robdd_get_id b1 = robdd_get_id b2) ⟷ b1 = b2))"
definition robdd_invar_ids_leafs_equal where "robdd_invar_ids_leafs_equal bs = (∀b f. (b ∈ subrobdds_set bs) ⟶ ((robdd_get_id b = robdd_get_id (robdd_leaf f)) ⟷ b = (robdd_leaf f)))"
text‹If two ROBDDs are equal up to ids and then they are in fact equal.› lemma robdd_invar_ids_equiv_implies_eq: assumes"robdd_invar_ids bs" and"b1 ∈ bs""b2 ∈ bs" and"robdd_equiv b1 b2" shows"b1 = b2" using assms proof (induct b1 arbitrary: b2 bs) case (robdd_var i l v r) note indhyp_l = robdd_var(1) note indhyp_r = robdd_var(2) note invar_ids = robdd_var(3) note in_bs = robdd_var(4,5) note equiv_b2 = robdd_var(6)
from equiv_b2 obtain i' l' r' where
b2_eq: "b2 = robdd_var i' l' v r'"and
equiv_l: "robdd_equiv l l'"and
equiv_r: "robdd_equiv r r'" unfolding robdd_equiv.simps by blast
have invar_ids': "robdd_invar_ids {robdd_var i l v r, b2}" apply (rule robdd_invar_ids_subset_subrobdds_rule[OF _ invar_ids]) apply (auto simp add: subrobdds_alt_def in_bs) done have invar_ids_sub: "robdd_invar_ids {l, r, l', r'}" apply (rule robdd_invar_ids_subset_subrobdds_rule[OF _ invar_ids']) apply (auto simp add: b2_eq subrobdds_alt_def) done
from robdd_invar_idsD[OF invar_ids', of "robdd_var i l v r" b2] have i'_eq[simp]: "i' = i"by (simp add: b2_eq robdd_α_def subrobdds_set_def)
show ?caseby (simp add: b2_eq) qed simp_all
subsubsection‹Variable order›
text‹We are formalising reduced \emph{ordered} binary decision diagrams. Therefore, the
need to appear in order.›
primrec robdd_invar_vars_greater where "robdd_invar_vars_greater n (robdd_leaf f) = True"
| "robdd_invar_vars_greater n (robdd_var i l v r) = (n ≤ v ∧ (robdd_invar_vars_greater (Suc v) l) ∧ (robdd_invar_vars_greater (Suc v) r))"
definition robdd_invar_vars where "robdd_invar_vars b = robdd_invar_vars_greater 0 b"
lemma robdd_invar_vars_greater___weaken : "robdd_invar_vars_greater n b ==> n' ≤ n ==> robdd_invar_vars_greater n' b" by (cases b) (simp_all)
lemma robdd_invar_vars_impl: "robdd_invar_vars_greater n robdd ==> robdd_invar_vars robdd" unfolding robdd_invar_vars_def by (rule robdd_invar_vars_greater___weaken[of n]) (simp_all)
subsubsection‹Reduced›
text‹We are formalising \emph{reduced} ordered binary decision diagrams. Therefore, it should
reduced.›
primrec robdd_invar_reduced where "robdd_invar_reduced (robdd_leaf f) = True"
| "robdd_invar_reduced (robdd_var i l v r) = (¬(robdd_equiv l r) ∧ (robdd_invar_reduced l) ∧ (robdd_invar_reduced r))"
lemma subrobdds_leaf_in_reduced: "robdd_invar_reduced b ==>¬(robdd_is_leaf b) ==> (robdd_one ∈ subrobdds b ∧ robdd_zero ∈ subrobdds b)" proof (induct b) case (robdd_leaf f) thus ?caseby simp next case (robdd_var i l v r) note reduced_b = robdd_var(3) from reduced_b have not_equiv_lr: "¬ robdd_equiv l r"and
reduced_l: "robdd_invar_reduced l"and reduced_r: "robdd_invar_reduced r" by simp_all
show ?case proof (cases "robdd_is_leaf l") case False with indhyp_l show ?thesis by simp next case True note l_is_leaf = this
show ?thesis proof (cases "robdd_is_leaf r") case False with indhyp_r show ?thesis by simp next case True note r_is_leaf = this
from l_is_leaf r_is_leaf not_equiv_lr show ?thesis unfolding robdd_is_leaf_alt_def by auto qed qed qed
lemma subrobdds_set_leaf_in_reduced: assumes bs_OK: "∧b. b ∈ bs ==> robdd_invar_reduced b" and bs_neq_leaf_set: "bs ≠ {robdd_one}""bs ≠ {robdd_zero}" and bs_neq_emp: "bs ≠ {}" shows"robdd_one ∈ subrobdds_set bs ∧ robdd_zero ∈ subrobdds_set bs" proof (cases "∃b∈bs. ¬(robdd_is_leaf b)") case True thenobtain b where b_in: "b ∈ bs"and not_leaf_b: "¬(robdd_is_leaf b)"by blast
from bs_OK b_in have invar_reduced: "robdd_invar_reduced b"by simp
from subrobdds_leaf_in_reduced[OF invar_reduced not_leaf_b] have in_b: "robdd_one ∈ subrobdds b ∧ robdd_zero ∈ subrobdds b" .
from in_b b_in show ?thesis unfolding subrobdds_set_def by auto next case False hence only_leafs: "∧b. b ∈ bs ==> robdd_is_leaf b"by simp
from bs_neq_emp obtain b1 where b1_in: "b1 ∈ bs"by auto with only_leafs have leaf_b1: "robdd_is_leaf b1"by simp
from leaf_b1 bs_neq_leaf_set have"bs ≠ {b1}" by (auto simp add: robdd_is_leaf_alt_def) with b1_in obtain b2 where b2_in: "b2 ∈ bs"and b2_neq: "b1 ≠ b2" by auto
from b2_in only_leafs have leaf_b2: "robdd_is_leaf b2"by simp
from b1_in b2_in b2_neq leaf_b1 leaf_b2 have"robdd_one ∈ bs ∧ robdd_zero ∈ bs" unfolding robdd_is_leaf_alt_def by auto thus ?thesis unfolding subrobdds_set_def by simp (metis subrobdds_refl) qed
lemma robdd_invar_ids_leafs_intro : assumes bs_OK: "∧b. b ∈ bs ==> robdd_invar_reduced b" and weak_invar: "robdd_invar_ids bs" shows"robdd_invar_ids_leafs bs" proof (cases "bs = {} ∨ bs = {robdd_one} ∨ bs = {robdd_zero}") case True thus ?thesis proof (elim disjE) assume"bs = {}"thus"robdd_invar_ids_leafs bs" unfolding robdd_invar_ids_leafs_def by simp next assume"bs = {robdd_one}"thus"robdd_invar_ids_leafs bs" unfolding robdd_invar_ids_leafs_def by simp next assume"bs = {robdd_zero}"thus"robdd_invar_ids_leafs bs" unfolding robdd_invar_ids_leafs_def by simp qed next case False with subrobdds_set_leaf_in_reduced[of bs, OF bs_OK] have one_in: "robdd_one ∈ subrobdds_set bs"and
zero_in: "robdd_zero ∈ subrobdds_set bs"by auto
with weak_invar show ?thesis unfolding robdd_invar_ids_leafs_def robdd_invar_ids_def by auto qed
subsubsection‹Overall Invariant›
definition robdd_invar_ext where "robdd_invar_ext bs n b = (b ∈ subrobdds_set bs ∧ robdd_invar_ids bs ∧ robdd_invar_vars_greater n b ∧ robdd_invar_reduced b)"
definition robdd_invar where "robdd_invar b = robdd_invar_ext {b} 0 b"
lemma robdd_invar_alt_def : "robdd_invar b = (robdd_invar_ids {b} ∧ robdd_invar_vars b ∧ robdd_invar_reduced b)" unfolding robdd_invar_def robdd_invar_ext_def robdd_invar_vars_def subrobdds_set_def by simp
lemma robdd_invar_simps_var : "robdd_invar (robdd_var i l v r) ==> (¬(robdd_equiv l r) ∧ robdd_invar l ∧ robdd_invar r)" apply (simp add: robdd_invar_alt_def robdd_invar_ids_def robdd_invar_vars_def subrobdds_set_def) apply (metis robdd_invar_vars_def robdd_invar_vars_impl) done
lemma robdd_invar_subrobdds_set : assumes bs_OK: "∧b. b ∈ bs ==> robdd_invar b" and b_in: "b ∈ subrobdds_set bs" shows"robdd_invar b" proof - from b_in obtain b' where b'_in: "b' ∈ bs"and b_in': "b ∈ subrobdds b'" unfolding subrobdds_set_def by auto
from bs_OK[OF b'_in] have"robdd_invar b'" . with b_in' show"robdd_invar b" apply (induct b') apply simp_all apply (metis robdd_invar_simps_var) done qed
lemma robdd_invar_ext_simps [simp] : "robdd_invar_ext bs n (robdd_leaf f) = (robdd_invar_ids bs ∧ ((robdd_leaf f) ∈ (subrobdds_set bs)))" (is ?T1) "robdd_invar_ext bs n (robdd_var i l v r) = ((robdd_var i l v r) ∈ (subrobdds_set bs) ∧¬(robdd_equiv l r) ∧ n ≤ v ∧ robdd_invar_ext bs (Suc v) l ∧ robdd_invar_ext bs (Suc v) r)" (is ?T2) proof - show ?T1 by (auto simp add: robdd_invar_ext_def) next show ?T2 (is"?ls = ?rs") proof assume ?rs thus ?ls by (simp add: robdd_invar_ext_def subrobdds_set_def) next assume ?ls thenobtain b where b_props: "b ∈ bs""robdd_var i l v r ∈ subrobdds b" by (auto simp add: robdd_invar_ext_def subrobdds_set_def)
from subrobdds_trans [of l "robdd_var i l v r" b]
subrobdds_trans [of r "robdd_var i l v r" b] have"r ∈ subrobdds b""l ∈ subrobdds b"by (simp_all add: b_props) with‹?ls›‹b ∈ bs›show ?rs by (auto simp add: robdd_invar_ext_def subrobdds_set_def) qed qed
lemma rodd_invar_ext_idempot_subrobdds_set [simp]: "robdd_invar_ext (subrobdds_set bs) n b = robdd_invar_ext bs n b" unfolding robdd_invar_ext_def robdd_invar_ids_def by simp
lemma robdd_invar_ext_weaken : assumespre: "robdd_invar_ext bs2 n b" and bs2_props: "∧b2. b ∈ subrobdds_set bs2 ==> b2 ∈ bs1 ==>∃b1 ∈ bs2. b2 ∈ (subrobdds b1)" and b_in: "b ∈ subrobdds_set bs2 ==> b ∈ subrobdds_set bs1" and m_le: "m ≤ n" shows"robdd_invar_ext bs1 m b" proof - fromprehave "b ∈ subrobdds_set bs2" "robdd_invar_ids bs2" "robdd_invar_vars_greater n b" "robdd_invar_reduced b" unfolding robdd_invar_ext_def by simp_all
lemma robdd_α_invar_greater : assumes invar_vars: "robdd_invar_vars_greater n b" and a_equiv: "∧v. v ≥ n ==> a1 v = a2 v" shows"robdd_α b a1 = robdd_α b a2" using assms apply (induct b) apply (simp_all) apply (metis le_Suc_eq robdd_invar_vars_greater___weaken) done
subsection‹ROBDDs are unique›
text‹An important property of ROBDDs is that two ROBDDs have the same semantics if and only
they are equal (up to ids in our case). Before we can prove this property some
are needed.›
lemma robdd_unique_leaf : assumes invars_b: "robdd_invar_vars b""robdd_invar_reduced b" and sem_eq: "robdd_α b = robdd_α (robdd_leaf value)" shows"b = (robdd_leaf value)" using assms proof (induct b) case (robdd_leaf f) thus ?caseby (simp add: fun_eq_iff) next case (robdd_var i l v r) note invar_l = robdd_var(1) note invar_r = robdd_var(2) note invars = robdd_var(3,4) note α_eq = robdd_var(5)
{ fix a from invars(1) have invars_b11_b12: "robdd_invar_vars_greater (Suc v) l" "robdd_invar_vars_greater (Suc v) r" by (simp_all add: robdd_invar_vars_def)
let ?a1 = "λv'. if v = v' then True else a v'" let ?a2 = "λv'. if v = v' then False else a v'" from α_eq have a_neg: "∧a. (if a v then robdd_α l a else robdd_α r a) ⟷ value" by (simp add: fun_eq_iff)
from robdd_α_invar_greater [OF invars_b11_b12(1), of a ?a1, symmetric]
robdd_α_invar_greater [OF invars_b11_b12(2), of a ?a2, symmetric]
a_neg[of ?a1] a_neg[of ?a2] have"robdd_α l a = value ∧ robdd_α r a = value"by simp
} hence α_l: "robdd_α l = robdd_α (robdd_leaf value)"and
α_r: "robdd_α r = robdd_α (robdd_leaf value)" by (simp_all add: fun_eq_iff)
from invars have"robdd_invar_vars l""robdd_invar_vars r" "robdd_invar_reduced l""robdd_invar_reduced r" apply (simp_all add: robdd_invar_vars_def) apply (metis robdd_invar_vars_def robdd_invar_vars_impl)+ done with invar_l[OF _ _ α_l] invar_r[OF _ _ α_r] have"l = r"by simp with invars(2) have"False"by simp thus ?caseby simp qed
from sem_eq have sem_eq_a: "∧a. robdd_α (robdd_var i1 l1 v1 r1) a = robdd_α (robdd_var i2 l2 v2 r2) a" by (simp add: fun_eq_iff)
define a1 where"a1 a v' = (if v1 = v' then True else a v')"for a v'
define a2 where"a2 a v' = (if v1 = v' then False else a v')"for a v'
have a12_eval: "∧a. a1 a v1""∧a. ~(a2 a v1)""∧a v. v ≠ v1 ==> a1 a v = a v ∧ a2 a v = a v" unfolding a1_def a2_def by simp_all
{ fix a from robdd_α_invar_greater [OF invars_lr1(1), of a "a1 a", symmetric]
robdd_α_invar_greater [OF invars_lr1(2), of a "a2 a", symmetric]
robdd_α_invar_greater [OF invars_lr2(1), of a "a1 a", symmetric]
robdd_α_invar_greater [OF invars_lr2(2), of a "a2 a", symmetric]
robdd_α_invar_greater [OF invars_lr1(1), of a "a2 a", symmetric]
robdd_α_invar_greater [OF invars_lr1(2), of a "a1 a", symmetric]
robdd_α_invar_greater [OF invars_lr2(1), of a "a2 a", symmetric]
robdd_α_invar_greater [OF invars_lr2(2), of a "a1 a", symmetric]
sem_eq_a[of "a1 a"] sem_eq_a[of "a2 a"] have a12_sem : "robdd_α l1 (a1 a) = robdd_α l1 a""robdd_α l2 (a1 a) = robdd_α l2 a" "robdd_α r1 (a2 a) = robdd_α r1 a""robdd_α r2 (a2 a) = robdd_α r2 a" "robdd_α l1 (a2 a) = robdd_α l1 a""robdd_α l2 (a2 a) = robdd_α l2 a" "robdd_α r1 (a1 a) = robdd_α r1 a""robdd_α r2 (a2 a) = robdd_α r2 a" "v1 ≠ v2 ==> robdd_α r1 a = robdd_α (robdd_var i2 l2 v2 r2) a" "v1 ≠ v2 ==> robdd_α l1 a = robdd_α (robdd_var i2 l2 v2 r2) a" unfolding a1_def a2_def by simp_all
} note a12_sem = this
from a12_sem(9,10) have"v1 ≠ v2 ==> robdd_α l1 = robdd_α r1" by (simp add: fun_eq_iff) with sem_neq have v2_eq: "v2 = v1"by metis
{ fix a from sem_eq_a[of "a1 a"] sem_eq_a[of "a2 a"] a12_sem[of a] have"robdd_α l1 a = robdd_α l2 a ∧ robdd_α r1 a = robdd_α r2 a" by (simp add: v2_eq a12_eval)
} hence"v1 = v2 ∧ robdd_α l1 = robdd_α l2 ∧ robdd_α r1 = robdd_α r2" by (simp add: fun_eq_iff v2_eq)
} note aux = this
show ?thesis proof (cases "v1 ≤ v2") case True note v1_le = this from aux[OF invars_b1[unfolded robdd_invar_vars_def] invars_b2[unfolded robdd_invar_vars_def] sem_neq_b1 sem_eq v1_le] show ?thesis by simp next case False hence v2_le: "v2 ≤ v1"by simp from aux[OF invars_b2[unfolded robdd_invar_vars_def] invars_b1[unfolded robdd_invar_vars_def] sem_neq_b2 sem_eq[symmetric] v2_le] show ?thesis by simp qed qed
lemma robdd_equiv_implies_sem_equiv : "robdd_equiv b1 b2 ==> robdd_α b1 = robdd_α b2" proof (induct b1 arbitrary: b2) case (robdd_var i l v r) note ind_hyp_l = robdd_var(1) note ind_hyp_r = robdd_var(2) note equiv_b2 = robdd_var(3)
from equiv_b2 obtain i' l' r' where
b2_eq: "b2 = robdd_var i' l' v r'"and
equiv_l: "robdd_equiv l l'"and
equiv_r: "robdd_equiv r r'" unfolding robdd_equiv.simps by blast
from ind_hyp_l[OF equiv_l] ind_hyp_r[OF equiv_r] b2_eq show ?caseby simp qed simp_all
show ?case proof (cases b1) case (robdd_leaf f) thus ?thesis using robdd_unique_leaf[OF invars_b2] sem_eq by simp next case (robdd_var i1 l1 v1 r1) note b1_eq = this
show ?thesis proof (cases b2) case (robdd_leaf f) thus ?thesis using robdd_unique_leaf[OF invars_b1] sem_eq by (simp add: fun_eq_iff) next case (robdd_var i2 l2 v2 r2) note b2_eq = this
text‹ROBDDs talk about assignments that consider infinitely many variables. However,
result depends only on a finite set of variables. Let's have a closer look at these
.›
definition robdd_depends_on_var where "robdd_depends_on_var v b ⟷ (∃a. robdd_α b (a(v := True)) ≠ robdd_α b (a(v := False)))"
lemma robdd_depends_on_varI : "robdd_α b (a(v := True)) ≠ robdd_α b (a(v := False)) ==> robdd_depends_on_var v b" unfolding robdd_depends_on_var_def by auto
lemma robbd_depends_on_var_leaf [simp] : "¬(robdd_depends_on_var v (robdd_leaf f))" by (simp_all add: robdd_depends_on_var_def fun_eq_iff)
lemma robdd_depends_on_var_invar_greater: assumes invar: "robdd_invar_vars_greater n b" and m_less: "m < n" shows"¬(robdd_depends_on_var m b)" proof -
{ fix a f
have"robdd_α b (a(m := f)) = robdd_α b a" apply (rule robdd_α_invar_greater[OF invar, of "a(m := f)" a]) apply (insert m_less) apply (simp) done
} thus ?thesis by (simp add: robdd_depends_on_var_def) qed
lemma robbd_depends_on_var_var_impl1 : assumes depend: "robdd_depends_on_var v (robdd_var i l v' r)" shows"(v = v') ∨ robdd_depends_on_var v l ∨ robdd_depends_on_var v r" proof (cases "v = v'") case True thus ?thesis by simp next case False note v_neq = this
from depend obtain a where a_props: "(if a v' then robdd_α l (a(v := True)) else robdd_α r (a(v := True))) ≠ (if a v' then robdd_α l (a(v := False)) else robdd_α r (a(v := False)))" unfolding robdd_depends_on_var_def by (auto simp add: v_neq v_neq[symmetric])
show ?thesis proof (cases "a v'") case True note a_v'_eq = this
have"robdd_depends_on_var v l" apply (rule robdd_depends_on_varI[of _ a]) apply (insert a_props a_v'_eq) apply (simp) done thus ?thesis by simp next case False note a_v'_eq = this
have"robdd_depends_on_var v r" apply (rule robdd_depends_on_varI[of _ a]) apply (insert a_props a_v'_eq) apply (simp) done thus ?thesis by simp qed qed
lemma robbd_depends_on_var_var : assumes invar: "robdd_invar (robdd_var i l v' r)" shows"robdd_depends_on_var v (robdd_var i l v' r) ⟷ (v = v') ∨ robdd_depends_on_var v l ∨ robdd_depends_on_var v r" proof (cases "v = v'") case True note v_eq = this
from invar have invar_greater: "robdd_invar_vars_greater (Suc v) l""robdd_invar_vars_greater (Suc v) r" unfolding robdd_invar_def robdd_invar_ext_def v_eq by simp_all
from invar robdd_equiv_alt_def[of l r] have"robdd_α l ≠ robdd_α r"by (metis robdd_invar_simps_var) thenobtain a where not_equiv: "robdd_α l a ≠ robdd_α r a"by (simp add: fun_eq_iff) metis
from robdd_α_invar_greater[OF invar_greater(1), of "a (v := True)" a] have l_eval: "robdd_α l (a(v := True)) = robdd_α l a"by simp
from robdd_α_invar_greater[OF invar_greater(2), of "a (v := False)" a] have r_eval: "robdd_α r (a(v := False)) = robdd_α r a"by simp
show ?thesis apply (simp add: v_eq[symmetric] robdd_depends_on_var_def) apply (rule exI [where x = a]) apply (insert not_equiv) apply (simp add: r_eval l_eval) done next case False note v_neq = this
from invar have invar_greater: "robdd_invar_vars_greater (Suc v') l""robdd_invar_vars_greater (Suc v') r" unfolding robdd_invar_def robdd_invar_ext_def by simp_all
{ fix a f1 f2
from robdd_α_invar_greater[OF invar_greater(1), of "a (v' := f1, v := f2)""a (v := f2)"]
robdd_α_invar_greater[OF invar_greater(2), of "a (v' := f1, v := f2)""a (v := f2)"] have"robdd_α l (a(v' := f1, v := f2)) = robdd_α l (a (v:=f2))" "robdd_α r (a(v' := f1, v := f2)) = robdd_α r (a (v:=f2))"by simp_all
} note robdd_α_lr_modified = this
show ?thesis proof (cases "robdd_depends_on_var v l") case True note depends_on_l = this
from depends_on_l obtain a where not_equiv: "robdd_α l (a(v := True)) ≠ robdd_α l (a(v := False))" unfolding robdd_depends_on_var_def by metis
have"robdd_depends_on_var v (robdd_var i l v' r)" unfolding robdd_depends_on_var_def apply (simp add: v_neq[symmetric]) apply (rule exI [where x = "a (v':=True)"]) apply (insert not_equiv) apply (simp add: robdd_α_lr_modified) done thus ?thesis by (simp add: depends_on_l) next case False note not_depends_on_l = this hence l_simp: "∧a. robdd_α l (a(v := True)) = robdd_α l (a(v := False))" unfolding robdd_depends_on_var_def by simp
{ fix a assume"robdd_α r (a(v := True)) ≠ robdd_α r (a(v := False))" hence"robdd_α r (a(v' := False, v := True)) ≠ robdd_α r (a(v' := False, v := False))" by (simp add: robdd_α_lr_modified)
} thus ?thesis unfolding robdd_depends_on_var_def apply (simp add: v_neq[symmetric] v_neq l_simp) by (metis fun_upd_same) qed qed
primrec robdd_used_vars where "robdd_used_vars (robdd_leaf f) = {}"
| "robdd_used_vars (robdd_var i l v r) = robdd_used_vars l ∪ {v} ∪ robdd_used_vars r"
lemma robdd_depends_on_var_eq_used : "robdd_invar b ==> robdd_depends_on_var v b ⟷ v ∈ robdd_used_vars b" proof (induct b) case (robdd_leaf f) thus ?caseby (simp add: robdd_depends_on_var_def) next case (robdd_var i l v' r) note indhyp_l = robdd_var(1) note indhyp_r = robdd_var(2)
note invar_b = robdd_var(3) from invar_b have invar_l: "robdd_invar l"and invar_r: "robdd_invar r"by (metis robdd_invar_simps_var)+
from robbd_depends_on_var_var[OF invar_b, of v] indhyp_l[OF invar_l] indhyp_r[OF invar_r] show ?caseby simp qed
lemma robdd_depends_on_var_implies_used : "robdd_depends_on_var v b ==> v ∈ robdd_used_vars b" apply (induct b) apply (simp_all) apply (metis robbd_depends_on_var_var_impl1) done
subsection‹Inverse Map›
text‹If the invariant for ids is satisfied, one can find a find a unique mapping between ids
ROBDDs.›
definition robdd_id_map_OK where "robdd_id_map_OK bs m ⟷ (∀b ∈ subrobdds_set bs. m (robdd_get_id b) = Some b)"
lemma robdd_id_map_OK_D : "[robdd_id_map_OK bs m; b ∈ subrobdds_set bs]==> m (robdd_get_id b) = Some b" unfolding robdd_id_map_OK_def by blast
definition robdd_id_map where "robdd_id_map bs i = Eps_Opt (λb. b ∈ subrobdds_set bs ∧ robdd_get_id b = i)"
let ?P = "λb b'. b' ∈ subrobdds_set bs ∧ robdd_get_id b' = robdd_get_id b"
from map_OK b1_in b2_in have Eps_Opt_Eval: "Eps_Opt (?P b1) = Some b1""Eps_Opt (?P b2) = Some b2" unfolding robdd_id_map_OK_def robdd_id_map_def by simp_all
from id_eq have"?P b1 = ?P b2"by simp with Eps_Opt_Eval show"b1 = b2"by (metis option.inject) qed simp qed
lemma robdd_id_map_union : assumes invar_ids_bs12: "robdd_invar_ids_equal (bs1 ∪ bs2)" shows"robdd_id_map (bs1 ∪ bs2) = (robdd_id_map bs1) ++ (robdd_id_map bs2)" proof fix i from invar_ids_bs12 have invar_ids_bs1: "robdd_invar_ids_equal bs1" and invar_ids_bs2: "robdd_invar_ids_equal bs2" unfolding robdd_invar_ids_equal_def by auto
from invar_ids_bs1 invar_ids_bs2 invar_ids_bs12 robdd_id_map_properties have map_OK_bs1: "robdd_id_map_OK bs1 (robdd_id_map bs1)" and map_OK_bs2: "robdd_id_map_OK bs2 (robdd_id_map bs2)" and map_OK_bs12: "robdd_id_map_OK (bs1 ∪ bs2) (robdd_id_map (bs1 ∪ bs2))" by simp_all
show"robdd_id_map (bs1 ∪ bs2) i = (robdd_id_map bs1 ++ robdd_id_map bs2) i" proof (cases "∃b. b ∈ subrobdds_set (bs1 ∪ bs2) ∧ robdd_get_id b = i") case False hence"robdd_id_map (bs1 ∪ bs2) i = None"and "robdd_id_map bs1 i = None"and "robdd_id_map bs2 i = None" unfolding robdd_id_map_def Eps_Opt_eq_None by auto thus ?thesis by (simp add: map_add_find_left) next case True thenobtain b where
b_in: "b ∈ subrobdds_set (bs1 ∪ bs2)" and b_id: "robdd_get_id b = i"by auto
from map_OK_bs12 b_in b_id have ls_eq: "robdd_id_map (bs1 ∪ bs2) i = Some b" unfolding robdd_id_map_OK_def by metis
have rs_eq: "(robdd_id_map bs1 ++ robdd_id_map bs2) i = Some b" proof (cases "b ∈ subrobdds_set bs2") case True with map_OK_bs2 b_id have rs_eq2: "robdd_id_map bs2 i = Some b" unfolding robdd_id_map_OK_def by metis from ls_eq rs_eq2 show ?thesis by simp next case False note b_nin_bs2 = this
from b_in b_nin_bs2 have"b ∈ subrobdds_set bs1"by simp with map_OK_bs1 b_id have rs_eq1: "robdd_id_map bs1 i = Some b" unfolding robdd_id_map_OK_def by metis
from invar_ids_bs12 b_in b_nin_bs2 b_id have"∧b'. b' ∈ subrobdds_set bs2 ==> robdd_get_id b' ≠ i" unfolding robdd_invar_ids_equal_def by simp metis hence rs_eq2: "robdd_id_map bs2 i = None" unfolding robdd_id_map_def Eps_Opt_eq_None by auto
from ls_eq rs_eq1 rs_eq2 show ?thesis by (simp add: map_add_find_left) qed
from ls_eq rs_eq show ?thesis by simp qed qed
subsection‹Extended Boolean Operations›
text‹For Boolean Operations on ROBDDs it is important to extend boolean operations
option types. This allows to get the information that the result of the operation does
depend on the value of some arguments.›
fun bool_op_extend :: "(bool ==> bool ==> bool) ==> (bool option ==> bool option ==> bool option)"where "bool_op_extend bop None None = (if ((bop True False = bop True True) ∧ (bop False True = bop True True) ∧ (bop False False = bop True True)) then Some (bop True True) else None)"
| "bool_op_extend bop None (Some b') = (if (bop True b' ⟷ bop False b') then Some (bop False b') else None)"
| "bool_op_extend bop (Some b) None = (if (bop b True ⟷ bop b False) then Some (bop b True) else None)"
| "bool_op_extend bop (Some b) (Some b') = Some (bop b b')"
text‹Common Operations›
fun bope_neg where "bope_neg None = None"
| "bope_neg (Some True) = Some False"
| "bope_neg (Some False) = (Some True)"
definition"bope_and = bool_op_extend (λx y. x ∧ y)" definition"bope_or = bool_op_extend (λx y. x ∨ y)" definition"bope_nand = bool_op_extend (λx y. ¬(x ∧ y))" definition"bope_nor = bool_op_extend (λx y. ¬(x ∨ y))" definition"bope_xor = bool_op_extend (λx y. x ≠ y)" definition"bope_eq = bool_op_extend (λx y. x = y)" definition"bope_imp = bool_op_extend (λx y. x ⟶ y)"
lemma bool_opt_exhaust: "(y = None ==> P) ==> (y = Some True ==> P) ==> (y = Some False ==> P) ==> P" by auto
lemma bope_and_code [code] : "bope_and None None = None" "bope_and bo (Some True) = bo" "bope_and bo (Some False) = (Some False)" "bope_and (Some True) bo = bo" "bope_and (Some False) bo = (Some False)" unfolding bope_and_def apply (case_tac [!] bo rule: bool_opt_exhaust) apply (simp_all) done
lemma bope_or_code [code] : "bope_or None None = None" "bope_or bo (Some False) = bo" "bope_or bo (Some True) = (Some True)" "bope_or (Some False) bo = bo" "bope_or (Some True) bo = (Some True)" unfolding bope_or_def apply (case_tac [!] bo rule: bool_opt_exhaust) apply (simp_all) done
text‹For building boolean combinations of BDDs it is essential to use
map storing already used IDs and a cache.
datastructures cache can be implemented in different ways. Therefore, here the
properties are abstracted by using a locale.›
definition rev_map_invar where "rev_map_invar bs rev_map = (r_invar (fst rev_map) ∧ snd rev_map > 1 ∧ (∀b ∈ subrobdds_set bs. robdd_invar_ext bs 0 b ∧ robdd_get_id b < (snd rev_map)) ∧ (∀li v ri b. r_α (fst rev_map) (li, v, ri) = Some b ⟶ (robdd_invar_ext bs v b ∧ b ∈ bs ∧ (∃l r i. b = robdd_var i l v r ∧ robdd_get_id l = li ∧ robdd_get_id r = ri))) ∧ (∀i l r v. robdd_var i l v r ∈ subrobdds_set bs ⟶ r_α (fst rev_map) (robdd_get_id l, v, robdd_get_id r) = Some (robdd_var i l v r)))"
lemma rev_map_invarI[intro!] : "[r_invar (fst rev_map); snd rev_map > 1; ∧b. b ∈ subrobdds_set bs ==> robdd_invar_ext bs 0 b ∧ robdd_get_id b < (snd rev_map); ∧li v ri b. r_α (fst rev_map) (li, v, ri) = Some b ==> (robdd_invar_ext bs v b ∧ b ∈ bs ∧ (∃l r i. b = robdd_var i l v r ∧ robdd_get_id l = li ∧ robdd_get_id r = ri)); ∧i l r v. robdd_var i l v r ∈ subrobdds_set bs ==> r_α (fst rev_map) (robdd_get_id l, v, robdd_get_id r) = Some (robdd_var i l v r)]==> rev_map_invar bs rev_map" unfolding rev_map_invar_def by blast
lemma rev_map_invar_D1 : assumes"rev_map_invar bs rev_map" and"robdd_var i l v r ∈ subrobdds_set bs" shows"r_α (fst rev_map) (robdd_get_id l, v, robdd_get_id r) = Some (robdd_var i l v r)" using assms unfolding rev_map_invar_def by blast
lemma rev_map_invar_D2 : assumes"rev_map_invar bs rev_map" and"r_α (fst rev_map) (li, v, ri) = Some b" shows"robdd_invar_ext bs v b ∧ b ∈ bs ∧ (∃l r i. b = robdd_var i l v r ∧ robdd_get_id l = li ∧ robdd_get_id r = ri)" using assms unfolding rev_map_invar_def by blast
lemma rev_map_invar_D3 : assumes"rev_map_invar bs rev_map" and"b ∈ subrobdds_set bs" shows"robdd_invar_ext bs 0 b""robdd_get_id b < snd (rev_map)" using assms unfolding rev_map_invar_def by blast+
lemma rev_map_invar_implies_invar_ids : assumes invar: "rev_map_invar bs rev_map" shows"robdd_invar_ids bs" proof (cases "bs = {}") case True thus ?thesis by (simp add: robdd_invar_ids_def subrobdds_set_def) next case False thenobtain b where"b ∈ bs"by auto thenhave b_in: "b ∈ subrobdds_set bs" unfolding subrobdds_set_def by rule simp from rev_map_invar_D3(1)[OF invar b_in] show ?thesis by (simp add: robdd_invar_ext_def) qed
lemma rev_map_invar_implies_invar_bs : assumes invar: "rev_map_invar bs rev_map" and b_in: "b ∈ subrobdds_set bs" shows"robdd_invar b" using rev_map_invar_D3(1)[OF invar b_in] by (rule robdd_invar_impl)
note bs_OK_full = rev_map_invar_implies_invar_bs[OF invar] have bs_OK: "∧b. b ∈ bs ==> robdd_invar b" by (metis bs_OK_full subrobdds_set_mono subsetD)
show"robdd_invar_ids_equal bs" by (rule robdd_invar_ids_equal_intro [OF bs_OK invar_ids]) qed
definition robdd_construct :: "'r_map × node_id ==> robdd ==> var ==> robdd ==> robdd × ('r_map × node_id)"where "robdd_construct rev_map l v r = (let l_id = robdd_get_id l in let r_id = robdd_get_id r in (if l_id = r_id then (l, rev_map) else (case r_lookup (l_id, v, r_id) (fst rev_map) of Some b ==> (b, rev_map) | None ==> (let b = robdd_var (snd rev_map) l v r in (b, (r_update (l_id, v, r_id) b (fst rev_map), Suc (snd rev_map)))))))"
lemma robdd_construct_correct : fixes l v r bs rev_map defines"res ≡ robdd_construct rev_map l v r" defines"rev_map' ≡ (snd res)" defines"b ≡ fst res" defines"bs' ≡ insert b bs" assumes invar_rev_map: "rev_map_invar bs rev_map" and lr_in: "l ∈ bs""r ∈ bs" and invar_lr: "robdd_invar_ext bs (Suc v) l""robdd_invar_ext bs (Suc v) r" shows"robdd_invar_ext bs' v b ∧ rev_map_invar bs' rev_map' ∧ robdd_α b = robdd_α (robdd_var 0 l v r)" proof -
define l_id where"l_id = robdd_get_id l"
define r_id where"r_id = robdd_get_id r"
from invar_lr have invar_ids: "robdd_invar_ids bs" and lr_in': "l ∈ subrobdds_set bs""r ∈ subrobdds_set bs" unfolding robdd_invar_ext_def by simp_all
from robdd_invar_ids_equal_intro[of bs, OF bs_OK invar_ids]
subrobdds_set_mono[of bs] have invar_ids_equal: "robdd_invar_ids_equal bs"by (simp add: subset_iff)
from invar_rev_map have r_invar: "r_invar (fst rev_map)"unfolding rev_map_invar_def bysimp
show ?thesis proof (cases "l_id = r_id") case True note l_id_eq = this
from lr_in' invar_ids l_id_eq have l_α: "robdd_α l = robdd_α r" unfolding robdd_invar_ids_def l_id_def r_id_def by simp
from invar_lr(1) have invar_l': "robdd_invar_ext bs v l" apply (rule robdd_invar_ext_weaken_var) apply (simp) done from lr_in(1) have bs'_eq: "insert l bs = bs"by auto from res_def l_id_eq show ?thesis unfolding robdd_construct_def l_id_def[symmetric] r_id_def[symmetric]
b_def bs'_def rev_map'_def by (simp add: fun_eq_iff l_α bs'_eq invar_lr(1) invar_rev_map invar_l') next case False note l_id_neq = this
show ?thesis proof (cases "r_lookup (l_id, v, r_id) (fst rev_map)") case (Some b) note map_eq = this
from r_invar rev_map_invar_D2[OF invar_rev_map, of l_id v r_id b] map_eq obtain l' r' i where
invar_b: "robdd_invar_ext bs v b"and
b_in: "b ∈ bs"and
b_eq: "b = robdd_var i l' v r'"and
l_id_eq: "robdd_get_id l' = l_id"and
r_id_eq: "robdd_get_id r' = r_id" unfolding rev_map_invar_def by (auto simp add: r.lookup_correct)
from b_in have bs'_eq: "insert b bs = bs"by auto
have b_α: "robdd_α b = robdd_α (robdd_var 0 l' v r')" unfolding b_eq by (simp add: fun_eq_iff)
from invar_ids_equal lr_in' lr'_in' l_id_eq r_id_eq show"l' = l""r' = r" unfolding robdd_invar_ids_equal_def l_id_def r_id_def by auto qed from res_def l_id_neq show ?thesis unfolding robdd_construct_def l_id_def[symmetric] r_id_def[symmetric]
bs'_def rev_map'_def b_def by (simp add: map_eq bs'_eq invar_b b_α lr'_eq invar_rev_map) next case None note map_eq = this
define b' where"b' = robdd_var (snd rev_map) l v r"
have α_b': "robdd_α b' = robdd_α (robdd_var 0 l v r)" unfolding b'_defby (simp add: fun_eq_iff)
from lr_in' invar_ids l_id_neq have"robdd_α l ≠ robdd_α r" unfolding robdd_invar_ids_def l_id_def r_id_def by simp with robdd_equiv_implies_sem_equiv[of l r] have l_not_equiv: "~(robdd_equiv l r)"by blast
from invar_lr have b'_invar_vars: "robdd_invar_vars b'"and b'_invar_reduced: "robdd_invar_reduced b'" unfolding b'_def robdd_invar_vars_def by (simp_all add: robdd_invar_ext_def l_not_equiv)
{ fix b2 assume b2_in: "b2 ∈ subrobdds_set bs"
from rev_map_invar_D3[OF invar_rev_map b2_in] have id_neq: "robdd_get_id b2 ≠ robdd_get_id b'" unfolding b'_defby simp
have invar_b2: "robdd_invar b2"by (metis b2_in bs_OK)
with invar_b2 robdd_equiv_alt_def_full[OF b'_invar_vars b'_invar_reduced, of b2] have"robdd_equiv b' b2"by (metis robdd_invar_alt_def) thenobtain i' l' r' where
b2_eq: "b2 = robdd_var i' l' v r'"and
l'_equiv: "robdd_equiv l l'"and
r'_equiv: "robdd_equiv r r'" unfolding b'_defby auto
have r'_eq[simp]: "r' = r"and l'_eq[simp]: "l' = l" proof - have"l' ∈ subrobdds b2""r' ∈ subrobdds b2" unfolding b2_eq by simp_all with b2_in have"l' ∈ subrobdds_set bs""r' ∈ subrobdds_set bs" by (metis subrobdds_set_subset_simp subsetD)+ with robdd_invar_ids_equiv_implies_eq[of "subrobdds_set bs" l l']
robdd_invar_ids_equiv_implies_eq[of "subrobdds_set bs" r r'] show"r' = r""l' = l" by (simp_all add: l'_equiv r'_equiv robdd_invar_ids_expand invar_ids lr_in') qed
from rev_map_invar_D1[OF invar_rev_map b2_in[unfolded b2_eq]] map_eq show"False"by (simp add: l_id_def r_id_def r.lookup_correct r_invar) qed
note invar_b2 α_b2 id_neq
} note in_bs_b'_props = this
have subrobdds_set_bs_simp: "subrobdds_set (insert b' bs) = insert b' (subrobdds_set bs)" unfolding subrobdds_set_def b'_defusing lr_in by (auto simp add: set_eq_iff Bex_def)
have invar_ids': "robdd_invar_ids (insert b' bs)" proof (rule robdd_invar_idsI) fix b1 b2
assume b1_in: "b1 ∈ subrobdds_set (insert b' bs)"and
b2_in: "b2 ∈ subrobdds_set (insert b' bs)"
from b1_in b2_in show"(robdd_α b1 = robdd_α b2) = (robdd_get_id b1 = robdd_get_id b2)" unfolding subrobdds_set_bs_simp using robdd_invar_idsD[OF invar_ids, of b1 b2] in_bs_b'_props by simp metis qed
from invar_ids' b'_invar_reduced b'_invar_vars have invar_b': "robdd_invar_ext (insert b' bs) v b'" by (simp add: robdd_invar_ext_def robdd_invar_vars_def b'_def)
have invar_rev_map': "rev_map_invar bs' rev_map'" proof - let ?rm = "(r_update (l_id, v, r_id) b' (fst rev_map), Suc (snd rev_map))" have"rev_map_invar (insert b' bs) ?rm" proof from map_eq show"r_invar (fst ?rm)" apply (simp) apply (rule r.update_dj_correct) apply (simp_all add: r_invar r.lookup_correct dom_def) done next from invar_rev_map show"1 < snd ?rm"unfolding rev_map_invar_def by simp next fix b assume b_in: "b ∈ subrobdds_set (insert b' bs)" show"robdd_invar_ext (insert b' bs) 0 b ∧ robdd_get_id b < snd ?rm" proof (cases "b = b'") case True with invar_b' show ?thesis unfolding b'_defby simp next case False with subrobdds_set_bs_simp b_in have b_in': "b ∈ subrobdds_set bs"by simp
from rev_map_invar_D3[OF invar_rev_map b_in'] show ?thesis by (simp add: robdd_invar_ext_def invar_ids') qed next fix i l r v' assume b_in: "robdd_var i l v' r ∈ subrobdds_set (insert b' bs)" show"r_α (fst ?rm) (robdd_get_id l, v', robdd_get_id r) = Some (robdd_var i l v' r)" proof (cases "robdd_var i l v' r = b'") case True with map_eq show ?thesis by (simp add: b'_def l_id_def[symmetric] r_id_def[symmetric]
r.lookup_correct r_invar dom_def r.update_dj_correct) next case False with subrobdds_set_bs_simp b_in have b_in': "robdd_var i l v' r ∈ subrobdds_set bs"by simp
from rev_map_invar_D1[OF invar_rev_map b_in'] map_eq show ?thesis by (auto simp add: r.lookup_correct r.update_dj_correct dom_def r_invar) qed next fix li v' ri b assume b_intro: "r_α (fst ?rm) (li, v', ri) = Some b" show"robdd_invar_ext (insert b' bs) v' b ∧ b ∈ insert b' bs ∧ (∃l r i. b = robdd_var i l v' r ∧ robdd_get_id l = li ∧ robdd_get_id r = ri)" proof (cases "(li, v', ri) = (robdd_get_id l, v, robdd_get_id r)") case True note lriv'_eq = this with b_intro map_eq have b_eq: "b = b'" by (simp_all add: r.update_dj_correct dom_def r.lookup_correct r_invar l_id_def r_id_def) with lriv'_eq show ?thesis apply (simp add: invar_b') apply (simp add: b'_def) done next case False with b_intro map_eq have b_intro': "r_α (fst rev_map) (li, v', ri) = Some b" by (auto simp add: r.lookup_correct r.update_dj_correct dom_def r_invar l_id_def r_id_def)
from rev_map_invar_D2[OF invar_rev_map b_intro'] show ?thesis apply simp apply (simp add: robdd_invar_ext_def invar_ids') done qed qed
thus ?thesis unfolding bs'_def rev_map'_def res_def robdd_construct_def l_id_def[symmetric]
r_id_def[symmetric] b_def by (simp add: map_eq b'_def[symmetric] α_b' invar_b' l_id_neq) qed
from res_def l_id_neq invar_rev_map' show ?thesis unfolding robdd_construct_def l_id_def[symmetric] r_id_def[symmetric]
bs'_def rev_map'_def b_def by (simp add: map_eq b'_def[symmetric] α_b' invar_b' ) qed qed qed
fun (in -) robdd_apply_next where "robdd_apply_next (robdd_leaf f) (robdd_leaf f') = (robdd_leaf f, robdd_leaf f, 0, robdd_leaf f', robdd_leaf f')"
| "robdd_apply_next (robdd_leaf f) (robdd_var i l v r) = (robdd_leaf f, robdd_leaf f, v, l, r)"
| "robdd_apply_next (robdd_var i l v r) (robdd_leaf f) = (l, r, v, robdd_leaf f, robdd_leaf f)"
| "robdd_apply_next (robdd_var i l v r) (robdd_var i' l' v' r') = (if v < v' then (l, r, v, (robdd_var i' l' v' r'), (robdd_var i' l' v' r')) else (if v = v' then (l, r, v, l', r') else ((robdd_var i l v r), (robdd_var i l v r), v', l', r')))"
definition (in -) robdd_neg_next where "robdd_neg_next b = (let (l, r, v, _, _) = robdd_apply_next b robdd_one in (l, r, v))"
lemma (in -) robdd_neg_simps[code, simp] : "robdd_neg_next (robdd_leaf f) = (robdd_leaf f, robdd_leaf f, 0)" "robdd_neg_next (robdd_var i l v r) = (l, r, v)" unfolding robdd_neg_next_def by simp_all
fun (in -) robdd_get_min_var where "robdd_get_min_var (robdd_leaf _) (robdd_leaf _) = 0"
| "robdd_get_min_var (robdd_leaf _) (robdd_var _ _ v _) = v"
| "robdd_get_min_var (robdd_var _ _ v _) (robdd_leaf _) = v"
| "robdd_get_min_var (robdd_var _ _ v1 _) (robdd_var _ _ v2 _) = (if v1 ≤ v2 then v1 else v2)"
lemma (in -) robdd_apply_next_correct : assumes invar_b1: "robdd_invar_ext bs1 n1 b1" and invar_b2: "robdd_invar_ext bs2 n2 b2" and eval: "robdd_apply_next b1 b2 = (b1_l, b1_r, v'', b2_l, b2_r)" shows"robdd_α b1_l = (λa. robdd_α b1 (a (v'' := True)))" (is ?T1) "robdd_α b1_r = (λa. robdd_α b1 (a (v'' := False)))" (is ?T2) "robdd_α b2_l = (λa. robdd_α b2 (a (v'' := True)))" (is ?T3) "robdd_α b2_r = (λa. robdd_α b2 (a (v'' := False)))" (is ?T4) "robdd_invar_ext bs1 (Suc v'') b1_l" (is ?T5) "robdd_invar_ext bs1 (Suc v'') b1_r" (is ?T6) "robdd_invar_ext bs2 (Suc v'') b2_l" (is ?T7) "robdd_invar_ext bs2 (Suc v'') b2_r" (is ?T8) "b1_l ∈ subrobdds b1" (is ?T9) "b2_l ∈ subrobdds b2" (is ?T10) "b1_r ∈ subrobdds b1" (is ?T11) "b2_r ∈ subrobdds b2" (is ?T12) "robdd_get_min_var b1 b2 = v''" (is ?T13) "~(robdd_is_leaf b1 ∧ robdd_is_leaf b2) ⟶ size_robdd b1_l + size_robdd b2_l < size_robdd b1 + size_robdd b2" (is ?T14) "~(robdd_is_leaf b1 ∧ robdd_is_leaf b2) ⟶ size_robdd b1_r + size_robdd b2_r < size_robdd b1 + size_robdd b2" (is ?T15) proof - have"?T1 ∧ ?T2 ∧ ?T3 ∧ ?T4 ∧ ?T5 ∧ ?T6 ∧ ?T7 ∧ ?T8 ∧ ?T9 ∧ ?T10 ∧ ?T11 ∧ ?T12 ∧?T13 ∧ ?T14 ∧ ?T15" proof (cases b1) case (robdd_leaf f) note b1_eq = this show ?thesis proof (cases b2) case (robdd_leaf f') note b2_eq = this with b1_eq eval[symmetric] invar_b1 invar_b2 show ?thesis by (simp add: fun_eq_iff) next case (robdd_var i' l' v' r') note b2_eq = this with b1_eq eval[symmetric] invar_b1 invar_b2 show ?thesis apply (simp add: fun_eq_iff) apply (intro allI conjI robdd_α_invar_greater [of "Suc v'"]) apply (simp_all add: robdd_invar_ext_def) done qed next case (robdd_var i l v r) note b1_eq = this show ?thesis proof (cases b2) case (robdd_leaf f') note b2_eq = this with b1_eq eval[symmetric] invar_b1 invar_b2 show ?thesis apply (simp add: fun_eq_iff) apply (intro allI conjI robdd_α_invar_greater [of "Suc v"]) apply (simp_all add: robdd_invar_ext_def) done next case (robdd_var i' l' v' r') note b2_eq = this show ?thesis proof (cases "v < v'") case True with robdd_invar_vars_greater___weaken[of "Suc v'" _ "Suc v"] b1_eq b2_eq eval[symmetric] invar_b1 invar_b2 show ?thesis apply (simp add: fun_eq_iff) apply (intro allI conjI impI robdd_α_invar_greater [of "Suc v''"]) apply (simp_all add: robdd_invar_ext_def) done next case False hence v'_le: "v' ≤ v"by simp show ?thesis proof (cases "v = v'") case True with robdd_invar_vars_greater___weaken[of "Suc v'" _ "Suc v"] b1_eq b2_eq eval[symmetric] invar_b1 invar_b2 show ?thesis apply (simp add: fun_eq_iff) apply (intro allI conjI impI robdd_α_invar_greater [of "Suc v''"]) apply (simp_all add: robdd_invar_ext_def) done next case False with v'_le have"v' < v"by simp with robdd_invar_vars_greater___weaken[of "Suc v" _ "Suc v'"] b1_eq b2_eq eval[symmetric] invar_b1 invar_b2 show ?thesis apply (simp add: fun_eq_iff) apply (intro allI conjI impI robdd_α_invar_greater [of "Suc v''"]) apply (simp_all add: robdd_invar_ext_def) done qed qed qed qed thus ?T1 ?T2 ?T3 ?T4 ?T5 ?T6 ?T7 ?T8 ?T9 ?T10 ?T11 ?T12 ?T13 ?T14 ?T15 by auto qed
function robdd_apply where "robdd_apply apply_map rev_map bop b1 b2 = (case (bool_op_extend bop (robdd_to_bool b1) (robdd_to_bool b2)) of Some f ==> (robdd_leaf f, apply_map, rev_map) | None ==> (case c_lookup (robdd_get_id b1, robdd_get_id b2) apply_map of Some b3 ==> (b3, apply_map, rev_map) | None ==> (let (l1, r1, var, l2, r2) = robdd_apply_next b1 b2 in let (l, apply_map, rev_map) = robdd_apply apply_map rev_map bop l1 l2 in let (r, apply_map, rev_map) = robdd_apply apply_map rev_map bop r1 r2 in let (b, rev_map) = robdd_construct rev_map l var r in let apply_map = c_update (robdd_get_id b1, robdd_get_id b2) b apply_map in (b, apply_map, rev_map))))" by pat_completeness auto termination apply (relation "measure (λ(_, _, _, b1, b2). size_robdd b1 + size_robdd b2)") apply simp apply (clarify, simp) defer apply (clarify, simp) proof - fix b1 b2 l1 l2 r1 r2 v bop assume bop_eq: "bool_op_extend bop (robdd_to_bool b1) (robdd_to_bool b2) = None" and next_eq: "(l1, r1, v, l2, r2) = robdd_apply_next b1 b2"
lemma apply_map_invar_D2 : "[apply_map_invar bop bs bs1 bs2 apply_map; c_lookup (i1, i2) apply_map = Some b]==> ∃b1 b2. robdd_id_map bs1 i1 = Some b1 ∧ robdd_id_map bs2 i2 = Some b2 ∧ robdd_invar_ext bs (robdd_get_min_var b1 b2) b ∧ (∀a. robdd_α b a ⟷ bop (robdd_α b1 a) (robdd_α b2 a))" unfolding apply_map_invar_def by blast
lemma apply_map_invar_extend : assumes invar: "apply_map_invar bop bs bs1 bs2 apply_map" and bs1'_OK: "bs1 ⊆ bs1'""robdd_invar_ids bs1'""∧b. b ∈ bs1' ==> robdd_invar b" and bs2'_OK: "bs2 ⊆ bs2'""robdd_invar_ids bs2'""∧b. b ∈ bs2' ==> robdd_invar b" shows"apply_map_invar bop bs bs1' bs2' apply_map" proof (rule apply_map_invar_I, goal_cases) case1 thus ?caseusing apply_map_invar_D1[OF invar] . next case lookup_eq: (2 i1 i2 b)
from apply_map_invar_D2[OF invar lookup_eq] obtain b1 b2 where
id_map_bs1: "robdd_id_map bs1 i1 = Some b1"and
id_map_bs2: "robdd_id_map bs2 i2 = Some b2"and
invar_b: "robdd_invar_ext bs (robdd_get_min_var b1 b2) b"and
sem_b: "∀a. robdd_α b a = bop (robdd_α b1 a) (robdd_α b2 a)" by blast
from bs1'_OK(1) obtain bs1'' where bs1'_eq: "bs1' = bs1'' ∪ bs1"by auto from bs2'_OK(1) obtain bs2'' where bs2'_eq: "bs2' = bs2'' ∪ bs2"by auto
from robdd_invar_ids_equal_intro [OF bs1'_OK(3) bs1'_OK(2)] bs1'_eq have ids_equal_bs1': "robdd_invar_ids_equal (bs1'' ∪ bs1)"by simp
from robdd_invar_ids_equal_intro [OF bs2'_OK(3) bs2'_OK(2)] bs2'_eq have ids_equal_bs2': "robdd_invar_ids_equal (bs2'' ∪ bs2)"by simp
show ?case apply (rule_tac exI[where x = b1]) apply (rule_tac exI[where x = b2]) apply (simp add: invar_b sem_b bs1'_eq bs2'_eq
robdd_id_map_union [OF ids_equal_bs1']
robdd_id_map_union [OF ids_equal_bs2']
map_add_Some_iff id_map_bs1 id_map_bs2) done qed
lemma robdd_apply_correct_full : fixes b1 b2 bop rev_map apply_map bs defines"res ≡ robdd_apply apply_map rev_map bop b1 b2" defines"b ≡ fst res" defines"apply_map' ≡ fst (snd res)" defines"rev_map' ≡ snd (snd res)" assumes invar_rev_map: "rev_map_invar bs rev_map" and invar_apply_map: "apply_map_invar bop bs bs1 bs2 apply_map" and b1_invar: "robdd_invar_ext bs1 n b1" and b2_invar: "robdd_invar_ext bs2 n b2" and bs1_OK: "∧b. b ∈ bs1 ==> robdd_invar b" and bs2_OK: "∧b. b ∈ bs2 ==> robdd_invar b" shows"∃bs'. subrobdds b ∪ bs ⊆ bs' ∧ robdd_invar_ext bs' n b ∧ apply_map_invar bop bs' bs1 bs2 apply_map' ∧ rev_map_invar bs' rev_map' ∧ (∀a. robdd_α b a ⟷ bop (robdd_α b1 a) (robdd_α b2 a))" using invar_rev_map invar_apply_map b1_invar b2_invar unfolding b_def apply_map'_def rev_map'_def res_def proof (induct "(b1, b2)" arbitrary: b1 b2 bs n apply_map rev_map rule: measure_induct_rule [of "λ(b1, b2). size_robdd b1 + size_robdd b2"]) case less note indhyp = less(1) note invar_rev_map = less(2) note invar_apply_map = less(3) note b1_invar = less(4) note b2_invar = less(5) let ?res = "robdd_apply apply_map rev_map bop b1 b2" note res_def = robdd_apply.simps [of apply_map rev_map bop b1 b2]
from rev_map_invar_implies_invar_ids[OF invar_rev_map] have invar_ids_bs: "robdd_invar_ids bs"by simp note bs_OK_full = rev_map_invar_implies_invar_bs[OF invar_rev_map] have bs_OK: "∧b. b ∈ bs ==> robdd_invar b"by (metis bs_OK_full subrobdds_set_mono subsetD)
from b1_invar have b1_in: "b1 ∈ subrobdds_set bs1"unfolding robdd_invar_ext_def by simp from b2_invar have b2_in: "b2 ∈ subrobdds_set bs2"unfolding robdd_invar_ext_def by simp from b1_invar have invar_ids_bs1: "robdd_invar_ids bs1"unfolding robdd_invar_ext_def by simp from b2_invar have invar_ids_bs2: "robdd_invar_ids bs2"unfolding robdd_invar_ext_def by simp have invar_ids_equal_bs1: "robdd_invar_ids_equal bs1" by (rule robdd_invar_ids_equal_intro [OF bs1_OK invar_ids_bs1]) have invar_ids_equal_bs2: "robdd_invar_ids_equal bs2" by (rule robdd_invar_ids_equal_intro [OF bs2_OK invar_ids_bs2])
have invar_ids_leafs_bs : "robdd_invar_ids_leafs bs" proof (rule robdd_invar_ids_leafs_intro[of bs, OF _ invar_ids_bs]) fix b assume"b ∈ bs" with bs_OK[of b] have"robdd_invar b"by simp thus"robdd_invar_reduced b"unfolding robdd_invar_def robdd_invar_ext_def by simp qed
from invar_rev_map invar_ids_bs' have invar_rev_map': "rev_map_invar (insert (robdd_leaf f) bs) rev_map" unfolding rev_map_invar_def by (simp add: robdd_invar_ext_def)
from robdd_id_map_union [of "{robdd_leaf f}" bs] invar_ids_equal_bs' have id_map'_eq: "robdd_id_map (insert (robdd_leaf f) bs) = robdd_id_map {robdd_leaf f} ++ robdd_id_map bs" by simp
from invar_apply_map have invar_apply_map': "apply_map_invar bop (insert (robdd_leaf f) bs) bs1 bs2 apply_map" unfolding apply_map_invar_def robdd_invar_ext_def invar_ids_equal_bs' by (simp add: invar_ids_bs') metis
have"?P (insert (robdd_leaf f) bs)"by (simp add: invar_ids_bs' f_eq invar_rev_map' invar_apply_map') thus ?thesis by blast next case None note extend_eq_None = this
have min_var_b12_ge_n: "(robdd_get_min_var b1 b2) ≥ n" proof - from b1_invar b2_invar have"robdd_invar_vars_greater n b1 ∧ robdd_invar_vars_greater n b2" unfolding robdd_invar_ext_def by simp_all with extend_eq_None show"(robdd_get_min_var b1 b2) ≥ n" by (cases b1, case_tac [!] b2, simp_all) qed
show ?thesis proof (cases "c_lookup (robdd_get_id b1, robdd_get_id b2) apply_map") case (Some b3) note lookup_eq_Some = this
from extend_eq_None lookup_eq_Some res_def have res_eq[simp]: "?res = (b3, apply_map, rev_map)" by simp
from apply_map_invar_D2[OF invar_apply_map, OF lookup_eq_Some]
robdd_id_map_properties[of bs1] invar_ids_equal_bs1
robdd_id_map_properties[of bs2] invar_ids_equal_bs2
b1_in b2_in have invar_b3: "robdd_invar_ext bs (robdd_get_min_var b1 b2) b3"and
sem_b3: "∧a. robdd_α b3 a = bop (robdd_α b1 a) (robdd_α b2 a)" by (simp_all add: robdd_id_map_OK_def)
from invar_b3 have b3_in: "b3 ∈ subrobdds_set bs"unfolding robdd_invar_ext_def by simp hence subrobdds_b3_bs_eq: "subrobdds_set (subrobdds b3 ∪ bs) = subrobdds_set bs" using subrobdds_set_subset_simp[of b3 bs] by auto
from subrobdds_b3_bs_eq invar_b3 have invar_b3': "robdd_invar_ext (subrobdds b3 ∪ bs) n b3" unfolding robdd_invar_ext_def using robdd_invar_ids_expand[of "subrobdds b3 ∪ bs", symmetric]
robdd_invar_ids_expand[of bs]
robdd_invar_vars_greater___weaken[OF _ min_var_b12_ge_n, of b3] by simp from invar_b3' have invar_ids': "robdd_invar_ids (subrobdds b3 ∪ bs)" unfolding robdd_invar_ext_def by simp
from invar_rev_map invar_ids' have invar_rev_map': "rev_map_invar (subrobdds b3 ∪ bs) rev_map" unfolding rev_map_invar_def subrobdds_b3_bs_eq robdd_invar_ext_def by simp
from invar_apply_map invar_ids' have invar_apply_map': "apply_map_invar bop (subrobdds b3 ∪ bs) bs1 bs2 apply_map" unfolding apply_map_invar_def robdd_invar_ext_def by simp blast
have"?P (subrobdds b3 ∪ bs)"by (simp add: invar_b3' sem_b3 invar_rev_map' invar_apply_map') thus ?thesis by blast next case None note lookup_eq_None = this
from extend_eq_None have not_leaf_b12: "~(robdd_is_leaf b1 ∧ robdd_is_leaf b2)" by (cases b1, case_tac [!] b2) simp_all
obtain b1_l b1_r v'' b2_l b2_r where
next_eq: "robdd_apply_next b1 b2 = (b1_l, b1_r, v'', b2_l, b2_r)"by (metis prod.exhaust) obtain l apply_map' rev_map' where
apply_l_eq: "robdd_apply apply_map rev_map bop b1_l b2_l = (l, apply_map', rev_map')" by (metis prod.exhaust) obtain r apply_map'' rev_map'' where
apply_r_eq: "robdd_apply apply_map' rev_map' bop b1_r b2_r = (r, apply_map'', rev_map'')" by (metis prod.exhaust) obtain b' rev_map''' where const_eq: "robdd_construct rev_map'' l v'' r = (b', rev_map''')" by (metis prod.exhaust)
define apply_map''' where"apply_map''' = c_update (robdd_get_id b1, robdd_get_id b2) b' apply_map''" note next_props = robdd_apply_next_correct [OF b1_invar b2_invar next_eq] not_leaf_b12 note v''_eq = next_props(13)
have res_eq[simp]: "?res =(b', apply_map''', rev_map''')" by (simp_all add: b_def next_eq res_def extend_eq_None lookup_eq_None apply_r_eq apply_l_eq
const_eq apply_map'_def apply_map'''_def rev_map'_def)
from subset_bs' have"l ∈ bs'"by auto with subset_bs'' have l_in_bs'': "l ∈ bs''"by auto from subset_bs'' have r_in_bs'': "r ∈ bs''"by auto
from l_invar0 r_invar1 l_in_bs'' have l_invar1: "robdd_invar_ext bs'' (Suc v'') l" unfolding robdd_invar_ext_def by simp (metis subrobdds_set_mono subsetD)
define bs''' where"bs''' = insert b' bs''" from robdd_construct_correct[OF invar_rev_map'' _ _ l_invar1 r_invar1] have b'_invar: "robdd_invar_ext bs''' v'' b'" and invar_rev_map''': "rev_map_invar bs''' rev_map'''" and sem_b': "robdd_α b' = robdd_α (robdd_var 0 l v'' r)" by (simp_all add: const_eq bs'''_def l_in_bs'' r_in_bs'')
have sem_OK: "∀a. robdd_α b' a = bop (robdd_α b1 a) (robdd_α b2 a)" by (simp add: sem_b' sem_l sem_r fun_upd_idem)
have"?P (subrobdds_set bs''')" unfolding res_eq fst_conv snd_conv proof (intro conjI) from subset_bs'' subset_bs' have"bs ⊆ bs''"by auto with subrobdds_set_mono2 [of bs bs''] have"subrobdds_set bs ⊆ subrobdds_set bs''"by simp with subrobdds_set_mono[of bs] have"bs ⊆ subrobdds_set bs''"by simp thus"subrobdds b' ∪ bs ⊆ subrobdds_set bs'''" unfolding bs'''_def by (simp add: subset_iff) next from b'_invar show"robdd_invar_ext (subrobdds_set bs''') n b'" unfolding robdd_invar_ext_def robdd_invar_ids_def using robdd_invar_vars_greater___weaken[of v'' b' n]
v''_eq min_var_b12_ge_n by simp next show"∀a. robdd_α b' a = bop (robdd_α b1 a) (robdd_α b2 a)"by fact next from invar_rev_map''' subrobdds_set_mono[of bs'''] show"rev_map_invar (subrobdds_set bs''') rev_map'''" unfolding rev_map_invar_def by (simp add: subset_iff) next from robdd_id_map_properties[of bs1] invar_ids_equal_bs1 b1_in have id_map_b1: "robdd_id_map bs1 (robdd_get_id b1) = Some b1" by (simp add: robdd_id_map_OK_def)
from robdd_id_map_properties[of bs2] invar_ids_equal_bs2 b2_in have id_map_b2: "robdd_id_map bs2 (robdd_get_id b2) = Some b2" by (simp add: robdd_id_map_OK_def)
{ fix n b assume b_invar: "robdd_invar_ext bs'' n b"
from b'_invar have ids_bs''': "robdd_invar_ids bs'''"unfolding robdd_invar_ext_def by simp
from b_invar subrobdds_set_mono2 [of bs'' bs'''] ids_bs''' have"robdd_invar_ext bs''' n b" unfolding robdd_invar_ext_def bs'''_defby simp
} note invar_bs'''_ext = this
from invar_apply_map'' b'_invar show"apply_map_invar bop (subrobdds_set bs''') bs1 bs2 apply_map'''" unfolding apply_map'''_def apply_map_invar_def apply (elim conjE) apply (simp add: c.lookup_correct c.update_correct id_map_b1 id_map_b2 v''_eq sem_OK) apply (metis invar_bs'''_ext) done qed thus ?thesis by blast qed qed qed
lemma robdd_apply_correct : fixes b1 b2 bop rev_map apply_map defines"res ≡ robdd_apply (c_empty ()) (r_empty (), 2) bop b1 b2" defines"b ≡ fst res" assumes b1_invar: "robdd_invar b1" and b2_invar: "robdd_invar b2" shows"robdd_invar b ∧ (∀a. robdd_α b a ⟷ bop (robdd_α b1 a) (robdd_α b2 a))" proof - from robdd_apply_correct_full [OF rev_map_invar_empty apply_map_invar_empty
b1_invar[unfolded robdd_invar_def] b2_invar[unfolded robdd_invar_def], of bop,
folded res_def b_def] b1_invar b2_invar obtain bs where invar_ext: "robdd_invar_ext bs 0 b" and sem_OK: "∀a. robdd_α b a = bop (robdd_α b1 a) (robdd_α b2 a)"by auto
from invar_ext have invar: "robdd_invar b" by (rule robdd_invar_impl)
from invar sem_OK show ?thesis by simp qed
definition robdd_neg where "robdd_neg apply_map rev_map b = robdd_apply apply_map rev_map (λb1 b2. ¬(b1 ∧ b2)) b robdd_one"
lemma robdd_neg_correct_full : fixes b rev_map apply_map bs defines"res ≡ robdd_neg apply_map rev_map b" defines"b' ≡ fst res" defines"apply_map' ≡ fst (snd res)" defines"rev_map' ≡ snd (snd res)" assumes invar_rev_map: "rev_map_invar bs rev_map" and invar_apply_map: "apply_map_invar (λb1 b2. ¬(b1 ∧ b2)) bs bs1 bs2 apply_map" and b_invar: "robdd_invar_ext bs1 n b" and bs1_OK: "∧b. b ∈ bs1 ==> robdd_invar b" and bs2_OK: "∧b. b ∈ bs2 ==> robdd_invar b""robdd_invar_ids bs2" shows"∃bs'. subrobdds b' ∪ bs ⊆ bs' ∧ robdd_invar_ext bs' n b' ∧ apply_map_invar (λb1 b2. ¬(b1 ∧ b2)) bs' bs1 (insert robdd_zero (insert robdd_one bs2)) apply_map' ∧ rev_map_invar bs' rev_map' ∧ (∀a. robdd_α b' a ⟷¬ (robdd_α b a))" proof -
from robdd_apply_correct_full[OF invar_rev_map invar_apply_map' b_invar _ bs1_OK, of robdd_one]
res_def[symmetric] show ?thesis apply (simp add: robdd_neg_def b'_def[symmetric] apply_map'_def[symmetric]
rev_map'_def[symmetric]) by (metis bs2_OK(1) bs2'_invar robdd_invar_simps_leafs) qed
lemma robdd_neg_correct : fixes b rev_map apply_map bs defines"res ≡ robdd_neg (c_empty ()) (r_empty (), 2) b" defines"bn ≡ fst res" assumes b_invar: "robdd_invar b" shows"robdd_invar bn ∧ (∀a. robdd_α bn a ⟷¬(robdd_α b a))" unfolding res_def bn_def robdd_neg_def using robdd_apply_correct [OF b_invar, of robdd_one "(λb1 b2. ¬(b1 ∧ b2))"] by simp
lemma robdd_neg_alt_def : "robdd_neg apply_map rev_map b = (case (bope_neg (robdd_to_bool b)) of Some f ==> (robdd_leaf f, apply_map, rev_map) | None ==> (case c_lookup (robdd_get_id b, 1) apply_map of Some b3 ==> (b3, apply_map, rev_map) | None ==> (let (l1, r1, var) = robdd_neg_next b in let (l, apply_map, rev_map) = robdd_neg apply_map rev_map l1 in let (r, apply_map, rev_map) = robdd_neg apply_map rev_map r1 in let (b3, rev_map) = robdd_construct rev_map l var r in let apply_map = c_update (robdd_get_id b, 1) b3 apply_map in (b3, apply_map, rev_map))))" proof - have bope_neg_intro: "(bool_op_extend (λb1 b2. b1 ⟶¬ b2) (robdd_to_bool b) (Some True)) = (bope_neg (robdd_to_bool b))" apply (cases "robdd_to_bool b" rule: bool_opt_exhaust) apply (simp_all) done
obtain b1_l b1_r v'' b2_l b2_r where
next_eq: "robdd_apply_next b robdd_one = (b1_l, b1_r, v'', b2_l, b2_r)"by (metis prod.exhaust)
from next_eq have b2_eq[simp]: "b2_l = robdd_one""b2_r = robdd_one" by (case_tac[!] b) auto
show ?thesis unfolding robdd_neg_def robdd_apply.simps[of _ _ _ b] by (simp split: option.splits add: bope_neg_intro next_eq split_def robdd_neg_next_def) qed
text‹An auxiliary construct to get the ids of a ROBDD consistent with some cache or
other ROBDDs.› definition robdd_copy where "robdd_copy apply_map rev_map b = robdd_apply apply_map rev_map (λb1 b2. (b1 ∧ b2)) b robdd_one"
lemma robdd_copy_correct_full : fixes b rev_map apply_map bs defines"res ≡ robdd_copy apply_map rev_map b" defines"b' ≡ fst res" defines"apply_map' ≡ fst (snd res)" defines"rev_map' ≡ snd (snd res)" assumes invar_rev_map: "rev_map_invar bs rev_map" and invar_apply_map: "apply_map_invar (λb1 b2. (b1 ∧ b2)) bs bs1 bs2 apply_map" and b_invar: "robdd_invar_ext bs1 n b" and bs1_OK: "∧b. b ∈ bs1 ==> robdd_invar b" and bs2_OK: "∧b. b ∈ bs2 ==> robdd_invar b""robdd_invar_ids bs2" shows"∃bs'. subrobdds b' ∪ bs ⊆ bs' ∧ robdd_invar_ext bs' n b' ∧ apply_map_invar (λb1 b2. (b1 ∧ b2)) bs' bs1 (insert robdd_zero (insert robdd_one bs2)) apply_map' ∧ rev_map_invar bs' rev_map' ∧ (∀a. robdd_α b' a ⟷ (robdd_α b a))" proof -
from robdd_apply_correct_full[OF invar_rev_map invar_apply_map' b_invar _ bs1_OK, of robdd_one]
res_def[symmetric] show ?thesis apply (simp add: robdd_copy_def b'_def[symmetric] apply_map'_def[symmetric]
rev_map'_def[symmetric]) by (metis bs2_OK(1) bs2'_invar robdd_invar_simps_leafs) qed
lemma robdd_copy_correct : fixes b rev_map apply_map bs defines"res ≡ robdd_copy (c_empty ()) rev_map b" defines"b' ≡ fst res" defines"rev_map' ≡ snd (snd res)" assumes invar_rev_map: "rev_map_invar bs rev_map" and b_invar: "robdd_invar_ext {b} n b" shows"∃bs'. subrobdds b' ∪ bs ⊆ bs' ∧ robdd_invar_ext bs' n b' ∧ rev_map_invar bs' rev_map' ∧ (∀a. robdd_α b' a ⟷ (robdd_α b a))" using res_def[symmetric] using robdd_copy_correct_full [OF invar_rev_map _ b_invar, of "{}""c_empty ()"] apply (simp add: apply_map_invar_def c.empty_correct c.lookup_correct robdd_invar_ids_def
b'_def[symmetric] rev_map'_def[symmetric]) apply (metis b_invar robdd_invar_impl) done
lemma robdd_copy_alt_def : "robdd_copy apply_map rev_map b = (case (robdd_to_bool b) of Some f ==> (robdd_leaf f, apply_map, rev_map) | None ==> (case c_lookup (robdd_get_id b, 1) apply_map of Some b3 ==> (b3, apply_map, rev_map) | None ==> (let (l1, r1, var) = robdd_neg_next b in let (l, apply_map, rev_map) = robdd_copy apply_map rev_map l1 in let (r, apply_map, rev_map) = robdd_copy apply_map rev_map r1 in let (b3, rev_map) = robdd_construct rev_map l var r in let apply_map = c_update (robdd_get_id b, 1) b3 apply_map in (b3, apply_map, rev_map))))" proof - have bope_neg_intro: "(bool_op_extend (λb1 b2. b1 ∧ b2) (robdd_to_bool b) (Some True)) = (robdd_to_bool b)" apply (cases "robdd_to_bool b" rule: bool_opt_exhaust) apply (simp_all) done
obtain b1_l b1_r v'' b2_l b2_r where
next_eq: "robdd_apply_next b robdd_one = (b1_l, b1_r, v'', b2_l, b2_r)"by (metis prod.exhaust)
from next_eq have b2_eq[simp]: "b2_l = robdd_one""b2_r = robdd_one" by (case_tac[!] b) auto
show ?thesis unfolding robdd_copy_def robdd_apply.simps[of _ _ _ b] by (simp split: option.splits add: bope_neg_intro next_eq split_def robdd_neg_next_def) qed
definition restrict_map_invar where "restrict_map_invar f bs res_map ⟷ c_invar res_map ∧ (∀i v b. c_lookup (v, i) res_map = Some b ⟶ (∃b'. robdd_id_map bs i = Some b' ∧ b ∈ bs ∧ robdd_invar_ext bs (robdd_get_var b') b ∧ (∀a. robdd_α b a ⟷ robdd_α b' (a(v := f)))))"
lemma restrict_map_invar_empty : "restrict_map_invar f bs (c_empty ())" unfolding restrict_map_invar_def by (simp add: c.empty_correct c.lookup_correct)
lemma restrict_map_invar_I : "[c_invar res_map; ∧i v b. c_lookup (v, i) res_map = Some b ==> (∃b'. robdd_id_map bs i = Some b' ∧ b ∈ bs ∧ robdd_invar_ext bs (robdd_get_var b') b ∧ (∀a. robdd_α b a ⟷ robdd_α b' (a(v := f))))]==> restrict_map_invar f bs res_map" unfolding restrict_map_invar_def by blast
lemma restrict_map_invar_D1 : "restrict_map_invar f bs res_map ==> c_invar res_map" unfolding restrict_map_invar_def by blast
lemma restrict_map_invar_D2 : "[restrict_map_invar f bs res_map; c_lookup (v, i) res_map = Some b]==> (∃b'. robdd_id_map bs i = Some b' ∧ b ∈ bs ∧ robdd_invar_ext bs (robdd_get_var b') b ∧ (∀a. robdd_α b a ⟷ robdd_α b' (a(v := f))))" unfolding restrict_map_invar_def by blast
fun robdd_restrict where "robdd_restrict res_map rev_map f rv b = (case b of (robdd_leaf f') ==> (robdd_leaf f', res_map, rev_map) | (robdd_var i l v r) ==> (if (rv < v) then (b, res_map, rev_map) else ( if (rv = v) then (if f then l else r, res_map, rev_map) else ( (case c_lookup (rv, i) res_map of Some b3 ==> (b3, res_map, rev_map) | None ==> (let (l', res_map, rev_map) = robdd_restrict res_map rev_map f rv l in let (r', res_map, rev_map) = robdd_restrict res_map rev_map f rv r in let (b3, rev_map) = robdd_construct rev_map l' v r' in let res_map = c_update (rv, i) b3 res_map in (b3, res_map, rev_map)) )))))" declare robdd_restrict.simps [simp del]
lemma robdd_restrict_correct_full : fixes b f rv rev_map res_map bs defines"res ≡ robdd_restrict res_map rev_map f rv b" defines"b' ≡ fst res" defines"res_map' ≡ fst (snd res)" defines"rev_map' ≡ snd (snd res)" assumes invar_rev_map: "rev_map_invar bs rev_map" and invar_res_map: "restrict_map_invar f bs res_map" and b_invar: "robdd_invar_ext bs n b" and b_sub: "subrobdds b ⊆ bs" shows"∃bs'. insert b' bs ⊆ bs' ∧ robdd_invar_ext bs' n b' ∧ restrict_map_invar f bs' res_map' ∧ rev_map_invar bs' rev_map' ∧ (∀a. robdd_α b' a ⟷ (robdd_α b (a(rv := f))))" using invar_rev_map invar_res_map b_invar b_sub unfolding b'_def res_map'_def rev_map'_def res_def proof (induct b arbitrary: bs n res_map rev_map) case (robdd_leaf f') thus ?caseby (rule_tac exI [where x = bs]) (simp add: robdd_restrict.simps) next case (robdd_var i l v r) note indhyp_l = robdd_var(1) note indhyp_r = robdd_var(2) note invar_rev_map = robdd_var(3) note invar_res_map = robdd_var(4) note b_invar = robdd_var(5) note b_sub = robdd_var(6)
let ?b = "robdd_var i l v r" let ?res = "robdd_restrict res_map rev_map f rv ?b"
from b_invar have b_in_bs: "?b ∈ subrobdds_set bs"unfolding robdd_invar_ext_def by simp from rev_map_invar_implies_invar_ids[OF invar_rev_map] have invar_ids_bs: "robdd_invar_ids bs"by simp note bs_OK_full = rev_map_invar_implies_invar_bs[OF invar_rev_map] have bs_OK: "∧b. b ∈ bs ==> robdd_invar b"by (metis bs_OK_full subrobdds_set_mono subsetD) have invar_ids_equal_bs: "robdd_invar_ids_equal bs" by (rule robdd_invar_ids_equal_intro [OF bs_OK invar_ids_bs])
have invar_ids_leafs_bs : "robdd_invar_ids_leafs bs" proof (rule robdd_invar_ids_leafs_intro[of bs, OF _ invar_ids_bs]) fix b assume"b ∈ bs" with bs_OK[of b] have"robdd_invar b"by simp thus"robdd_invar_reduced b"unfolding robdd_invar_def robdd_invar_ext_def by simp qed
from b_invar have invars_greater: "robdd_invar_vars_greater (Suc v) l""robdd_invar_vars_greater (Suc v) r" by (simp_all add: robdd_invar_ext_def)
show ?case proof (cases "rv < v") case True note rv_less = this
show ?thesis using rv_less b_invar b_sub apply (rule_tac exI[where x = bs]) apply (simp add: invar_rev_map invar_res_map robdd_restrict.simps) apply (simp add: invars_greater sem_simp) done next case False hence v_le: "v ≤ rv"by simp
show ?thesis proof (cases "rv = v") case True note rv_eq [simp] = this
from invars_greater(2) have r_simp : "∧a. robdd_α r (λx. x ≠ v ∧ a x) = robdd_α r a" apply (rule_tac robdd_α_invar_greater[of "Suc v"]) apply (simp_all) done
from invars_greater(1) have l_simp : "∧a. robdd_α l (λx. (x ≠ v ⟶ a x)) = robdd_α l a" apply (rule_tac robdd_α_invar_greater[of "Suc v"]) apply (simp_all) done
from b_invar robdd_invar_ext_weaken_var[of bs "Suc v" _ n] have"robdd_invar_ext bs n l""robdd_invar_ext bs n r"by simp_all thus ?thesis using b_invar b_sub
supply map_upd_eq_restrict[simp] apply (rule_tac exI[where x = bs]) apply (simp add: invar_rev_map invar_res_map robdd_restrict.simps) apply (simp add: l_simp r_simp subset_iff) done next case False with v_le have v_less: "v < rv"by simp
show ?thesis proof (cases "c_lookup (rv, i) res_map") case (Some b3) note lookup_eq = this
from robdd_id_map_properties[of bs] invar_ids_equal_bs have"robdd_id_map_OK bs (robdd_id_map bs)"by simp with robdd_id_map_OK_D[of bs "robdd_id_map bs", OF _ b_in_bs] have"robdd_id_map bs i = Some ?b"by simp
with restrict_map_invar_D2[OF invar_res_map lookup_eq] v_less have invar_b3: "robdd_invar_ext bs v b3"and
b3_in_bs: "b3 ∈ bs"and
sem_b3: "∀a. robdd_α b3 a = (if a v then robdd_α l (a(rv := f)) else robdd_α r (a(rv := f)))"by simp_all
from invar_b3 b_invar have invar_b3': "robdd_invar_ext bs n b3" apply (rule_tac robdd_invar_ext_weaken_var[of _ v]) apply simp_all done
have"∧a. (λx. (x = rv ⟶ f) ∧ (x ≠ rv ⟶ a x)) = a (rv := f)" by (simp add: fun_eq_iff) with lookup_eq show ?thesis using v_less b3_in_bs apply (rule_tac exI[where x = bs]) apply (simp add: sem_b3 invar_b3' invar_rev_map invar_res_map robdd_restrict.simps) done next case None note lookup_eq = this
obtain l' res_map' rev_map' where
res_l_eq: "robdd_restrict res_map rev_map f rv l = (l', res_map', rev_map')" by (metis prod.exhaust) obtain r' res_map'' rev_map'' where
res_r_eq: "robdd_restrict res_map' rev_map' f rv r = (r', res_map'', rev_map'')" by (metis prod.exhaust) obtain b3 rev_map''' where
const_eq: "robdd_construct rev_map'' l' v r' = (b3, rev_map''')" by (metis prod.exhaust)
from b_invar b_sub indhyp_l [OF invar_rev_map invar_res_map, of "Suc v"] obtain bs' where
subset_bs': "insert l' bs ⊆ bs'"and
l'_invar: "robdd_invar_ext bs' (Suc v) l'"and
invar_res_map': "restrict_map_invar f bs' res_map'"and
invar_rev_map': "rev_map_invar bs' rev_map'"and
sem_l': "∀a. robdd_α l' a = (robdd_α l (λb. if b = rv then f else a b))" by (simp add: invar_rev_map invar_res_map res_l_eq) blast
from b_invar have"robdd_invar_ext bs (Suc v) r"by simp with l'_invar subset_bs' have"robdd_invar_ext bs' (Suc v) r" unfolding robdd_invar_ext_def by simp (metis subrobdds_set_mono2 subsetD) with b_sub subset_bs' indhyp_r [OF invar_rev_map' invar_res_map', of "Suc v"] obtain bs'' where
subset_bs'': "insert r' bs' ⊆ bs''"and
r'_invar: "robdd_invar_ext bs'' (Suc v) r'"and
invar_res_map'': "restrict_map_invar f bs'' res_map''"and
invar_rev_map'': "rev_map_invar bs'' rev_map''"and
sem_r': "∀a. robdd_α r' a = (robdd_α r (λb. if b = rv then f else a b))" by (simp add: subset_iff invar_rev_map invar_res_map res_r_eq) blast from l'_invar r'_invar subset_bs' subset_bs'' have l'_invar': "robdd_invar_ext bs'' (Suc v) l'" unfolding robdd_invar_ext_def by simp (metis subrobdds_set_mono2 subsetD)
from subset_bs' subset_bs'' have"l' ∈ bs''""r' ∈ bs''" by (simp_all add: subset_iff)
from robdd_construct_correct [OF invar_rev_map'' ‹l' ∈ bs''›‹r' ∈ bs''›
l'_invar' r'_invar] have b3_invar: "robdd_invar_ext (insert b3 bs'') v b3"and
invar_rev_map''': "rev_map_invar (insert b3 bs'') rev_map'''"and
sem_b3: "robdd_α b3 = robdd_α (robdd_var 0 l' v r')" by (simp_all add: const_eq)
from b3_invar b_invar have b3_invar': "robdd_invar_ext (insert b3 bs'') n b3" apply (rule_tac robdd_invar_ext_weaken_var[of _ v]) apply simp_all done
from subset_bs' subset_bs'' have bs_sub: "bs ⊆ insert b3 bs''" by (simp add: subset_iff)
have invar_res_map''': "restrict_map_invar f (insert b3 bs'') (c_update (rv, i) b3 res_map'')" proof - from b_in_bs subset_bs' subset_bs'' have b_in': "robdd_var i l v r ∈ subrobdds_set bs''" unfolding subrobdds_set_def by (simp add: subset_iff Bex_def) blast
from robdd_id_map_union [of "{b3}" bs'']
rev_map_invar_implies_invar_ids_equal[OF invar_rev_map'''] have id_map_eq: "robdd_id_map (insert b3 bs'') = robdd_id_map {b3} ++ robdd_id_map bs''"by simp
from robdd_id_map_properties[of "insert b3 bs''"] b_in'
rev_map_invar_implies_invar_ids_equal[OF invar_rev_map''']
robdd_id_map_OK_D [of "insert b3 bs''""robdd_id_map (insert b3 bs'')" ?b] have map_id_i: "robdd_id_map (insert b3 bs'') i = Some ?b"by simp note c_invar = restrict_map_invar_D1[OF invar_res_map'']
show ?thesis proof (rule restrict_map_invar_I, goal_cases) from restrict_map_invar_D1[OF invar_res_map''] show"c_invar (c_update (rv, i) b3 res_map'')"by (simp add: c.update_correct) next case prems: (2 i' v' b') note lookup_eq = prems(1)
show ?case proof (cases "i' = i ∧ v' = rv") case True note iv'_eq = this with lookup_eq map_id_i sem_b3 b3_invar v_less show ?thesis by (simp add: c_invar c.update_correct c.lookup_correct
sem_l' sem_r' fun_upd_def) next case False with lookup_eq have lookup_eq': "c_lookup (v', i') res_map'' = Some b'" by (auto simp add: c_invar c.lookup_correct c.update_correct)
from restrict_map_invar_D2[OF invar_res_map'' lookup_eq'] obtain b'' where b''_props: "robdd_id_map bs'' i' = Some b''""b' ∈ bs''" "robdd_invar_ext bs'' (robdd_get_var b'') b'" "∀a. robdd_α b' a = robdd_α b'' (a(v' := f))"by auto
show ?thesis apply (rule_tac exI[where x = b'']) apply (simp add: id_map_eq map_add_Some_iff b''_props) apply (insert b3_invar b''_props(3)) apply (simp add: robdd_invar_ext_def) done qed qed qed
from robdd_restrict.simps[of res_map rev_map f rv ?b] show ?thesis using v_less apply (rule_tac exI[where x = "insert b3 bs''"]) apply (simp add: lookup_eq res_l_eq res_r_eq const_eq invar_rev_map'''
sem_b3 sem_l' sem_r' b3_invar' bs_sub invar_res_map''') done qed qed qed qed
end
subsection‹Semantics on lists›
text‹BDDs represent boolean expression. I.e. they are functions from assignments to \texttt{True} or \texttt{False}. Here, assignments are represented by functions from
variable indices to the values of these Boolean variables. While this reprentation of
is convenient for proofs, a representation based on lists is more convinient for execution.›
definition list_to_assignment_set :: "bool option list ==> (nat ==> bool) set"where "list_to_assignment_set l = {a . (∀v < length l. (∀f. l ! v = Some f ⟶ a v = f))}"
definition shift_assignment where "shift_assignment (b::bool) a = (λv. case v of 0 ==> b | Suc v' ==> a v')"
lemma inj_shift_assignement : "inj_on (shift_assignment b) S" unfolding inj_on_def shift_assignment_def by (simp add: fun_eq_iff split: nat.splits)
lemma list_to_assignment_set_simps [simp]: "list_to_assignment_set [] = UNIV" (is ?T1) "list_to_assignment_set (Some b # l) = (shift_assignment b) ` (list_to_assignment_set l)" (is"?T3 b") proof - show ?T1 unfolding list_to_assignment_set_def by simp next show"?T3 b" unfolding list_to_assignment_set_def apply (simp add: set_eq_iff less_Suc_eq_0_disj shift_assignment_def
del: all_simps add: all_simps[symmetric]) apply (simp add: all_conj_distrib image_iff) apply (intro allI iffI) apply (rule_tac x = "λv. x (Suc v)"in exI) apply (simp add: fun_eq_iff split: nat.split) apply auto done qed
lemma infinite_list_to_assignment_set : "¬(finite (list_to_assignment_set l))" proof (induct l) case Nil note l_eq = this
have inf_UNIV: "¬(finite (UNIV :: (nat ==> bool) set))" proof (rule notI) assume fin_UNIV: "finite (UNIV :: (nat ==> bool) set)" from finite_fun_UNIVD1[OF fin_UNIV] show False by simp qed thus ?caseby simp next case (Cons bo l') note ind_hyp = Cons
obtain b where sub_b: "list_to_assignment_set (Some b # l') ⊆ list_to_assignment_set (bo # l')" by (cases bo) auto
have not_fin_b: "¬(finite (list_to_assignment_set (Some b # l')))" proof (rule notI) assume"finite (list_to_assignment_set (Some b # l'))" hence"finite (list_to_assignment_set l')" apply (simp) apply (rule finite_imageD [of "shift_assignment b"]) apply (simp_all add: inj_shift_assignement) done with ind_hyp show False by simp qed from finite_subset[OF sub_b] not_fin_b show ?caseby blast qed
fun robdd_list_α where "robdd_list_α (robdd_leaf f) n l = f"
| "robdd_list_α (robdd_var i l v r) n [] = False"
| "robdd_list_α (robdd_var i l v r) n (bo # bs) = (if n = v then (case bo of None ==> robdd_list_α l (Suc n) bs ∧ robdd_list_α r (Suc n) bs | Some True ==> robdd_list_α l (Suc n) bs | Some False ==> robdd_list_α r (Suc n) bs) else (robdd_list_α (robdd_var i l v r) (Suc n) bs))"
lemma robdd_list_α_correct_aux : assumes invar: "robdd_invar_vars_greater n b""robdd_invar_reduced b" shows"robdd_list_α b n l ⟷ (∀a ∈ (list_to_assignment_set l). robdd_α b (λv. a (v - n)))" using invar proof (induct b n l rule: robdd_list_α.induct) case (1 f n l) with list_to_assignment_set_not_empty[of l] show ?caseby auto next case prems: (2 i ll v rr n) note invar = prems(1,2)
from invar have"robdd_α ll ≠ robdd_α rr" by (metis robdd_equiv_alt_def_full robdd_invar_reduced.simps(2)
robdd_invar_vars_greater.simps(2) robdd_invar_vars_impl) thenobtain a where a_sem_neq: "robdd_α ll a ≠ robdd_α rr a"by (auto simp add: fun_eq_iff)
define aa where"aa v = a (v + n)"for v from invar(1) have ll_sem: "∧b. robdd_α ll (λv'. (aa(v - n := b)) (v' - n)) = robdd_α ll a" apply (rule_tac robdd_α_invar_greater [of "Suc v"]) apply (simp_all add: aa_def) apply auto done from invar(1) have rr_sem: "∧b. robdd_α rr (λv'. (aa(v - n := b)) (v' - n)) = robdd_α rr a" apply (rule_tac robdd_α_invar_greater [of "Suc v"]) apply (simp_all add: aa_def) apply auto done
show ?case proof (cases "robdd_α ll a") case True with a_sem_neq rr_sem show ?thesis apply (simp) apply (rule_tac exI[where x = "aa(v-n := False)"]) apply simp done next case False with a_sem_neq ll_sem show ?thesis apply (simp) apply (rule_tac exI[where x = "aa(v-n := True)"]) apply simp done qed next case prems: (3 i ll v rr n b bs)
note invar = prems(6,7) hence invar_rr: "robdd_invar_vars_greater (Suc n) rr"and red_ll: "robdd_invar_reduced ll" and invar_ll: "robdd_invar_vars_greater (Suc n) ll"and red_rr: "robdd_invar_reduced rr" and invar_n: "n ≠ v ==> robdd_invar_vars_greater (Suc n) (robdd_var i ll v rr)" and n_le: "n ≤ v" using robdd_invar_vars_greater___weaken [of "Suc v" _ "Suc n"] by simp_all
from invar_ll have ll_sem: "∧a b. robdd_α ll (λv. case_nat b a (v - n)) = robdd_α ll (λv. a (v - Suc n))" apply (rule_tac robdd_α_invar_greater [of "Suc n"]) apply (simp_all split: nat.splits) apply (metis diff_Suc nat.case(2)) done
from invar_rr have rr_sem: "∧a b. robdd_α rr (λv. case_nat b a (v - n)) = robdd_α rr (λv. a (v - Suc n))" apply (rule_tac robdd_α_invar_greater [of "Suc n"]) apply (simp_all split: nat.splits) apply (metis diff_Suc nat.case(2)) done
show ?case proof (cases "n = v") case False with n_le have n_less: "n < v"by simp hence"v - n = Suc (v - (Suc n))"by simp with indhyp_5 n_less show ?thesis apply (simp add: Ball_def all_conj_distrib del: Suc_diff) apply (cases b) apply (simp_all add: image_iff Bex_def ex_disj_distrib all_conj_distrib imp_conjR
shift_assignment_def imp_ex all_simps(6)[symmetric]
ll_sem rr_sem split: nat.split
del: ex_simps all_simps Suc_diff)
done next case True note n_eq[simp] = this
from indhyp_1 indhyp_2 indhyp_3 indhyp_4 show ?thesis apply (simp add: Ball_def split: option.splits bool.splits) apply (simp_all add: image_iff Bex_def ex_disj_distrib all_conj_distrib imp_conjR
shift_assignment_def imp_ex all_simps(6)[symmetric]
ll_sem[unfolded n_eq] rr_sem[unfolded n_eq]
del: ex_simps all_simps) done qed qed
lemma robdd_list_α_correct: assumes b_OK: "robdd_invar_vars b""robdd_invar_reduced b" shows"robdd_list_α b 0 l ⟷ (∀a ∈ (list_to_assignment_set l). robdd_α b a)" using robdd_list_α_correct_aux [of 0 b] b_OK unfolding robdd_invar_vars_def by simp
fun robdd_iteratei where "robdd_iteratei n ac (robdd_leaf f) = (if f then set_iterator_sng ac else set_iterator_emp)" | "robdd_iteratei n ac (robdd_var i l v r) = (set_iterator_union (robdd_iteratei (Suc v) ((Some True) # ((replicate (v-n) None) @ ac)) l) (robdd_iteratei (Suc v) ((Some False) # ((replicate (v-n) None) @ ac)) r))"
(* TODO: Prove correctness of this iterator *)
end
Messung V0.5 in Prozent
¤ 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.0.88Bemerkung:
(Wie Sie bei der Firma Beratungs- und Dienstleistungen beauftragen können 2026-06-10)
¤
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.