-
Notifications
You must be signed in to change notification settings - Fork 0
/
sat_solver.ml
63 lines (51 loc) · 1.44 KB
/
sat_solver.ml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
module type VARIABLES = sig
type t
val compare : t -> t -> int
end
module Make (V : VARIABLES) = struct
type literal = bool * V.t
module L = struct
type t = literal
let compare (b1,v1) (b2,v2) =
let r = compare b1 b2 in
if r = 0 then compare v1 v2
else r
let mk_not (b,v) = (not b, v)
end
module S = Set.Make(L)
exception Unsat
exception Sat of S.t
type t = { gamma : S.t ; delta : L.t list list }
let rec assume env f =
if S.mem f env.gamma then env
else bcp { gamma = S.add f env.gamma ; delta = env.delta }
and bcp env =
List.fold_left
(fun env l -> try
let l = List.filter
(fun f ->
if S.mem f env.gamma then raise Exit;
not (S.mem (L.mk_not f) env.gamma)
) l
in
match l with
| [] -> raise Unsat (* conflict *)
| [f] -> assume env f
| _ -> { env with delta = l :: env.delta }
with Exit -> env)
{ env with delta = [] }
env.delta
let rec unsat env = try
match env.delta with
| [] -> raise (Sat env.gamma)
| ([_] | []) :: _ -> assert false
| (a :: _ ) :: _ ->
begin try unsat (assume env a) with Unsat -> () end ;
unsat (assume env (L.mk_not a))
with Unsat -> ()
let solve delta = try
unsat (bcp { gamma = S.empty ; delta }) ; None
with
| Sat g -> Some (S.elements g)
| Unsat -> None
end