Lua can't unpack a table starts with two nil assigned elementwise - lua

I tried the following code in Lua. The first four cases work well but the last two fail. I get nil as results in those two. What is the problem?
v = {nil, 10, nil}
a, b, c = unpack(v)
-- Output: a, b, c = nil 10 nil
print('a, b, c = ', a, b, c)
v = {nil, nil, 10}
a, b, c = unpack(v)
-- Output: a, b, c = nil nil 10
print('a, b, c = ', a, b, c)
v = {}
v[2] = 10
a, b, c = unpack(v)
-- Output: a, b, c = nil 10 nil
print('a, b, c = ', a, b, c)
v = {}
v[1] = nil
v[2] = 10
v[3] = nil
a, b, c = unpack(v)
-- Output: a, b, c = nil 10 nil
print('a, b, c = ', a, b, c)
v = {}
v[3] = 10
a, b, c = unpack(v)
-- Output: a, b, c = nil nil nil
print('a, b, c = ', a, b, c)
v = {}
v[1] = nil
v[2] = nil
v[3] = 10
a, b, c = unpack(v)
-- Output: a, b, c = nil nil nil
print('a, b, c = ', a, b, c)

When using a table as an array, all elements are required to have values different than nil.
Setting the value for a key to nil effectively removes that key from the table. But in an array all integer keys from 1 to the length of that array must be set. “Holes” are not allowed. So the behaviour in all your cases is unspecified.
You can verify by printing all key/value pairs in the table:
t = {0, nil, 2, 3}
print("pairs:")
for k, v in pairs(t) do
print("["..k.."]", v)
end
And note how ipairs breaks, since it stops at the first nil element.
print("ipairs:")
for k, v in ipairs(t) do
print("["..k.."]", v)
end
Workaround in your case is described in an answer here: Lua unpack bug?

Related

Get atoms of a Boolean formula in Z3

I was wondering if there is a method to get the atoms of a Boolean formula:
a = Bool('a')
b = Bool('b')
c = Bool('C')
d = Bool('D')
e = Bool('E')
f = Bool('F')
formula = And(Or(a, b), Or(c, d), Or(e, f))
I wonder if something like this exists:
formula.get_atoms() or get_atoms(formula)
to give me following desired output:
{A, B, C, D, E, F}
In pySMT, get_atoms() exists the provides the atoms. However, for some reason, I need to experiment on Z3.
You can traverse through the hierarchy of children() (documentation):
def atoms(expr):
a = set()
if not str(expr) in {'True', 'False'}:
c = expr.children()
if len(c):
for child in c:
a = a.union(atoms(child))
else:
a = {expr}
return a
a = Bool('a')
b = Bool('b')
c = Bool('C')
d = Bool('D')
e = Bool('E')
f = Bool('F')
formula = And(Or(a, b), Or(c, d), Or(e, f))
print(atoms(formula))

Trying to find all solutions to a boolean formula using Z3 in python

I'm new to Z3, and trying to make a solver which returns every satisfiable solution to a boolean formula. Taking notes from other SO-posts, I've coded what I hoped would work, but isn't. The problem seems to that by adding the previous solutions, I remove some of the variables, but then they return in later solutions?
Currently I am just trying to solve a or b or c.
If I explained poorly, let me know and I will try to explain further.
Thanks in advance for the response :)
My code:
from z3 import *
a, b, c = Bools('a b c')
s = Solver()
s.add(Or([a, b, c]))
while (s.check() == sat):
print(s.check())
print(s)
print(s.model())
print(s.model().decls())
print("\n")
s.add(Or([ f() != s.model()[f] for f in s.model().decls() if f.arity() == 0]))
My output:
sat
[Or(a, b, c)]
[c = False, b = False, a = True]
[c, b, a]
sat
[Or(a, b, c), Or(c != False, b != False, a != True)]
[b = True, a = False]
[b, a]
sat
[Or(a, b, c),
Or(c != False, b != False, a != True),
Or(b != True, a != False)]
[b = True, a = True]
[b, a]
sat
[Or(a, b, c),
Or(c != False, b != False, a != True),
Or(b != True, a != False),
Or(b != True, a != True)]
[b = False, c = True]
[b, c]
The typical way to code such problems is as follows:
from z3 import *
a, b, c = Bools('a b c')
s = Solver()
s.add(Or([a, b, c]))
res = s.check()
while (res == sat):
m = s.model()
print(m)
block = []
for var in m:
block.append(var() != m[var])
s.add(Or(block))
res = s.check()
This prints:
[b = True, a = False, c = False]
[a = True]
[c = True, a = False]
You'll notice that not all models are "complete." This is because z3 will typically "stop" assigning variables once it decides the problem is sat, as the other variables are irrelevant.
I suppose your confusion is that there should be 7 models to your problem: Aside from the all-False assignment, you should have a model. If you want to get the values of all your variables in this way, then you should explicitly query for them, like this:
from z3 import *
a, b, c = Bools('a b c')
s = Solver()
s.add(Or([a, b, c]))
myvars = [a, b, c]
res = s.check()
while (res == sat):
m = s.model()
block = []
for var in myvars:
v = m.evaluate(var, model_completion=True)
print("%s = %s " % (var, v)),
block.append(var != v)
s.add(Or(block))
print("\n")
res = s.check()
This prints:
a = False b = True c = False
a = True b = False c = False
a = True b = True c = False
a = True b = True c = True
a = True b = False c = True
a = False b = False c = True
a = False b = True c = True
And there are exactly 7 models as you would've expected.
Note the model_completion parameter. This is a common pitfall for newcomers as there isn't a "out-of-the-box" method in z3 for getting all possible assignments, so you have to be careful coding it yourself like above. The reason why there isn't such a function is that it's really hard to implement it in general: Think about how it should work if your variables were functions, arrays, user-defined data-types, etc. as opposed to simple booleans. It can get really tricky to implement a generic all-sat function with all these possibilities handled correctly and efficiently. So, it's left to the user, as most of the time you only care about a specific notion of all-sat that's typically not hard to code once you learn the basic idioms.

z3py optimization as variables chosen from a list

For the example, how to write code in z3py to maximize value of a+b+c+d as a,b,c,d are all chosen from list [1,2,3,4,5,6,7,8], which is given as the input. a, b, c, d are distinct values.
a, b, c, d = Ints("a b c d")
o = Optimize()
list = [1,2,3,4,5,6,7,8]
o.maximize(a+b+c+d)
how to write code corresponding to choose "a b c d" value from list. The correct out value of a+b+c+d is 26
Thanks!
Here's one way:
from z3 import *
a, b, c, d = Ints("a b c d")
o = Optimize()
list = [1,2,3,4,5,6,7,8]
vars = [a, b, c, d]
for v in vars:
o.add(Or([v == e for e in list]))
o.add(Distinct(*vars))
goal = Int("goal")
o.add(goal == a+b+c+d)
o.maximize(goal)
if o.check() == sat:
print o.model()
else:
print "not satisfiable"
When I run this, I get:
$ python a.py
[d = 5, c = 8, b = 6, a = 7, goal = 26]

Lua iterator using an iterator

I have a function defined as a C binding that provides a generic for iterator:
for el in doc:each() do ... end
I want to write an iterator in Lua that iterates using this function, but return a modification of each result. How can I do this?
Edit: I'm sure my iterator has to start something like this, but I'm getting lost in the body of the function.
function myiterator()
local f, c, v = doc:each()
return (function(c2, v2)
-- ??
end), ??, ??
end
function myiterator()
local generator, state, prev_x = doc:each()
local function my_generator()
local x, y = generator(state, prev_x)
if x ~= nil then
prev_x = x
-- modify x, y
local modified_x = x + 100
local modified_y = "("..y..")"
-- modified_x must be non-nil
return modified_x, modified_y
end
end
return my_generator
end
Before:
local doc = {each = function() return ipairs{"aa", "bb", "cc"} end}
for x, y in doc:each() do
print(x, y)
end
Output:
1 aa
2 bb
3 cc
After:
local doc = {each = function() return ipairs{"aa", "bb", "cc"} end}
-- insert myiterator definition here
for x, y in myiterator() do
print(x, y) -- now x and y are modified
end
Output:
101 (aa)
102 (bb)
103 (cc)
I don't know how your C function works, but here is an iterator function that should do what you are looking for. It calls an iterator triplet repeatedly, takes the first return value, and calls a function on it to return a new value:
function map(transformer, f, c, v)
return function()
v = f(c, v)
if v ~= nil then
return transformer(v)
end
end
end
For instance, this takes the keys in the table { 'a', 'b', 'c' } and squares them. The second return value (the values corresponding to the keys) is ignored:
for v in map(function (x) return x * x end, pairs { 'a', 'b', 'c' }) do
print(v)
end
You can do map(function (elem) return do_something_to(elem) end, doc:each()).
It's easier to read the map function when it's written using a coroutine:
function map(transformer, f, c, v)
return coroutine.wrap(function ()
for val in f, c, v do
coroutine.yield(transformer(val))
end
end)
end
For completeness, either of these functions would allow you to use two return values from the original iterator triplet:
function map2(transformer, f, c, v)
return function()
local v2
v, v2 = f(c, v)
if v ~= nil then
return transformer(v, v2)
end
end
end
function map(transformer, f, c, v)
return coroutine.wrap(function ()
for v, v2 in f, c, v do
coroutine.yield(transformer(v, v2))
end
end)
end
for v in map2(function (a, b) return a .. b end, pairs { 'a', 'b', 'c' }) do
print(v)
end
-- This prints out:
-- 1a
-- 2b
-- 3c
You could wrap the iterator into a coroutine, see also https://www.lua.org/pil/9.3.html
-- dummy object
local doc = {
each = function()
return pairs{ 11, 22, 33 }
end
}
local myiterator = coroutine.wrap(function()
local f, c, v = doc:each()
return f, c, v
end)
for f, c, v in myiterator() do
print(f, c, v)
end
$ lua test.lua
1 11 nil
2 22 nil
3 33 nil
Thanks to those that helped. I learned that my iterator function does not HAVE to return 2 or 3 values. This is a valid list-table iterator:
function every(list)
local i=0
return function() -- no arguments used!
i = i+1
return list[i]
end
end
for word in every{'foo', 'bar', 'jim'} do print(word) end
--> foo
--> bar
--> jim
Because every() does not return a second value (the "invariant" value), a nil is passed as the first parameter to the anonymous function on each iteration. The second value passed to that anonymous function is the value returned from the function on a previous pass (or the third return value from every() on the very first pass)...but if that does not help us iterate, we don't need to use it.
Because none of the answers so far exactly answered what I needed, here is the solution I ended up with:
function myiterator()
local f, c, v = doc:each()
return function()
v = f(c,v)
if v then
-- NOTE: Do NOT change the `v` variable here, because
-- f() may expect it to be exactly what it returned
-- in order to iterator properly on the next invocation.
local myvalue = mutate(v)
return myvalue
end
end
end

why this code returns Unsat?

Given c == a + 4 and t == c + b, if b == -4, then t == a. I am trying to do the opposite, meaning given the above 2 equations and t == a, I try to find value of b.
This is pretty similar to the related question, but this time I only switch a and b, and I am really confused that the code returns different result.
Following the code posted at above link, I have below code (similar, only a and b swiched):
#!/usr/bin/python
from z3 import *
a, b, c, t = BitVecs('a b c t', 32)
g = True
g = And(g, c == (a + 4))
g = And(g, t == (c + b))
s = Solver()
s.add(ForAll([t, a, c], Implies(t == a, g)))
if s.check() == sat:
print s.model()[b]
else:
print 'Unsat'
However, on Ubuntu, running the above code returns unexpected result Unsat, but not value -4 (or 0xfffffffc)
Any idea why this is wrong?
Thanks so much.
Z3 is actually returning unknown. The method check returns: sat, unsat or unknown.
Here is a custom tactic that shows that the formula is indeed unsat.
#!/usr/bin/python
from z3 import *
a, b, c, t = BitVecs('a b c t', 32)
g = True
g = And(g, c == (a + 4))
g = And(g, t == (c + b))
s = Goal()
s.add(ForAll([t, a, c], Implies(t == a, g)))
T = Then("simplify", "der", "distribute-forall")
# print the simplified formula. Note that it is unsat
print T(s)
# Create a solver using the tactic above and qe
s = Then("simplify", "der", "distribute-forall", "qe", "smt").solver()
s.add(ForAll([t, a, c], Implies(t == a, g)))
print s.check()
Update
The formula is of the form
forall t, a, c: t == a ==> c == (a + 4) and t == (c + b).
This formula is logically equivalent to:
forall a, c: c == (a + 4) and a == (c + b).
which is logically equivalent to
(forall a, c: c == (a + 4)) and (forall a, c: a == (c + b)).
Both subformulas are logically equivalent to false.
This is why the formula is unsatisfiable.
The comment you wrote suggests that you believe you created the slightly different formula
forall t, a, c: t == a ==> c == (a + 4) ==> t == (c + b).
This formula is sat. To create this formula we have to replace
g = True
g = And(g, c == (a + 4))
g = And(g, t == (c + b))
with
g = Implies(c == (a + 4), t == (c + b))
The updated example is available here.

Resources