diff --git a/source/pervasive/set.rs b/source/pervasive/set.rs index c504fa4f15..4841cead53 100644 --- a/source/pervasive/set.rs +++ b/source/pervasive/set.rs @@ -212,6 +212,8 @@ pub proof fn axiom_set_remove_same(s: Set, a: A) #[verifier(external_body)] #[verifier(broadcast_forall)] pub proof fn axiom_set_remove_insert(s: Set, a: A) + requires + s.contains(a), ensures (#[trigger] s.remove(a)).insert(a) == s, { diff --git a/source/pervasive/set_lib.rs b/source/pervasive/set_lib.rs index 40b5c2cb76..f322166d3d 100644 --- a/source/pervasive/set_lib.rs +++ b/source/pervasive/set_lib.rs @@ -84,8 +84,11 @@ impl Set { #[via_fn] pub proof fn decreases_proof(self) { lemma_set_properties::(); - let x = self.choose(); - assert(self.remove(x).len() < self.len()); + if self.len() >0 { + let x = self.choose(); + assert(self.contains(x)); + assert(self.remove(x).len() < self.len()); + } } /// Converts a set into a sequence sorted by the given ordering function `leq` @@ -113,7 +116,7 @@ impl Set { via Self::prove_decrease_min_unique { - if self.len() == 1 {self.choose()} + if self.len() <= 1 {self.choose()} else { let x = choose |x: A| self.contains(x); let min = self.remove(x).find_unique_minimal(r); @@ -125,6 +128,11 @@ impl Set { proof fn prove_decrease_min_unique(self, r: FnSpec(A,A) -> bool) { lemma_set_properties::(); + if self.len() >0 { + let x = self.choose(); + assert(self.contains(x)); + assert(self.remove(x).len() < self.len()); + } } @@ -141,7 +149,7 @@ impl Set { via Self::prove_decrease_max_unique { - if self.len() == 1 {self.choose()} + if self.len() <= 1 {self.choose()} else { let x = choose |x: A| self.contains(x); let max = self.remove(x).find_unique_maximal(r); @@ -162,7 +170,10 @@ impl Set { when self.finite() { - Multiset::::empty().insert(self.choose()).add(self.remove(self.choose()).to_multiset()) + if self.len() == 0 {Multiset::::empty()} + else { + Multiset::::empty().insert(self.choose()).add(self.remove(self.choose()).to_multiset()) + } } } @@ -798,7 +809,7 @@ pub proof fn lemma_set_difference_len(a: Set, b: Set) a.finite(), b.finite(), ensures - (#[trigger] a.difference(b).len() + b.difference(a).len() + a.intersect(b).len() == (a+b).len()) + (a.difference(b).len() + b.difference(a).len() + a.intersect(b).len() == (a+b).len()) && (a.difference(b).len() == a.len() - a.intersect(b).len()), decreases a.len(), @@ -846,21 +857,21 @@ pub proof fn lemma_set_difference_len(a: Set, b: Set) assert(a.remove(x).difference(b).len() == a.difference(b).len() -1); assert(!b.difference(a).contains(x)); assert(!b.difference(a.remove(x)).contains(x)); + + assert(b.difference(a.remove(x)) =~= b.difference(a)); assert(b.difference(a).len() == b.difference(a.remove(x)).len()); - assert(a.remove(x).intersect(b).len() == a.intersect(b).len()); + + assert(b.remove(x) =~= b); + assert(!a.remove(x).intersect(b).contains(x)); + assert(!a.intersect(b).contains(x)); + assert(a.remove(x).intersect(b) =~= a.intersect(b)); + assert(a.remove(x).intersect(b).len() == a.intersect(b).len()); //key assert(a.difference(b).len() + b.difference(a).len() + a.intersect(b).len() == (a+b).len()); } - assert(a.difference(b).len() == a.len() - a.intersect(b).len()); + //assert(a.difference(b).len() == a.len() - a.intersect(b).len()); } } -// pub proof fn lemma_multiset_from_set() -// ensures -// forall |s: Set, a: A| -// (#[trigger] s.to_multiset().count(a) == 0 <==> (!s.contains(a))) -// && (s.to_multiset().count(a) == 1 <==> s.contains(a)), -// {} - // magic auto style bundle of lemmas that Dafny considers when proving properties of sets pub proof fn lemma_set_properties() ensures @@ -875,7 +886,7 @@ pub proof fn lemma_set_properties() forall |s: Set, a: A| (s.contains(a) && s.finite()) ==> #[trigger] s.insert(a).len() == s.len(), //lemma_set_insert_same_len forall |s: Set, a: A| (s.finite() && !s.contains(a)) ==> #[trigger] s.insert(a).len() == s.len() + 1, //lemma_set_insert_diff_len forall |s: Set, a: A| ((s.finite() && s.contains(a)) ==> (#[trigger] (s.remove(a).len()) == s.len() -1)) - && (!s.contains(a) ==> s.len() == s.remove(a).len()), //lemma_set_remove_len_contains + && ((s.finite() && !s.contains(a)) ==> s.len() == s.remove(a).len()), //lemma_set_remove_len_contains forall |a: Set, b: Set| (a.finite() && b.finite() && a.disjoint(b)) ==> #[trigger] (a+b).len() == a.len() + b.len(), //lemma_set_disjoint_lens forall |a: Set, b: Set| (a.finite() && b.finite()) ==> #[trigger] (a+b).len() + #[trigger] a.intersect(b).len() == a.len() + b.len(), //lemma_set_intersect_union_lens forall |a: Set, b: Set| (a.finite() && b.finite()) ==> ((#[trigger] a.difference(b).len() + b.difference(a).len() + a.intersect(b).len() == (a+b).len()) @@ -905,6 +916,9 @@ pub proof fn lemma_set_properties() assert forall |s: Set, a: A| (s.finite() && !s.contains(a)) implies #[trigger] s.insert(a).len() == s.len() + 1 by { lemma_set_insert_diff_len(s,a); } + assert forall |s: Set, a: A| (s.finite() && !s.contains(a)) implies s.len() == #[trigger] s.remove(a).len() by { + lemma_set_remove_len_contains(s, a); + } assert forall |s: Set, a: A| s.contains(a) && s.finite() implies (#[trigger] (s.remove(a).len()) == s.len() -1) by { lemma_set_remove_len_contains(s, a); }