-
Notifications
You must be signed in to change notification settings - Fork 0
/
sat.ml
177 lines (149 loc) · 5.62 KB
/
sat.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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
open Mytypes;;
exception No_more_models
exception Bad_file
module DPLL = struct
type assignment =
|Aff of int
|Ref of int
|Dec of int
type assign_value =
|AffVal
|RefVal
|DecVal
|UndVal
type t = {
formula : sat;
mutable model : assignment list;
}
let create sat = {
formula = sat;
model = [];
}
let create_map dpll =
let arr = Array.make (dpll.formula.nbvars+1) UndVal in
let rec aux model = match model with
|[] -> ()
|hd::tl -> match hd with
|Aff(n) -> Array.set arr n AffVal; aux tl
|Ref(n) -> Array.set arr n RefVal; aux tl
|Dec(n) -> Array.set arr n DecVal; aux tl
in
aux dpll.model;
arr
let search var modelmap = modelmap.(var)
let sat_litteral modelmap litteral = match litteral with
|Val n -> begin
match search n modelmap with
|AffVal|DecVal -> true
|_ -> false end
|Neg n -> begin
match search n modelmap with
|RefVal -> true
|_ -> false
end
let sat_clause modelmap clause =
List.exists (sat_litteral modelmap) clause
let sat_formula modelmap formula =
List.for_all (sat_clause modelmap) formula
let sat dpll =
sat_formula (create_map dpll) (dpll.formula.cnf)
let backtrack dpll modelmap=
let rec aux l = match l with
|Dec(l)::tl -> Array.set modelmap l RefVal; Ref(l)::tl
|Aff(l)::tl|Ref(l)::tl -> Array.set modelmap l UndVal; aux tl
|[] -> raise No_more_models in
dpll.model <- aux dpll.model
let refine clause modelmap =
let rec aux clause acc = match clause with
|[] -> Some(acc)
|hd::tl -> match hd with
|Val(n) -> begin match search n modelmap with
|AffVal|DecVal -> None
|UndVal -> aux tl (hd::acc)
|RefVal -> aux tl acc
end
|Neg(n) -> begin match search n modelmap with
|RefVal -> None
|UndVal -> aux tl (hd::acc)
|AffVal|DecVal -> aux tl acc
end
in
aux clause []
let assign dpll modelmap assignment = match assignment with
|Aff(n) -> Array.set modelmap n AffVal;
dpll.model <- (Aff(n)::dpll.model);
|Ref(n) -> Array.set modelmap n RefVal;
dpll.model <- (Ref(n)::dpll.model);
|Dec(n) -> Array.set modelmap n DecVal;
dpll.model <- (Dec(n)::dpll.model);
()
let rec check_modelmap dpll modelmap =
let arr = create_map dpll in
Array.for_all (fun x -> x) (Array.map2 (fun x y -> x = y) arr modelmap)
let rec solution dpll modelmap =
let rec aux clauselist model modelmap acc=
match clauselist with
|[] -> begin match acc with
|[] -> model
|[]::tl -> aux clauselist model modelmap tl
|(hd1::tl1)::tl -> match hd1 with
|Val(n)|Neg(n) -> assign dpll modelmap (Dec(n));
solution dpll modelmap
end
|hd::tl -> match refine hd modelmap with
|Some([]) -> backtrack dpll modelmap;
solution dpll modelmap
|None -> aux tl model modelmap acc
|Some(hd1::[]) -> begin match hd1 with
|Val(n) -> assign dpll modelmap (Aff(n));
solution dpll modelmap
|Neg(n) -> assign dpll modelmap (Ref(n));
solution dpll modelmap
end
(* edit next line to change priorities *)
|Some(hd1::tl1) -> aux tl model modelmap ((hd1::tl1)::acc) in
aux (dpll.formula.cnf) (dpll.model) modelmap []
let rec solgen dpll = match dpll.model with
|[] -> solution dpll (create_map dpll)
|_ -> let modelmap = create_map dpll in
backtrack dpll modelmap;
solution dpll modelmap
let rec solgen_from_dec dpll at = match dpll.model with
|[] -> assert false
|hd::tl when hd = at -> let modelmap = create_map dpll in
backtrack dpll modelmap;
solution dpll modelmap
|hd::tl -> dpll.model <- tl;
solgen_from_dec dpll at
let fromfile path =
let rec start ic = match Str.split (Str.regexp "[ \t]+") (input_line ic) with
|[] -> start ic
|"c"::tl -> start ic
|"p" ::tl -> begin
match tl with
|"cnf"::vars::clauses::tl -> (int_of_string vars,int_of_string clauses)
|_ -> assert false end
|_ -> raise Bad_file in
let rec clause stringlist = match stringlist with
|"0"::[]|"0"::""::[]|[] -> []
|""::tl |"\t"::tl -> clause tl
|hd::tl -> match int_of_string hd with
|n when n>0 -> Val(n)::(clause tl)
|n when n<0 -> Neg(-n)::(clause tl)
|_ -> raise Bad_file (* cas n = 0 *) in
let rec clauses ic =
try
match Str.split (Str.regexp "[ \t]+") (input_line ic) with
|[]|""::[] -> clauses ic
|"c"::tl -> clauses ic
|hd::tl -> ((clause (hd::tl)) ::(clauses ic))
with
|End_of_file -> [] in
let ic = open_in path in
let nbVars,nbclauses = start ic in
let cllist = clauses ic in
let sat = {nbvars = nbVars;
cnf = cllist;
} in
create sat
end