Why does this never verify? It's mostly equations and it seems like they're pretty much all equalities. Am I relying too heavily on the modulus axioms causing the problem? It doesn't return any feedback.
I have figured out that it is getting stuck on remainderTheorem, but the difference is that it does not get stuck on remainderTheorem(b, p, c); but it does for remainderTheorem(a,p*q,b). Why does p * q break it?
/*
Suppose ≡mod and ≡mod, then we have
=+=+(+)=(+)+
so that ≡mod
*/
lemma congruencePersistMod(a: nat, b: nat, p: nat, q: nat, c: nat)
requires p != 0
requires q != 0
requires p*q != 0
requires a % p*q == b;
requires b % p == c;
ensures a % p == c
{
assert c % p == c;
remainderTheorem(a,p*q,b);
var r :| divAdd(r, p*q, b) == a;
remainderTheorem(b, p, c);
var s :| divAdd(s, p, c) == b;
calc {
a % p;
(r * p * q + b) % p;
(r * p * q + s*p + c) % p;
(p*(r*q+s) + c) % p;
== {modPlus(p*(r*q+s), c, p);}
( ((p*(r*q+ s)) % p) + (c % p)) % p;
== {selfAnnihilation(p, (r*q+s));}
(0 + c % p) % p;
c % p;
c;
}
}
function divAdd(b: int, a: int, c: int): int {
b * a + c
}
lemma remainderTheorem(x: int, a: int, c: int)
requires a != 0
requires x % a == c;
ensures exists q :: divAdd(q,a,c) == x
{
var q := (x-c) / a;
remainderSubtract(x,a,c);
assert divAdd(q,a,c) == x;
}
lemma remainderSubtract(x: int, a: int, c: int)
requires a != 0
requires c == x % a
ensures (x-c) % a == 0
lemma modPlus(a: int, b: int, n: int)
requires n != 0;
ensures ((a % n) + (b % n)) % n == (a + b) % n
lemma selfAnnihilation(a: int, b: int)
requires a != 0
ensures (b*a) % a == 0
{
calc {
(b * a) % a;
{modMultiplication(a,0,b,b%a,a);}
(0 * b%a) % a;
0;
}
}
lemma modMultiplication(aone: int, bone: int, atwo: int, btwo: int, n: int)
requires n != 0
requires aone % n == bone
requires atwo % n == btwo
ensures (aone * atwo) % n == (bone * btwo) % n
Works but it's feels so silly...