I am trying to figure out how to code quantifiers in CVC4, using the C++ interface. Here is an example I am trying to get to run, but cannot.
int main() {
SmtEngine smt(&em);
smt.setLogic("AUFLIRA"); // Set the logic
Expr three = em.mkConst(Rational(3));
Expr four = em.mkConst(Rational(4));
// make the list of bound variables in CVC4
Expr bound_var = em.mkBoundVar("x_bound", em.integerType());
vector<Expr> bound_vars;
bound_vars.push_back(bound_var);
Expr bound_var_list = em.mkExpr(kind::BOUND_VAR_LIST, bound_vars);
Expr declare = em.mkExpr(kind::EQUAL, bound_var, three); //x_bound =3
Expr check = em.mkExpr(kind::EQUAL, bound_var, four); //x_bound=4
//forall x_bound, x_bound=3, the constraint I want to declare as true
Expr expr = em.mkExpr(kind::FORALL, bound_var_list, declare);
smt.assertFormula(expr);
smt.push();
// expect to be INVALID
// I want to check that given forall x_bound, x_bound = 3
// then I ask CVC4: is it true that x_bound=4, or is it false?
std::cout << "Quantifier " << smt.query(check) << std::endl;
return 0;
}
Instead, I just get an error message:
Bound variables test
Quantifier unknown (INCOMPLETE)
But I define the quantifier as forall. What did I do wrong?
EDIT (asked https://www.andrew.cmu.edu/user/liminjia/):
Syntax is wrong. We want to know if
(forall x, x=3) IMPLIES (forall x, x=4)
is true or not. But CVC4 does not if the above formula is valid or not, because SMT solvers are not full-fledged first-order logic theorem provers.
If you want to try something that works, try in CVC4 language:
QUERY (FORALL (x:INT): x =4);
And in C++, we have
// check that forall x, x=3 is INVALID
void cvc4BoundVar() {
std::cout << "Bound variables test" << std::endl;
SmtEngine smt(&em);
smt.setLogic("AUFLIRA"); // Set the logic
Expr three = em.mkConst(Rational(3));
Expr v_expr = em.mkBoundVar("x_bound", em.integerType());
vector<Expr> bound_vars;
bound_vars.push_back(v_expr);
Expr bound_var_list = em.mkExpr(kind::BOUND_VAR_LIST, bound_vars);
Expr declare = em.mkExpr(kind::EQUAL, v_expr, three); //x=3
Expr check = em.mkExpr(kind::EQUAL, v_expr, three);
Expr expr = em.mkExpr(kind::FORALL, bound_var_list, declare); //forall x, x=3
std::cout << "Quantifier " << smt.query(expr) << std::endl;
}
Related
For example, I got a constraint: "(number < 10) && (name == "hello")";
I can do the following now:
context c;
expr number= c.int_const(number);
expr name = c->string_val(name.c_str());
expr constrain = ***procedure***("(number < 10) && (name == \"hello\")");
How can I implement this procedure()?
there is an incomplete and unproofed answer in Use a C++ string in z3::expr?, and I still can not figure out how to implement it?
I am very eagered and appreciateed for your help! Thanks!
Try:
#include <z3++.h>
using namespace z3;
using namespace std;
int main ()
{
context c;
expr number = c.int_const("number");
expr name = c.constant(c.str_symbol("name"), c.string_sort());
expr hello = c.string_val("hello");
expr constraint = number < 10 && name == hello;
solver s(c);
s.add(constraint);
cout << s.check() << "\n";
cout << s.get_model() << "\n";
return 0;
};
Assuming you put the above in a file called a.cpp, you compile it like this:
$ g++ -std=c++11 a.cpp -l z3
And when run, it produces:
sat
(define-fun number () Int
9)
(define-fun name () String
"hello")
Using higher-level APIs
As you no doubt noticed, programming z3 in C/C++ is very verbose and terribly error prone. Unless you've some other reason to use C/C++, I'd recommend using a higher-level API, such as Python or Haskell, which simplifies programming in z3 to a great extent.
Python
For instance, you'd code your problem in Python like this:
from z3 import *
number = Int('number')
name = String('name')
s = Solver()
s.add(number < 10, name == "hello")
print(s.check())
print(s.model())
producing:
sat
[number = 9, name = "hello"]
Haskell
And in Haskell, it would look like:
import Data.SBV
ex :: IO SatResult
ex = sat $ do number <- sInteger "number"
name <- sString "name"
constrain $ number .< 10 .&& name .== literal "hello"
producing:
*Main> ex
Satisfiable. Model:
number = 9 :: Integer
name = "hello" :: String
Summary
Long story short, programming z3 in C/C++—while entirely possible—is something that's best avoided if you can use a higher-level interface. If you must stick to C/C++, be sure to study the API: https://z3prover.github.io/api/html/namespacez3.html
For example, I want to cast nat to seq of char in VDM++.
In the code below, I want operation setValueOfX to return "X is {value of q}", if q is of type nat and q < 3.
class A1
instance variables
private x : nat := 0;
operations
public setValueOfX : nat ==> seq of char
setValueOfX(q) ==
(
if is_nat(q) and q < 3
then
(
x := q;
-- The following line doesn't work
-- return "X is " ^ q;
)
else
return "Invalid value! Value of x must be more than 0 and less than 3.";
);
end A1
I've tried using ^ but I got the following error:
Error[207] : Rhs of '^' is not a sequence type
act : nat
exp : ( seq1 of # | [] )
No, you can't implicitly convert values like that in VDM.
If you just want to see the result in a textural form, you could look at the IO library, which lets you "print" a mixture of types to the console. Alternatively, if you must return a string, you could specify a function that converts a nat to a decimal string, and the return "Result is" ^ nat2str(q).
I need to use Z3_parse_smtlib2_string to parse some SMTLIB strings into Z3 using the C++ API, and the use the Z3 C++ API to find the unsat core of this.
I know that there are other ways to find the unsat core as described here and here that are easier and less cumbersome, but I really want to be able to do this using only data structures parsed from strings to Z3. The reason is that I am trying to automate something using Z3.
It is obvious that if I passed this SMTLIB program into Z3, it is UNSAT.
(declare-const p0 Bool)
(assert(= p0 true)) (assert(= p0 false))
(assert (exists ((x Int)) (= 3 x)))
What I want to do, is to be able to get the unsat core programmatically using Z3. What I did was to read each of those lines separately into Z3 and give them a name using solver.add(expr, name), using the program below.
void my_test() {
context c1;
solver s(c1);
std::string declare = "(declare-const p0 Bool)";
std::string testing = "(assert(= p0 true)) (assert(= p0 false))";
std::string obvious = "(assert (exists ((x Int)) (= 3 x)))";
Z3_ast parsed1 = Z3_parse_smtlib2_string(c1, declare.c_str(), 0,0,0,0,0,0);
expr e1(c1, parsed1);
Z3_ast parsed2 = Z3_parse_smtlib2_string(c1, testing.c_str(), 0,0,0,0,0,0);
expr e2(c1, parsed2);
std::cout << "what: " << e2 << std::endl;
Z3_ast parsed3 = Z3_parse_smtlib2_string(c1, obvious.c_str(), 0,0,0,0,0,0);
expr e3(c1, parsed3);
s.add(e1, "declare");
s.add(e2, "testing");
s.add(e3, "obvious");
if (s.check() == z3::sat) {
std::cout << "SAT!\n";
model m = s.get_model();
std::cout << m << std::endl;
} else {
std::cout << "UNSAT!\n";
expr_vector core = s.unsat_core();
std::cout << core << "\n";
std::cout << "size: " << core.size() << "\n";
for (unsigned i = 0; i < core.size(); i++) {
std::cout << core[i] << "\n";
}
}
}
I expect to get the unsat core to be just declare, since that is clearly false, while the other expressions are clearly valid. However, Z3 gives me this response:
(error "line 1 column 11: unknown constant p0")
(error "line 1 column 31: unknown constant p0")
what: true
SAT!
(define-fun testing () Bool
true)
(define-fun declare () Bool
true)
(define-fun obvious () Bool
true)
Which is clearly wrong, since declare, which references (assert(= p0 true)) (assert(= p0 false)), is SAT! Obviously this should be UNSAT. Also, I do in fact declare p0, but Z3 doesn't seem to know that I declared it already.
Any ideas what I'm doing wrong?
The second call to Z3_parse_smtlib2_string does not know about the declaration in the first call:
Z3_ast parsed2 = Z3_parse_smtlib2_string(c1, testing.c_str(), 0,0,0,0,0,0);
The bunch of zero's in the end means "do not assume anything else", so it doesn't know that p0 exists. For more details see the Z3_parse_smtlib2_string in the API documentation; in your case you want to pass a non-empty decls.
When querying a model, with model_completion set to false in Z3_model_eval: What will Z3 return to signify that an interpretation is a "don't care"?
In case someone wants to suggest that: I guess it's probably not the return value of the function Z3_model_eval, since the z3++.h file (the C++ API) contains the lines:
Z3_bool status = Z3_model_eval(ctx(), m_model, n, model_completion, &r);
check_error();
if (status == Z3_FALSE)
throw exception("failed to evaluate expression");
In general: How does Z3 signify that a certain constant is a "don't care" in a model?
For true don't-cares, the model will not assign any value. Consequently, calls to eval or Z3_model_eval with model_completion set to false will keep the original constants untouched and only replace those for which a model value is assigned (and it will potentially simplify the expression). Here's an example:
context c;
expr e = c.int_const("x");
solver s(c);
s.add(e == e);
model m = s.get_model();
std::cout << m.eval(e, false) << std::endl;
std::cout << m.eval(e, true) << std::endl;
Note that the first line of output prints x, i.e., the original expression is untouched, while the call to eval with model_completion set to true will print 0.
I am working on ANLTR to support type checking. I am in trouble at some point. I will try to explain it with an example grammar, suppose that I have the following:
#members {
private java.util.HashMap<String, String> mapping = new java.util.HashMap<String, String>();
}
var_dec
: type_specifiers d=dec_list? SEMICOLON
{
mapping.put($d.ids.get(0).toString(), $type_specifiers.type_name);
System.out.println("identext = " + $d.ids.get(0).toString() + " - " + $type_specifiers.type_name);
};
type_specifiers returns [String type_name]
: 'int' { $type_name = "int";}
| 'float' {$type_name = "float"; }
;
dec_list returns [List ids]
: ( a += ID brackets*) (COMMA ( a += ID brackets* ) )*
{$ids = $a;}
;
brackets : LBRACKET (ICONST | ID) RBRACKET;
ID : ('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'0'..'9'|'_')*;
LBRACKET : '[';
RBRACKET : ']';
In rule dec_list, you will see that I am returning List with ids. However, in var_dec when I try to put the first element of the list (I am using only get(0) just to see the return value from dec_list rule, I can iterate it later, that's not my point) into mapping I get a whole string like
[#4,6:6='a',<17>,1:6]
for an input
int a, b;
What I am trying to do is to get text of each ID, in this case a and b in the list of index 0 and 1, respectively.
Does anyone have any idea?
The += operator creates a List of Tokens, not just the text these Tokens match. You'll need to initialize the List in the #init{...} block of the rule and add the inner-text of the tokens yourself.
Also, you don't need to do this:
type_specifiers returns [String type_name]
: 'int' { $type_name = "int";}
| ...
;
simply access type_specifiers's text attribute from the rule you use it in and remove the returns statement, like this:
var_dec
: t=type_specifiers ... {System.out.println($t.text);}
;
type_specifiers
: 'int'
| ...
;
Try something like this:
grammar T;
var_dec
: type dec_list? ';'
{
System.out.println("type = " + $type.text);
System.out.println("ids = " + $dec_list.ids);
}
;
type
: Int
| Float
;
dec_list returns [List ids]
#init{$ids = new ArrayList();}
: a=ID {$ids.add($a.text);} (',' b=ID {$ids.add($b.text);})*
;
Int : 'int';
Float : 'float';
ID : ('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'0'..'9'|'_')*;
Space : ' ' {skip();};
which will print the following to the console:
type = int
ids = [a, b, foo]
If you run the following class:
import org.antlr.runtime.*;
public class Main {
public static void main(String[] args) throws Exception {
TLexer lexer = new TLexer(new ANTLRStringStream("int a, b, foo;"));
TParser parser = new TParser(new CommonTokenStream(lexer));
parser.var_dec();
}
}