Below solution i am not able to implement in java. Please help me. Below is snippet code which i am trying to implement.
I found the same question:
Z3: finding all satisfying models
(Z3Py) checking all solutions for equation
BitVecExpr a = ctx.mkBVConst("a",8);
BitVecExpr b = ctx.mkBVConst("b",8);
BitVecExpr c = ctx.mkBVConst("c",8);
Solver s = ctx.mkSolver();
//s.add(ctx.mkEq(c,ctx.mkBVXOR(a,b))); // I am able to get distinct value for a and b for XOR.
//s.add(ctx.mkEq(c,ctx.mkBVOR(b,a))); // If i swap the position of the a and b then i was able to generate distinct pattern. For example for this add method of OR my code was working.
s.add(ctx.mkEq(c,ctx.mkBVOR(a,b))); // Not working getting same model.
s.add(ctx.mkEq(c,ctx.mkBV(11,8)));
if (s.check() == Status.SATISFIABLE)
{
System.out.println("status :"+ s.check());
Model m = s.getModel();
System.out.println("Model :"+ m);
}
BitVecExpr test1[] = {a,b};
s.add(ctx.mkDistinct(test1)); // If i use this line then only i get distinct pattern
if (s.check() == Status.SATISFIABLE)
{
System.out.println("status :"+ s.check());
Model m = s.getModel();
System.out.println("Model :"+ m);
}
Also i don't have model()[] method in java.In java i have getModel() method without any arguments.
One more question. How can we implement '!=' inside add. For example.
s.add(Or(a != s.model()[a], b != s.model()[b]))
For == we have mkEq() method, But i was unable to find any method related to '!='.
I tried using:
s.add(ctx.mkOr(ctx.mkEq(a,ctx.mkNot(s.getModel())),ctx.mkEq(a,ctx.mkNot(s.getModel()))));
For which i am getting compilation error. Which i should get because its not possible to implement in that way.
BitVecExpr a = ctx.mkBVConst("a",2);
BitVecExpr b = ctx.mkBVConst("b",2);
BitVecExpr c = ctx.mkBVConst("c",2);
Model m = null;
Solver s = ctx.mkSolver();
s.add(ctx.mkEq(c,ctx.mkBVXOR(a,b)));
s.add(ctx.mkEq(c,ctx.mkBV(3,2)));
while(s.check() == Status.SATISFIABLE){
System.out.println("status :"+ s.check());
m = s.getModel();
System.out.println("m.eval(a) " + m.eval(a,false));
System.out.println("m.eval(b) " + m.eval(b,false));
System.out.println("m.eval(c) " + m.eval(c,false));
Integer b_int = Integer.parseInt(m.eval(b,false).toString());
Integer a_int = Integer.parseInt(m.eval(a,false).toString());
BoolExpr b_bol = ctx.mkEq(b,(BitVecExpr) ctx.mkBV(b_int,2));
BoolExpr a_bol = ctx.mkEq(a,(BitVecExpr) ctx.mkBV(a_int,2));
s.add(ctx.mkOr(ctx.mkEq(b_bol,ctx.mkFalse()),ctx.mkEq(a_bol,ctx.mkFalse())));
}
Above code worked for me. Do you guys have any suggestion.
Related
I want to use z3py to implement an access policy analyzer just like AWS Zelkova. The first step I need to do is to encode the policy language into logical expressions. For instance, a control policy
effect:Allow
principal:students
action: getObject
resource: cs240/Example.pdf,cs240/Answer.pdf
should be converted into
p = students ∧ a = getObject ∧ (r = cs240/Example.pdf ∨ r = cs240/Answer.pdf)
and using z3py I can represent it as
s.add(x1 == And(a == StringVal("GetObject"),p == StringVal("tas"),Or(r == StringVal("cs240/Exam.pdf"),r == StringVal("cs240/Answer.pdf"))))
Here comes the question. When input a policy, After parsing the policy, I may get an Array of values about one key and I need to use a loop to call Or() in order to get the result as Or(r[0],r[1],...). How can I do that? I have tried something like this but obviously it doesn't work.
from z3 import *
Action = ["getObject"]
Principal = ["tas"]
Resource = ["cs240/Exam.pdf","cs240/Answer.pdf"]
a,p,r,x = Bools('a p r x')
a_t,p_t,r_t = Strings('a_t p_t r_t')
s = Solver()
for act in Action:
a = Or(a,a_t == StringVal(act))
for principal in Principal:
p = Or(p,p_t == StringVal(principal))
for resource in Resource:
r = Or(r,r_t == StringVal(resource))
s.add(And(a,p,r))
print(s.check())
print(s.model())
That's the result of my program:
sat
[a_t = "", p = True, r_t = "", a = True, p_t = "", r = True]
You should build the expression one piece at a time and add it all together. Pseudocode:
foo = False
for i in items:
foo = Or(foo, i == ...whatever it should equal...)
s.add(foo)
When you build the expression, make sure to start the variable at False. Something like:
from z3 import *
Action = ["getObject"]
Principal = ["tas"]
Resource = ["cs240/Exam.pdf","cs240/Answer.pdf"]
a = False
p = False
r = False
a_t,p_t,r_t = Strings('a_t p_t r_t')
s = Solver()
for act in Action:
a = Or(a,a_t == StringVal(act))
for principal in Principal:
p = Or(p,p_t == StringVal(principal))
for resource in Resource:
r = Or(r,r_t == StringVal(resource))
s.add(And(a,p,r))
print(s.check())
print(s.model())
This prints:
sat
[r_t = "cs240/Exam.pdf", p_t = "tas", a_t = "getObject"]
I can't tell whether this is a correct answer as I haven't really studied your constraints, but the model seems more relevant to the question.
assign wfwe = wb_acc & (adr_i == 2'b10) & ack_o & we_i;
For the above assign statement which is in verilog, i getting error while implememting it in z3
My code:
BitVecExpr[] wfwe = new BitVecExpr[1];
BitVecExpr[] wb_acc = new BitVecExpr[1];
BitVecExpr[] adr_i = new BitVecExpr[1];
BitVecExpr[] ack_o = new BitVecExpr[1];
BitVecExpr[] we_i = new BitVecExpr[1];
wfwe[0] = ctx.mkBVConst("wfwe",1);
wb_acc[0] = ctx.mkBVConst("wb_acc",1);
adr_i[0] = ctx.mkBVConst("adr_i",2);
ack_o[0] = ctx.mkBVConst("ack_o",1);
we_i[0] = ctx.mkBVConst("we_i",1);
Solver s = ctx.mkSolver();
s.add(ctx.mkBVAND(wb_acc[0],ctx.mkEq(adr_i[0],ctx.mkNumeral("2",2)),ack_o[0],we_i[0]));
I am getting error in above add statement:
error: method mkBVAND in class Context cannot be applied to given types;
required: BitVecExpr,BitVecExpr
found: BitVecExpr,BoolExpr
Which is true. Can anyone suggest me workaround. Am i implementing it incorrectly please let me know.
This error is reported because the second argument of mkBVAND is a Boolean expression (ctx.mkEq ...). Note that Booleans and BitVectors of size 1 are not the same thing, and they will not be converted automatically. The easiest way to convert between them is an if-then-else the selects the right values.
These are the problems with this example:
1) ctx.mkNumeral("2",2) is incorrect. I guess the intention was to create a bv-numeral of 2 bits with value 2; the easiest way to achieve that is ctx.mkBV(2, 2)
2) The 2nd argument of mkBVAND needs to be converted from Bool to BitVector, e.g., like so:
BoolExpr c = ctx.mkEq(adr_i[0], ctx.mkBV(2, 2));
BitVecExpr e = (BitVecExpr) ctx.mkITE(c, ctx.mkBV(1, 1), ctx.mkBV(0, 1));
e being the result.
3) ctx.mkBVAND takes exactly 2 arguments, no more and no less. Thus, the BVAND expression needs to be rewritten, e.g., like so:
ctx.mkBVAND(ctx.mkBVAND(wb_acc[0], e), ctx.mkBVAND(ack_o[0], we_i[0])))
4) The result needs to be converted to a Boolean expression again, e.g.
ctx.mkEq(q, ctx.mkBV(1, 1))
where q is the result of the BVAND.
I'm using Z3 C++ API (Version 4.3.1) and I want to extract variables of a formula (An object of type expr). I've found a similar question but it is in Z3py. I am wonder if there is a method in Z3 C/C++ API to extract variables from expr object. Thanks!
For example (some details omitted):
expr fs = implies(x + y == 0, z * x < 15);
std::vector<expr> varlist = get_vars(fs);
Then varlist should contain x,y,z.
The C++ example in the distribution (examples/c++/example.cpp) shows a sample visitor pattern.
It is very simplistic, but will give the idea.
I repeat it here below:
void visit(expr const & e) {
if (e.is_app()) {
unsigned num = e.num_args();
for (unsigned i = 0; i < num; i++) {
visit(e.arg(i));
}
// do something
// Example: print the visited expression
func_decl f = e.decl();
std::cout << "application of " << f.name() << ": " << e << "\n";
}
else if (e.is_quantifier()) {
visit(e.body());
// do something
}
else {
assert(e.is_var());
// do something
}
}
The visitor function can be improved by using
a cache of previously visited expressions because in general Z3 uses shared sub-expressions.
This is similar to the Python example.
Hope this helps
Z3 currently supports the DIMACS format for input. Is there any way to output the DIMACS format for the problem before solution? I mean converting the problem to a system CNFs and output it in a DIMACS format.
If not, any ideas towards this direction would be more than helpful.
The DIMACS format is very primitive, it supports only Boolean variables. Z3 does not reduce every problem into SAT. Some problems are solved using a propositional SAT solver, but this is not the rule. This usually only happens if the input contains only Boolean and/or Bit-vector variables. Moreover, even if the input problem contains only Boolean and Bit-vector variables, there is no guarantee that Z3 will use a pure SAT solver to solve it.
That being said, you can use the tactic framework to control Z3. For example, for Bit-vector problems, the following tactic will convert it into a propositional formula in CNF format. It should be straightforward to convert it into DIMACS. Here is the example. You can try it online at: http://rise4fun.com/Z3Py/E1s
x, y, z = BitVecs('x y z', 16)
g = Goal()
g.add(x == y, z > If(x < 0, x, -x))
print g
# t is a tactic that reduces a Bit-vector problem into propositional CNF
t = Then('simplify', 'bit-blast', 'tseitin-cnf')
subgoal = t(g)
assert len(subgoal) == 1
# Traverse each clause of the first subgoal
for c in subgoal[0]:
print c
Thanks to Leonardo's answer I came up with this code that will do what you want:
private static void Output(Context ctx,Solver slv)
{
var goal = ctx.MkGoal();
goal.Add(slv.Assertions);
var applyResult = ctx.Then(ctx.MkTactic("simplify"),
ctx.MkTactic("bit-blast"),
ctx.MkTactic("tseitin-cnf")).Apply(goal);
Debug.Assert(applyResult.Subgoals.Length==1);
var map = new Dictionary<BoolExpr,int>();
foreach (var f in applyResult.Subgoals[0].Formulas)
{
Debug.Assert(f.IsOr);
foreach (var e in f.Args)
if (e.IsNot)
{
Debug.Assert(e.Args.Length==1);
Debug.Assert(e.Args[0].IsConst);
map[(BoolExpr)e.Args[0]] = 0;
}
else
{
Debug.Assert(e.IsConst);
map[(BoolExpr)e] = 0;
}
}
var id = 1;
foreach (var key in map.Keys.ToArray())
map[key] = id++;
using (var fos = File.CreateText("problem.cnf"))
{
fos.WriteLine("c DIMACS file format");
fos.WriteLine($"p cnf {map.Count} {applyResult.Subgoals[0].Formulas.Length}");
foreach(var f in applyResult.Subgoals[0].Formulas)
{
foreach (var e in f.Args)
if (e.IsNot)
fos.Write($"{map[(BoolExpr)e.Args[0]]} ");
else
fos.Write($"-{map[(BoolExpr)e]} ");
fos.WriteLine("0");
}
}
}
For it to work you should add all your constraints to the solver directly, by calling slv.Assert(...).
I tried to use ctx.mkExist in the fixedpoint, howwever, it occurs error said "contains recursive predicate", I don't know why? and How to use ctx.MkExists in fixedpoint?For example:
exist (lamda real) that lamb>=0 AND inv(c,i) AND phi(c+lamb,i) => phi(c,i)
using (Context ctx = new Context())
{
var s = ctx.MkFixedpoint();
IntSort B = ctx.IntSort;
BoolSort T = ctx.BoolSort;
RealSort R = ctx.RealSort;
FuncDecl phi = ctx.MkFuncDecl("phi", new Sort[] { R,B }, T);
s.RegisterRelation(phi);
FuncDecl Inv = ctx.MkFuncDecl("inv", new Sort[] { R, B }, T);
s.RegisterRelation(Inv);
RealExpr c= (RealExpr)ctx.MkBound(0, R);
IntExpr i = (IntExpr) ctx.MkBound(1, B);
Expr[] InvArg=new Expr[2];
InvArg[0] = ctx.MkConst("inv0" , Inv.Domain[0]);
InvArg[1] = ctx.MkConst("inv1", Inv.Domain[1]);
Expr invExpr = ctx.MkImplies(ctx.MkOr(
ctx.MkAnd(ctx.MkEq(InvArg[1], ctx.MkInt(0)), ctx.MkGe((RealExpr)InvArg[0], ctx.MkReal(0))),
ctx.MkAnd(ctx.MkEq(InvArg[1], ctx.MkInt(1)), ctx.MkGe((RealExpr)InvArg[0], ctx.MkReal(2)))
),
(BoolExpr)Inv[InvArg]);
Quantifier invQ = ctx.MkForall(InvArg, invExpr, 1);
s.AddRule(invQ);
RealExpr[] lamb = new RealExpr[1];
lamb[0] = ctx.MkRealConst("lamb");
Expr existExpr = ctx.MkAnd(
(BoolExpr)Inv[c,i],
(BoolExpr)phi[ctx.MkAdd(c,lamb[0]),i],
ctx.MkGe(lamb[0], ctx.MkReal(0)));
BoolExpr t= ctx.MkExists(lamb, existExpr, 1);
s.AddRule(ctx.MkImplies(t,(BoolExpr)phi[c,i]));
}
sometimes, there is an error said "AccessViolationException was unhandlered,Attempted to read or write protected memory. This is often an indication that other memory is corrupt." when running to ctx.MkExists()
The fixedpoint solver only supports universal quantifiers at the top-level.
You should rewrite the rule as follows:
s.AddRule(ctx.MkForall(lamb,
ctx.MkImplies((BoolExpr)existExpr,(BoolExpr)phi[c,i])));
Z3 should ideally not result in any access violation. This is typically indicating a bug.
I would really appreciate repros for such bugs when/if you encounter them.