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
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
(** {1 Clauses} *)
open Logtk
module BV = CCBV
module T = Term
module S = Subst
module Lit = Literal
module Lits = Literals
module Stmt = Statement
let stat_clause_create = Util.mk_stat "clause.create"
module type S = Clause_intf.S
type proof_step = Proof.Step.t
(** Bundle of clause sets *)
type 'c sets = {
c_set: 'c CCVector.ro_vector; (** main set of clauses *)
c_sos: 'c CCVector.ro_vector; (** set of support *)
}
(** {2 Type def} *)
module Make(Ctx : Ctx.S) : S with module Ctx = Ctx = struct
module Ctx = Ctx
type flag = SClause.flag
type sclause = SClause.t = private {
id: int;
lits: Literals.t;
trail: Trail.t;
mutable flags: flag;
}
type t = {
sclause : sclause;
penalty: int; (** heuristic penalty *)
mutable selected : BV.t Lazy.t; (** bitvector for selected lits*)
mutable proof : proof_step; (** Proof of the clause *)
mutable eligible_res: BV.t option;
}
type clause = t
(** {2 boolean flags} *)
let get_flag flag c = SClause.get_flag flag c.sclause
let set_flag flag c b = SClause.set_flag flag c.sclause b
let mark_redundant c = set_flag SClause.flag_redundant c true
let is_redundant c = get_flag SClause.flag_redundant c
let mark_backward_simplified c = set_flag SClause.flag_backward_simplified c true
let is_backward_simplified c = get_flag SClause.flag_backward_simplified c
(** {2 Hashcons} *)
let equal c1 c2 = SClause.equal c1.sclause c2.sclause
let compare c1 c2 = SClause.compare c1.sclause c2.sclause
let hash c = SClause.hash c.sclause
let id c = SClause.id c.sclause
let is_ground c = Literals.is_ground c.sclause.lits
let weight c = Lits.weight c.sclause.lits
let trail c = c.sclause.trail
let has_trail c = not (Trail.is_empty c.sclause.trail)
let trail_subsumes c1 c2 = Trail.subsumes c1.sclause.trail c2.sclause.trail
let is_active c ~v = Trail.is_active c.sclause.trail ~v
let penalty c = c.penalty
let trail_l = function
| [] -> Trail.empty
| [c] -> c.sclause.trail
| [c1; c2] -> Trail.merge c1.sclause.trail c2.sclause.trail
| l -> Trail.merge_l (List.map trail l)
let lits c = c.sclause.lits
module Tbl = CCHashtbl.Make(struct
type t = clause
let hash = hash
let equal = equal
end)
(** {2 Utils} *)
let is_goal c = Proof.Step.is_goal c.proof
let distance_to_goal c = Proof.Step.distance_to_goal c.proof
let comes_from_goal c = CCOpt.is_some @@ distance_to_goal c
let create_inner ~penalty ~selected sclause proof =
let c = {
sclause;
penalty;
selected;
proof;
eligible_res=None;
} in
Util.incr_stat stat_clause_create;
c
let of_sclause ?(penalty=0) c proof =
let selected = lazy (Ctx.select c.lits) in
create_inner ~penalty ~selected c proof
let lit_is_false_ = function
| Literal.False -> true
| _ -> false
let create_a ~penalty ~trail lits proof =
let lits =
if CCArray.exists lit_is_false_ lits
then CCArray.filter (fun lit -> not (lit_is_false_ lit)) lits
else lits
in
let selected = lazy (Ctx.select lits) in
create_inner ~penalty ~selected (SClause.make ~trail lits) proof
let create ~penalty ~trail lits proof =
create_a ~penalty ~trail (Array.of_list lits) proof
let of_forms ?(penalty=0) ~trail forms proof =
let lits = List.map Ctx.Lit.of_form forms |> Array.of_list in
create_a ~penalty ~trail lits proof
let of_forms_axiom ?(penalty=0) ~file ~name forms =
let lits = List.map Ctx.Lit.of_form forms in
let proof = Proof.Step.assert' ~file ~name () in
create ~penalty ~trail:Trail.empty lits proof
let of_statement st =
let of_lits lits =
let lits = List.map Ctx.Lit.of_form lits in
let proof = Stmt.proof_step st in
let c = create ~trail:Trail.empty ~penalty:0 lits proof in
c
in
match Stmt.view st with
| Stmt.Data _
| Stmt.TyDecl _ -> []
| Stmt.Def _
| Stmt.Rewrite _ -> []
| Stmt.Assert lits -> [of_lits lits]
| Stmt.Goal lits -> [of_lits lits]
| Stmt.Lemma l
| Stmt.NegatedGoal (_,l) -> List.map of_lits l
let update_trail f c =
let sclause = SClause.update_trail f c.sclause in
create_inner sclause c.proof ~selected:c.selected ~penalty:c.penalty
let proof_step c = c.proof
let proof c = Proof.S.mk c.proof (SClause.mk_proof_res c.sclause)
let proof_parent c = Proof.Parent.from (proof c)
let proof_parent_subst renaming (c,sc) subst =
Proof.Parent.from_subst renaming (proof c,sc) subst
let update_proof c f =
let new_proof = f c.proof in
create_a ~trail:c.sclause.trail ~penalty:c.penalty c.sclause.lits new_proof
let is_empty c =
Lits.is_absurd c.sclause.lits && Trail.is_empty c.sclause.trail
let length c = SClause.length c.sclause
let _apply_subst_no_simpl subst (lits,sc) =
if Subst.is_empty subst
then lits
else
let renaming = S.Renaming.create () in
Array.map
(fun l -> Lit.apply_subst_no_simp renaming subst (l,sc))
lits
(** Bitvector that indicates which of the literals of [subst(clause)]
are maximal under [ord] *)
let maxlits (c,sc) subst =
let ord = Ctx.ord () in
let lits' = _apply_subst_no_simpl subst (lits c,sc) in
Lits.maxlits ~ord lits'
(** Check whether the literal is maximal *)
let is_maxlit (c,sc) subst ~idx =
let ord = Ctx.ord () in
let lits' = _apply_subst_no_simpl subst (lits c,sc) in
Lits.is_max ~ord lits' idx
(** Bitvector that indicates which of the literals of [subst(clause)]
are eligible for resolution. *)
let eligible_res (c,sc) subst =
let ord = Ctx.ord () in
let lits' = _apply_subst_no_simpl subst (lits c,sc) in
let selected = Lazy.force c.selected in
if BV.is_empty selected
then (
Lits.maxlits ~ord lits'
) else (
let bv = BV.copy selected in
let n = Array.length lits' in
for i = 0 to n-1 do
if not (BV.get bv i) then () else
let lit = lits'.(i) in
for j = i+1 to n-1 do
let lit' = lits'.(j) in
if Lit.is_pos lit = Lit.is_pos lit' && BV.get bv j
then match Lit.Comp.compare ~ord lit lit' with
| Comparison.Incomparable
| Comparison.Eq -> ()
| Comparison.Gt -> BV.reset bv j
| Comparison.Lt -> BV.reset bv i
done;
done;
bv
)
let eligible_res_no_subst c =
begin match c.eligible_res with
| Some r -> r
| None ->
let bv = eligible_res (c,0) Subst.empty in
c.eligible_res <- Some bv;
bv
end
(** Bitvector that indicates which of the literals of [subst(clause)]
are eligible for paramodulation. *)
let eligible_param (c,sc) subst =
let ord = Ctx.ord () in
if BV.is_empty (Lazy.force c.selected) then (
let lits' = _apply_subst_no_simpl subst (lits c,sc) in
let bv = Lits.maxlits ~ord lits' in
BV.filter bv (fun i -> Lit.is_pos lits'.(i));
bv
) else
BV.empty ()
let is_eligible_param (c,sc) subst ~idx =
Lit.is_pos c.sclause.lits.(idx)
&&
BV.is_empty (Lazy.force c.selected)
&&
is_maxlit (c,sc) subst ~idx
(** are there selected literals in the clause? *)
let has_selected_lits c = not (BV.is_empty (Lazy.force c.selected))
(** Check whether the literal is selected *)
let is_selected c i = BV.get (Lazy.force c.selected) i
(** Indexed list of selected literals *)
let selected_lits c = BV.selecti (Lazy.force c.selected) c.sclause.lits
(** is the clause a unit clause? *)
let is_unit_clause c = match c.sclause.lits with
| [|_|] -> true
| _ -> false
let is_oriented_rule c =
let ord = Ctx.ord () in
match c.sclause.lits with
| [| Lit.Equation (l, r, true) |] ->
begin match Ordering.compare ord l r with
| Comparison.Gt
| Comparison.Lt -> true
| Comparison.Eq
| Comparison.Incomparable -> false
end
| [| Lit.Prop (_, true) |] -> true
| _ -> false
let symbols ?(init=ID.Set.empty) seq =
Iter.fold
(fun set c -> Lits.symbols ~init:set c.sclause.lits)
init seq
let to_forms c = Lits.Conv.to_forms c.sclause.lits
let to_sclause c = c.sclause
let to_s_form c = SClause.to_s_form c.sclause
module Seq = struct
let lits c = Iter.of_array c.sclause.lits
let terms c = lits c |> Iter.flat_map Lit.Seq.terms
let vars c = terms c |> Iter.flat_map T.Seq.vars
end
(** {2 Filter literals} *)
module Eligible = struct
type t = int -> Lit.t -> bool
let res c =
let bv = eligible_res (Scoped.make c 0) S.empty in
fun i _lit -> BV.get bv i
let param c =
let bv = eligible_param (Scoped.make c 0) S.empty in
fun i _lit -> BV.get bv i
let eq _ lit = match lit with
| Lit.Equation (_, _, true) -> true
| _ -> false
let arith _ lit = Lit.is_arith lit
let filter f _ lit = f lit
let max c =
let bv = lazy (Lits.maxlits ~ord:(Ctx.ord ()) c.sclause.lits) in
fun i _ -> BV.get (Lazy.force bv) i
let pos _ lit = Lit.is_pos lit
let neg _ lit = Lit.is_neg lit
let always _ _ = true
let combine l = match l with
| [] -> (fun _ _ -> true)
| [x] -> x
| [x; y] -> (fun i lit -> x i lit && y i lit)
| [x; y; z] -> (fun i lit -> x i lit && y i lit && z i lit)
| _ -> (fun i lit -> List.for_all (fun eligible -> eligible i lit) l)
let ( ** ) f1 f2 i lit = f1 i lit && f2 i lit
let ( ++ ) f1 f2 i lit = f1 i lit || f2 i lit
let ( ~~ ) f i lit = not (f i lit)
end
(** {2 Set of clauses} *)
(** Simple set *)
module ClauseSet = CCSet.Make(struct
type t = clause
let compare c1 c2 = SClause.compare c1.sclause c2.sclause
end)
(** {2 Positions in clauses} *)
module Pos = struct
let at c pos = Lits.Pos.at c.sclause.lits pos
end
module WithPos = struct
type t = {
clause : clause;
pos : Position.t;
term : T.t;
}
let compare t1 t2 =
let c = SClause.compare t1.clause.sclause t2.clause.sclause in
if c <> 0 then c else
let c = T.compare t1.term t2.term in
if c <> 0 then c else
Position.compare t1.pos t2.pos
let pp out t =
Format.fprintf out "@[clause @[%a@]@ at pos @[%a@]@]"
Lits.pp t.clause.sclause.lits Position.pp t.pos
end
(** {2 IO} *)
let pp_trail = SClause.pp_trail
let pp out c =
let pp_selected selected out i =
if BV.get selected i then Format.fprintf out "@{<Black>+@}"
and pp_maxlit maxlits out i =
if BV.get maxlits i then Format.fprintf out "@{<Black>*@}"
in
let selected = Lazy.force c.selected in
let max = maxlits (Scoped.make c 0) S.empty in
let pp_lits out lits =
if Array.length lits = 0
then CCFormat.string out "⊥"
else (
let pp_lit out (i,lit) =
Format.fprintf out "@[%a%a%a@]"
Lit.pp lit (pp_selected selected) i (pp_maxlit max) i
in
Format.fprintf out "[@[%a@]]"
(Util.pp_seq ~sep:" ∨ " pp_lit)
(Iter.of_array_i lits)
)
in
Format.fprintf out "@[%a@[<2>%a%a@]@]/%d"
SClause.pp_vars c.sclause pp_lits c.sclause.lits
SClause.pp_trail c.sclause.trail c.sclause.id;
()
let pp_tstp out c = SClause.pp_tstp out c.sclause
let pp_tstp_full out c = SClause.pp_tstp_full out c.sclause
let to_string = CCFormat.to_string pp
let pp_set out set =
Format.fprintf out "{@[<hv>%a@]}"
(Util.pp_seq ~sep:"," pp)
(ClauseSet.to_seq set)
let pp_set_tstp out set =
Format.fprintf out "@[<v>%a@]"
(Util.pp_seq ~sep:"," pp_tstp)
(ClauseSet.to_seq set)
let check_types c =
Util.debugf 5 "(@[check_types@ %a@])" (fun k->k pp c);
lits c
|> Literals.Seq.terms
|> Iter.iter
(fun t -> ignore (Term.rebuild_rec t))
end