src/HOL/Tools/sat_funcs.ML
changeset 19976 aa35f8e27c73
parent 19553 9d15911f1893
child 20039 4293f932fe83
equal deleted inserted replaced
19975:ecd684d62808 19976:aa35f8e27c73
    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