I'd like to create an uninterpreted datatype in Z3 lets call it "A". According to z3 documentations, I can declare it by using "DeclareSort" as follows:
A = DeclareSort('A')
a, b = Consts('a b', A)
s = Solver()
s.add(a != b)
s.check()
However I've seen some people using the following:
A = Datatype('Event')
A.declare('A0')
A = A.create()
a, b = Consts('a b', A)
My question is that what is the difference between those two and which one is correct to declare new uninterpreted datatype. Also I could not understand what does A.declare('A0') means in the second part.
The Event datatype contains just one element called A0, so you should use the first suggestion to use DeclareSort.
Related
I've been trying to enumerate solutions to the following problem. I've started with simple approach first.
Below I have two sets of size k, intersection between them is of size 1 and I want to see how sets A and B look:
Els, elems = EnumSort('Els',['a1', 'a2', 'a3'])
A, B = Consts('A B', SetSort(Els))
k, c = Ints('k c')
s = Solver()
s.add(SetHasSize(A, k))
s.add(SetHasSize(B, k))
s.add(k == 2, c == 1)
s.add(SetHasSize(SetIntersect(A, B), c))
s.check()
s.model()
Here, the solution should be A == ['a1', 'a2'] and B == ['a2', 'a3'] but satisfiability was not reached.
Even a simple task like one below results in never ending execution:
V, _ = EnumSort('Els',['a1', 'a2', 'a3'])
A = Const('A', SetSort(V))
k = Int('k')
s = SimpleSolver()
s.add(SetHasSize(A, k))
s.add(k == IntVal(2))
s.check()
s.model()
Changing k == IntVal(2) to k <= IntVal(2) makes the problem satisfiable and returns [A = ∃k!0 : k!0 = a1 ∨ k!0 = a2, k = 2] as a model of the set. I'm not sure if there is a faster approach.
If I run your program, I get:
WARNING: correct handling of finite domains is TBD
WARNING: correct handling of finite domains is TBD
WARNING: correct handling of finite domains is TBD
before it starts looping. This is a known issue in the implementation: Z3 cannot really deal with sets that have a finite domain.
Alas, replacing it with an infinite domain doesn't help either. Making this change:
A, B = Consts('A B', SetSort(IntSort()))
You get:
unsat
which is clearly bogus. I strongly suspect this is related to the following issue: https://github.com/Z3Prover/z3/issues/3854 (In short, the SMTLib frontend does not support set-has-size. For whatever reason, they left it in the Python and C/C++ interfaces, but clearly it's not really functional.)
So, strictly speaking, this is a bug. But more realistic answer is that set-has-size is no longer supported by z3. You should file an issue at https://github.com/Z3Prover/z3/issues so the authors are aware of this problem and perhaps remove it from the API completely if it won't ever be supported.
UPDATE:
As of this commit, z3 no longer accepts the set-has-size predicate; it is no longer supported.
Context: I'm using the Programming Z3 guide:
https://theory.stanford.edu/~nikolaj/programmingz3.html
It looks like Z3 now has built-in support for transitive-closure, but for the moment it's only accessible via Z3py:
https://theory.stanford.edu/~nikolaj/programmingz3.html#sec-transitive-closure
I have two questions:
(1) Is there any means of accessing TransitiveClosure via other APIs or the executable directly via "z3 -in", or is it just for Z3py at the moment?
(2) Is TransitiveClosure supposed to interoperate with push and pop? We built from the master branch earlier this week (commit 2788f72bbb6bfd6bdad2da2b4c37ef1bb502469d) and ran the following example:
from z3 import *
B = BoolSort()
S = DeclareSort('S')
a, b, c = Consts('a b c', S)
R = Function('R', S, S, B)
TCR = TransitiveClosure(R)
s = Solver()
s.add(R(a, b) == True)
s.push() # If this line is uncommented (or both are) the result is sat, which is wrong.
s.add(TCR(a, b) == False)
s.push() # But if THIS line is uncommented (or neither are), the result is unsat, which is correct.
print(s)
print(s.check())
As the comments indicate, a push() call between assertions about R and its transitive closure seem to break the link between the two relations. Not sure if this is a bug, or my own misunderstanding...
From the looks of it, it's also available via the C/C++ api as well:
https://github.com/Z3Prover/z3/blob/62de187d02d8d2e7a3667a31753c508f7c73aaa1/src/api/c%2B%2B/z3%2B%2B.h#L637-L639
I don't think it's available from the SMTLib interface (what you meant by z3 -in I presume), as it's itself returning a relation; and such higher-order constructs are usually not allowed in SMTLib. (But there might be a "magic" switch, of course; z3 is known to experiment with functionality that's not part of SMTLib.)
Regarding whether it should work with push/pop: I don't think the fixed-point engine in z3 allows for incremental solving; so I'm not surprised that it's behaving erratically. You should definitely report this behaviour at their issues site (https://github.com/Z3Prover/z3/issues) so they can at least issue an error message if you try to do incremental stuff, instead of spitting out misleading info. (Or maybe you hit a bug! So, that'd also be good for them to know.)
s.pop(),s.push() is not necessary.
# https://theory.stanford.edu/~nikolaj/programmingz3.html#sec-transitive-closure
from z3 import *
B = BoolSort()
S = DeclareSort('S')
R = Function('R', S, S, B)
TCR = TransitiveClosure(R)
a, b, c = Consts('a b c', S)
s = Solver()
s.add(R(a, b))
s.add(R(b, c))
s.add(Not(TCR(a, c))) # s.add(Not(R(a, c))) will be “sat”,because TCR is transitiveclosure but R is not.
print(s)
print(s.check()) # unsat
I have a Boolean formula (format: CNF) whose satisfiablity I check using the Z3 SAT solver. I am interested in obtaining partial assignments when the formula is satisfiable. I tried model.partial=true on a simple formula for an OR gate and did not get any partial assignment.
Can you suggest how this can be done? I have no constraints on the assignment other than that it be partial.
Z3's partial model mode are just for models of functions. For propositional formulas there is no assurance that models use a minimal number of assignments. On the contrary, the default mode of SAT solvers is that they find complete assignments.
Suppose you are interested in a minimized number of literals, such that the conjunction of the literals imply the formula. You can use unsat cores to get such subsets. The idea is that you first find a model of your formula F as a conjunction of literals l1, l2, ..., ln. Then given that this is a model of F we have that l1 & l2 & ... & ln & not F is unsatisfiable.
So the idea is to assert "not F" and check satisfiability of "not F" modulo assumptions l1, l2, .., ln. Since the result is unsat, you can query Z3 to retrieve an unsat core among l1, l2, .., ln.
From python what you would do is to create two solver objects:
s1 = Solver()
s2 = Solver()
Then you add F, respectively, Not(F):
s1.add(F)
s2.add(Not(F))
then you find a reduced model for F using both solvers:
is_Sat = s1.check()
if is_Sat != sat:
# do something else, return
m = s1.model()
literals = [sign(m, m[idx]()) for idx in range(len(m)) ]
is_sat = s2.check(literals)
if is_Sat != unsat:
# should not happen
core = s2.unsat_core()
print core
where
def sign(m, c):
val = m.eval(c)
if is_true(val):
return c
else if is_false(val):
return Not(c)
else:
# should not happen for propositional variables.
return BoolVal(True)
There are of course other ways to get reduced set of literals. A partial cheap way is to eagerly evaluate each clause and add literals from the model until each clause is satisfied by at least one literal in the model. In other words, you are looking for a minimal hitting set. You would have to implement this outside of Z3.
I'd like to define an unordered set of values using an Extended Backus-Naur Form (EBNF) context free grammar. It's easy to define an unordered list of values in EBNF, for example:
value = 'A' | 'B' | 'C';
list = value, {',', value};
However, I'm having doubts it can be done for an unordered set.
Below are examples of valid unordered sets of values:
A, B, C, D
A, B, D, C
A, D, C, B
...
D, C, B, A
Whilst invalid lists would be:
A, A, C, D
B, C, C, B
A, A, A, A
...
or lists of arbitrary length.
A, A, B, C, D, A
A, B, C, D, A, B, C, D
...
You can define unordered sets in EBNF, but only by listing all possible enumerations. That's impractical for sets larger than about two elements.
The standard -- to the extent that EBNF is a standardized notation -- allows you to use English (or any other language you feel comfortable with) to describe a sequence which is not otherwise describable. For example, the EBNF for EBNF includes this production:
syntactic exception
= ? a syntactic-factor that could be replaced
by a syntactic-factor containing no
meta-identifiers
? ;
Similarly, you could write something like:
value = 'A' | 'B' | 'C';
list = value, {',', value};
set = ? a "list" where all "value"s are unique ? ;
or perhaps
set = ? a "list" with exactly three values
where all "value"s are unique
? ;
That's not much use for building a parser generator, but it might be helpful for a human reader who understands the same language as you do.
For real parser generators, a common strategy is to allow any list, which might include repeated elements, and then reject invalid lists during semantic analysis. (Or even earlier. It's not a difficult analysis.)
I want to apply a function to both members of a homogenous tuple, resulting in another tuple. Following on from my previous question I defined an operator that seemed to make sense to me:
let (||>>) (a,b) f = f a, f b
However, again I feel like this might be a common use case but couldn't find it in the standard library. Does it exist?
I don't think there is any standard library function that does this.
My personal preference would be to avoid too many custom operators (they make code shorter, but they make it harder to read for people who have not seen the definition before). Applying function to both elements of a tuple is logically close to the map operation on lists (which applies a function to all elements of a list), so I would probably define Tuple2.map:
module Tuple2 =
let map f (a, b) = (f a, f b)
Then you can use the function quite nicely with pipelining:
let nums = (1, 2)
nums |> Tuple2.map (fun x -> x + 1)