I've been trying to show that two bitvectors are equivalent when all its individual bits are equivalent. In other words, the following statement where a
and b
are bv64
and BitIsSet
is a function extracting the ith
bit from the bitvector, and WORD_SIZE
is 64.
(a == b) == (forall i | 0 <= i < WORD_SIZE :: (BitIsSet(a, i) == BitIsSet(b, i)))
The first case, where a == b
seems trivial for Dafny. So what I'm left to show is that
if a != b {
assert !(forall i | 0 <= i < WORD_SIZE :: (BitIsSet(a, i) == BitIsSet(b, i)));
}
which basically is showing that there exists an i
such that the two bits are different:
assert exists i | 0 <= i < WORD_SIZE :: (BitIsSet(a, i) != BitIsSet(b, i))
Any hints on how to best go about this?
For completeness, BitIsSet
basically masks the bit at ith
position and compares it against 0.
predicate method {:opaque} BitIsSet(x:bv64, i: nat)
requires i < WORD_SIZE
{
(x & ((1 as bv64) << (i as bv7))) != 0
}
The same thing by using sequences of booleans seems to be pretty much trivial, I suspect that there is some kind of axiom being used?
lemma SeqBoolEquiv(a: seq<bool>, b: seq<bool>)
requires |a| == WORD_SIZE && |b| == WORD_SIZE
ensures (a == b) <==> (forall i | 0 <= i < WORD_SIZE :: a[i] == b[i])
{
}
Edit: Trying to understand what's going on here: Would the inability to show equivalence for bitvectors (as opposed to sequences) likely be due to a missing axiom at Dafny level, or some possible limitations at Boogie or Z3 showing equivalence of bitvectors there?