| author | wenzelm | 
| Sat, 15 Jan 2011 14:02:24 +0100 | |
| changeset 41572 | 089049b768c6 | 
| parent 41491 | a2ad5b824051 | 
| child 44058 | ae85c5d64913 | 
| permissions | -rw-r--r-- | 
| 17618 | 1 | (* Title: HOL/Tools/sat_funcs.ML | 
| 2 | Author: Stephan Merz and Alwen Tiu, QSL Team, LORIA (http://qsl.loria.fr) | |
| 29269 
5c25a2012975
moved term order operations to structure TermOrd (cf. Pure/term_ord.ML);
 wenzelm parents: 
27115diff
changeset | 3 | Author: Tjark Weber, TU Muenchen | 
| 17618 | 4 | |
| 5 | Proof reconstruction from SAT solvers. | |
| 6 | ||
| 7 | Description: | |
| 8 | This file defines several tactics to invoke a proof-producing | |
| 9 | SAT solver on a propositional goal in clausal form. | |
| 10 | ||
| 11 | We use a sequent presentation of clauses to speed up resolution | |
| 17695 | 12 | proof reconstruction. | 
| 13 | We call such clauses "raw clauses", which are of the form | |
| 20440 
e6fe74eebda3
faster clause representation (again): full CNF formula as a hypothesis, instead of separate clauses
 webertj parents: 
20371diff
changeset | 14 | [x1, ..., xn, P] |- False | 
| 19236 
150e8b0fb991
clauses now use (meta-)hyps instead of (meta-)implications; significant speedup
 webertj parents: 
17843diff
changeset | 15 | (note the use of |- instead of ==>, i.e. of Isabelle's (meta-)hyps here), | 
| 20440 
e6fe74eebda3
faster clause representation (again): full CNF formula as a hypothesis, instead of separate clauses
 webertj parents: 
20371diff
changeset | 16 | where each xi is a literal (see also comments in cnf_funcs.ML). | 
| 17618 | 17 | |
| 19236 
150e8b0fb991
clauses now use (meta-)hyps instead of (meta-)implications; significant speedup
 webertj parents: 
17843diff
changeset | 18 | This does not work for goals containing schematic variables! | 
| 
150e8b0fb991
clauses now use (meta-)hyps instead of (meta-)implications; significant speedup
 webertj parents: 
17843diff
changeset | 19 | |
| 20039 
4293f932fe83
"solver" reference added to make the SAT solver configurable
 webertj parents: 
19976diff
changeset | 20 | The tactic produces a clause representation of the given goal | 
| 
4293f932fe83
"solver" reference added to make the SAT solver configurable
 webertj parents: 
19976diff
changeset | 21 | in DIMACS format and invokes a SAT solver, which should return | 
| 
4293f932fe83
"solver" reference added to make the SAT solver configurable
 webertj parents: 
19976diff
changeset | 22 | a proof consisting of a sequence of resolution steps, indicating | 
| 
4293f932fe83
"solver" reference added to make the SAT solver configurable
 webertj parents: 
19976diff
changeset | 23 | the two input clauses, and resulting in new clauses, leading to | 
| 
4293f932fe83
"solver" reference added to make the SAT solver configurable
 webertj parents: 
19976diff
changeset | 24 | the empty clause (i.e. "False"). The tactic replays this proof | 
| 
4293f932fe83
"solver" reference added to make the SAT solver configurable
 webertj parents: 
19976diff
changeset | 25 | in Isabelle and thus solves the overall goal. | 
| 17618 | 26 | |
| 20440 
e6fe74eebda3
faster clause representation (again): full CNF formula as a hypothesis, instead of separate clauses
 webertj parents: 
20371diff
changeset | 27 | There are three SAT tactics available. They differ in the CNF transformation | 
| 20039 
4293f932fe83
"solver" reference added to make the SAT solver configurable
 webertj parents: 
19976diff
changeset | 28 | used. "sat_tac" uses naive CNF transformation to transform the theorem to be | 
| 
4293f932fe83
"solver" reference added to make the SAT solver configurable
 webertj parents: 
19976diff
changeset | 29 | proved before giving it to the SAT solver. The naive transformation in the | 
| 20440 
e6fe74eebda3
faster clause representation (again): full CNF formula as a hypothesis, instead of separate clauses
 webertj parents: 
20371diff
changeset | 30 | worst case can lead to an exponential blow up in formula size. Another | 
| 20039 
4293f932fe83
"solver" reference added to make the SAT solver configurable
 webertj parents: 
19976diff
changeset | 31 | tactic, "satx_tac", uses "definitional CNF transformation" which attempts to | 
| 
4293f932fe83
"solver" reference added to make the SAT solver configurable
 webertj parents: 
19976diff
changeset | 32 | produce a formula of linear size increase compared to the input formula, at | 
| 
4293f932fe83
"solver" reference added to make the SAT solver configurable
 webertj parents: 
19976diff
changeset | 33 | the cost of possibly introducing new variables. See cnf_funcs.ML for more | 
| 20440 
e6fe74eebda3
faster clause representation (again): full CNF formula as a hypothesis, instead of separate clauses
 webertj parents: 
20371diff
changeset | 34 | comments on the CNF transformation. "rawsat_tac" should be used with | 
| 
e6fe74eebda3
faster clause representation (again): full CNF formula as a hypothesis, instead of separate clauses
 webertj parents: 
20371diff
changeset | 35 | caution: no CNF transformation is performed, and the tactic's behavior is | 
| 
e6fe74eebda3
faster clause representation (again): full CNF formula as a hypothesis, instead of separate clauses
 webertj parents: 
20371diff
changeset | 36 | undefined if the subgoal is not already given as [| C1; ...; Cn |] ==> False, | 
| 
e6fe74eebda3
faster clause representation (again): full CNF formula as a hypothesis, instead of separate clauses
 webertj parents: 
20371diff
changeset | 37 | where each Ci is a disjunction. | 
| 17618 | 38 | |
| 20039 
4293f932fe83
"solver" reference added to make the SAT solver configurable
 webertj parents: 
19976diff
changeset | 39 | The SAT solver to be used can be set via the "solver" reference. See | 
| 
4293f932fe83
"solver" reference added to make the SAT solver configurable
 webertj parents: 
19976diff
changeset | 40 | sat_solvers.ML for possible values, and etc/settings for required (solver- | 
| 
4293f932fe83
"solver" reference added to make the SAT solver configurable
 webertj parents: 
19976diff
changeset | 41 | dependent) configuration settings. To replay SAT proofs in Isabelle, you | 
| 
4293f932fe83
"solver" reference added to make the SAT solver configurable
 webertj parents: 
19976diff
changeset | 42 | must of course use a proof-producing SAT solver in the first place. | 
| 
4293f932fe83
"solver" reference added to make the SAT solver configurable
 webertj parents: 
19976diff
changeset | 43 | |
| 
4293f932fe83
"solver" reference added to make the SAT solver configurable
 webertj parents: 
19976diff
changeset | 44 | Proofs are replayed only if "!quick_and_dirty" is false. If | 
| 
4293f932fe83
"solver" reference added to make the SAT solver configurable
 webertj parents: 
19976diff
changeset | 45 | "!quick_and_dirty" is true, the theorem (in case the SAT solver claims its | 
| 
4293f932fe83
"solver" reference added to make the SAT solver configurable
 webertj parents: 
19976diff
changeset | 46 | negation to be unsatisfiable) is proved via an oracle. | 
| 17618 | 47 | *) | 
| 48 | ||
| 49 | signature SAT = | |
| 50 | sig | |
| 41447 | 51 | val trace_sat: bool Unsynchronized.ref (* input: print trace messages *) | 
| 52 | val solver: string Unsynchronized.ref (* input: name of SAT solver to be used *) | |
| 53 | val counter: int Unsynchronized.ref (* output: number of resolution steps during last proof replay *) | |
| 54 | val rawsat_thm: Proof.context -> cterm list -> thm | |
| 55 | val rawsat_tac: Proof.context -> int -> tactic | |
| 56 | val sat_tac: Proof.context -> int -> tactic | |
| 57 | val satx_tac: Proof.context -> int -> tactic | |
| 17618 | 58 | end | 
| 59 | ||
| 32232 | 60 | functor SATFunc(cnf : CNF) : SAT = | 
| 17622 
5d03a69481b6
code reformatted and restructured, many minor modifications
 webertj parents: 
17618diff
changeset | 61 | struct | 
| 17618 | 62 | |
| 32740 | 63 | val trace_sat = Unsynchronized.ref false; | 
| 17622 
5d03a69481b6
code reformatted and restructured, many minor modifications
 webertj parents: 
17618diff
changeset | 64 | |
| 32740 | 65 | val solver = Unsynchronized.ref "zchaff_with_proofs"; | 
| 66 | (*see HOL/Tools/sat_solver.ML for possible values*) | |
| 20039 
4293f932fe83
"solver" reference added to make the SAT solver configurable
 webertj parents: 
19976diff
changeset | 67 | |
| 32740 | 68 | val counter = Unsynchronized.ref 0; | 
| 17622 
5d03a69481b6
code reformatted and restructured, many minor modifications
 webertj parents: 
17618diff
changeset | 69 | |
| 32010 | 70 | val resolution_thm = | 
| 71 |   @{lemma "(P ==> False) ==> (~ P ==> False) ==> False" by (rule case_split)}
 | |
| 17622 
5d03a69481b6
code reformatted and restructured, many minor modifications
 webertj parents: 
17618diff
changeset | 72 | |
| 32010 | 73 | val cP = cterm_of @{theory} (Var (("P", 0), HOLogic.boolT));
 | 
| 20278 
28be10991666
proof reconstruction now uses its own data structure to manage hyps; should be both faster and more robust
 webertj parents: 
20170diff
changeset | 74 | |
| 
28be10991666
proof reconstruction now uses its own data structure to manage hyps; should be both faster and more robust
 webertj parents: 
20170diff
changeset | 75 | (* ------------------------------------------------------------------------- *) | 
| 21768 
69165d27b55b
ordered lists instead of tables for resolving hyps; speedup
 webertj parents: 
21756diff
changeset | 76 | (* lit_ord: an order on integers that considers their absolute values only, *) | 
| 
69165d27b55b
ordered lists instead of tables for resolving hyps; speedup
 webertj parents: 
21756diff
changeset | 77 | (* thereby treating integers that represent the same atom (positively *) | 
| 
69165d27b55b
ordered lists instead of tables for resolving hyps; speedup
 webertj parents: 
21756diff
changeset | 78 | (* or negatively) as equal *) | 
| 
69165d27b55b
ordered lists instead of tables for resolving hyps; speedup
 webertj parents: 
21756diff
changeset | 79 | (* ------------------------------------------------------------------------- *) | 
| 
69165d27b55b
ordered lists instead of tables for resolving hyps; speedup
 webertj parents: 
21756diff
changeset | 80 | |
| 41447 | 81 | fun lit_ord (i, j) = int_ord (abs i, abs j); | 
| 21768 
69165d27b55b
ordered lists instead of tables for resolving hyps; speedup
 webertj parents: 
21756diff
changeset | 82 | |
| 
69165d27b55b
ordered lists instead of tables for resolving hyps; speedup
 webertj parents: 
21756diff
changeset | 83 | (* ------------------------------------------------------------------------- *) | 
| 20278 
28be10991666
proof reconstruction now uses its own data structure to manage hyps; should be both faster and more robust
 webertj parents: 
20170diff
changeset | 84 | (* CLAUSE: during proof reconstruction, three kinds of clauses are *) | 
| 
28be10991666
proof reconstruction now uses its own data structure to manage hyps; should be both faster and more robust
 webertj parents: 
20170diff
changeset | 85 | (* distinguished: *) | 
| 
28be10991666
proof reconstruction now uses its own data structure to manage hyps; should be both faster and more robust
 webertj parents: 
20170diff
changeset | 86 | (* 1. NO_CLAUSE: clause not proved (yet) *) | 
| 
28be10991666
proof reconstruction now uses its own data structure to manage hyps; should be both faster and more robust
 webertj parents: 
20170diff
changeset | 87 | (* 2. ORIG_CLAUSE: a clause as it occurs in the original problem *) | 
| 
28be10991666
proof reconstruction now uses its own data structure to manage hyps; should be both faster and more robust
 webertj parents: 
20170diff
changeset | 88 | (* 3. RAW_CLAUSE: a raw clause, with additional precomputed information *) | 
| 
28be10991666
proof reconstruction now uses its own data structure to manage hyps; should be both faster and more robust
 webertj parents: 
20170diff
changeset | 89 | (* (a mapping from int's to its literals) for faster proof *) | 
| 
28be10991666
proof reconstruction now uses its own data structure to manage hyps; should be both faster and more robust
 webertj parents: 
20170diff
changeset | 90 | (* reconstruction *) | 
| 
28be10991666
proof reconstruction now uses its own data structure to manage hyps; should be both faster and more robust
 webertj parents: 
20170diff
changeset | 91 | (* ------------------------------------------------------------------------- *) | 
| 
28be10991666
proof reconstruction now uses its own data structure to manage hyps; should be both faster and more robust
 webertj parents: 
20170diff
changeset | 92 | |
| 41447 | 93 | datatype CLAUSE = | 
| 94 | NO_CLAUSE | |
| 95 | | ORIG_CLAUSE of thm | |
| 96 | | RAW_CLAUSE of thm * (int * cterm) list; | |
| 20278 
28be10991666
proof reconstruction now uses its own data structure to manage hyps; should be both faster and more robust
 webertj parents: 
20170diff
changeset | 97 | |
| 17622 
5d03a69481b6
code reformatted and restructured, many minor modifications
 webertj parents: 
17618diff
changeset | 98 | (* ------------------------------------------------------------------------- *) | 
| 17809 
195045659c06
Tactics sat and satx reimplemented, several improvements
 webertj parents: 
17697diff
changeset | 99 | (* resolve_raw_clauses: given a non-empty list of raw clauses, we fold *) | 
| 
195045659c06
Tactics sat and satx reimplemented, several improvements
 webertj parents: 
17697diff
changeset | 100 | (* resolution over the list (starting with its head), i.e. with two raw *) | 
| 
195045659c06
Tactics sat and satx reimplemented, several improvements
 webertj parents: 
17697diff
changeset | 101 | (* clauses *) | 
| 20440 
e6fe74eebda3
faster clause representation (again): full CNF formula as a hypothesis, instead of separate clauses
 webertj parents: 
20371diff
changeset | 102 | (* [P, x1, ..., a, ..., xn] |- False *) | 
| 17622 
5d03a69481b6
code reformatted and restructured, many minor modifications
 webertj parents: 
17618diff
changeset | 103 | (* and *) | 
| 20440 
e6fe74eebda3
faster clause representation (again): full CNF formula as a hypothesis, instead of separate clauses
 webertj parents: 
20371diff
changeset | 104 | (* [Q, y1, ..., a', ..., ym] |- False *) | 
| 19976 
aa35f8e27c73
comments fixed, minor optimization wrt. certifying terms
 webertj parents: 
19553diff
changeset | 105 | (* (where a and a' are dual to each other), we convert the first clause *) | 
| 
aa35f8e27c73
comments fixed, minor optimization wrt. certifying terms
 webertj parents: 
19553diff
changeset | 106 | (* to *) | 
| 20440 
e6fe74eebda3
faster clause representation (again): full CNF formula as a hypothesis, instead of separate clauses
 webertj parents: 
20371diff
changeset | 107 | (* [P, x1, ..., xn] |- a ==> False , *) | 
| 19976 
aa35f8e27c73
comments fixed, minor optimization wrt. certifying terms
 webertj parents: 
19553diff
changeset | 108 | (* the second clause to *) | 
| 20440 
e6fe74eebda3
faster clause representation (again): full CNF formula as a hypothesis, instead of separate clauses
 webertj parents: 
20371diff
changeset | 109 | (* [Q, y1, ..., ym] |- a' ==> False *) | 
| 19976 
aa35f8e27c73
comments fixed, minor optimization wrt. certifying terms
 webertj parents: 
19553diff
changeset | 110 | (* and then perform resolution with *) | 
| 
aa35f8e27c73
comments fixed, minor optimization wrt. certifying terms
 webertj parents: 
19553diff
changeset | 111 | (* [| ?P ==> False; ~?P ==> False |] ==> False *) | 
| 
aa35f8e27c73
comments fixed, minor optimization wrt. certifying terms
 webertj parents: 
19553diff
changeset | 112 | (* to produce *) | 
| 20440 
e6fe74eebda3
faster clause representation (again): full CNF formula as a hypothesis, instead of separate clauses
 webertj parents: 
20371diff
changeset | 113 | (* [P, Q, x1, ..., xn, y1, ..., ym] |- False *) | 
| 21768 
69165d27b55b
ordered lists instead of tables for resolving hyps; speedup
 webertj parents: 
21756diff
changeset | 114 | (* Each clause is accompanied with an association list mapping integers *) | 
| 
69165d27b55b
ordered lists instead of tables for resolving hyps; speedup
 webertj parents: 
21756diff
changeset | 115 | (* (positive for positive literals, negative for negative literals, and *) | 
| 
69165d27b55b
ordered lists instead of tables for resolving hyps; speedup
 webertj parents: 
21756diff
changeset | 116 | (* the same absolute value for dual literals) to the actual literals as *) | 
| 
69165d27b55b
ordered lists instead of tables for resolving hyps; speedup
 webertj parents: 
21756diff
changeset | 117 | (* cterms. *) | 
| 17622 
5d03a69481b6
code reformatted and restructured, many minor modifications
 webertj parents: 
17618diff
changeset | 118 | (* ------------------------------------------------------------------------- *) | 
| 17618 | 119 | |
| 17809 
195045659c06
Tactics sat and satx reimplemented, several improvements
 webertj parents: 
17697diff
changeset | 120 | fun resolve_raw_clauses [] = | 
| 32091 
30e2ffbba718
proper context for Display.pretty_thm etc. or old-style versions Display.pretty_thm_global, Display.pretty_thm_without_context etc.;
 wenzelm parents: 
32010diff
changeset | 121 |       raise THM ("Proof reconstruction failed (empty list of resolvents)!", 0, [])
 | 
| 17809 
195045659c06
Tactics sat and satx reimplemented, several improvements
 webertj parents: 
17697diff
changeset | 122 | | resolve_raw_clauses (c::cs) = | 
| 41447 | 123 | let | 
| 124 | (* merges two sorted lists wrt. 'lit_ord', suppressing duplicates *) | |
| 125 | fun merge xs [] = xs | |
| 126 | | merge [] ys = ys | |
| 127 | | merge (x :: xs) (y :: ys) = | |
| 128 | (case (lit_ord o pairself fst) (x, y) of | |
| 129 | LESS => x :: merge xs (y :: ys) | |
| 130 | | EQUAL => x :: merge xs ys | |
| 131 | | GREATER => y :: merge (x :: xs) ys) | |
| 21768 
69165d27b55b
ordered lists instead of tables for resolving hyps; speedup
 webertj parents: 
21756diff
changeset | 132 | |
| 41447 | 133 | (* find out which two hyps are used in the resolution *) | 
| 134 | fun find_res_hyps ([], _) _ = | |
| 135 |               raise THM ("Proof reconstruction failed (no literal for resolution)!", 0, [])
 | |
| 136 | | find_res_hyps (_, []) _ = | |
| 137 |               raise THM ("Proof reconstruction failed (no literal for resolution)!", 0, [])
 | |
| 138 | | find_res_hyps (h1 :: hyps1, h2 :: hyps2) acc = | |
| 139 | (case (lit_ord o pairself fst) (h1, h2) of | |
| 140 | LESS => find_res_hyps (hyps1, h2 :: hyps2) (h1 :: acc) | |
| 141 | | EQUAL => | |
| 142 | let | |
| 143 | val (i1, chyp1) = h1 | |
| 144 | val (i2, chyp2) = h2 | |
| 145 | in | |
| 146 | if i1 = ~ i2 then | |
| 147 | (i1 < 0, chyp1, chyp2, rev acc @ merge hyps1 hyps2) | |
| 148 | else (* i1 = i2 *) | |
| 149 | find_res_hyps (hyps1, hyps2) (h1 :: acc) | |
| 150 | end | |
| 151 | | GREATER => find_res_hyps (h1 :: hyps1, hyps2) (h2 :: acc)) | |
| 19976 
aa35f8e27c73
comments fixed, minor optimization wrt. certifying terms
 webertj parents: 
19553diff
changeset | 152 | |
| 41447 | 153 | fun resolution (c1, hyps1) (c2, hyps2) = | 
| 154 | let | |
| 155 | val _ = | |
| 156 | if ! trace_sat then | |
| 157 |                 tracing ("Resolving clause: " ^ Display.string_of_thm_without_context c1 ^
 | |
| 158 | " (hyps: " ^ ML_Syntax.print_list (Syntax.string_of_term_global (theory_of_thm c1)) (#hyps (rep_thm c1)) | |
| 159 | ^ ")\nwith clause: " ^ Display.string_of_thm_without_context c2 ^ | |
| 160 | " (hyps: " ^ ML_Syntax.print_list (Syntax.string_of_term_global (theory_of_thm c2)) (#hyps (rep_thm c2)) ^ ")") | |
| 161 | else () | |
| 17809 
195045659c06
Tactics sat and satx reimplemented, several improvements
 webertj parents: 
17697diff
changeset | 162 | |
| 41447 | 163 | (* the two literals used for resolution *) | 
| 164 | val (hyp1_is_neg, hyp1, hyp2, new_hyps) = find_res_hyps (hyps1, hyps2) [] | |
| 19236 
150e8b0fb991
clauses now use (meta-)hyps instead of (meta-)implications; significant speedup
 webertj parents: 
17843diff
changeset | 165 | |
| 41447 | 166 | val c1' = Thm.implies_intr hyp1 c1 (* Gamma1 |- hyp1 ==> False *) | 
| 167 | val c2' = Thm.implies_intr hyp2 c2 (* Gamma2 |- hyp2 ==> False *) | |
| 17618 | 168 | |
| 41447 | 169 | val res_thm = (* |- (lit ==> False) ==> (~lit ==> False) ==> False *) | 
| 170 | let | |
| 171 | val cLit = | |
| 172 | snd (Thm.dest_comb (if hyp1_is_neg then hyp2 else hyp1)) (* strip Trueprop *) | |
| 173 | in | |
| 174 | Thm.instantiate ([], [(cP, cLit)]) resolution_thm | |
| 175 | end | |
| 19236 
150e8b0fb991
clauses now use (meta-)hyps instead of (meta-)implications; significant speedup
 webertj parents: 
17843diff
changeset | 176 | |
| 41447 | 177 | val _ = | 
| 178 | if !trace_sat then | |
| 179 |                 tracing ("Resolution theorem: " ^ Display.string_of_thm_without_context res_thm)
 | |
| 180 | else () | |
| 19236 
150e8b0fb991
clauses now use (meta-)hyps instead of (meta-)implications; significant speedup
 webertj parents: 
17843diff
changeset | 181 | |
| 41447 | 182 | (* Gamma1, Gamma2 |- False *) | 
| 183 | val c_new = | |
| 184 | Thm.implies_elim | |
| 185 | (Thm.implies_elim res_thm (if hyp1_is_neg then c2' else c1')) | |
| 186 | (if hyp1_is_neg then c1' else c2') | |
| 20278 
28be10991666
proof reconstruction now uses its own data structure to manage hyps; should be both faster and more robust
 webertj parents: 
20170diff
changeset | 187 | |
| 41447 | 188 | val _ = | 
| 189 | if !trace_sat then | |
| 190 |                 tracing ("Resulting clause: " ^ Display.string_of_thm_without_context c_new ^
 | |
| 191 | " (hyps: " ^ ML_Syntax.print_list | |
| 192 | (Syntax.string_of_term_global (theory_of_thm c_new)) (#hyps (rep_thm c_new)) ^ ")") | |
| 193 | else () | |
| 194 | val _ = Unsynchronized.inc counter | |
| 195 | in | |
| 196 | (c_new, new_hyps) | |
| 197 | end | |
| 198 | in | |
| 199 | fold resolution cs c | |
| 200 | end; | |
| 17618 | 201 | |
| 17622 
5d03a69481b6
code reformatted and restructured, many minor modifications
 webertj parents: 
17618diff
changeset | 202 | (* ------------------------------------------------------------------------- *) | 
| 17809 
195045659c06
Tactics sat and satx reimplemented, several improvements
 webertj parents: 
17697diff
changeset | 203 | (* replay_proof: replays the resolution proof returned by the SAT solver; *) | 
| 
195045659c06
Tactics sat and satx reimplemented, several improvements
 webertj parents: 
17697diff
changeset | 204 | (* cf. SatSolver.proof for details of the proof format. Updates the *) | 
| 
195045659c06
Tactics sat and satx reimplemented, several improvements
 webertj parents: 
17697diff
changeset | 205 | (* 'clauses' array with derived clauses, and returns the derived clause *) | 
| 
195045659c06
Tactics sat and satx reimplemented, several improvements
 webertj parents: 
17697diff
changeset | 206 | (* at index 'empty_id' (which should just be "False" if proof *) | 
| 
195045659c06
Tactics sat and satx reimplemented, several improvements
 webertj parents: 
17697diff
changeset | 207 | (* reconstruction was successful, with the used clauses as hyps). *) | 
| 20278 
28be10991666
proof reconstruction now uses its own data structure to manage hyps; should be both faster and more robust
 webertj parents: 
20170diff
changeset | 208 | (* 'atom_table' must contain an injective mapping from all atoms that *) | 
| 
28be10991666
proof reconstruction now uses its own data structure to manage hyps; should be both faster and more robust
 webertj parents: 
20170diff
changeset | 209 | (* occur (as part of a literal) in 'clauses' to positive integers. *) | 
| 17622 
5d03a69481b6
code reformatted and restructured, many minor modifications
 webertj parents: 
17618diff
changeset | 210 | (* ------------------------------------------------------------------------- *) | 
| 
5d03a69481b6
code reformatted and restructured, many minor modifications
 webertj parents: 
17618diff
changeset | 211 | |
| 20278 
28be10991666
proof reconstruction now uses its own data structure to manage hyps; should be both faster and more robust
 webertj parents: 
20170diff
changeset | 212 | fun replay_proof atom_table clauses (clause_table, empty_id) = | 
| 41447 | 213 | let | 
| 214 | fun index_of_literal chyp = | |
| 215 | (case (HOLogic.dest_Trueprop o Thm.term_of) chyp of | |
| 216 |         (Const (@{const_name Not}, _) $ atom) =>
 | |
| 217 | SOME (~ (the (Termtab.lookup atom_table atom))) | |
| 218 | | atom => SOME (the (Termtab.lookup atom_table atom))) | |
| 219 | handle TERM _ => NONE; (* 'chyp' is not a literal *) | |
| 20278 
28be10991666
proof reconstruction now uses its own data structure to manage hyps; should be both faster and more robust
 webertj parents: 
20170diff
changeset | 220 | |
| 41447 | 221 | fun prove_clause id = | 
| 222 | (case Array.sub (clauses, id) of | |
| 223 | RAW_CLAUSE clause => clause | |
| 224 | | ORIG_CLAUSE thm => | |
| 225 | (* convert the original clause *) | |
| 226 | let | |
| 227 | val _ = | |
| 228 |               if !trace_sat then tracing ("Using original clause #" ^ string_of_int id) else ()
 | |
| 229 | val raw = cnf.clause2raw_thm thm | |
| 230 | val hyps = sort (lit_ord o pairself fst) (map_filter (fn chyp => | |
| 231 | Option.map (rpair chyp) (index_of_literal chyp)) (#hyps (Thm.crep_thm raw))) | |
| 232 | val clause = (raw, hyps) | |
| 233 | val _ = Array.update (clauses, id, RAW_CLAUSE clause) | |
| 234 | in | |
| 235 | clause | |
| 236 | end | |
| 237 | | NO_CLAUSE => | |
| 238 | (* prove the clause, using information from 'clause_table' *) | |
| 239 | let | |
| 240 | val _ = | |
| 241 |               if !trace_sat then tracing ("Proving clause #" ^ string_of_int id ^ " ...") else ()
 | |
| 242 | val ids = the (Inttab.lookup clause_table id) | |
| 243 | val clause = resolve_raw_clauses (map prove_clause ids) | |
| 244 | val _ = Array.update (clauses, id, RAW_CLAUSE clause) | |
| 245 | val _ = | |
| 246 | if !trace_sat then | |
| 247 |                 tracing ("Replay chain successful; clause stored at #" ^ string_of_int id)
 | |
| 248 | else () | |
| 249 | in | |
| 250 | clause | |
| 251 | end) | |
| 17618 | 252 | |
| 41447 | 253 | val _ = counter := 0 | 
| 254 | val empty_clause = fst (prove_clause empty_id) | |
| 255 | val _ = | |
| 256 | if !trace_sat then | |
| 257 |         tracing ("Proof reconstruction successful; " ^
 | |
| 258 | string_of_int (!counter) ^ " resolution step(s) total.") | |
| 259 | else () | |
| 260 | in | |
| 261 | empty_clause | |
| 262 | end; | |
| 17622 
5d03a69481b6
code reformatted and restructured, many minor modifications
 webertj parents: 
17618diff
changeset | 263 | |
| 20278 
28be10991666
proof reconstruction now uses its own data structure to manage hyps; should be both faster and more robust
 webertj parents: 
20170diff
changeset | 264 | (* ------------------------------------------------------------------------- *) | 
| 
28be10991666
proof reconstruction now uses its own data structure to manage hyps; should be both faster and more robust
 webertj parents: 
20170diff
changeset | 265 | (* string_of_prop_formula: return a human-readable string representation of *) | 
| 
28be10991666
proof reconstruction now uses its own data structure to manage hyps; should be both faster and more robust
 webertj parents: 
20170diff
changeset | 266 | (* a 'prop_formula' (just for tracing) *) | 
| 
28be10991666
proof reconstruction now uses its own data structure to manage hyps; should be both faster and more robust
 webertj parents: 
20170diff
changeset | 267 | (* ------------------------------------------------------------------------- *) | 
| 
28be10991666
proof reconstruction now uses its own data structure to manage hyps; should be both faster and more robust
 webertj parents: 
20170diff
changeset | 268 | |
| 41471 | 269 | fun string_of_prop_formula Prop_Logic.True = "True" | 
| 270 | | string_of_prop_formula Prop_Logic.False = "False" | |
| 271 | | string_of_prop_formula (Prop_Logic.BoolVar i) = "x" ^ string_of_int i | |
| 272 | | string_of_prop_formula (Prop_Logic.Not fm) = "~" ^ string_of_prop_formula fm | |
| 273 | | string_of_prop_formula (Prop_Logic.Or (fm1, fm2)) = | |
| 41447 | 274 |       "(" ^ string_of_prop_formula fm1 ^ " v " ^ string_of_prop_formula fm2 ^ ")"
 | 
| 41471 | 275 | | string_of_prop_formula (Prop_Logic.And (fm1, fm2)) = | 
| 41447 | 276 |       "(" ^ string_of_prop_formula fm1 ^ " & " ^ string_of_prop_formula fm2 ^ ")";
 | 
| 17622 
5d03a69481b6
code reformatted and restructured, many minor modifications
 webertj parents: 
17618diff
changeset | 277 | |
| 
5d03a69481b6
code reformatted and restructured, many minor modifications
 webertj parents: 
17618diff
changeset | 278 | (* ------------------------------------------------------------------------- *) | 
| 21267 | 279 | (* rawsat_thm: run external SAT solver with the given clauses. Reconstructs *) | 
| 280 | (* a proof from the resulting proof trace of the SAT solver. The *) | |
| 281 | (* theorem returned is just "False" (with some of the given clauses as *) | |
| 282 | (* hyps). *) | |
| 283 | (* ------------------------------------------------------------------------- *) | |
| 284 | ||
| 32432 
64f30bdd3ba1
modernized messages -- eliminated ctyp/cterm operations;
 wenzelm parents: 
32283diff
changeset | 285 | fun rawsat_thm ctxt clauses = | 
| 41447 | 286 | let | 
| 287 | (* remove premises that equal "True" *) | |
| 288 | val clauses' = filter (fn clause => | |
| 289 | (not_equal HOLogic.true_const o HOLogic.dest_Trueprop o Thm.term_of) clause | |
| 290 |         handle TERM ("dest_Trueprop", _) => true) clauses
 | |
| 291 | (* remove non-clausal premises -- of course this shouldn't actually *) | |
| 292 | (* remove anything as long as 'rawsat_tac' is only called after the *) | |
| 293 | (* premises have been converted to clauses *) | |
| 294 | val clauses'' = filter (fn clause => | |
| 295 | ((cnf.is_clause o HOLogic.dest_Trueprop o Thm.term_of) clause | |
| 296 |         handle TERM ("dest_Trueprop", _) => false)
 | |
| 297 | orelse ( | |
| 298 |         warning ("Ignoring non-clausal premise " ^ Syntax.string_of_term ctxt (Thm.term_of clause));
 | |
| 299 | false)) clauses' | |
| 300 | (* remove trivial clauses -- this is necessary because zChaff removes *) | |
| 301 | (* trivial clauses during preprocessing, and otherwise our clause *) | |
| 302 | (* numbering would be off *) | |
| 303 | val nontrivial_clauses = | |
| 304 | filter (not o cnf.clause_is_trivial o HOLogic.dest_Trueprop o Thm.term_of) clauses'' | |
| 305 | (* sort clauses according to the term order -- an optimization, *) | |
| 306 | (* useful because forming the union of hypotheses, as done by *) | |
| 307 | (* Conjunction.intr_balanced and fold Thm.weaken below, is quadratic for *) | |
| 308 | (* terms sorted in descending order, while only linear for terms *) | |
| 309 | (* sorted in ascending order *) | |
| 310 | val sorted_clauses = sort (Term_Ord.fast_term_ord o pairself Thm.term_of) nontrivial_clauses | |
| 311 | val _ = | |
| 312 | if !trace_sat then | |
| 313 |         tracing ("Sorted non-trivial clauses:\n" ^
 | |
| 314 | cat_lines (map (Syntax.string_of_term ctxt o Thm.term_of) sorted_clauses)) | |
| 315 | else () | |
| 41471 | 316 | (* translate clauses from HOL terms to Prop_Logic.prop_formula *) | 
| 41447 | 317 | val (fms, atom_table) = | 
| 41471 | 318 | fold_map (Prop_Logic.prop_formula_of_term o HOLogic.dest_Trueprop o Thm.term_of) | 
| 41447 | 319 | sorted_clauses Termtab.empty | 
| 320 | val _ = | |
| 321 | if !trace_sat then | |
| 322 |         tracing ("Invoking SAT solver on clauses:\n" ^ cat_lines (map string_of_prop_formula fms))
 | |
| 323 | else () | |
| 41471 | 324 | val fm = Prop_Logic.all fms | 
| 41447 | 325 | (* unit -> Thm.thm *) | 
| 326 | fun make_quick_and_dirty_thm () = | |
| 327 | let | |
| 328 | val _ = | |
| 329 | if !trace_sat then | |
| 330 | tracing "'quick_and_dirty' is set: proof reconstruction skipped, using oracle instead." | |
| 331 | else () | |
| 332 |         val False_thm = Skip_Proof.make_thm @{theory} (HOLogic.Trueprop $ HOLogic.false_const)
 | |
| 333 | in | |
| 334 | (* 'fold Thm.weaken (rev sorted_clauses)' is linear, while 'fold *) | |
| 335 | (* Thm.weaken sorted_clauses' would be quadratic, since we sorted *) | |
| 336 | (* clauses in ascending order (which is linear for *) | |
| 337 | (* 'Conjunction.intr_balanced', used below) *) | |
| 338 | fold Thm.weaken (rev sorted_clauses) False_thm | |
| 339 | end | |
| 340 | in | |
| 341 | case | |
| 342 | let val the_solver = ! solver | |
| 343 |       in (tracing ("Invoking solver " ^ the_solver); SatSolver.invoke_solver the_solver fm) end
 | |
| 344 | of | |
| 345 | SatSolver.UNSATISFIABLE (SOME (clause_table, empty_id)) => | |
| 346 | (if !trace_sat then | |
| 347 |           tracing ("Proof trace from SAT solver:\n" ^
 | |
| 348 | "clauses: " ^ ML_Syntax.print_list | |
| 41491 | 349 | (ML_Syntax.print_pair ML_Syntax.print_int (ML_Syntax.print_list ML_Syntax.print_int)) | 
| 41447 | 350 | (Inttab.dest clause_table) ^ "\n" ^ | 
| 41491 | 351 | "empty clause: " ^ string_of_int empty_id) | 
| 41447 | 352 | else (); | 
| 353 | if !quick_and_dirty then | |
| 354 | make_quick_and_dirty_thm () | |
| 355 | else | |
| 356 | let | |
| 357 | (* optimization: convert the given clauses to "[c_1 && ... && c_n] |- c_i"; *) | |
| 358 | (* this avoids accumulation of hypotheses during resolution *) | |
| 359 | (* [c_1, ..., c_n] |- c_1 && ... && c_n *) | |
| 360 | val clauses_thm = Conjunction.intr_balanced (map Thm.assume sorted_clauses) | |
| 361 | (* [c_1 && ... && c_n] |- c_1 && ... && c_n *) | |
| 362 | val cnf_cterm = cprop_of clauses_thm | |
| 363 | val cnf_thm = Thm.assume cnf_cterm | |
| 364 | (* [[c_1 && ... && c_n] |- c_1, ..., [c_1 && ... && c_n] |- c_n] *) | |
| 365 | val cnf_clauses = Conjunction.elim_balanced (length sorted_clauses) cnf_thm | |
| 366 | (* initialize the clause array with the given clauses *) | |
| 367 | val max_idx = the (Inttab.max_key clause_table) | |
| 368 | val clause_arr = Array.array (max_idx + 1, NO_CLAUSE) | |
| 369 | val _ = | |
| 370 | fold (fn thm => fn idx => (Array.update (clause_arr, idx, ORIG_CLAUSE thm); idx+1)) | |
| 371 | cnf_clauses 0 | |
| 372 | (* replay the proof to derive the empty clause *) | |
| 373 | (* [c_1 && ... && c_n] |- False *) | |
| 374 | val raw_thm = replay_proof atom_table clause_arr (clause_table, empty_id) | |
| 375 | in | |
| 376 | (* [c_1, ..., c_n] |- False *) | |
| 377 | Thm.implies_elim (Thm.implies_intr cnf_cterm raw_thm) clauses_thm | |
| 378 | end) | |
| 379 | | SatSolver.UNSATISFIABLE NONE => | |
| 380 | if !quick_and_dirty then | |
| 381 | (warning "SAT solver claims the formula to be unsatisfiable, but did not provide a proof"; | |
| 382 | make_quick_and_dirty_thm ()) | |
| 383 | else | |
| 384 |           raise THM ("SAT solver claims the formula to be unsatisfiable, but did not provide a proof", 0, [])
 | |
| 385 | | SatSolver.SATISFIABLE assignment => | |
| 386 | let | |
| 387 | val msg = | |
| 388 | "SAT solver found a countermodel:\n" ^ | |
| 389 | (commas o map (fn (term, idx) => | |
| 390 |                 Syntax.string_of_term_global @{theory} term ^ ": " ^
 | |
| 391 | (case assignment idx of NONE => "arbitrary" | |
| 392 | | SOME true => "true" | SOME false => "false"))) | |
| 393 | (Termtab.dest atom_table) | |
| 394 | in | |
| 395 | raise THM (msg, 0, []) | |
| 396 | end | |
| 397 | | SatSolver.UNKNOWN => | |
| 398 |         raise THM ("SAT solver failed to decide the formula", 0, [])
 | |
| 399 | end; | |
| 17618 | 400 | |
| 17622 
5d03a69481b6
code reformatted and restructured, many minor modifications
 webertj parents: 
17618diff
changeset | 401 | (* ------------------------------------------------------------------------- *) | 
| 
5d03a69481b6
code reformatted and restructured, many minor modifications
 webertj parents: 
17618diff
changeset | 402 | (* Tactics *) | 
| 
5d03a69481b6
code reformatted and restructured, many minor modifications
 webertj parents: 
17618diff
changeset | 403 | (* ------------------------------------------------------------------------- *) | 
| 17618 | 404 | |
| 17809 
195045659c06
Tactics sat and satx reimplemented, several improvements
 webertj parents: 
17697diff
changeset | 405 | (* ------------------------------------------------------------------------- *) | 
| 
195045659c06
Tactics sat and satx reimplemented, several improvements
 webertj parents: 
17697diff
changeset | 406 | (* rawsat_tac: solves the i-th subgoal of the proof state; this subgoal *) | 
| 
195045659c06
Tactics sat and satx reimplemented, several improvements
 webertj parents: 
17697diff
changeset | 407 | (* should be of the form *) | 
| 
195045659c06
Tactics sat and satx reimplemented, several improvements
 webertj parents: 
17697diff
changeset | 408 | (* [| c1; c2; ...; ck |] ==> False *) | 
| 
195045659c06
Tactics sat and satx reimplemented, several improvements
 webertj parents: 
17697diff
changeset | 409 | (* where each cj is a non-empty clause (i.e. a disjunction of literals) *) | 
| 
195045659c06
Tactics sat and satx reimplemented, several improvements
 webertj parents: 
17697diff
changeset | 410 | (* or "True" *) | 
| 
195045659c06
Tactics sat and satx reimplemented, several improvements
 webertj parents: 
17697diff
changeset | 411 | (* ------------------------------------------------------------------------- *) | 
| 
195045659c06
Tactics sat and satx reimplemented, several improvements
 webertj parents: 
17697diff
changeset | 412 | |
| 32232 | 413 | fun rawsat_tac ctxt i = | 
| 32432 
64f30bdd3ba1
modernized messages -- eliminated ctyp/cterm operations;
 wenzelm parents: 
32283diff
changeset | 414 |   Subgoal.FOCUS (fn {context = ctxt', prems, ...} =>
 | 
| 
64f30bdd3ba1
modernized messages -- eliminated ctyp/cterm operations;
 wenzelm parents: 
32283diff
changeset | 415 | rtac (rawsat_thm ctxt' (map cprop_of prems)) 1) ctxt i; | 
| 17618 | 416 | |
| 17809 
195045659c06
Tactics sat and satx reimplemented, several improvements
 webertj parents: 
17697diff
changeset | 417 | (* ------------------------------------------------------------------------- *) | 
| 
195045659c06
Tactics sat and satx reimplemented, several improvements
 webertj parents: 
17697diff
changeset | 418 | (* pre_cnf_tac: converts the i-th subgoal *) | 
| 
195045659c06
Tactics sat and satx reimplemented, several improvements
 webertj parents: 
17697diff
changeset | 419 | (* [| A1 ; ... ; An |] ==> B *) | 
| 
195045659c06
Tactics sat and satx reimplemented, several improvements
 webertj parents: 
17697diff
changeset | 420 | (* to *) | 
| 
195045659c06
Tactics sat and satx reimplemented, several improvements
 webertj parents: 
17697diff
changeset | 421 | (* [| A1; ... ; An ; ~B |] ==> False *) | 
| 
195045659c06
Tactics sat and satx reimplemented, several improvements
 webertj parents: 
17697diff
changeset | 422 | (* (handling meta-logical connectives in B properly before negating), *) | 
| 
195045659c06
Tactics sat and satx reimplemented, several improvements
 webertj parents: 
17697diff
changeset | 423 | (* then replaces meta-logical connectives in the premises (i.e. "==>", *) | 
| 
195045659c06
Tactics sat and satx reimplemented, several improvements
 webertj parents: 
17697diff
changeset | 424 | (* "!!" and "==") by connectives of the HOL object-logic (i.e. by *) | 
| 19553 
9d15911f1893
pre_cnf_tac: beta-eta-normalization restricted to the current subgoal
 webertj parents: 
19534diff
changeset | 425 | (* "-->", "!", and "="), then performs beta-eta-normalization on the *) | 
| 
9d15911f1893
pre_cnf_tac: beta-eta-normalization restricted to the current subgoal
 webertj parents: 
19534diff
changeset | 426 | (* subgoal *) | 
| 17809 
195045659c06
Tactics sat and satx reimplemented, several improvements
 webertj parents: 
17697diff
changeset | 427 | (* ------------------------------------------------------------------------- *) | 
| 
195045659c06
Tactics sat and satx reimplemented, several improvements
 webertj parents: 
17697diff
changeset | 428 | |
| 23533 | 429 | val pre_cnf_tac = | 
| 41447 | 430 | rtac ccontr THEN' | 
| 431 | Object_Logic.atomize_prems_tac THEN' | |
| 432 | CONVERSION Drule.beta_eta_conversion; | |
| 17809 
195045659c06
Tactics sat and satx reimplemented, several improvements
 webertj parents: 
17697diff
changeset | 433 | |
| 
195045659c06
Tactics sat and satx reimplemented, several improvements
 webertj parents: 
17697diff
changeset | 434 | (* ------------------------------------------------------------------------- *) | 
| 
195045659c06
Tactics sat and satx reimplemented, several improvements
 webertj parents: 
17697diff
changeset | 435 | (* cnfsat_tac: checks if the empty clause "False" occurs among the premises; *) | 
| 
195045659c06
Tactics sat and satx reimplemented, several improvements
 webertj parents: 
17697diff
changeset | 436 | (* if not, eliminates conjunctions (i.e. each clause of the CNF formula *) | 
| 
195045659c06
Tactics sat and satx reimplemented, several improvements
 webertj parents: 
17697diff
changeset | 437 | (* becomes a separate premise), then applies 'rawsat_tac' to solve the *) | 
| 
195045659c06
Tactics sat and satx reimplemented, several improvements
 webertj parents: 
17697diff
changeset | 438 | (* subgoal *) | 
| 
195045659c06
Tactics sat and satx reimplemented, several improvements
 webertj parents: 
17697diff
changeset | 439 | (* ------------------------------------------------------------------------- *) | 
| 17697 | 440 | |
| 32232 | 441 | fun cnfsat_tac ctxt i = | 
| 41447 | 442 | (etac FalseE i) ORELSE (REPEAT_DETERM (etac conjE i) THEN rawsat_tac ctxt i); | 
| 17618 | 443 | |
| 17809 
195045659c06
Tactics sat and satx reimplemented, several improvements
 webertj parents: 
17697diff
changeset | 444 | (* ------------------------------------------------------------------------- *) | 
| 
195045659c06
Tactics sat and satx reimplemented, several improvements
 webertj parents: 
17697diff
changeset | 445 | (* cnfxsat_tac: checks if the empty clause "False" occurs among the *) | 
| 
195045659c06
Tactics sat and satx reimplemented, several improvements
 webertj parents: 
17697diff
changeset | 446 | (* premises; if not, eliminates conjunctions (i.e. each clause of the *) | 
| 
195045659c06
Tactics sat and satx reimplemented, several improvements
 webertj parents: 
17697diff
changeset | 447 | (* CNF formula becomes a separate premise) and existential quantifiers, *) | 
| 
195045659c06
Tactics sat and satx reimplemented, several improvements
 webertj parents: 
17697diff
changeset | 448 | (* then applies 'rawsat_tac' to solve the subgoal *) | 
| 
195045659c06
Tactics sat and satx reimplemented, several improvements
 webertj parents: 
17697diff
changeset | 449 | (* ------------------------------------------------------------------------- *) | 
| 
195045659c06
Tactics sat and satx reimplemented, several improvements
 webertj parents: 
17697diff
changeset | 450 | |
| 32232 | 451 | fun cnfxsat_tac ctxt i = | 
| 41447 | 452 | (etac FalseE i) ORELSE | 
| 453 | (REPEAT_DETERM (etac conjE i ORELSE etac exE i) THEN rawsat_tac ctxt i); | |
| 17618 | 454 | |
| 17809 
195045659c06
Tactics sat and satx reimplemented, several improvements
 webertj parents: 
17697diff
changeset | 455 | (* ------------------------------------------------------------------------- *) | 
| 
195045659c06
Tactics sat and satx reimplemented, several improvements
 webertj parents: 
17697diff
changeset | 456 | (* sat_tac: tactic for calling an external SAT solver, taking as input an *) | 
| 
195045659c06
Tactics sat and satx reimplemented, several improvements
 webertj parents: 
17697diff
changeset | 457 | (* arbitrary formula. The input is translated to CNF, possibly causing *) | 
| 
195045659c06
Tactics sat and satx reimplemented, several improvements
 webertj parents: 
17697diff
changeset | 458 | (* an exponential blowup. *) | 
| 
195045659c06
Tactics sat and satx reimplemented, several improvements
 webertj parents: 
17697diff
changeset | 459 | (* ------------------------------------------------------------------------- *) | 
| 
195045659c06
Tactics sat and satx reimplemented, several improvements
 webertj parents: 
17697diff
changeset | 460 | |
| 32232 | 461 | fun sat_tac ctxt i = | 
| 41447 | 462 | pre_cnf_tac i THEN cnf.cnf_rewrite_tac ctxt i THEN cnfsat_tac ctxt i; | 
| 17809 
195045659c06
Tactics sat and satx reimplemented, several improvements
 webertj parents: 
17697diff
changeset | 463 | |
| 
195045659c06
Tactics sat and satx reimplemented, several improvements
 webertj parents: 
17697diff
changeset | 464 | (* ------------------------------------------------------------------------- *) | 
| 
195045659c06
Tactics sat and satx reimplemented, several improvements
 webertj parents: 
17697diff
changeset | 465 | (* satx_tac: tactic for calling an external SAT solver, taking as input an *) | 
| 
195045659c06
Tactics sat and satx reimplemented, several improvements
 webertj parents: 
17697diff
changeset | 466 | (* arbitrary formula. The input is translated to CNF, possibly *) | 
| 
195045659c06
Tactics sat and satx reimplemented, several improvements
 webertj parents: 
17697diff
changeset | 467 | (* introducing new literals. *) | 
| 
195045659c06
Tactics sat and satx reimplemented, several improvements
 webertj parents: 
17697diff
changeset | 468 | (* ------------------------------------------------------------------------- *) | 
| 
195045659c06
Tactics sat and satx reimplemented, several improvements
 webertj parents: 
17697diff
changeset | 469 | |
| 32232 | 470 | fun satx_tac ctxt i = | 
| 41447 | 471 | pre_cnf_tac i THEN cnf.cnfx_rewrite_tac ctxt i THEN cnfxsat_tac ctxt i; | 
| 17618 | 472 | |
| 23533 | 473 | end; |