问题
I would like to express this problem in the SMTLib Format and evaluate it using Z3.
edge("som1","som3").
edge("som2","som4").
edge("som4","som1").
edge("som3","som4").
path(x,y) :- edge(x,y). % x and y are strings
path(x,z) :- edge(x,y), path(y,z).
:- path(x,y), path(y,x). %cyclic path.
My question is how to write the rule (or query) which detect the existence of a cycle in the relation path (this rule in basic datalog : :- path(x,y), path(y,x)
).
回答1:
The tutorial Levent Erkok pointed out actually contains all the right information (I think). Knowing neither Datalog nor Z3's fixpoint features, I was still able to piece together the following:
(set-option :fixedpoint.engine datalog)
(define-sort s () Int)
(declare-rel edge (s s))
(declare-rel path (s s))
(declare-var a s)
(declare-var b s)
(declare-var c s)
(rule (=> (edge a b) (path a b)) P-1)
(rule (=> (and (path a b) (path b c)) (path a c)) P-2)
(rule (edge 1 2) E-1)
(rule (edge 2 3) E-2)
(rule (edge 3 1) E-3)
(declare-rel cycle (s))
(rule (=> (path a a) (cycle a)))
(query cycle :print-answer true)
Z3 4.8.0 nightly reports sat
, indicating that there is a cycle, but unsat
if any of the E
-rules is removed.
I had to use ints instead of strings, though, since (my version of) Z3 aborts with the error Rule contains infinite sorts in rule P-1
if strings are used.
来源:https://stackoverflow.com/questions/51244112/cyclic-relation-in-datalog-using-smtlib-for-z3