Use z3 to Prove Identity of Boolean/Arithmetic Formula - python

I'm trying to use z3 to prove the following identity:
x+y == x^y + 2*(x&y)
That is, we can replace any addition with a mixture of boolean and arithmetic instructions (example taken from Chapter 2.2, Hacker's Delight).
I'm using the following z3 python snippet:
from z3 import *
x = BitVec("x", 32)
y = BitVec("y", 32)
lhs = x ^ y + (2*(x&y))
rhs = x + y
s = Solver()
s.add(lhs != rhs)
print s.check()
print s.model()
However, z3 gives me this:
sat
[y = 1509949440, x = 1040187384]
So I suppose I'm somehow using the API incorrectly. Any idea what my error is?

Apparently it is an issue with the precedence of the ^ operator. Using
lhs = (x ^ y) + (2*(x&y))
makes the example work for me.

Related

z3.z3types.Z3Exception: Z3 integer expression expected

from z3 import *
x = Int('x')
y = Int('y')
s = Solver()
s.add((2 * y ** 3 + x * y + 5 * x) % 11223344 == 33445566)
s.add((2 * y + x ** 3) % 11223344 == 33445566)
Upon running s.check(), z3 throws an error z3.z3types.Z3Exception: Z3 integer expression expected. I do not understand why as everything I used is an integer. I also tried BitVector however that gave a different error: unsupported operand type(s) for ** or pow(): 'BitVecRef' and 'BitRefValue'
I'm sorry that I could not provide the actual values here as it is sensitive data - but I simply replaced integer values and kept everything else the same.
In z3, power operator always returns a Real value. Which makes your arithmetic use mixed-types, and z3 rightfully complains.
There's a very recent discussion of this on stack-overflow, see here: Why does the type change to Real in z3 python?
You can avoid the issue by casting to integer explicitly:
from z3 import *
x = Int('x')
y = Int('y')
s = Solver()
s.add((2 * ToInt(y ** 3) + x * y + 5 * x) % 11223344 == 33445566)
s.add((2 * y + ToInt(x ** 3)) % 11223344 == 33445566)
The above goes through without any complaints.
However, keep in mind the caveats that come with using the power-operator in the linked answer. If you're always raising to the third power, I'd recommend simply writing x * x * x (or define a function that does that for you). Your problem will still be non-linear, but at least you'll avoid the issues due to the further complexity of exponentiation.

z3py: Symbolic expressions cannot be cast to concrete Boolean values?

from z3 import *
x = Real('x')
s = Solver()
s.add(x > 1 or x < -1)
print(s.check())
if s.check() == sat:
print(s.model())
I want to solve a or expressions , how can i do it?
when z3 told me "Symbolic expressions cannot be cast to concrete Boolean values"
Python's or is not symbolic aware. Instead, use z3py's Or:
from z3 import *
x = Real('x')
s = Solver()
s.add(Or(x > 1, x < -1))
r = s.check()
print(r)
if r == sat:
print(s.model())
This prints:
sat
[x = -2]
Note that I'd also avoid two separate calls to check, by storing the result in a variable first. (Which I called r above.) In general, the second call to check will be cheap since you haven't added any constraints after the first, but this makes the intention clearer.

Python sympy symbols

When I use "x" and "z" as symbols, I have no problem with this code:
from sympy import *
x, z = symbols('x z')
y = -6*x**2 + 2*x*z**0.5 + 50*x - z
solve((diff(y, x), diff(y, z)))
y.subs({x: 5, z: 25})
But when I use "q" and "a", solve does not give me any solution.
q, a = symbols('q a')
y = -6*q**2 + 2*q*a**0.5 + 50*q - a
solve((diff(y, q), diff(y, a)))
y.subs({q: 5, a: 25})
As you can see I use "subs" to check that there is no typo in the objective function.
UPDATE: I used "Symbol" to set each variable individually, but again using "q" and "a" does not work.
# This works
x = Symbol('x')
z = Symbol('z')
y = -6*x**2 + 2*x*z**0.5 + 50*x - z
solve((diff(y, x), diff(y, z)))
# This does not work
q = Symbol('q')
a = Symbol('a')
y = -6*q**2 + 2*q*a**0.5 + 50*q-a
solve((diff(y, q), diff(y, a)))
Thank you.
Got it!
It all depends on an alphabetic order of your variables.
If you substitute x for z and z for x in your first example it will also stop working.
Internally solve sends the expression to the function _solve in sympy.solvers which then tries to solve your equation and fails many times.
Finally as a last effort what it does is it tries to solve -sqrt(a) + q or x - sqrt(z) by picking symbols from it through an internal function _ok_syms, with an argument that sorts those alphabetically (even without this argument it still would, but if wrapped with reversed it magically makes your examples works in the exactly opposite way).
And so it does solve x - sqrt(z) as x: sqrt(z) and -sqrt(a) + q as a: q**2.
While in the first case it ends up with an easily solvable 50 - 10*sqrt(z), in the second case it is lost on -12*q + 2*sqrt(q**2) + 50 as it is not able to simplify sqrt(q**2).
source:
a lot of testing on:
https://github.com/sympy/sympy/blob/master/sympy/solvers/solvers.py

Sympy: working with equalities manually

I'm currently doing a maths course where my aim is to understand the concepts and process rather than crunch through problem sets as fast as possible. When solving equations, I'd like to be able to poke at them myself rather than have them solved for me.
Let's say we have the very simple equation z + 1 = 4- if I were to solve this myself, I would obviously subtract 1 from both sides, but I can't figure out if sympy provides a simple way to do this. At the moment the best solution I can come up with is:
from sympy import *
z = symbols('z')
eq1 = Eq(z + 1, 4)
Eq(eq1.lhs - 1, eq1.rhs - 1)
# Output:
# z == 3
Where the more obvious expression eq1 - 1 only subtracts from the left-hand side. How can I use sympy to work through equalities step-by-step like this (i.e. without getting the solve() method to just given me the answer)? Any pointers to the manipulations that are actually possible with sympy equalities would be appreciated.
There is a "do" method and discussion at https://github.com/sympy/sympy/issues/5031#issuecomment-36996878 that would allow you to "do" operations to both sides of an Equality. It's not been accepted as an addition to SymPy but it is a simple add-on that you can use. It is pasted here for convenience:
def do(self, e, i=None, doit=False):
"""Return a new Eq using function given or a model
model expression in which a variable represents each
side of the expression.
Examples
========
>>> from sympy import Eq
>>> from sympy.abc import i, x, y, z
>>> eq = Eq(x, y)
When the argument passed is an expression with one
free symbol that symbol is used to indicate a "side"
in the Eq and an Eq will be returned with the sides
from self replaced in that expression. For example, to
add 2 to both sides:
>>> eq.do(i + 2)
Eq(x + 2, y + 2)
To add x to both sides:
>>> eq.do(i + x)
Eq(2*x, x + y)
In the preceding it was actually ambiguous whether x or i
was to be added but the rule is that any symbol that are
already in the expression are not to be interpreted as the
dummy variable. If we try to add z to each side, however, an
error is raised because now it is unclear whether i or z is being
added:
>>> eq.do(i + z)
Traceback (most recent call last):
...
ValueError: not sure what symbol is being used to represent a side
The ambiguity must be resolved by indicating with another parameter
which is the dummy variable representing a side:
>>> eq.do(i + z, i)
Eq(x + z, y + z)
Alternatively, if only one Dummy symbol appears in the expression then
it will be automatically used to represent a side of the Eq.
>>> eq.do(2*Dummy() + z)
Eq(2*x + z, 2*y + z)
Operations like differentiation must be passed as a
lambda:
>>> Eq(x, y).do(lambda i: i.diff(x))
Eq(1, 0)
Because doit=False by default, the result is not evaluated. to
evaluate it, either use the doit method or pass doit=True.
>>> _.doit == Eq(x, y).do(lambda i: i.diff(x), doit=True)
True
"""
if not isinstance(e, (FunctionClass, Lambda, type(lambda:1))):
e = S(e)
imaybe = e.free_symbols - self.free_symbols
if not imaybe:
raise ValueError('expecting a symbol')
if imaybe and i and i not in imaybe:
raise ValueError('indicated i not in given expression')
if len(imaybe) != 1 and not i:
d = [i for i in imaybe if isinstance(i, Dummy)]
if len(d) != 1:
raise ValueError(
'not sure what symbol is being used to represent a side')
i = set(d)
else:
i = imaybe
i = i.pop()
f = lambda side: e.subs(i, side)
else:
f = e
return self.func(*[f(side) for side in self.args], evaluate=doit)
from sympy.core.relational import Equality
Equality.do = do

Equation solver in Python

Given a simple equation such as:
x = y + z
You can get the third variable if you bind the other two (ie: y = x - z and z = x - y). A straightforward way to put this in code:
def solve(args):
if 'x' not in args:
return args['y'] + args['z']
elif 'z' not in args:
return args['x'] - args['y']
elif 'y' not in args:
return args['x'] - args['z']
else:
raise SomeError
I obviously can take an equation, parse it and simplify it to achieve the same effect.
But I believe in doing so I would be re-inventing the wheel. So where's my ready-made wheel?
Consider using Sympy. It includes various tools to solve equations and a lot more.
The following is an excerpt from the docs:
>>> from sympy import I, solve
>>> from sympy.abc import x, y
>>> solve(x**4-1, x)
[1, -1, -I, I]

Categories

Resources