mirror of
https://github.com/c-cube/sidekick.git
synced 2025-12-06 03:05:31 -05:00
Better explanations in equivalence closure
This commit is contained in:
parent
dbf0646171
commit
384bcb7270
10 changed files with 161 additions and 34 deletions
2
Makefile
2
Makefile
|
|
@ -5,7 +5,7 @@ COMP=ocamlbuild -log $(LOG) -use-ocamlfind -classic-display
|
||||||
FLAGS=
|
FLAGS=
|
||||||
DIRS=-Is sat,smt,util,util/smtlib
|
DIRS=-Is sat,smt,util,util/smtlib
|
||||||
DOC=msat.docdir/index.html
|
DOC=msat.docdir/index.html
|
||||||
TEST=sat_solve.native smt_solve.native
|
TEST=sat_solve.native
|
||||||
|
|
||||||
NAME=msat
|
NAME=msat
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,8 +10,10 @@ Tseitin
|
||||||
Tseitin_intf
|
Tseitin_intf
|
||||||
|
|
||||||
# Smt Modules
|
# Smt Modules
|
||||||
Unionfind
|
Cc
|
||||||
|
Sig
|
||||||
Smt
|
Smt
|
||||||
|
Unionfind
|
||||||
|
|
||||||
# Old modules
|
# Old modules
|
||||||
#Arith
|
#Arith
|
||||||
|
|
|
||||||
91
smt/cc.ml
Normal file
91
smt/cc.ml
Normal file
|
|
@ -0,0 +1,91 @@
|
||||||
|
(*
|
||||||
|
MSAT is free software, using the Apache license, see file LICENSE
|
||||||
|
Copyright 2014 Guillaume Bury
|
||||||
|
Copyright 2014 Simon Cruanes
|
||||||
|
*)
|
||||||
|
|
||||||
|
module Make(T : Sig.OrderedType) = struct
|
||||||
|
|
||||||
|
module M = Map.Make(T)
|
||||||
|
module U = Unionfind.Make(T)
|
||||||
|
|
||||||
|
exception Unsat of (T.t * T.t * (T.t list))
|
||||||
|
|
||||||
|
type t = {
|
||||||
|
repr : U.t;
|
||||||
|
expl : T.t M.t;
|
||||||
|
size : int M.t;
|
||||||
|
}
|
||||||
|
|
||||||
|
let empty = {
|
||||||
|
repr = U.empty;
|
||||||
|
expl = M.empty;
|
||||||
|
size = M.empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
let map_find m v default = try M.find v m with Not_found -> default
|
||||||
|
let find_parent v m = map_find m v v
|
||||||
|
|
||||||
|
let rev_root m root =
|
||||||
|
let rec aux m curr next =
|
||||||
|
if T.compare curr next = 0 then
|
||||||
|
m, curr
|
||||||
|
else
|
||||||
|
let parent = find_parent next m in
|
||||||
|
let m' = M.add next curr (M.remove curr m) in
|
||||||
|
aux m' next parent
|
||||||
|
in
|
||||||
|
aux m root (find_parent root m)
|
||||||
|
|
||||||
|
let rec root m acc curr =
|
||||||
|
let parent = find_parent curr m in
|
||||||
|
if T.compare curr parent = 0 then
|
||||||
|
curr :: acc
|
||||||
|
else
|
||||||
|
root m (curr :: acc) parent
|
||||||
|
|
||||||
|
let expl t a b =
|
||||||
|
let rec aux last = function
|
||||||
|
| x :: r, y :: r' when T.compare x y = 0 ->
|
||||||
|
aux (Some x) (r, r')
|
||||||
|
| l, l' -> begin match last with
|
||||||
|
| Some z -> List.rev_append (z :: l) l'
|
||||||
|
| None -> List.rev_append l l'
|
||||||
|
end
|
||||||
|
in
|
||||||
|
aux None (root t.expl [] a, root t.expl [] b)
|
||||||
|
|
||||||
|
let add_eq_aux t i j =
|
||||||
|
if T.compare (U.find t.repr i) (U.find t.repr j) = 0 then
|
||||||
|
t
|
||||||
|
else
|
||||||
|
let m, old_root_i = rev_root t.expl i in
|
||||||
|
let m, old_root_j = rev_root m j in
|
||||||
|
let nb_i = map_find t.size old_root_i 0 in
|
||||||
|
let nb_j = map_find t.size old_root_j 0 in
|
||||||
|
if nb_i < nb_j then {
|
||||||
|
repr = t.repr;
|
||||||
|
expl = M.add i j m;
|
||||||
|
size = M.add j (nb_i + nb_j + 1) t.size; }
|
||||||
|
else {
|
||||||
|
repr = t.repr;
|
||||||
|
expl = M.add j i m;
|
||||||
|
size = M.add i (nb_i + nb_j + 1) t.size; }
|
||||||
|
|
||||||
|
let add_eq t i j =
|
||||||
|
let t' = add_eq_aux t i j in
|
||||||
|
try
|
||||||
|
let u' = U.union t.repr i j in
|
||||||
|
{ t' with repr = u' }
|
||||||
|
with U.Unsat (a, b) ->
|
||||||
|
raise (Unsat (a, b, expl t' a b))
|
||||||
|
|
||||||
|
let add_neq t i j =
|
||||||
|
try
|
||||||
|
let u' = U.forbid t.repr i j in
|
||||||
|
{ t with repr = u' }
|
||||||
|
with U.Unsat (a, b) ->
|
||||||
|
raise (Unsat (a, b, expl t a b))
|
||||||
|
|
||||||
|
|
||||||
|
end
|
||||||
15
smt/cc.mli
Normal file
15
smt/cc.mli
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
(*
|
||||||
|
MSAT is free software, using the Apache license, see file LICENSE
|
||||||
|
Copyright 2014 Guillaume Bury
|
||||||
|
Copyright 2014 Simon Cruanes
|
||||||
|
*)
|
||||||
|
|
||||||
|
module Make(T : Sig.OrderedType) : sig
|
||||||
|
type t
|
||||||
|
|
||||||
|
exception Unsat of (T.t * T.t * (T.t list))
|
||||||
|
|
||||||
|
val empty : t
|
||||||
|
val add_eq : t -> T.t -> T.t -> t
|
||||||
|
val add_neq : t -> T.t -> T.t -> t
|
||||||
|
end
|
||||||
13
smt/sig.mli
Normal file
13
smt/sig.mli
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
(*
|
||||||
|
MSAT is free software, using the Apache license, see file LICENSE
|
||||||
|
Copyright 2014 Guillaume Bury
|
||||||
|
Copyright 2014 Simon Cruanes
|
||||||
|
*)
|
||||||
|
|
||||||
|
|
||||||
|
module type OrderedType = sig
|
||||||
|
(** Signature for ordered types (mainly for use in Map.Make) *)
|
||||||
|
|
||||||
|
type t
|
||||||
|
val compare : t -> t -> int
|
||||||
|
end
|
||||||
31
smt/smt.ml
31
smt/smt.ml
|
|
@ -62,7 +62,7 @@ module Tseitin = Tseitin.Make(Fsmt)
|
||||||
|
|
||||||
module Tsmt = struct
|
module Tsmt = struct
|
||||||
|
|
||||||
module U = Unionfind.Make(String)
|
module CC = Cc.Make(String)
|
||||||
|
|
||||||
type formula = Fsmt.t
|
type formula = Fsmt.t
|
||||||
type proof = unit
|
type proof = unit
|
||||||
|
|
@ -72,37 +72,44 @@ module Tsmt = struct
|
||||||
get : int -> formula;
|
get : int -> formula;
|
||||||
push : formula -> formula list -> proof -> unit;
|
push : formula -> formula list -> proof -> unit;
|
||||||
}
|
}
|
||||||
type level = {
|
type level = CC.t
|
||||||
uf : U.t;
|
|
||||||
seen : formula list
|
|
||||||
}
|
|
||||||
|
|
||||||
type res =
|
type res =
|
||||||
| Sat of level
|
| Sat of level
|
||||||
| Unsat of formula list * proof
|
| Unsat of formula list * proof
|
||||||
|
|
||||||
let dummy = { uf = U.empty; seen = [] }
|
let dummy = CC.empty
|
||||||
|
|
||||||
let env = ref dummy
|
let env = ref dummy
|
||||||
|
|
||||||
let current_level () = !env
|
let current_level () = !env
|
||||||
|
|
||||||
|
let to_clause (a, b, l) =
|
||||||
|
Log.debug 10 "Expl : %s; %s" a b;
|
||||||
|
List.iter (fun s -> Log.debug 10 " |- %s" s) l;
|
||||||
|
let rec aux acc = function
|
||||||
|
| [] | [_] -> acc
|
||||||
|
| x :: ((y :: _) as r) ->
|
||||||
|
aux (Fsmt.mk_eq x y :: acc) r
|
||||||
|
in
|
||||||
|
(Fsmt.mk_eq a b) :: (List.rev_map Fsmt.neg (aux [] l))
|
||||||
|
|
||||||
let assume s =
|
let assume s =
|
||||||
try
|
try
|
||||||
for i = s.start to s.start + s.length - 1 do
|
for i = s.start to s.start + s.length - 1 do
|
||||||
|
Log.debug 10 "Propagating in th : %s" (Log.on_fmt Fsmt.print (s.get i));
|
||||||
match s.get i with
|
match s.get i with
|
||||||
| Fsmt.Prop _ -> ()
|
| Fsmt.Prop _ -> ()
|
||||||
| Fsmt.Equal (i, j) as f ->
|
| Fsmt.Equal (i, j) as f ->
|
||||||
env := { !env with seen = f :: !env.seen };
|
env := CC.add_eq !env i j
|
||||||
env := { !env with uf = U.union !env.uf i j }
|
|
||||||
| Fsmt.Distinct (i, j) as f ->
|
| Fsmt.Distinct (i, j) as f ->
|
||||||
env := { !env with seen = f :: !env.seen };
|
env := CC.add_neq !env i j
|
||||||
env := { !env with uf = U.forbid !env.uf i j }
|
|
||||||
| _ -> assert false
|
| _ -> assert false
|
||||||
done;
|
done;
|
||||||
Sat (current_level ())
|
Sat (current_level ())
|
||||||
with U.Unsat ->
|
with CC.Unsat x ->
|
||||||
Unsat (List.rev_map Fsmt.neg !env.seen, ())
|
Log.debug 8 "Making explanation clause...";
|
||||||
|
Unsat (to_clause x, ())
|
||||||
|
|
||||||
let backtrack l = env := l
|
let backtrack l = env := l
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,7 @@
|
||||||
|
|
||||||
module type OrderedType = sig
|
|
||||||
type t
|
|
||||||
val compare : t -> t -> int
|
|
||||||
end
|
|
||||||
|
|
||||||
(* Union-find Module *)
|
(* Union-find Module *)
|
||||||
module Make(T : OrderedType) = struct
|
module Make(T : Sig.OrderedType) = struct
|
||||||
exception Unsat
|
exception Unsat of T.t * T.t
|
||||||
|
|
||||||
type var = T.t
|
type var = T.t
|
||||||
module M = Map.Make(T)
|
module M = Map.Make(T)
|
||||||
|
|
@ -48,12 +43,11 @@ let possible h =
|
||||||
let aux (a, b) =
|
let aux (a, b) =
|
||||||
let ca = find h a in
|
let ca = find h a in
|
||||||
let cb = find h b in
|
let cb = find h b in
|
||||||
ca != cb
|
if T.compare ca cb = 0 then
|
||||||
|
raise (Unsat (a, b))
|
||||||
in
|
in
|
||||||
if List.for_all aux h.forbid then
|
List.iter aux h.forbid;
|
||||||
h
|
h
|
||||||
else
|
|
||||||
raise Unsat
|
|
||||||
|
|
||||||
let union_aux h x y =
|
let union_aux h x y =
|
||||||
let cx = find h x in
|
let cx = find h x in
|
||||||
|
|
@ -78,7 +72,7 @@ let forbid h x y =
|
||||||
let cx = find h x in
|
let cx = find h x in
|
||||||
let cy = find h y in
|
let cy = find h y in
|
||||||
if cx = cy then
|
if cx = cy then
|
||||||
raise Unsat
|
raise (Unsat (x, y))
|
||||||
else
|
else
|
||||||
{ h with forbid = (x, y) :: h.forbid }
|
{ h with forbid = (x, y) :: h.forbid }
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,12 @@
|
||||||
module type OrderedType = sig
|
(*
|
||||||
type t
|
MSAT is free software, using the Apache license, see file LICENSE
|
||||||
val compare : t -> t -> int
|
Copyright 2014 Guillaume Bury
|
||||||
end
|
Copyright 2014 Simon Cruanes
|
||||||
|
*)
|
||||||
|
|
||||||
module Make(T : OrderedType) : sig
|
module Make(T : Sig.OrderedType) : sig
|
||||||
type t
|
type t
|
||||||
exception Unsat
|
exception Unsat of T.t * T.t
|
||||||
val empty : t
|
val empty : t
|
||||||
val find : t -> T.t -> T.t
|
val find : t -> T.t -> T.t
|
||||||
val union : t -> T.t -> T.t -> t
|
val union : t -> T.t -> T.t -> t
|
||||||
|
|
|
||||||
2
tests/unsat/test-009.smt2
Normal file
2
tests/unsat/test-009.smt2
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
(assert (and (= a b) (or (= b c) (= b d)) (not (= a d)) (not (= a c))))
|
||||||
|
(check-sat)
|
||||||
|
|
@ -72,7 +72,9 @@ let rec translate_term = function
|
||||||
| "or", l -> T.make_or l
|
| "or", l -> T.make_or l
|
||||||
| "xor" as s, l -> left_assoc s T.make_xor l
|
| "xor" as s, l -> left_assoc s T.make_xor l
|
||||||
| "=>" as s, l -> right_assoc s T.make_imply l
|
| "=>" as s, l -> right_assoc s T.make_imply l
|
||||||
| _ -> raise Unknown_command
|
| _ ->
|
||||||
|
Format.printf "unknown : %s@." s;
|
||||||
|
raise Unknown_command
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
| e -> (get_atom (translate_atom e))
|
| e -> (get_atom (translate_atom e))
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue