1(* Title: Tools/Argo/argo_proof.ML 2 Author: Sascha Boehme 3 4The proof language of the Argo solver. 5 6Proofs trace the inferences of the solver. They can be used to check unsatisfiability results. 7 8The proof language is inspired by: 9 10 Leonardo de Moura and Nikolaj Bj/orner. Proofs and Refutations, and Z3. In 11 Proceedings of the LPAR 2008 Workshops, Knowledge Exchange: Automated Provers and Proof 12 Assistants, and the 7th International Workshop on the Implementation of Logics, 13 volume 418 of CEUR Workshop Proceedings. CEUR-WS.org, 2008. 14*) 15 16signature ARGO_PROOF = 17sig 18 (* types *) 19 type proof_id 20 datatype tautology = 21 Taut_And_1 of int | Taut_And_2 of int * int | Taut_Or_1 of int * int | Taut_Or_2 of int | 22 Taut_Iff_1 | Taut_Iff_2 | Taut_Iff_3 | Taut_Iff_4 | Taut_Ite_Then | Taut_Ite_Else 23 datatype side = Left | Right 24 datatype inequality = Le | Lt 25 datatype rewrite = 26 Rewr_Not_True | Rewr_Not_False | Rewr_Not_Not | Rewr_Not_And of int | Rewr_Not_Or of int | 27 Rewr_Not_Iff | 28 Rewr_And_False of int | Rewr_And_Dual of int * int | Rewr_And_Sort of int * int list list | 29 Rewr_Or_True of int | Rewr_Or_Dual of int * int | Rewr_Or_Sort of int * int list list | 30 Rewr_Iff_True | Rewr_Iff_False | Rewr_Iff_Not_Not | Rewr_Iff_Refl | Rewr_Iff_Symm | 31 Rewr_Iff_Dual | 32 Rewr_Imp | Rewr_Ite_Prop | Rewr_Ite_True | Rewr_Ite_False | Rewr_Ite_Eq | 33 Rewr_Eq_Refl | Rewr_Eq_Symm | 34 Rewr_Neg | Rewr_Add of (Rat.rat * int option) list * (Rat.rat * int option) list | Rewr_Sub | 35 Rewr_Mul_Nums of Rat.rat * Rat.rat | Rewr_Mul_Zero | Rewr_Mul_One | Rewr_Mul_Comm | 36 Rewr_Mul_Assoc of side | Rewr_Mul_Sum of side | Rewr_Mul_Div of side | 37 Rewr_Div_Zero | Rewr_Div_One | Rewr_Div_Nums of Rat.rat * Rat.rat | 38 Rewr_Div_Num of side * Rat.rat | Rewr_Div_Mul of side * Rat.rat | Rewr_Div_Div of side | 39 Rewr_Div_Sum | Rewr_Min_Eq | Rewr_Min_Lt | Rewr_Min_Gt | Rewr_Max_Eq | Rewr_Max_Lt | 40 Rewr_Max_Gt | Rewr_Abs | Rewr_Eq_Nums of bool | Rewr_Eq_Sub | Rewr_Eq_Le | 41 Rewr_Ineq_Nums of inequality * bool | Rewr_Ineq_Add of inequality * Rat.rat | 42 Rewr_Ineq_Sub of inequality | Rewr_Ineq_Mul of inequality * Rat.rat | 43 Rewr_Not_Ineq of inequality 44 datatype conv = 45 Keep_Conv | Then_Conv of conv * conv | Args_Conv of Argo_Expr.kind * conv list | 46 Rewr_Conv of rewrite 47 datatype rule = 48 Axiom of int | Taut of tautology * Argo_Expr.expr | Conjunct of int * int | Rewrite of conv | 49 Hyp of int * Argo_Expr.expr | Clause of int list | Lemma of int list | Unit_Res of int | 50 Refl of Argo_Expr.expr | Symm | Trans | Cong | Subst | Linear_Comb 51 type proof 52 53 (* equalities and orders *) 54 val eq_proof_id: proof_id * proof_id -> bool 55 val proof_id_ord: proof_id ord 56 57 (* conversion constructors *) 58 val keep_conv: conv 59 val mk_then_conv: conv -> conv -> conv 60 val mk_args_conv: Argo_Expr.kind -> conv list -> conv 61 val mk_rewr_conv: rewrite -> conv 62 63 (* context *) 64 type context 65 val cdcl_context: context 66 val cc_context: context 67 val simplex_context: context 68 val solver_context: context 69 70 (* proof constructors *) 71 val mk_axiom: int -> context -> proof * context 72 val mk_taut: tautology -> Argo_Expr.expr -> context -> proof * context 73 val mk_conj: int -> int -> proof -> context -> proof * context 74 val mk_rewrite: conv -> proof -> context -> proof * context 75 val mk_hyp: Argo_Lit.literal -> context -> proof * context 76 val mk_clause: Argo_Lit.literal list -> proof -> context -> proof * context 77 val mk_lemma: Argo_Lit.literal list -> proof -> context -> proof * context 78 val mk_unit_res: Argo_Lit.literal -> proof -> proof -> context -> proof * context 79 val mk_refl: Argo_Term.term -> context -> proof * context 80 val mk_symm: proof -> context -> proof * context 81 val mk_trans: proof -> proof -> context -> proof * context 82 val mk_cong: proof -> proof -> context -> proof * context 83 val mk_subst: proof -> proof -> proof -> context -> proof * context 84 val mk_linear_comb: proof list -> context -> proof * context 85 86 (* proof destructors *) 87 val id_of: proof -> proof_id 88 val dest: proof -> proof_id * rule * proof list 89 90 (* string representations *) 91 val string_of_proof_id: proof_id -> string 92 val string_of_taut: tautology -> string 93 val string_of_rule: rule -> string 94 95 (* unsatisfiability *) 96 exception UNSAT of proof 97 val unsat: proof -> 'a (* raises UNSAT *) 98end 99 100structure Argo_Proof: ARGO_PROOF = 101struct 102 103(* types *) 104 105datatype tautology = 106 Taut_And_1 of int | Taut_And_2 of int * int | Taut_Or_1 of int * int | Taut_Or_2 of int | 107 Taut_Iff_1 | Taut_Iff_2 | Taut_Iff_3 | Taut_Iff_4 | Taut_Ite_Then | Taut_Ite_Else 108 109datatype side = Left | Right 110 111datatype inequality = Le | Lt 112 113datatype rewrite = 114 Rewr_Not_True | Rewr_Not_False | Rewr_Not_Not | Rewr_Not_And of int | Rewr_Not_Or of int | 115 Rewr_Not_Iff | 116 Rewr_And_False of int | Rewr_And_Dual of int * int | Rewr_And_Sort of int * int list list | 117 Rewr_Or_True of int | Rewr_Or_Dual of int * int | Rewr_Or_Sort of int * int list list | 118 Rewr_Iff_True | Rewr_Iff_False | Rewr_Iff_Not_Not | Rewr_Iff_Refl | Rewr_Iff_Symm | 119 Rewr_Iff_Dual | 120 Rewr_Imp | Rewr_Ite_Prop | Rewr_Ite_True | Rewr_Ite_False | Rewr_Ite_Eq | 121 Rewr_Eq_Refl | Rewr_Eq_Symm | 122 Rewr_Neg | Rewr_Add of (Rat.rat * int option) list * (Rat.rat * int option) list | Rewr_Sub | 123 Rewr_Mul_Nums of Rat.rat * Rat.rat | Rewr_Mul_Zero | Rewr_Mul_One | Rewr_Mul_Comm | 124 Rewr_Mul_Assoc of side | Rewr_Mul_Sum of side | Rewr_Mul_Div of side | 125 Rewr_Div_Zero | Rewr_Div_One | Rewr_Div_Nums of Rat.rat * Rat.rat | 126 Rewr_Div_Num of side * Rat.rat | Rewr_Div_Mul of side * Rat.rat | Rewr_Div_Div of side | 127 Rewr_Div_Sum | Rewr_Min_Eq | Rewr_Min_Lt | Rewr_Min_Gt | Rewr_Max_Eq | Rewr_Max_Lt | 128 Rewr_Max_Gt | Rewr_Abs | Rewr_Eq_Nums of bool | Rewr_Eq_Sub | Rewr_Eq_Le | 129 Rewr_Ineq_Nums of inequality * bool | Rewr_Ineq_Add of inequality * Rat.rat | 130 Rewr_Ineq_Sub of inequality | Rewr_Ineq_Mul of inequality * Rat.rat | 131 Rewr_Not_Ineq of inequality 132 133datatype conv = 134 Keep_Conv | Then_Conv of conv * conv | Args_Conv of Argo_Expr.kind * conv list | 135 Rewr_Conv of rewrite 136 137datatype rule = 138 Axiom of int | Taut of tautology * Argo_Expr.expr | Conjunct of int * int | Rewrite of conv | 139 Hyp of int * Argo_Expr.expr | Clause of int list | Lemma of int list | Unit_Res of int | 140 Refl of Argo_Expr.expr | Symm | Trans | Cong | Subst | Linear_Comb 141 142(* 143 Proof identifiers are intentially hidden to prevent that functions outside of this structure 144 are able to build proofs. Proof can hence only be built by the functions provided by 145 this structure. 146*) 147 148datatype proof_id = Cdcl of int | Cc of int | Simplex of int | Solver of int 149 150datatype proof = Proof of proof_id * rule * proof list 151 152 153(* internal functions *) 154 155val proof_id_card = 4 156 157fun raw_proof_id (Cdcl i) = i 158 | raw_proof_id (Cc i) = i 159 | raw_proof_id (Simplex i) = i 160 | raw_proof_id (Solver i) = i 161 162 163(* equalities and orders *) 164 165fun int_of_proof_id (Cdcl _) = 0 166 | int_of_proof_id (Cc _) = 1 167 | int_of_proof_id (Simplex _) = 2 168 | int_of_proof_id (Solver _) = 3 169 170fun eq_proof_id (Cdcl i1, Cdcl i2) = (i1 = i2) 171 | eq_proof_id (Cc i1, Cc i2) = (i1 = i2) 172 | eq_proof_id (Simplex i1, Simplex i2) = (i1 = i2) 173 | eq_proof_id (Solver i1, Solver i2) = (i1 = i2) 174 | eq_proof_id _ = false 175 176fun proof_id_ord (Cdcl i1, Cdcl i2) = int_ord (i1, i2) 177 | proof_id_ord (Cc i1, Cc i2) = int_ord (i1, i2) 178 | proof_id_ord (Simplex i1, Simplex i2) = int_ord (i1, i2) 179 | proof_id_ord (Solver i1, Solver i2) = int_ord (i1, i2) 180 | proof_id_ord (id1, id2) = int_ord (int_of_proof_id id1, int_of_proof_id id2) 181 182 183(* conversion constructors *) 184 185val keep_conv = Keep_Conv 186 187fun mk_then_conv Keep_Conv c = c 188 | mk_then_conv c Keep_Conv = c 189 | mk_then_conv c1 c2 = Then_Conv (c1, c2) 190 191fun mk_args_conv k cs = 192 if forall (fn Keep_Conv => true | _ => false) cs then Keep_Conv 193 else Args_Conv (k, cs) 194 195fun mk_rewr_conv r = Rewr_Conv r 196 197 198(* context *) 199 200(* 201 The proof context stores the next unused identifier. Incidentally, the same type as 202 for the proof identifier can be used as context. Every proof-producing module of the 203 solver has its own proof identifier domain to ensure globally unique identifiers 204 without sharing a single proof context. 205*) 206 207type context = proof_id 208 209val cdcl_context = Cdcl 0 210val cc_context = Cc 0 211val simplex_context = Simplex 0 212val solver_context = Solver 0 213 214fun next_id (id as Cdcl i) = (id, Cdcl (i + 1)) 215 | next_id (id as Cc i) = (id, Cc (i + 1)) 216 | next_id (id as Simplex i) = (id, Simplex (i + 1)) 217 | next_id (id as Solver i) = (id, Solver (i + 1)) 218 219 220(* proof destructors *) 221 222fun id_of (Proof (id, _, _)) = id 223 224fun dest (Proof p) = p 225 226 227(* proof constructors *) 228 229fun mk_proof r ps cx = 230 let val (id, cx) = next_id cx 231 in (Proof (id, r, ps), cx) end 232 233fun mk_axiom i = mk_proof (Axiom i) [] 234fun mk_taut t e = mk_proof (Taut (t, e)) [] 235fun mk_conj i n p = mk_proof (Conjunct (i, n)) [p] 236 237fun mk_rewrite Keep_Conv p cx = (p, cx) 238 | mk_rewrite c p cx = mk_proof (Rewrite c) [p] cx 239 240fun mk_hyp lit = mk_proof (Hyp (Argo_Lit.signed_id_of lit, Argo_Lit.signed_expr_of lit)) [] 241fun mk_clause lits p cx = mk_proof (Clause (map Argo_Lit.signed_id_of lits)) [p] cx 242fun mk_lemma lits p = mk_proof (Lemma (map Argo_Lit.signed_id_of lits)) [p] 243 244(* 245 Replay of unit-resolution steps can be optimized if all premises follow a specific form. 246 Therefore, each premise is checked if it is in clausal form. 247*) 248 249fun check_clause (p as Proof (_, Clause _, _)) = p 250 | check_clause (p as Proof (_, Lemma _, _)) = p 251 | check_clause (p as Proof (_, Unit_Res _, _)) = p 252 | check_clause _ = raise Fail "bad clause proof" 253 254fun mk_unit t p1 p2 = mk_proof (Unit_Res (Argo_Term.id_of t)) (map check_clause [p1, p2]) 255 256fun mk_unit_res (Argo_Lit.Pos t) p1 p2 = mk_unit t p1 p2 257 | mk_unit_res (Argo_Lit.Neg t) p1 p2 = mk_unit t p2 p1 258 259fun mk_refl t = mk_proof (Refl (Argo_Term.expr_of t)) [] 260fun mk_symm p = mk_proof Symm [p] 261 262fun mk_trans (Proof (_, Refl _, _)) p2 = pair p2 263 | mk_trans p1 (Proof (_, Refl _, _)) = pair p1 264 | mk_trans p1 p2 = mk_proof Trans [p1, p2] 265 266fun mk_cong p1 p2 = mk_proof Cong [p1, p2] 267 268fun mk_subst p1 (Proof (_, Refl _, _)) (Proof (_, Refl _, _)) = pair p1 269 | mk_subst p1 p2 p3 = mk_proof Subst [p1, p2, p3] 270 271fun mk_linear_comb ps = mk_proof Linear_Comb ps 272 273 274(* string representations *) 275 276fun string_of_proof_id id = string_of_int (proof_id_card * raw_proof_id id + int_of_proof_id id) 277 278fun string_of_list l r f xs = enclose l r (space_implode ", " (map f xs)) 279fun parens f xs = string_of_list "(" ")" f xs 280fun brackets f xs = string_of_list "[" "]" f xs 281 282fun string_of_taut (Taut_And_1 n) = "and " ^ string_of_int n 283 | string_of_taut (Taut_And_2 (i, n)) = "and " ^ parens string_of_int [i, n] 284 | string_of_taut (Taut_Or_1 (i, n)) = "or " ^ parens string_of_int [i, n] 285 | string_of_taut (Taut_Or_2 n) = "or " ^ string_of_int n 286 | string_of_taut Taut_Iff_1 = "(p1 == p2) | p1 | p2" 287 | string_of_taut Taut_Iff_2 = "(p1 == p2) | ~p1 | ~p2" 288 | string_of_taut Taut_Iff_3 = "~(p1 == p2) | ~p1 | p2" 289 | string_of_taut Taut_Iff_4 = "~(p1 == p2) | p1 | ~p2" 290 | string_of_taut Taut_Ite_Then = "~p | (ite p t1 t2) = t1" 291 | string_of_taut Taut_Ite_Else = "p | (ite p t1 t2) = t2" 292 293fun string_of_rewr Rewr_Not_True = "~T = F" 294 | string_of_rewr Rewr_Not_False = "~F = T" 295 | string_of_rewr Rewr_Not_Not = "~~p = p" 296 | string_of_rewr (Rewr_Not_And n) = 297 "~(and [" ^ string_of_int n ^ "]) = (or [" ^ string_of_int n ^ "])" 298 | string_of_rewr (Rewr_Not_Or n) = 299 "~(or [" ^ string_of_int n ^ "]) = (and [" ^ string_of_int n ^ "])" 300 | string_of_rewr Rewr_Not_Iff = "~(p1 == p2) = (~p1 == ~p2)" 301 | string_of_rewr (Rewr_And_False i) = "(and ... F(" ^ string_of_int i ^ ") ...) = F" 302 | string_of_rewr (Rewr_And_Dual (i1, i2)) = 303 "(and ... p(" ^ string_of_int i1 ^ ") ... ~p(" ^ string_of_int i2 ^ ") ...) = F" 304 | string_of_rewr (Rewr_And_Sort (n, iss)) = 305 "(and [" ^ string_of_int n ^ "]) = " ^ 306 "(and " ^ brackets (brackets string_of_int) iss ^ ")" 307 | string_of_rewr (Rewr_Or_True i) = "(or ... T(" ^ string_of_int i ^ ") ...) = T" 308 | string_of_rewr (Rewr_Or_Dual (i1, i2)) = 309 "(or ... p(" ^ string_of_int i1 ^ ") ... ~p(" ^ string_of_int i2 ^ ") ...) = T" 310 | string_of_rewr (Rewr_Or_Sort (n, iss)) = 311 "(or [" ^ string_of_int n ^ "]) = " ^ 312 "(or " ^ brackets (brackets string_of_int) iss ^ ")" 313 | string_of_rewr Rewr_Iff_True = "(p == T) = p" 314 | string_of_rewr Rewr_Iff_False = "(p == F) = ~p" 315 | string_of_rewr Rewr_Iff_Not_Not = "(~p1 == ~p2) = (p1 == p2)" 316 | string_of_rewr Rewr_Iff_Refl = "(p == p) = T" 317 | string_of_rewr Rewr_Iff_Symm = "(p1 == p2) = (p2 == p1)" 318 | string_of_rewr Rewr_Iff_Dual = "(p == ~p) = F" 319 | string_of_rewr Rewr_Imp = "(p1 --> p2) = (~p1 | p2)" 320 | string_of_rewr Rewr_Ite_Prop = "(if p1 p2 p2) = ((~p1 | p2) & (p1 | p3) & (p2 | p3))" 321 | string_of_rewr Rewr_Ite_True = "(if T t1 t2) = t1" 322 | string_of_rewr Rewr_Ite_False = "(if F t1 t2) = t2" 323 | string_of_rewr Rewr_Ite_Eq = "(if p t t) = t" 324 | string_of_rewr Rewr_Eq_Refl = "(e = e) = T" 325 | string_of_rewr Rewr_Eq_Symm = "(e1 = e2) = (e2 = e1)" 326 | string_of_rewr Rewr_Neg = "-e = -1 * e" 327 | string_of_rewr (Rewr_Add (p1, p2)) = 328 let 329 fun string_of_monom (n, NONE) = Rat.string_of_rat n 330 | string_of_monom (n, SOME i) = 331 (if n = @1 then "" else Rat.string_of_rat n ^ " * ") ^ "e" ^ string_of_int i 332 fun string_of_polynom ms = space_implode " + " (map string_of_monom ms) 333 in string_of_polynom p1 ^ " = " ^ string_of_polynom p2 end 334 | string_of_rewr Rewr_Sub = "e1 - e2 = e1 + -1 * e2" 335 | string_of_rewr (Rewr_Mul_Nums (n1, n2)) = 336 Rat.string_of_rat n1 ^ " * " ^ Rat.string_of_rat n2 ^ " = " ^ Rat.string_of_rat (n1 * n2) 337 | string_of_rewr Rewr_Mul_Zero = "0 * e = 0" 338 | string_of_rewr Rewr_Mul_One = "1 * e = e" 339 | string_of_rewr Rewr_Mul_Comm = "e1 * e2 = e2 * e1" 340 | string_of_rewr (Rewr_Mul_Assoc Left) = "(e1 * e2) * e3 = e1 * (e2 * e3)" 341 | string_of_rewr (Rewr_Mul_Assoc Right) = "e1 * (n * e2) = (e1 * n) * e2" 342 | string_of_rewr (Rewr_Mul_Sum Left) = "(e1 + ... + em) * e = e1 * e + ... em * e" 343 | string_of_rewr (Rewr_Mul_Sum Right) = "e * (e1 + ... + em) = e * e1 + ... e * em" 344 | string_of_rewr (Rewr_Mul_Div Left) = "(e1 / e2) * e3 = (e1 * e3) / e2" 345 | string_of_rewr (Rewr_Mul_Div Right) = "e1 * (e2 / * e3) = (e1 * e2) / e3" 346 | string_of_rewr Rewr_Div_Zero = "0 / e = 0" 347 | string_of_rewr Rewr_Div_One = "e / 1 = e" 348 | string_of_rewr (Rewr_Div_Nums (n1, n2)) = 349 Rat.string_of_rat n1 ^ " / " ^ Rat.string_of_rat n2 ^ " = " ^ Rat.string_of_rat (n1 / n2) 350 | string_of_rewr (Rewr_Div_Num (Left, n)) = 351 Rat.string_of_rat n ^ " / e = " ^ Rat.string_of_rat n ^ " * (1 / e)" 352 | string_of_rewr (Rewr_Div_Num (Right, n)) = 353 "e / " ^ Rat.string_of_rat n ^ " = " ^ Rat.string_of_rat (Rat.inv n) ^ " * e" 354 | string_of_rewr (Rewr_Div_Mul (Left, n)) = 355 "(" ^ Rat.string_of_rat n ^ " * e1) / e2 = " ^ Rat.string_of_rat n ^ " * (e1 / e2)" 356 | string_of_rewr (Rewr_Div_Mul (Right, n)) = 357 "e1 / (" ^ Rat.string_of_rat n ^ " * e2) = " ^ Rat.string_of_rat (Rat.inv n) ^ " * (e1 / e2)" 358 | string_of_rewr (Rewr_Div_Div Left) = "(e1 / e2) / e3 = e1 / (e2 * e3)" 359 | string_of_rewr (Rewr_Div_Div Right) = "e1 / (e2 / e3) = (e1 * e3) / e2" 360 | string_of_rewr Rewr_Div_Sum = "(e1 + ... + em) / e = e1 / e + ... + em / e" 361 | string_of_rewr Rewr_Min_Eq = "min e e = e" 362 | string_of_rewr Rewr_Min_Lt = "min e1 e2 = (if e1 <= e2 then e1 else e2)" 363 | string_of_rewr Rewr_Min_Gt = "min e1 e2 = (if e2 <= e1 then e2 else e1)" 364 | string_of_rewr Rewr_Max_Eq = "max e e = e" 365 | string_of_rewr Rewr_Max_Lt = "max e1 e2 = (if e1 < e2 then e2 else e1)" 366 | string_of_rewr Rewr_Max_Gt = "max e1 e2 = (if e2 < e1 then e1 else e2)" 367 | string_of_rewr Rewr_Abs = "abs e = (if 0 <= e then e else -e)" 368 | string_of_rewr (Rewr_Eq_Nums true) = "(n1 = n2) = true" 369 | string_of_rewr (Rewr_Eq_Nums false) = "(n1 ~= n2) = false" 370 | string_of_rewr Rewr_Eq_Sub = "(e1 = e2) = (e1 - e2 = 0)" 371 | string_of_rewr Rewr_Eq_Le = "(e1 = e2) = (and (e1 <= e2) (e2 <= e1))" 372 | string_of_rewr (Rewr_Ineq_Nums (Le, true)) = "(n1 <= n2) = true" 373 | string_of_rewr (Rewr_Ineq_Nums (Le, false)) = "(n1 <= n2) = false" 374 | string_of_rewr (Rewr_Ineq_Nums (Lt, true)) = "(n1 < n2) = true" 375 | string_of_rewr (Rewr_Ineq_Nums (Lt, false)) = "(n1 < n2) = false" 376 | string_of_rewr (Rewr_Ineq_Add (Le, _)) = "(e1 <= e2) = (e1 + n <= e2 + n)" 377 | string_of_rewr (Rewr_Ineq_Add (Lt, _)) = "(e1 < e2) = (e1 + n < e2 + n)" 378 | string_of_rewr (Rewr_Ineq_Sub Le) = "(e1 <= e2) = (e1 - e2 <= 0)" 379 | string_of_rewr (Rewr_Ineq_Sub Lt) = "(e1 < e2) = (e1 - e2 < 0)" 380 | string_of_rewr (Rewr_Ineq_Mul (Le, _)) = "(e1 <= e2) = (n * e1 <= n * e2)" 381 | string_of_rewr (Rewr_Ineq_Mul (Lt, _)) = "(e1 < e2) = (n * e1 < n * e2)" 382 | string_of_rewr (Rewr_Not_Ineq Le) = "~(e1 <= e2) = (e2 < e1)" 383 | string_of_rewr (Rewr_Not_Ineq Lt) = "~(e1 < e2) = (e2 <= e1)" 384 385fun flatten_then_conv (Then_Conv (c1, c2)) = flatten_then_conv c1 @ flatten_then_conv c2 386 | flatten_then_conv c = [c] 387 388fun string_of_conv Keep_Conv = "_" 389 | string_of_conv (c as Then_Conv _) = 390 space_implode " then " (map (enclose "(" ")" o string_of_conv) (flatten_then_conv c)) 391 | string_of_conv (Args_Conv (k, cs)) = 392 "args " ^ Argo_Expr.string_of_kind k ^ " " ^ brackets string_of_conv cs 393 | string_of_conv (Rewr_Conv r) = string_of_rewr r 394 395fun string_of_rule (Axiom i) = "axiom " ^ string_of_int i 396 | string_of_rule (Taut (t, _)) = "tautology: " ^ string_of_taut t 397 | string_of_rule (Conjunct (i, n)) = "conjunct " ^ string_of_int i ^ " of " ^ string_of_int n 398 | string_of_rule (Rewrite c) = "rewrite: " ^ string_of_conv c 399 | string_of_rule (Hyp (i, _)) = "hypothesis " ^ string_of_int i 400 | string_of_rule (Clause is) = "clause " ^ brackets string_of_int is 401 | string_of_rule (Lemma is) = "lemma " ^ brackets string_of_int is 402 | string_of_rule (Unit_Res i) = "unit-resolution " ^ string_of_int i 403 | string_of_rule (Refl _) = "reflexivity" 404 | string_of_rule Symm = "symmetry" 405 | string_of_rule Trans = "transitivity" 406 | string_of_rule Cong = "congruence" 407 | string_of_rule Subst = "substitution" 408 | string_of_rule Linear_Comb = "linear-combination" 409 410 411(* unsatisfiability *) 412 413exception UNSAT of proof 414 415fun unsat p = raise UNSAT p 416 417end 418