76 |
76 |
77 (* ------------------------------------------------------------------------- *) |
77 (* ------------------------------------------------------------------------- *) |
78 (* resolve_raw_clauses: given a non-empty list of raw clauses, we fold *) |
78 (* resolve_raw_clauses: given a non-empty list of raw clauses, we fold *) |
79 (* resolution over the list (starting with its head), i.e. with two raw *) |
79 (* resolution over the list (starting with its head), i.e. with two raw *) |
80 (* clauses *) |
80 (* clauses *) |
81 (* [| x1; ... ; a; ...; xn |] ==> False *) |
81 (* x1; ... ; a; ...; xn |- False *) |
82 (* and *) |
82 (* and *) |
83 (* [| y1; ... ; a'; ...; ym |] ==> False *) |
83 (* y1; ... ; a'; ...; ym |- False *) |
84 (* (where a and a' are dual to each other), we first convert the first *) |
84 (* (where a and a' are dual to each other), we convert the first clause *) |
85 (* clause to *) |
85 (* to *) |
86 (* [| x1; ...; xn |] ==> a' *) |
86 (* x1; ...; xn |- a ==> False , *) |
87 (* (using swap_prem and perhaps notnotD), and then do a resolution with *) |
87 (* the second clause to *) |
88 (* the second clause to produce *) |
88 (* y1; ...; ym |- a' ==> False *) |
|
89 (* and then perform resolution with *) |
|
90 (* [| ?P ==> False; ~?P ==> False |] ==> False *) |
|
91 (* to produce *) |
89 (* [| y1; ...; x1; ...; xn; ...; yn |] ==> False *) |
92 (* [| y1; ...; x1; ...; xn; ...; yn |] ==> False *) |
90 (* amd finally remove duplicate literals. *) |
93 (* amd finally remove duplicate literals. *) |
91 (* ------------------------------------------------------------------------- *) |
94 (* ------------------------------------------------------------------------- *) |
92 |
95 |
93 (* Thm.thm list -> Thm.thm *) |
96 (* Thm.thm list -> Thm.thm *) |
100 | dual x = HOLogic.Not $ x |
103 | dual x = HOLogic.Not $ x |
101 |
104 |
102 fun is_neg (Const ("Not", _) $ _) = true |
105 fun is_neg (Const ("Not", _) $ _) = true |
103 | is_neg _ = false |
106 | is_neg _ = false |
104 |
107 |
|
108 (* see the comments on the term order below for why this implementation is sound *) |
|
109 (* (Term.term * Term.term -> order) -> Thm.cterm list -> Term.term -> Thm.cterm option *) |
|
110 fun member _ [] _ = NONE |
|
111 | member ord (y::ys) x = (case term_of y of (* "un-certifying" y is faster than certifying x *) |
|
112 Const ("Trueprop", _) $ y' => |
|
113 (* compare the order *) |
|
114 (case ord (x, y') of |
|
115 LESS => NONE |
|
116 | EQUAL => SOME y |
|
117 | GREATER => member ord ys x) |
|
118 | _ => |
|
119 (* no need to continue in this case *) |
|
120 NONE) |
|
121 |
105 (* find out which two hyps are used in the resolution *) |
122 (* find out which two hyps are used in the resolution *) |
106 (* Term.term list -> Term.term list -> Term.term * Term.term *) |
123 (* Thm.cterm list -> Thm.cterm list -> Thm.cterm * Thm.cterm *) |
107 fun res_hyps [] _ = |
124 fun res_hyps [] _ = |
108 raise THM ("Proof reconstruction failed (no literal for resolution)!", 0, []) |
125 raise THM ("Proof reconstruction failed (no literal for resolution)!", 0, []) |
109 | res_hyps _ [] = |
126 | res_hyps _ [] = |
110 raise THM ("Proof reconstruction failed (no literal for resolution)!", 0, []) |
127 raise THM ("Proof reconstruction failed (no literal for resolution)!", 0, []) |
111 | res_hyps ((Const ("Trueprop", _) $ x) :: xs) ys = |
128 | res_hyps (x :: xs) ys = |
112 let val dx = dual x in |
129 (case term_of x of |
|
130 Const ("Trueprop", _) $ lit => |
113 (* hyps are implemented as ordered list in the kernel, and *) |
131 (* hyps are implemented as ordered list in the kernel, and *) |
114 (* stripping 'Trueprop' should not change the order *) |
132 (* stripping 'Trueprop' should not change the order *) |
115 if OrdList.member Term.fast_term_ord ys dx then |
133 (case member Term.fast_term_ord ys (dual lit) of |
116 (x, dx) |
134 SOME y => (x, y) |
117 else |
135 | NONE => res_hyps xs ys) |
118 res_hyps xs ys |
136 | _ => |
119 end |
137 (* hyps are implemented as ordered list in the kernel, all hyps are of *) |
120 | res_hyps (_ :: xs) ys = |
138 (* the form 'Trueprop $ lit' or 'implies $ (negated clause) $ False', *) |
121 (* hyps are implemented as ordered list in the kernel, all hyps are of *) |
139 (* and the former are LESS than the latter according to the order -- *) |
122 (* the form 'Trueprop $ lit' or 'implies $ (negated clause) $ False', *) |
140 (* therefore there is no need to continue the search via *) |
123 (* and the former are LESS than the latter according to the order -- *) |
141 (* 'res_hyps xs ys' here *) |
124 (* therefore there is no need to continue the search via *) |
142 raise THM ("Proof reconstruction failed (no literal for resolution)!", 0, [])) |
125 (* 'res_hyps xs ys' here *) |
|
126 raise THM ("Proof reconstruction failed (no literal for resolution)!", 0, []) |
|
127 |
143 |
128 (* Thm.thm -> Thm.thm -> Thm.thm *) |
144 (* Thm.thm -> Thm.thm -> Thm.thm *) |
129 fun resolution c1 c2 = |
145 fun resolution c1 c2 = |
130 let |
146 let |
131 val _ = if !trace_sat then |
147 val _ = if !trace_sat then |
132 tracing ("Resolving clause: " ^ string_of_thm c1 ^ " (hyps: " ^ space_implode ", " (map (Sign.string_of_term (theory_of_thm c1)) (#hyps (rep_thm c1))) |
148 tracing ("Resolving clause: " ^ string_of_thm c1 ^ " (hyps: " ^ space_implode ", " (map (Sign.string_of_term (theory_of_thm c1)) (#hyps (rep_thm c1))) |
133 ^ ")\nwith clause: " ^ string_of_thm c2 ^ " (hyps: " ^ space_implode ", " (map (Sign.string_of_term (theory_of_thm c2)) (#hyps (rep_thm c2))) ^ ")") |
149 ^ ")\nwith clause: " ^ string_of_thm c2 ^ " (hyps: " ^ space_implode ", " (map (Sign.string_of_term (theory_of_thm c2)) (#hyps (rep_thm c2))) ^ ")") |
134 else () |
150 else () |
135 |
151 |
136 (* Term.term list -> Term.term list *) |
152 val hyps1 = (#hyps o crep_thm) c1 |
137 fun dest_filter_Trueprop [] = [] |
153 val hyps2 = (#hyps o crep_thm) c2 |
138 | dest_filter_Trueprop ((Const ("Trueprop", _) $ x) :: xs) = x :: dest_filter_Trueprop xs |
154 |
139 | dest_filter_Trueprop (_ :: xs) = dest_filter_Trueprop xs |
155 val (l1, l2) = res_hyps hyps1 hyps2 (* the two literals used for resolution *) |
140 |
156 val l1_is_neg = (is_neg o HOLogic.dest_Trueprop o term_of) l1 |
141 val hyps1 = (#hyps o rep_thm) c1 |
157 |
142 (* minor optimization: dest/filter over the second list outside 'res_hyps' to do it only once *) |
158 val c1' = Thm.implies_intr l1 c1 (* Gamma1 |- l1 ==> False *) |
143 val hyps2 = (dest_filter_Trueprop o #hyps o rep_thm) c2 |
159 val c2' = Thm.implies_intr l2 c2 (* Gamma2 |- l2 ==> False *) |
144 |
160 |
145 val (l1, l2) = res_hyps hyps1 hyps2 (* the two literals used for resolution, with 'Trueprop' stripped *) |
161 val res_thm = (* |- (lit ==> False) ==> (~lit ==> False) ==> False *) |
146 val is_neg = is_neg l1 |
|
147 |
|
148 val c1' = Thm.implies_intr (cterm_of (theory_of_thm c1) (HOLogic.mk_Trueprop l1)) c1 (* Gamma1 |- l1 ==> False *) |
|
149 val c2' = Thm.implies_intr (cterm_of (theory_of_thm c2) (HOLogic.mk_Trueprop l2)) c2 (* Gamma2 |- l2 ==> False *) |
|
150 |
|
151 val res_thm = (* |- (lit ==> False) ==> (~lit ==> False) ==> False *) |
|
152 let |
162 let |
153 val P = Var (("P", 0), HOLogic.boolT) |
163 val thy = theory_of_thm (if l1_is_neg then c2' else c1') |
154 val (lit, thy) = if is_neg then (l2, theory_of_thm c2') else (l1, theory_of_thm c1') |
164 val cP = cterm_of thy (Var (("P", 0), HOLogic.boolT)) |
155 val cterm = cterm_of thy |
165 val cLit = (cterm_of thy o HOLogic.dest_Trueprop o term_of) (if l1_is_neg then l2 else l1) |
156 in |
166 in |
157 Thm.instantiate ([], [(cterm P, cterm lit)]) resolution_thm |
167 Thm.instantiate ([], [(cP, cLit)]) resolution_thm |
158 end |
168 end |
159 |
169 |
160 val _ = if !trace_sat then |
170 val _ = if !trace_sat then |
161 tracing ("Resolution theorem: " ^ string_of_thm res_thm) |
171 tracing ("Resolution theorem: " ^ string_of_thm res_thm) |
162 else () |
172 else () |
163 |
173 |
164 val c_new = Thm.implies_elim (Thm.implies_elim res_thm (if is_neg then c2' else c1')) (if is_neg then c1' else c2') (* Gamma1, Gamma2 |- False *) |
174 val c_new = Thm.implies_elim (Thm.implies_elim res_thm (if l1_is_neg then c2' else c1')) (if l1_is_neg then c1' else c2') (* Gamma1, Gamma2 |- False *) |
165 |
175 |
166 val _ = if !trace_sat then |
176 val _ = if !trace_sat then |
167 tracing ("Resulting clause: " ^ string_of_thm c_new ^ " (hyps: " ^ space_implode ", " (map (Sign.string_of_term (theory_of_thm c_new)) (#hyps (rep_thm c_new))) ^ ")") |
177 tracing ("Resulting clause: " ^ string_of_thm c_new ^ " (hyps: " ^ space_implode ", " (map (Sign.string_of_term (theory_of_thm c_new)) (#hyps (rep_thm c_new))) ^ ")") |
168 else () |
178 else () |
169 val _ = inc counter |
179 val _ = inc counter |