I want to implement the modulo operation using Z3Py. I've found this discussion on the Z3 github page where one of the creators has the following solution. However, I'm not sure I fully understand it.
from z3 import *
mod = z3.Function('mod', z3.RealSort(), z3.RealSort(), z3.RealSort())
quot = z3.Function('quot', z3.RealSort(), z3.RealSort(), z3.IntSort())
s = z3.Solver()
def mk_mod_axioms(X, k):
s.add(Implies(k != 0, 0 <= mod(X, k)),
Implies(k > 0, mod(X, k) < k),
Implies(k < 0, mod(X, k) < -k),
Implies(k != 0, k * quot(X, k) + mod(X, k) == X))
x, y = z3.Reals('x y')
mk_mod_axioms(x, 3)
mk_mod_axioms(y, 5)
print(s)
If you set no additional constraints the model evaluates to 0, the first solution. If you set additional constraints that x and y should be less than 0, it produces correct solutions. However, if you set the constraint that x and y should be above 0 it produces incorrect results.
s.add(x > 0)
s.add(y > 0)
The model evaluates to 1/2 for x and 7/2 for y.
Here's the model z3 prints:
sat
[y = 7/2,
x = 1/2,
mod = [(7/2, 5) -> 7/2, else -> 1/2],
quot = [else -> 0]]
So, what it's telling you is that it "picked" mod
and quot
to be functions that are:
def mod (x, y):
if x == 3.5 and y == 5:
return 3.5
else:
return 0.5
def quot (x, y):
return 0
Now go over the axioms you put in: You'll see that the model does satisfy them just fine; so there's nothing really wrong with this.
What the answer you linked to is saying is about what sort of properties you can state to get a "reasonable" model. Not that it's the unique such model. In particular, you want quot
to be the maximum such value, but there's nothing in the axioms that require that.
Long story short, the answer you're getting is correct; but it's perhaps not useful. Axiomatizing will take more work, in particular you'll need quantification and SMT solvers don't deal with such specifications that well. But it all depends on what you're trying to achieve: For specific problems you can get away with a simpler model. Without knowing your actual application, the only thing we can say is that this axiomatization is too weak for your use case.