how to suppress simplification of formulas to True or False? - z3

is it possible to disable automatic simplifications of boolean expressions in Z3?
For example, the expression 2 > 1 becomes True automatically while I would like it to stay 2 > 1:
>>> t = 2 > 1
>>> t
True
I found several options by calling help_simplify() in Z3Py. However, none of them seems to relate to my problem.
In another tutorial (http://citeseerx.ist.psu.edu/viewdoc/download?rep=rep1&type=pdf&doi=10.1.1.225.8231) an option "CONTEXT SIMPLIFIER" was mentioned: "This setting can be used to simplify sub-formulas to true or false." However, I could not find this option in Z3Py.
Background: I would like to be able to use expressions like And(2>1, 1!=2) where 2>1 and 1!=2 are automatically generated earlier and sometimes contain no variables (constants). Z3Py simplifies this to And(True, False) which is not accepted, because "At least one of the arguments must be a Z3 expression or probe". Therefore, I would like to suppress the simplification. Or is there a way to make And(True, False) an accepted expression?
Thanks in advance!

Indeed, this is because simple expressions like 2>1 are simplified to True/False by Python. Most operators (like Implies, Xor, ...) were fine with this, but the And and Or operators were not. They had a different implementation because they can be used for probes as well as expressions. I have now added a little bit more code to make them behave like the other Boolean operators (for fix see here). I hope this fixes this problem while not introducing any new problems with probes. I'd be grateful if other could test this some more.

Related

What is pb.conflict in Z3?

I am trying to find an optimal solution using the Z3 API for python. I have used set_option("verbose", 1) to print statements that Z3 generates while checking for sat. One of the statements it prints is pb.conflict statements. The statements look something like this -
pb.conflict statements.
I want to know what exactly is pb.conflict. What do these statements signify? Also, what are the two numbers that get printed along with it?
pb stands for Pseudo-boolean. A pseudo-boolean function is a function from booleans to some other domain, usually Real. A conflict happens when the choice of a variable leads to an unsatisfiable clause set, at which point the solver has to backtrack. Keeping the backtracking to a minimum is essential for efficiency, and many of the SAT engines carefully track that number. While the details are entirely solver specific (i.e., those two numbers you're asking about), in general the higher the numbers, the more conflict cases the solver met, and hence might decide to reset the state completely or take some other action. Often, there are parameters that users can set to specify when such actions are taken and exactly what those are. But again, this is entirely solver and implementation specific.
A google search on pseudo-boolean optimization will result in a bunch of scholarly articles that you might want to peruse.
If you really want to find Z3's treatment of pseudo-booleans, then your best bet is probably to look at the implementation itself: https://github.com/Z3Prover/z3/blob/master/src/smt/theory_pb.cpp

DLV Rule is not safe

I am starting to work with DLV (Disjunctive Datalog) and I have a rule that is reporting a "Rule is not safe" error, when running the code. The rule is the following:
foo(R, 1) :- not foo(R, _)
I have read the manual and seen that "cyclic dependencies are disallowed". I guess this is why I am being reported the error, but I am not sure how this statement is so problematic to DLV. The final goal is to have some kind of initialization in case that the predicate has not been defined.
More precisely, if there is no occurrence of 'foo' with the parameter R (and anything else), then define it with parameters R and 1. Once it is defined, the rule shouldn't be triggered again. So, this is not a real recursion in my opinion.
Any comments on how to solve this issue are welcomed!
I have realised that I probably need another predicate to match the parameter R in the body of the rule. Something like this:
foo(R, 1) :- not foo(R, _), bar(R)
Since, otherwise there would be no way to know whether there are no occurrences of foo(R, _). I don't know whether I made myself clear.
Anyway, this doesn't work either :(
To the particular "Rule is not safe" error: First of all this has nothing to do with cyclic or acyclic dependencies. The same error message shows up for the non-cyclic program:
foo2(R, 1) :- not foo(R,_), bar(R).
The problem is that the program is actually not safe (http://www.dlvsystem.com/html/DLV_User_Manual.html#SAFETY). As mentioned in the section on negative rules (anchor #AEN375, I am only allowed to use 2 links in my answer):
Variables, which occur in a negated literal, must also occur in a
positive literal in the body.
Observe that the _ is an anonymous variable. I.e., the program
foo(R,1) :- not foo(R,_), bar(R).
can be equivalently written as (and is equivalent to)
foo(R,1) :- not foo(R,X), bar(R).
Anonymous variables (DLV manual, anchor #AEN264 - at the end of the section) just allow us to avoid inventing names for variables that will only occur once within the rule (i.e. for variables that only express "there is some value, I absolutely do not care about it), but they are variables nevertheless. And since negation with not is "negation" and not "true negation" (or "strong negation" as it is also often called), none of the three safety conditions is satisfied by the rule.
A very rough and high-level intuition for safety is that it guarantees that every variable in the program can be assigned to some finite domain - as it is now the case with R by adding bar(R). However, the same also must be the case for the anonymous variable _ .
To the actual problem of defining default values:
As pointed out by lambda.xy.x, the problem here is the Answer Set (or stable model) semantics of DLV: Trying to do it in one rule does not give any solution:
In order to get a safe program, we could replace the above problems e.g. by
foo(1,2). bar(1). bar(2).
tmp(R) :- foo(R,_).
foo(R,1) :- not tmp(R), bar(R).
This has no stable model:
Assume the answer is, as intended,
{foo(1,2), bar(1), bar(2), foo(2,1)}
However, this is not a valid model, since tmp(R) :- foo(R,_) would require it to contain tmp(2). But then, "not tmp(2)" is no longer true, and therefore having foo(2,1) in the model violates the required minimality of the model. (This is not exactly what is going on, more a rough intuition. More technical details could be found in any article on answer set programming, a quick Google search gave me this paper as one of the first results: http://www.kr.tuwien.ac.at/staff/tkren/pub/2009/rw2009-asp.pdf)
In order to solve the problem, it is therefore somehow necessary to "break the cycle". One possibility would be:
foo(1,2). bar(1). bar(2). bar(3).
tmp(R) :- foo(R,X), X!=1.
foo(R,1) :- bar(R), not tmp(R).
I.e., by explicitly stating that we want to add R into the intermediate atom only if the value is different from 1, having foo(2,1) in the model does not contradict tmp(2) not being part of the model as well. Of course, this no longer allows to distinguish whether foo(R,1) is there as default value or by input, but if this is not required ...
Another possibility would be to not use foo for the computation, but some foo1 instead. I.e. having
foo1(R,X) :- foo(R,X).
tmp(R) :- foo(R,_).
foo1(R,1) :- bar(R), not tmp(R).
and then just use foo1 instead of foo.

use of define-fun in z3's input language

Going by this post, define-fun seems to be a macro that gets expanded by z3's preprocessor and not seen by the actual solver but makes the input file possibly compact and easier to read. I'm asking because I see some (apparently random) differences in the satisfying assignments and performance on the same problem: one which uses define-funand one which doesn't, which makes me wonder if it is more than just a macro. Does one have to be careful about the aggressive use of define-fun in certain cases? I observed this on some QF_NIRA, QF_LIRA problems that I have.
define-fun is treated as a macro in Z3.
The behavior of Z3 will be different if you use equalities and uninterpreted functions.
Furthermore, if you use "declare-fun" and then create quantified equalities,
the problem is no longer in the QF_LIRA fragment.

Z3 4.0: get complete model

I need a complete model of an SMTLIB2 formula:
http://pastebin.com/KiwFJTrK
Z3 (version 3.2 and 4.0) returns values for all variables but not for var4. I tried some configuration settings like
MODEL_COMPLETION = true
but it did not seem to work. Does anybody have a suggestion? CVC3 in comparison returns a model (including var4), so it is not an issue of SMTLIB or my example.
The reason I need this is explained here in detail. In short: I want to use the C API for incremental solving. For this reason I have to use the function Z3_parse_smtlib2_string multiple times. This function needs previously declared functions and constants as parameters. I am unable to get this information via Z3_get_smtlib_decl because these kind of functions work just when z3_parse_smtlib_string is called, not Z3_parse_smtlib2_string.
You can avoid this problem by adding the following option in the beginning of your script.
(set-option :auto-config false)
I will fix it for the next release.
Here is a short explanation of what is going on.
Z3 has a solver for 0-1 integer problems. After preprocessing, your script is tagged as a 0-1 integer problem by Z3. The value of var4 is a "don't care" when the problem is viewed as a 0-1 problem, but it is not a "don't care" when the problem is viewed as an integer problem (var4 must be 0 or 1). By default, Z3 will not display the value of "don't care" variables.
The MODEL_COMPLETION=true will complete the model as you request values for constants that are not included in the model. For example, if we execute (eval var4), Z3 will produce an interepretation for var4.

The "pull-nested-quantifiers" option seems to cause problems in the context for UFBV?

I am currently experimenting with Z3 as bounded engine for specifications written in Alloy (a relational logic/language). I am using the UFBV as target language.
I detect a problem using the Z3 option (set-option :pull-nested-quantifiers true).
For two semantically identical SMT specifications Spec1 and Spec2, Z3 times out (200 sec) for proving Spec1 but proves Spec2.
The only different between Spec1 and Spec2 is that they have different function identifiers (because I use java hash names). Can this be related to a bug?
The second observation I would like to share and discuss, is the "iff" operator in the context of UFBV. This operator is not supported, if (set-logic UFBV) is set. My solution was to use "=" instead but this do not work well if the operands contains deeply nested quantifiers and the "pull-nested-quantifiers" is set. The other saver solution is to use double implication.
Now the question:
Is there any other better solution for model "iff" in UFBV, because I think, that using double implication will in general loose maybe useable semantic information for improvement/simplifications.
http://i12www.ira.uka.de/~elghazi/tmp/
you can find: spec1 and spec2 the tow (I think) semantically identical SMT specifications, and spec3 an SMT specification using "=" to model "iff", for which z3 times out.
The default strategy for the UFBV logic is not effective for your problems. Actually, the default strategy solves all of them in less than 1 sec. To force Z3 to use the default strategy, you just need to comment the following lines in your script.
; (set-logic UFBV)
; (set-option :pull-nested-quantifiers true)
; (set-option :macro-finder true)
If the warning messages are bothering you, you can add:
(set-option :print-warning false)
That being said, I will try to address the issues you raised.
Does identifier names affect the behavior of Z3? Yes, they do.
Starting at version 3.0, we started using a total order on Z3 expressions for performing operations such as: sorting the arguments of associative-commutative operators.
This total order is based on the identifier names.
Ironically, this modification was motivated by user feedback. In previous versions, we used an internal ID for performing operations such as sorting, and breaking ties in many different heuristics. However, these IDs are based on the order Z3 creates/deletes expressions, which is based on the order users declare symbols. So, Z3 2.x behavior would be affected by trivial modifications such as removing unused declarations.
Regarding iff, it is not part of SMT-LIB 2.0 standard. In SMT-LIB 2.0, = is used for formulas and terms. To make sure Z3 is fully compliant with the SMT-LIB 2.0 standard, whenever users specify a SMT-LIB supported logic (or soon to be supported such as UFBV), Z3 only "loads" the symbols defined in it. When, a logic is not specified, Z3 assumes the user is using the "Z3 logic" that contains all supported theories in Z3, and many extra aliases such as: iff for Boolean =, if for ite, etc.

Resources