I have some code, which I want to check with help of some tactics. Since I have lot of if-then-else statements, I want to apply elim-term-ite tactic.
I have made use of following tactics
(check-sat-using (then (! simplify :arith-lhs true) elim-term-ite solve-eqs lia2pb pb2bv bit-blast sat))
However, if I an error with this as - "goal is in a fragment unsupported by lia2pb"
So then, if I try to remove the tactics lia2pb and the ones next to them, I get another error as unknown "incomplete".
I tried to remove all the tactics except for the simplify, however I would still get an incomplete error.
What is that I should try to help the sat solver solve the problem?
Should I try another tactics?
To use lia2pb (aka linear integer arithmetic to pseudo-boolean), all integer variables must be bounded. That is, they must have a lower and upper bound.
The tactic sat is only complete if the input goal does not contain theory atoms. That is, the goal contains only Boolean connectives and Boolean constants. If that is not the case, then it will return "unknown" if it cannot show the (Boolean abstraction of the input) goal to be unsatisfiable.
You can ask Z3 to display the input goal for lia2pb by using the following command:
(apply (then (! simplify :arith-lhs true) elim-term-ite solve-eqs)
If some of your formulas contain unbounded integer variables, you can build a strategy that reduces to SAT when possible, and invokes a general purpose solver otherwise. This can be accomplished using the or-else combinator. Here is an example:
(check-sat-using (then (! simplify :arith-lhs true) elim-term-ite solve-eqs
(or-else (then lia2pb pb2bv bit-blast sat)
smt)))
EDIT: The tactic lia2pb also assumes that the lower bound of every bounded integer variable is zero. This is not a big problem in practice, since we can use the tactic normalize-bounds before applying lia2pb. The tactic normalize-bounds will replace a bound variable x with y + l_x, where y is a fresh variable and l_x is the lower bound for x. For example, in a goal containing 3 <= x, x is replaced with y+3, where y is a new fresh variable.
Related
Algorithm:
if BitVecA > 0
BitVecB = Concat(BitVecA, BitVecB)
I want to Concat two conditional bitvec and with no else condition by using If
I want to using
BitVecB = Contact(BitVecA, If(BitVecA>0, BitVecA, EmptyBitVec )),
but len of BitVec cannot be zero
It isn't clear what your question is. But if you look at https://smtlib.cs.uiowa.edu/theories-FixedSizeBitVectors.shtml you'll see that SMTLib only allows bit-vectors that have strictly positive lengths. (i.e., zero-length bitvectors are not part of the logic.)
So, if you need to reason with 0-length bit vectors, you'll have to write your code to handle it outside of the SMTLib fragment; i.e., in your wrapper code. But without knowing what your context is, hard to answer in any further detail.
I have an expression that consists of functions of x and y, something like
ay+yf(x)+g(x)+bh(x)+k(y).
Is there a convenient method that removes all x-dependent terms and leaves ay+k(y)?
f,g,h,k are symbolic and not known functions.
As far as I know, dependence in maxima [defined with depends()] is only recognized in diff. I tried diff and then integrate/antidiff, but antidiff/integrate does not recognize y and b as constant, and gives an expression with integrals.
I am trying to get the habit to use Dafny as a friendly SAT-QBF solver for some simple formulae, since doing it in, for instance, Z3 is too uncomfortable.
The context for this is that I have implemented Cooper's algorithm for quantifier elimination and, when all the variables are bounded, it can be used as a decision procedure: therefore, I want to know which is the result that I should get before executing it.
However, I encountered a problem in Dafny.
Let us raise, for instance, this formula (written in Dafny):
assert forall x_1: int :: exists y_1: int :: forall x_2: int :: exists y_2 : int
:: (y_2<y_1) && (x_2<y_2) && (x_1<x_2);
In my Cooper, it returns False, while Dafny returns assertion violation (along with the typical triggerswarnings), which I interpret as False too. Okay, so no problem with this.
But if I raise:
assert exists x_1: int :: exists y_1: int :: exists x_2: int :: exists y_2 : int
:: (y_2<y_1) && (x_2<y_2) && (x_1<x_2);
In my Cooper, it returns True, while Dafny also returns assertion violation. I have done a manual Cooper execution (pencil and paper) and I think the True is right one.
Any idea of what is going on?
PS: I have not tried it in Z3, yet, because I am doing first other attempts with other theories.
EDIT
Trigger warnings can be avoided using a simple trick to instantiate the quantified variables: creating an uninterpreted function.
method Main() {
assert exists x_1 : int {:trigger P(x_1)} :: exists y_1: int {:trigger P(y_1)}
:: exists x_2: int {:trigger P(x_2)} :: exists y_2 : int {:trigger P(y_2)}
:: (y_2<y_1) && (x_2<y_2) && (x_1<x_2);
}
predicate P(a: int)
{
true
}
You cannot do this with Dafny. While Dafny supports quantifiers, booleans, arithmetic, and many other things (recursive functions, sets, sequences, objects and references, multi-dimensional arrays, induction, inductive and coinductive datatypes, bitvectors, greatest and least fixpoints of monotonic functions, etc.), it is not suitable for SAT-QBF (or QBF + artihmetic) benchmarks.
Dafny's errors, including the assertion violation, tell you that the verifier was not able to do the proof. It may be that the property still holds, but you'll need to supply more of the proof yourself. In other words, you should interpret the assertion violation as a "don't know" answer. Stated differently, you cannot decide (only semi-decide) formulas with Dafny.
Dafny uses quantifiers in the SMT solvers via matching patterns, aka triggers. When a quantifier has no good triggers, which is what Dafny's "no trigger" warning is telling you, you may see bad performance, unstable verifications, and so-called butterfly effects (where a small and seemingly unrelated part of the program causes a change in the automatic construction of other proofs). Triggers are driven by uninterpreted function symbols, which your example doesn't have at all.
If you want a readable syntax, you may be able to do what you're trying through Boogie. I have not tried that, but you could try putting Boogie in its monomorphic mode and then supplying prover options to ask for the SAT-QBF or something similar (see Boogie's /help). Otherwise, if you're interested in deciding these problems, then going directly to SMT solver is the way to go.
I have tried to implement Floor and Ceiling Function as defined in the following link
https://math.stackexchange.com/questions/3619044/floor-or-ceiling-function-encoding-in-first-order-logic/3619320#3619320
But Z3 query returning counterexample.
Floor Function
_X=Real('_X')
_Y=Int('_Y')
_W=Int('_W')
_n=Int('_n')
_Floor=Function('_Floor',RealSort(),IntSort())
..
_s.add(_X>=0)
_s.add(_Y>=0)
_s.add(Implies(_Floor(_X)==_Y,And(Or(_Y==_X,_Y<_X),ForAll(_W,Implies(And(_W>=0,_W<_X),And(_W ==_Y,_W<_Y))))))
_s.add(Implies(And(Or(_Y==_X,_Y<_X),ForAll(_W,Implies(And(_W>=0,_W<_X),And(_W==_Y,_W<_Y))),_Floor(_X)==_Y))
_s.add(Not(_Floor(0.5)==0))
Expected Result - Unsat
Actual Result - Sat
Ceiling Function
_X=Real('_X')
_Y=Int('_Y')
_W=Int('_W')
_Ceiling=Function('_Ceiling',RealSort(),IntSort())
..
..
_s.add(_X>=0)
_s.add(_Y>=0)
_s.add(Implies(_Ceiling(_X)==_Y,And(Or(_Y==_X,_Y<_X),ForAll(_W,Implies(And(_W>=0,_W<_X),And(_W ==_Y,_Y<_W))))))
_s.add(Implies(And(Or(_Y==_X,_Y<_X),ForAll(_W,Implies(And(_W>=0,_W<_X),And(_W==_Y,_Y<_W)))),_Ceiling(_X)==_Y))
_s.add(Not(_Ceilng(0.5)==1))
Expected Result - Unsat
Actual Result - Sat
[Your encoding doesn't load to z3, it gives a syntax error even after eliminating the '..', as your call to Implies needs an extra argument. But I'll ignore all that.]
The short answer is, you can't really do this sort of thing in an SMT-Solver. If you could, then you can solve arbitrary Diophantine equations. Simply cast it in terms of Reals, solve it (there is a decision procedure for Reals), and then add the extra constraint that the result is an integer by saying Floor(solution) = solution. So, by this argument, you can see that modeling such functions will be beyond the capabilities of an SMT solver.
See this answer for details: Get fractional part of real in QF_UFNRA
Having said that, this does not mean you cannot code this up in Z3. It just means that it will be more or less useless. Here's how I would go about it:
from z3 import *
s = Solver()
Floor = Function('Floor',RealSort(),IntSort())
r = Real('R')
f = Int('f')
s.add(ForAll([r, f], Implies(And(f <= r, r < f+1), Floor(r) == f)))
Now, if I do this:
s.add(Not(Floor(0.5) == 0))
print(s.check())
you'll get unsat, which is correct. If you do this instead:
s.add(Not(Floor(0.5) == 1))
print(s.check())
you'll see that z3 simply loops forever. To make this usefull, you'd want the following to work as well:
test = Real('test')
s.add(test == 2.4)
result = Int('result')
s.add(Floor(test) == result)
print(s.check())
but again, you'll see that z3 simply loops forever.
So, bottom line: Yes, you can model such constructs, and z3 will correctly answer the simplest of queries. But with anything interesting, it'll simply loop forever. (Essentially whenever you'd expect sat and most of the unsat scenarios unless they can be constant-folded away, I'd expect z3 to simply loop.) And there's a very good reason for that, as I mentioned: Such theories are just not decidable and fall well out of the range of what an SMT solver can do.
If you are interested in modeling such functions, your best bet is to use a more traditional theorem prover, like Isabelle, Coq, ACL2, HOL, HOL-Light, amongst others. They are much more suited for working on these sorts of problems. And also, give a read to Get fractional part of real in QF_UFNRA as it goes into some of the other details of how you can go about modeling such functions using non-linear real arithmetic.
I was looking for a way to set a comparison as a precondition to an action in PDDL. Is there a way to say for example:
(:functions (goal))
(:action CheckLoser
:parameters (?team)
:precondition
(> goals 5)
:effect
(loses ?team)
)
Fast Downward doesn't support using an arithmetic comparison as an action precondition, but the planner Metric-FF does. The latter can be downloaded from here, and it is easy to install:
ensure flex and bison are installed on your system; On Ubuntu just use:
sudo apt-get install bison flex
run make in the source directory
Metric-FF can be executed as follows :
./ff -o path/to/domain.pddl -f path/to/problem.pddl
To solve the problem in the question, I used a variable cost to track the time and allowed an action to occur after a certain amount of time has passed.
My code sample is as follows:
Define a :predicate in the domain file, e.g. (cost ?cost)
Define a :function in the domain file, e.g. (:functions (total-cost ?cost))
Add (cost) in the :objects part of the problem file
In the :init part of the problem file, set the "time" to start as "x", e.g. (= (total-cost ?cost) 0) where "time" is cost and "x" is equal to 0.
Now it is possible to use the arithmetic comparison in any action precondition; e.g. (> (total-cost ?cost) x), where x can be set to any value (including floating point numbers); Note that in this case ?cost must be included in the :parameters section of the said action
Finally, the value of total-cost can be increased (resp. decreased) after every action execution with (increase (total-cost ?cost) x) (resp. (decrease (total-cost ?cost) x)), where x can again be replace with any value.
In PDDL you cannot compare directly, Instead you can define some boolean function with parameters. Specification of such function in precondition means that the function holds true.
eg:
(operation
makebigger
(params
(<a> Object) (<b> Object))
(preconds
(greater <a> <b>))
effects
(greater <b> <a>)))
Something like greater function(written in preorder). Such boolean function that states a precondition will be used in your planning.