src/HOL/Tools/cnf_funcs.ML
changeset 38549 d0385f2764d8
parent 36945 9bec62c10714
child 38553 56965d8e4e11
equal deleted inserted replaced
38548:dea0d2cca822 38549:d0385f2764d8
    91 
    91 
    92 val weakening_thm        = @{lemma "[| P; Q |] ==> Q" by auto};
    92 val weakening_thm        = @{lemma "[| P; Q |] ==> Q" by auto};
    93 
    93 
    94 val cnftac_eq_imp        = @{lemma "[| P = Q; P |] ==> Q" by auto};
    94 val cnftac_eq_imp        = @{lemma "[| P = Q; P |] ==> Q" by auto};
    95 
    95 
    96 fun is_atom (Const ("False", _))                                           = false
    96 fun is_atom (Const (@{const_name "False"}, _))                                           = false
    97   | is_atom (Const ("True", _))                                            = false
    97   | is_atom (Const (@{const_name "True"}, _))                                            = false
    98   | is_atom (Const ("op &", _) $ _ $ _)                                    = false
    98   | is_atom (Const (@{const_name "op &"}, _) $ _ $ _)                                    = false
    99   | is_atom (Const ("op |", _) $ _ $ _)                                    = false
    99   | is_atom (Const (@{const_name "op |"}, _) $ _ $ _)                                    = false
   100   | is_atom (Const ("op -->", _) $ _ $ _)                                  = false
   100   | is_atom (Const (@{const_name "op -->"}, _) $ _ $ _)                                  = false
   101   | is_atom (Const ("op =", Type ("fun", Type ("bool", []) :: _)) $ _ $ _) = false
   101   | is_atom (Const (@{const_name "op ="}, Type ("fun", Type ("bool", []) :: _)) $ _ $ _) = false
   102   | is_atom (Const ("Not", _) $ _)                                         = false
   102   | is_atom (Const (@{const_name "Not"}, _) $ _)                                         = false
   103   | is_atom _                                                              = true;
   103   | is_atom _                                                              = true;
   104 
   104 
   105 fun is_literal (Const ("Not", _) $ x) = is_atom x
   105 fun is_literal (Const (@{const_name "Not"}, _) $ x) = is_atom x
   106   | is_literal x                      = is_atom x;
   106   | is_literal x                      = is_atom x;
   107 
   107 
   108 fun is_clause (Const ("op |", _) $ x $ y) = is_clause x andalso is_clause y
   108 fun is_clause (Const (@{const_name "op |"}, _) $ x $ y) = is_clause x andalso is_clause y
   109   | is_clause x                           = is_literal x;
   109   | is_clause x                           = is_literal x;
   110 
   110 
   111 (* ------------------------------------------------------------------------- *)
   111 (* ------------------------------------------------------------------------- *)
   112 (* clause_is_trivial: a clause is trivially true if it contains both an atom *)
   112 (* clause_is_trivial: a clause is trivially true if it contains both an atom *)
   113 (*      and the atom's negation                                              *)
   113 (*      and the atom's negation                                              *)
   116 (* Term.term -> bool *)
   116 (* Term.term -> bool *)
   117 
   117 
   118 fun clause_is_trivial c =
   118 fun clause_is_trivial c =
   119 	let
   119 	let
   120 		(* Term.term -> Term.term *)
   120 		(* Term.term -> Term.term *)
   121 		fun dual (Const ("Not", _) $ x) = x
   121 		fun dual (Const (@{const_name "Not"}, _) $ x) = x
   122 		  | dual x                      = HOLogic.Not $ x
   122 		  | dual x                      = HOLogic.Not $ x
   123 		(* Term.term list -> bool *)
   123 		(* Term.term list -> bool *)
   124 		fun has_duals []      = false
   124 		fun has_duals []      = false
   125 		  | has_duals (x::xs) = member (op =) xs (dual x) orelse has_duals xs
   125 		  | has_duals (x::xs) = member (op =) xs (dual x) orelse has_duals xs
   126 	in
   126 	in
   182 (*      eliminated (possibly causing an exponential blowup)                  *)
   182 (*      eliminated (possibly causing an exponential blowup)                  *)
   183 (* ------------------------------------------------------------------------- *)
   183 (* ------------------------------------------------------------------------- *)
   184 
   184 
   185 (* Theory.theory -> Term.term -> Thm.thm *)
   185 (* Theory.theory -> Term.term -> Thm.thm *)
   186 
   186 
   187 fun make_nnf_thm thy (Const ("op &", _) $ x $ y) =
   187 fun make_nnf_thm thy (Const (@{const_name "op &"}, _) $ x $ y) =
   188 	let
   188 	let
   189 		val thm1 = make_nnf_thm thy x
   189 		val thm1 = make_nnf_thm thy x
   190 		val thm2 = make_nnf_thm thy y
   190 		val thm2 = make_nnf_thm thy y
   191 	in
   191 	in
   192 		conj_cong OF [thm1, thm2]
   192 		conj_cong OF [thm1, thm2]
   193 	end
   193 	end
   194   | make_nnf_thm thy (Const ("op |", _) $ x $ y) =
   194   | make_nnf_thm thy (Const (@{const_name "op |"}, _) $ x $ y) =
   195 	let
   195 	let
   196 		val thm1 = make_nnf_thm thy x
   196 		val thm1 = make_nnf_thm thy x
   197 		val thm2 = make_nnf_thm thy y
   197 		val thm2 = make_nnf_thm thy y
   198 	in
   198 	in
   199 		disj_cong OF [thm1, thm2]
   199 		disj_cong OF [thm1, thm2]
   200 	end
   200 	end
   201   | make_nnf_thm thy (Const ("op -->", _) $ x $ y) =
   201   | make_nnf_thm thy (Const (@{const_name "op -->"}, _) $ x $ y) =
   202 	let
   202 	let
   203 		val thm1 = make_nnf_thm thy (HOLogic.Not $ x)
   203 		val thm1 = make_nnf_thm thy (HOLogic.Not $ x)
   204 		val thm2 = make_nnf_thm thy y
   204 		val thm2 = make_nnf_thm thy y
   205 	in
   205 	in
   206 		make_nnf_imp OF [thm1, thm2]
   206 		make_nnf_imp OF [thm1, thm2]
   207 	end
   207 	end
   208   | make_nnf_thm thy (Const ("op =", Type ("fun", Type ("bool", []) :: _)) $ x $ y) =
   208   | make_nnf_thm thy (Const (@{const_name "op ="}, Type ("fun", Type ("bool", []) :: _)) $ x $ y) =
   209 	let
   209 	let
   210 		val thm1 = make_nnf_thm thy x
   210 		val thm1 = make_nnf_thm thy x
   211 		val thm2 = make_nnf_thm thy (HOLogic.Not $ x)
   211 		val thm2 = make_nnf_thm thy (HOLogic.Not $ x)
   212 		val thm3 = make_nnf_thm thy y
   212 		val thm3 = make_nnf_thm thy y
   213 		val thm4 = make_nnf_thm thy (HOLogic.Not $ y)
   213 		val thm4 = make_nnf_thm thy (HOLogic.Not $ y)
   214 	in
   214 	in
   215 		make_nnf_iff OF [thm1, thm2, thm3, thm4]
   215 		make_nnf_iff OF [thm1, thm2, thm3, thm4]
   216 	end
   216 	end
   217   | make_nnf_thm thy (Const ("Not", _) $ Const ("False", _)) =
   217   | make_nnf_thm thy (Const (@{const_name "Not"}, _) $ Const (@{const_name "False"}, _)) =
   218 	make_nnf_not_false
   218 	make_nnf_not_false
   219   | make_nnf_thm thy (Const ("Not", _) $ Const ("True", _)) =
   219   | make_nnf_thm thy (Const (@{const_name "Not"}, _) $ Const (@{const_name "True"}, _)) =
   220 	make_nnf_not_true
   220 	make_nnf_not_true
   221   | make_nnf_thm thy (Const ("Not", _) $ (Const ("op &", _) $ x $ y)) =
   221   | make_nnf_thm thy (Const (@{const_name "Not"}, _) $ (Const (@{const_name "op &"}, _) $ x $ y)) =
   222 	let
   222 	let
   223 		val thm1 = make_nnf_thm thy (HOLogic.Not $ x)
   223 		val thm1 = make_nnf_thm thy (HOLogic.Not $ x)
   224 		val thm2 = make_nnf_thm thy (HOLogic.Not $ y)
   224 		val thm2 = make_nnf_thm thy (HOLogic.Not $ y)
   225 	in
   225 	in
   226 		make_nnf_not_conj OF [thm1, thm2]
   226 		make_nnf_not_conj OF [thm1, thm2]
   227 	end
   227 	end
   228   | make_nnf_thm thy (Const ("Not", _) $ (Const ("op |", _) $ x $ y)) =
   228   | make_nnf_thm thy (Const (@{const_name "Not"}, _) $ (Const (@{const_name "op |"}, _) $ x $ y)) =
   229 	let
   229 	let
   230 		val thm1 = make_nnf_thm thy (HOLogic.Not $ x)
   230 		val thm1 = make_nnf_thm thy (HOLogic.Not $ x)
   231 		val thm2 = make_nnf_thm thy (HOLogic.Not $ y)
   231 		val thm2 = make_nnf_thm thy (HOLogic.Not $ y)
   232 	in
   232 	in
   233 		make_nnf_not_disj OF [thm1, thm2]
   233 		make_nnf_not_disj OF [thm1, thm2]
   234 	end
   234 	end
   235   | make_nnf_thm thy (Const ("Not", _) $ (Const ("op -->", _) $ x $ y)) =
   235   | make_nnf_thm thy (Const (@{const_name "Not"}, _) $ (Const (@{const_name "op -->"}, _) $ x $ y)) =
   236 	let
   236 	let
   237 		val thm1 = make_nnf_thm thy x
   237 		val thm1 = make_nnf_thm thy x
   238 		val thm2 = make_nnf_thm thy (HOLogic.Not $ y)
   238 		val thm2 = make_nnf_thm thy (HOLogic.Not $ y)
   239 	in
   239 	in
   240 		make_nnf_not_imp OF [thm1, thm2]
   240 		make_nnf_not_imp OF [thm1, thm2]
   241 	end
   241 	end
   242   | make_nnf_thm thy (Const ("Not", _) $ (Const ("op =", Type ("fun", Type ("bool", []) :: _)) $ x $ y)) =
   242   | make_nnf_thm thy (Const (@{const_name "Not"}, _) $ (Const (@{const_name "op ="}, Type ("fun", Type ("bool", []) :: _)) $ x $ y)) =
   243 	let
   243 	let
   244 		val thm1 = make_nnf_thm thy x
   244 		val thm1 = make_nnf_thm thy x
   245 		val thm2 = make_nnf_thm thy (HOLogic.Not $ x)
   245 		val thm2 = make_nnf_thm thy (HOLogic.Not $ x)
   246 		val thm3 = make_nnf_thm thy y
   246 		val thm3 = make_nnf_thm thy y
   247 		val thm4 = make_nnf_thm thy (HOLogic.Not $ y)
   247 		val thm4 = make_nnf_thm thy (HOLogic.Not $ y)
   248 	in
   248 	in
   249 		make_nnf_not_iff OF [thm1, thm2, thm3, thm4]
   249 		make_nnf_not_iff OF [thm1, thm2, thm3, thm4]
   250 	end
   250 	end
   251   | make_nnf_thm thy (Const ("Not", _) $ (Const ("Not", _) $ x)) =
   251   | make_nnf_thm thy (Const (@{const_name "Not"}, _) $ (Const (@{const_name "Not"}, _) $ x)) =
   252 	let
   252 	let
   253 		val thm1 = make_nnf_thm thy x
   253 		val thm1 = make_nnf_thm thy x
   254 	in
   254 	in
   255 		make_nnf_not_not OF [thm1]
   255 		make_nnf_not_not OF [thm1]
   256 	end
   256 	end
   274 (*      (True, respectively).                                                *)
   274 (*      (True, respectively).                                                *)
   275 (* ------------------------------------------------------------------------- *)
   275 (* ------------------------------------------------------------------------- *)
   276 
   276 
   277 (* Theory.theory -> Term.term -> Thm.thm *)
   277 (* Theory.theory -> Term.term -> Thm.thm *)
   278 
   278 
   279 fun simp_True_False_thm thy (Const ("op &", _) $ x $ y) =
   279 fun simp_True_False_thm thy (Const (@{const_name "op &"}, _) $ x $ y) =
   280 	let
   280 	let
   281 		val thm1 = simp_True_False_thm thy x
   281 		val thm1 = simp_True_False_thm thy x
   282 		val x'   = (snd o HOLogic.dest_eq o HOLogic.dest_Trueprop o prop_of) thm1
   282 		val x'   = (snd o HOLogic.dest_eq o HOLogic.dest_Trueprop o prop_of) thm1
   283 	in
   283 	in
   284 		if x' = HOLogic.false_const then
   284 		if x' = HOLogic.false_const then
   296 					simp_TF_conj_True_r OF [thm1, thm2]  (* (x & y) = x' *)
   296 					simp_TF_conj_True_r OF [thm1, thm2]  (* (x & y) = x' *)
   297 				else
   297 				else
   298 					conj_cong OF [thm1, thm2]  (* (x & y) = (x' & y') *)
   298 					conj_cong OF [thm1, thm2]  (* (x & y) = (x' & y') *)
   299 			end
   299 			end
   300 	end
   300 	end
   301   | simp_True_False_thm thy (Const ("op |", _) $ x $ y) =
   301   | simp_True_False_thm thy (Const (@{const_name "op |"}, _) $ x $ y) =
   302 	let
   302 	let
   303 		val thm1 = simp_True_False_thm thy x
   303 		val thm1 = simp_True_False_thm thy x
   304 		val x'   = (snd o HOLogic.dest_eq o HOLogic.dest_Trueprop o prop_of) thm1
   304 		val x'   = (snd o HOLogic.dest_eq o HOLogic.dest_Trueprop o prop_of) thm1
   305 	in
   305 	in
   306 		if x' = HOLogic.true_const then
   306 		if x' = HOLogic.true_const then
   332 (* Theory.theory -> Term.term -> Thm.thm *)
   332 (* Theory.theory -> Term.term -> Thm.thm *)
   333 
   333 
   334 fun make_cnf_thm thy t =
   334 fun make_cnf_thm thy t =
   335 let
   335 let
   336 	(* Term.term -> Thm.thm *)
   336 	(* Term.term -> Thm.thm *)
   337 	fun make_cnf_thm_from_nnf (Const ("op &", _) $ x $ y) =
   337 	fun make_cnf_thm_from_nnf (Const (@{const_name "op &"}, _) $ x $ y) =
   338 		let
   338 		let
   339 			val thm1 = make_cnf_thm_from_nnf x
   339 			val thm1 = make_cnf_thm_from_nnf x
   340 			val thm2 = make_cnf_thm_from_nnf y
   340 			val thm2 = make_cnf_thm_from_nnf y
   341 		in
   341 		in
   342 			conj_cong OF [thm1, thm2]
   342 			conj_cong OF [thm1, thm2]
   343 		end
   343 		end
   344 	  | make_cnf_thm_from_nnf (Const ("op |", _) $ x $ y) =
   344 	  | make_cnf_thm_from_nnf (Const (@{const_name "op |"}, _) $ x $ y) =
   345 		let
   345 		let
   346 			(* produces a theorem "(x' | y') = t'", where x', y', and t' are in CNF *)
   346 			(* produces a theorem "(x' | y') = t'", where x', y', and t' are in CNF *)
   347 			fun make_cnf_disj_thm (Const ("op &", _) $ x1 $ x2) y' =
   347 			fun make_cnf_disj_thm (Const (@{const_name "op &"}, _) $ x1 $ x2) y' =
   348 				let
   348 				let
   349 					val thm1 = make_cnf_disj_thm x1 y'
   349 					val thm1 = make_cnf_disj_thm x1 y'
   350 					val thm2 = make_cnf_disj_thm x2 y'
   350 					val thm2 = make_cnf_disj_thm x2 y'
   351 				in
   351 				in
   352 					make_cnf_disj_conj_l OF [thm1, thm2]  (* ((x1 & x2) | y') = ((x1 | y')' & (x2 | y')') *)
   352 					make_cnf_disj_conj_l OF [thm1, thm2]  (* ((x1 & x2) | y') = ((x1 | y')' & (x2 | y')') *)
   353 				end
   353 				end
   354 			  | make_cnf_disj_thm x' (Const ("op &", _) $ y1 $ y2) =
   354 			  | make_cnf_disj_thm x' (Const (@{const_name "op &"}, _) $ y1 $ y2) =
   355 				let
   355 				let
   356 					val thm1 = make_cnf_disj_thm x' y1
   356 					val thm1 = make_cnf_disj_thm x' y1
   357 					val thm2 = make_cnf_disj_thm x' y2
   357 					val thm2 = make_cnf_disj_thm x' y2
   358 				in
   358 				in
   359 					make_cnf_disj_conj_r OF [thm1, thm2]  (* (x' | (y1 & y2)) = ((x' | y1)' & (x' | y2)') *)
   359 					make_cnf_disj_conj_r OF [thm1, thm2]  (* (x' | (y1 & y2)) = ((x' | y1)' & (x' | y2)') *)
   401 fun make_cnfx_thm thy t =
   401 fun make_cnfx_thm thy t =
   402 let
   402 let
   403 	val var_id = Unsynchronized.ref 0  (* properly initialized below *)
   403 	val var_id = Unsynchronized.ref 0  (* properly initialized below *)
   404 	fun new_free () =
   404 	fun new_free () =
   405 		Free ("cnfx_" ^ string_of_int (Unsynchronized.inc var_id), HOLogic.boolT)
   405 		Free ("cnfx_" ^ string_of_int (Unsynchronized.inc var_id), HOLogic.boolT)
   406 	fun make_cnfx_thm_from_nnf (Const ("op &", _) $ x $ y) : thm =
   406 	fun make_cnfx_thm_from_nnf (Const (@{const_name "op &"}, _) $ x $ y) : thm =
   407 		let
   407 		let
   408 			val thm1 = make_cnfx_thm_from_nnf x
   408 			val thm1 = make_cnfx_thm_from_nnf x
   409 			val thm2 = make_cnfx_thm_from_nnf y
   409 			val thm2 = make_cnfx_thm_from_nnf y
   410 		in
   410 		in
   411 			conj_cong OF [thm1, thm2]
   411 			conj_cong OF [thm1, thm2]
   412 		end
   412 		end
   413 	  | make_cnfx_thm_from_nnf (Const ("op |", _) $ x $ y) =
   413 	  | make_cnfx_thm_from_nnf (Const (@{const_name "op |"}, _) $ x $ y) =
   414 		if is_clause x andalso is_clause y then
   414 		if is_clause x andalso is_clause y then
   415 			inst_thm thy [HOLogic.mk_disj (x, y)] iff_refl
   415 			inst_thm thy [HOLogic.mk_disj (x, y)] iff_refl
   416 		else if is_literal y orelse is_literal x then let
   416 		else if is_literal y orelse is_literal x then let
   417 			(* produces a theorem "(x' | y') = t'", where x', y', and t' are *)
   417 			(* produces a theorem "(x' | y') = t'", where x', y', and t' are *)
   418 			(* almost in CNF, and x' or y' is a literal                      *)
   418 			(* almost in CNF, and x' or y' is a literal                      *)
   419 			fun make_cnfx_disj_thm (Const ("op &", _) $ x1 $ x2) y' =
   419 			fun make_cnfx_disj_thm (Const (@{const_name "op &"}, _) $ x1 $ x2) y' =
   420 				let
   420 				let
   421 					val thm1 = make_cnfx_disj_thm x1 y'
   421 					val thm1 = make_cnfx_disj_thm x1 y'
   422 					val thm2 = make_cnfx_disj_thm x2 y'
   422 					val thm2 = make_cnfx_disj_thm x2 y'
   423 				in
   423 				in
   424 					make_cnf_disj_conj_l OF [thm1, thm2]  (* ((x1 & x2) | y') = ((x1 | y')' & (x2 | y')') *)
   424 					make_cnf_disj_conj_l OF [thm1, thm2]  (* ((x1 & x2) | y') = ((x1 | y')' & (x2 | y')') *)
   425 				end
   425 				end
   426 			  | make_cnfx_disj_thm x' (Const ("op &", _) $ y1 $ y2) =
   426 			  | make_cnfx_disj_thm x' (Const (@{const_name "op &"}, _) $ y1 $ y2) =
   427 				let
   427 				let
   428 					val thm1 = make_cnfx_disj_thm x' y1
   428 					val thm1 = make_cnfx_disj_thm x' y1
   429 					val thm2 = make_cnfx_disj_thm x' y2
   429 					val thm2 = make_cnfx_disj_thm x' y2
   430 				in
   430 				in
   431 					make_cnf_disj_conj_r OF [thm1, thm2]  (* (x' | (y1 & y2)) = ((x' | y1)' & (x' | y2)') *)
   431 					make_cnf_disj_conj_r OF [thm1, thm2]  (* (x' | (y1 & y2)) = ((x' | y1)' & (x' | y2)') *)
   432 				end
   432 				end
   433 			  | make_cnfx_disj_thm (Const ("Ex", _) $ x') y' =
   433 			  | make_cnfx_disj_thm (Const (@{const_name "Ex"}, _) $ x') y' =
   434 				let
   434 				let
   435 					val thm1 = inst_thm thy [x', y'] make_cnfx_disj_ex_l   (* ((Ex x') | y') = (Ex (x' | y')) *)
   435 					val thm1 = inst_thm thy [x', y'] make_cnfx_disj_ex_l   (* ((Ex x') | y') = (Ex (x' | y')) *)
   436 					val var  = new_free ()
   436 					val var  = new_free ()
   437 					val thm2 = make_cnfx_disj_thm (betapply (x', var)) y'  (* (x' | y') = body' *)
   437 					val thm2 = make_cnfx_disj_thm (betapply (x', var)) y'  (* (x' | y') = body' *)
   438 					val thm3 = Thm.forall_intr (cterm_of thy var) thm2     (* !!v. (x' | y') = body' *)
   438 					val thm3 = Thm.forall_intr (cterm_of thy var) thm2     (* !!v. (x' | y') = body' *)
   439 					val thm4 = Thm.strip_shyps (thm3 COMP allI)            (* ALL v. (x' | y') = body' *)
   439 					val thm4 = Thm.strip_shyps (thm3 COMP allI)            (* ALL v. (x' | y') = body' *)
   440 					val thm5 = Thm.strip_shyps (thm4 RS make_cnfx_ex_cong) (* (EX v. (x' | y')) = (EX v. body') *)
   440 					val thm5 = Thm.strip_shyps (thm4 RS make_cnfx_ex_cong) (* (EX v. (x' | y')) = (EX v. body') *)
   441 				in
   441 				in
   442 					iff_trans OF [thm1, thm5]  (* ((Ex x') | y') = (Ex v. body') *)
   442 					iff_trans OF [thm1, thm5]  (* ((Ex x') | y') = (Ex v. body') *)
   443 				end
   443 				end
   444 			  | make_cnfx_disj_thm x' (Const ("Ex", _) $ y') =
   444 			  | make_cnfx_disj_thm x' (Const (@{const_name "Ex"}, _) $ y') =
   445 				let
   445 				let
   446 					val thm1 = inst_thm thy [x', y'] make_cnfx_disj_ex_r   (* (x' | (Ex y')) = (Ex (x' | y')) *)
   446 					val thm1 = inst_thm thy [x', y'] make_cnfx_disj_ex_r   (* (x' | (Ex y')) = (Ex (x' | y')) *)
   447 					val var  = new_free ()
   447 					val var  = new_free ()
   448 					val thm2 = make_cnfx_disj_thm x' (betapply (y', var))  (* (x' | y') = body' *)
   448 					val thm2 = make_cnfx_disj_thm x' (betapply (y', var))  (* (x' | y') = body' *)
   449 					val thm3 = Thm.forall_intr (cterm_of thy var) thm2     (* !!v. (x' | y') = body' *)
   449 					val thm3 = Thm.forall_intr (cterm_of thy var) thm2     (* !!v. (x' | y') = body' *)