Cartesian product in Z3 - z3

I have two different sets for example {e1, e2, e3} type of E1 and {g1, g2, g3} type of E2 which defined as follows:
E1 = DeclareSort('E1')
e1,e2,e3 = Consts('e1 e2 e3', E1)
E2 = DeclareSort('E2')
g1,g2,g3 = Consts('g1 g2 g3', E2)
My question is how can I make Z3 give me a Cartesian product between the two sets. I need the result like following:
{(e1, g1),(e1, g2),(e1, g3),(e2, g1),(e2, g2),(e2, g3),(e3, g1),(e3, g2),(e3, g3)}.
Anyone can help?
Thanks

Note that e1,e2, e3, g1, g2, g3 are variables. They are not different by definition. So, the assertion e1 == e2 is satisfiable.
You can create products in Python in the usual way:
[(x,y) for x in [e1,e2,e3] for y in [g1,g2,g3]]
If you want to create the product of two sorts, you can use algebraic data-types.
Declare a datatype "Tuple"
>>> Tuple = Datatype('Tuple')
>>> Tuple.declare('mk_tuple', (('first', E1), ('second', E2)))
>>> Tuple = CreateDatatypes(Tuple)[0]
>>> Tuple.mk_tuple(e1, g1)
mk_tuple(e1, g1)

Maybe you're looking for itertools.product()?
>>> import itertools
>>> for x in itertools.product(['e1', 'e2', 'e3'], ['g1', 'g2', 'g3']):
... print(x)
...
('e1', 'g1')
('e1', 'g2')
('e1', 'g3')
('e2', 'g1')
('e2', 'g2')
('e2', 'g3')
('e3', 'g1')
('e3', 'g2')
('e3', 'g3')
>>>

Related

Google Sheets QUERY with dropdown menu + multiple conditions

I have this kind of table on a tab (called "Log"):
A B C D E F G H
a1 b1 c1 d1 5 f1 g1 h1
a2 b1 c2 d1 3 f2 g2
a3 b2 c1 d2 4 f3 g3 h2
a4 b1 d1 5 f4 g4
a5 b2 c3 d1 3 f5 g5 h3
On another tab (called "Watch") of the same file I have a dropdwon menu with all the "D"s.
I'm trying, on the "Watch" tab, with the QUERY function to visualize C,E,G and H. C,E and H have to always be visualized while I need G only if "E"s are between "1" and "3".
The closest I got was this:
=QUERY(Log!B:H, "SELECT C,E,H,G WHERE D='"&B1&"' and H is not null and E<=3")
but it shows only where "E"s are <=3 ignoring the choice from the dropdown menu (WHERE D='"&B1&"')
try:
=QUERY(Log!B:H,
"select C,E,H,G
where lower(D) = '"&TRIM(LOWER(B1))&"'
and H is not null
and E<=3", 0)
Try with this:
=filter({Log!C1:C5,Log!E1:E5,Log!H1:H5,arrayformula(if((Log!H1:H5="")*(Log!E1:E5<=3),Log!G1:G5,""))}, Log!D1:D5="d1")
or
=filter({Log!C1:C5,Log!E1:E5,Log!H1:H5,arrayformula(if((Log!H1:H5="")*(Log!E1:E5<=3),Log!G1:G5,""))}, Log!D1:D5 = B1)
or
=filter({Log!C1:C5,Log!E1:E5, Log!H1:H5,if((Log!H1:H5="")*(Log!E1:E5<=3)=1,Log!G1:G5,"")},Log!D1:D5="d1")
The Result:
c1 5 h1
c2 3 g2
5
c3 3 h3

add iteratively in z3

I want to check the value of a, b, c, and if value 'a' equals to 1, 'x' is added one. We continue the process for values 'b' and 'c'.
So if a=1, b=1, c=1, the result of x should be 3.
if a=1, b=1, c=0, so the result of x should be 2.
Any methods to be implemented in z3?
The source code looks like this:
from z3 import *
a, b, c = Ints('a b c')
x, y = Ints('x y')
s = Solver()
s.add(If(a==1, x=x + 1, y = y-1))
s.add(If(b==1, x=x + 1, y = y-1))
s.add(If(c==1, x=x + 1, y = y-1))
s.check()
print s.model()
Any suggestions about what I can do?
This sort of "iterative" processing is usually modeled by unrolling the assignments and creating what's known as SSA form. (Static single assignment.) In this format, every variable is assigned precisely once, but can be used many times. This is usually done by some underlying tool as it is rather tedious, but you can do it by hand as well. Applied to your problem, it'd look something like:
from z3 import *
s = Solver()
a, b, c = Ints('a b c')
x0, x1, x2, x3 = Ints('x0 x1 x2 x3')
s.add(x0 == 0)
s.add(x1 == If(a == 1, x0+1, x0))
s.add(x2 == If(b == 1, x1+1, x1))
s.add(x3 == If(c == 1, x2+1, x2))
# Following asserts are not part of your problem, but
# they make the output interesting
s.add(b == 1)
s.add(c == 0)
# Find the model
if s.check() == sat:
m = s.model()
print("a=%d, b=%d, c=%d, x=%d" % (m[a].as_long(), m[b].as_long(), m[c].as_long(), m[x3].as_long()))
else:
print "no solution"
SSA transformation is applied to the variable x, creating as many instances as necessary to model the assignments. When run, this program produces:
a=0, b=1, c=0, x=1
Hope that helps!
Note that z3 has many functions. One you could use here is Sum() for the sum of a list. Inside the list you can put simple variables, but also expression. Here an example for both a simple and a more complex sum:
from z3 import *
a, b, c = Ints('a b c')
x, y = Ints('x y')
s = Solver()
s.add(a==1, b==0, c==1)
s.add(x==Sum([a,b,c]))
s.add(y==Sum([If(a==1,-1,0),If(b==1,-1,0),If(c==1,-1,0)]))
if s.check() == sat:
print ("solution:", s.model())
else:
print ("no solution possible")
Result:
solution: [y = 2, x = 2, c = 1, b = 0, a = 1]
If your problem is more complex, using BitVecs instead of Ints can make it run a little faster.
edit: Instead of Sum() you could also simply use addition as in
s.add(x==a+b+c)
s.add(y==If(a==1,-1,0)+If(b==1,-1,0)+If(c==1,-1,0))
Sum() makes sense towards readability when you have a longer list of variables, or when the variables already are in a list.

Split huge F# file with mutually recursive functions

In F# I have a very long code file like
let rec f1 a1 a2 a3 a4 a5 .. aN =
...
and f2 a1 a2 a3 a4 a5 ... aN =
...
and f3 a1 a2 a3 a4 a5 ... aN =
...
and f40 a1 a2 a3 a4 a5 ... aN =
...
In other words there are many mutually recursive functions, each with a lot of parameters.
Now the problem is that the file is 17000 lines long, and Visual Studio has become too slow. (For example, I can't hover the mouse over an item to see its type; if I press the dot, there is no completion, and so on)
Therefore I need to split the file into many smaller files. But I can't see a mechanical and easy way to do it.
Could you please give me an advice? I would like a mechanical way to split the code into multiple files, which does not involve writing the type of all functions (preserve type inference).
In the meantime I found a solution (tested):
This is the initial situation (simplified to only have four functions, but in reality they are many more):
let rec f1 a b c =
f2 a b c;
f3 a b c;
f4 a b c;
and f2 a b c =
f1 a b c;
f3 a b c
f4 a b c
and f3 a b c =
f1 a b c;
f2 a b c
f4 a b c
and f4 a b c =
f1 a b c;
f2 a b c
f3 a b c
And here is the solution:
Suppose you decide to move f3 to another file. Then you can split the file above in two files as follows:
FILE 1
======
let callRef mf =
match !mf with
| None -> failwith "function ref is none"
| Some f -> f
let r_f3 = ref None;
let rec f1 a1 a2 a3 =
f2 a b c;
callRef r_f3 a1 b1 c1;
f4 a1 b1 c1;
and f2 a1 a2 a3 =
f1 a b c;
callRef r_f3 a1 b1 c1;
f4 a1 b1 c1;
and f4 a1 a2 a3 =
f1 a b c;
f2 a1 b1 c1;
callRef r_f3 a1 b1 c1;
FILE 2
======
let f3 a1 a2 a3 =
f1 a b c;
f2 a1 b1 c1;
f4 an bn cn;
Then, in the main initialization function (which is in a third file), you need to do
r_f3 := Some f3;
And that's it.
Repeat the same strategy to move f1, f2 and f4 out of the first file.
Update: This solution works well for functions which return unit, but unfortunately for functions which return an actual type it forces you to specify the function type explicitely, e.g.
let (r_f3 : (t1 -> t2 -> t3 -> t4 -> t5) option ref) = ref None;
or you can do this:
let (r_f3 : 'a option ref) = ref None;
but you'll get a compiler warning.

Function return bad value based on parameter (Z3, Python)

I am emulating an array with simple function (Tab) and it doesn't work as expected. If I code it in SMT2, it works well, but in Z3py it doesn't work.
from z3 import *
A = BitVec('A', 8)
B1 = BitVec('B1', 8)
B2 = BitVec('B2', 8)
B3 = BitVec('B3', 8)
B4 = BitVec('B4', 8)
# Emulate Array
def Tab(N):
if N == 0x01: return B1
if N == 0x02: return B2
if N == 0x03: return B3
if N == 0x04: return B4
s = Solver()
s.add(A == 0x01)
s.add(Tab(A + 0x02) == 0x09 )
s.check()
m = s.model()
print (m)
print("Pos:", m.eval(A + 0x02))
print("Tab(3a):", m.eval(Tab(A + 0x02)))
print("Tab(3):", m.eval(Tab(0x03)))
print("B1: ", m[B1])
print("B2: ", m[B2])
print("B3: ", m[B3])
print("B4: ", m[B4])
print("B3n:", m.eval(B3))
Output:
[B1 = 9, A = 1] <- Model
Pos: 3 <- this is OK
Tab(3a): 9 <- this is OK (based on our condition)
Tab(3): B3 <- why does this return name B3? (should return None or 9)
B1: 9 <- this is BAD, here should be None
B2: None
B3: None <- this is BAD, here should be 9
B4: None
B3n: B3 <- why does this return name B3?! (should return None or 9)
From the output we see that Tab always returns B1 for parameter 0x03 instead of B3. It looks like A + 0x02 is calculated as 0x01 where it's used as a parameter. Am I doing something wrong, or is it some Z3py implementation error? Or does this have to do with how BitVec terms work?
This looks like the same problem as in this post: How to correctly use Solver() command in Python API of Z3 with declared function.
The problem is that if N == 0x01: ... does not create a Z3 if-then-else expression; it literally check whether N is a Python-int with concrete value 1. To get the desired expression you need to use Z3's If(...) function.

Array.map2 type inference on records

I ran into something with Array.map2 that I don't understand.
Consider this code:
type r1 = {
v1 : int
X : int
}
type r2 = {
v1 : int
Y : int
}
let a1 = [|{v1=1; X=1}; {v1=2; X=2}|] // val a1 : r1 [] ...
let a2 = [|{v1=100; Y=100}; {v1=200; Y=200}|] // val a2 : r2 [] ...
Array.map2 (fun x1 x2 -> (x1.X, x2.Y)) a1 a2 // works as expected
Array.map2 (fun x1 x2 -> (x1.v1, x2.v1)) a1 a2 // error FS0001: Type mismatch. Expecting a r2 [] but given a r1 []
Both records have a field v1. In the last line, I try to get a tuple of the values of v1, but from the different record types r1 and r2. It seems to throw an error when I try to select fields that have the same name on different records.
Somehow it jumps to the conclusion that x1 must be of type r2, why doesn't the second line infer the type from the two parameters a1 and a2?
edit
This fixes it but I would expect to get the type right from the parameters.
Array.map2 (fun (x1:r1) x2 -> (x1.v1, x2.v1)) a1 a2 // works
The type checker works from left to right, so there isn't enough information to resolve conflicts in the second example. Your first example is fine because .X and .Y are unique fields on r1 and r2 respectively.
That said, in this case you could use piping to make types of a1 and a2 available to the type checker prior accessing record fields:
(a1, a2) ||> Array.map2 (fun x1 x2 -> (x1.v1, x2.v1))
In general, you should use record patterns which contain unique fields to identify correct types:
Array.map2 (fun {v1 = a; X = _} {v1 = b; Y = _} -> (a, b)) a1 a2
or provide fully qualified field names:
Array.map2 (fun {r1.v1 = a} {r2.v1 = b} -> (a, b)) a1 a2

Resources