-
Notifications
You must be signed in to change notification settings - Fork 0
/
cong.ml
85 lines (67 loc) · 3.45 KB
/
cong.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
(* ========================================================================= *)
(* Simple congruence closure. *)
(* *)
(* Copyright (c) 2003-2007, John Harrison. (See "LICENSE.txt" for details.) *)
(* ========================================================================= *)
let rec subterms tm =
match tm with
Fn(f,args) -> itlist (union ** subterms) args [tm]
| _ -> [tm];;
(* ------------------------------------------------------------------------- *)
(* Test whether subterms are congruent under an equivalence. *)
(* ------------------------------------------------------------------------- *)
let congruent eqv (s,t) =
match (s,t) with
Fn(f,a1),Fn(g,a2) -> f = g & forall2 (equivalent eqv) a1 a2
| _ -> false;;
(* ------------------------------------------------------------------------- *)
(* Merging of terms, with congruence closure. *)
(* ------------------------------------------------------------------------- *)
let rec emerge (s,t) (eqv,pfn) =
let s' = canonize eqv s and t' = canonize eqv t in
if s' = t' then (eqv,pfn) else
let sp = tryapplyl pfn s' and tp = tryapplyl pfn t' in
let eqv' = equate (s,t) eqv in
let st' = canonize eqv' s' in
let pfn' = (st' |-> union sp tp) pfn in
itlist (fun (u,v) (eqv,pfn) ->
if congruent eqv (u,v) then emerge (u,v) (eqv,pfn)
else eqv,pfn)
(allpairs (fun u v -> (u,v)) sp tp) (eqv',pfn');;
(* ------------------------------------------------------------------------- *)
(* Satisfiability of conjunction of ground equations and inequations. *)
(* ------------------------------------------------------------------------- *)
let predecessors t pfn =
match t with
Fn(f,a) -> itlist (fun s f -> (s |-> insert t (tryapplyl f s)) f)
(setify a) pfn
| _ -> pfn;;
let ccsatisfiable fms =
let pos,neg = partition positive fms in
let eqps = map dest_eq pos and eqns = map (dest_eq ** negate) neg in
let lrs = map fst eqps @ map snd eqps @ map fst eqns @ map snd eqns in
let pfn = itlist predecessors (unions(map subterms lrs)) undefined in
let eqv,_ = itlist emerge eqps (unequal,pfn) in
forall (fun (l,r) -> not(equivalent eqv l r)) eqns;;
(* ------------------------------------------------------------------------- *)
(* Validity checking a universal formula. *)
(* ------------------------------------------------------------------------- *)
let ccvalid fm =
let fms = simpdnf(askolemize(Not(generalize fm))) in
not (exists ccsatisfiable fms);;
(* ------------------------------------------------------------------------- *)
(* Example. *)
(* ------------------------------------------------------------------------- *)
START_INTERACTIVE;;
ccvalid <<f(f(f(f(f(c))))) = c /\ f(f(f(c))) = c
==> f(c) = c \/ f(g(c)) = g(f(c))>>;;
ccvalid <<f(f(f(f(c)))) = c /\ f(f(c)) = c ==> f(c) = c>>;;
(* ------------------------------------------------------------------------- *)
(* For debugging. Maybe I will incorporate into a prettyprinter one day. *)
(* ------------------------------------------------------------------------- *)
(**********
let showequiv ptn =
let fn = reverseq (equated ptn) ptn in
map (apply fn) (dom fn);;
**********)
END_INTERACTIVE;;