src/HOL/Tools/cnf.ML
changeset 80637 e2f0265f64e3
parent 70486 1dc3514c1719
child 80638 21637b691fab
equal deleted inserted replaced
80636:4041e7c8059d 80637:e2f0265f64e3
    52 end;
    52 end;
    53 
    53 
    54 structure CNF : CNF =
    54 structure CNF : CNF =
    55 struct
    55 struct
    56 
    56 
    57 fun is_atom (Const (\<^const_name>\<open>False\<close>, _)) = false
    57 fun is_atom \<^Const_>\<open>False\<close> = false
    58   | is_atom (Const (\<^const_name>\<open>True\<close>, _)) = false
    58   | is_atom \<^Const_>\<open>True\<close> = false
    59   | is_atom (Const (\<^const_name>\<open>HOL.conj\<close>, _) $ _ $ _) = false
    59   | is_atom \<^Const_>\<open>conj for _ _\<close> = false
    60   | is_atom (Const (\<^const_name>\<open>HOL.disj\<close>, _) $ _ $ _) = false
    60   | is_atom \<^Const_>\<open>disj for _ _\<close> = false
    61   | is_atom (Const (\<^const_name>\<open>HOL.implies\<close>, _) $ _ $ _) = false
    61   | is_atom \<^Const_>\<open>implies for _ _\<close> = false
    62   | is_atom (Const (\<^const_name>\<open>HOL.eq\<close>, Type ("fun", \<^typ>\<open>bool\<close> :: _)) $ _ $ _) = false
    62   | is_atom \<^Const_>\<open>HOL.eq \<^Type>\<open>bool\<close> for _ _\<close> = false
    63   | is_atom (Const (\<^const_name>\<open>Not\<close>, _) $ _) = false
    63   | is_atom \<^Const_>\<open>Not for _\<close> = false
    64   | is_atom _ = true;
    64   | is_atom _ = true;
    65 
    65 
    66 fun is_literal (Const (\<^const_name>\<open>Not\<close>, _) $ x) = is_atom x
    66 fun is_literal \<^Const_>\<open>Not for x\<close> = is_atom x
    67   | is_literal x = is_atom x;
    67   | is_literal x = is_atom x;
    68 
    68 
    69 fun is_clause (Const (\<^const_name>\<open>HOL.disj\<close>, _) $ x $ y) = is_clause x andalso is_clause y
    69 fun is_clause \<^Const_>\<open>disj for x y\<close> = is_clause x andalso is_clause y
    70   | is_clause x = is_literal x;
    70   | is_clause x = is_literal x;
    71 
    71 
    72 (* ------------------------------------------------------------------------- *)
    72 (* ------------------------------------------------------------------------- *)
    73 (* clause_is_trivial: a clause is trivially true if it contains both an atom *)
    73 (* clause_is_trivial: a clause is trivially true if it contains both an atom *)
    74 (*      and the atom's negation                                              *)
    74 (*      and the atom's negation                                              *)
    75 (* ------------------------------------------------------------------------- *)
    75 (* ------------------------------------------------------------------------- *)
    76 
    76 
    77 fun clause_is_trivial c =
    77 fun clause_is_trivial c =
    78   let
    78   let
    79     fun dual (Const (\<^const_name>\<open>Not\<close>, _) $ x) = x
    79     fun dual \<^Const_>\<open>Not for x\<close> = x
    80       | dual x = HOLogic.Not $ x
    80       | dual x = \<^Const>\<open>Not for x\<close>
    81     fun has_duals [] = false
    81     fun has_duals [] = false
    82       | has_duals (x::xs) = member (op =) xs (dual x) orelse has_duals xs
    82       | has_duals (x::xs) = member (op =) xs (dual x) orelse has_duals xs
    83   in
    83   in
    84     has_duals (HOLogic.disjuncts c)
    84     has_duals (HOLogic.disjuncts c)
    85   end;
    85   end;
   134 (*      negation normal form (i.e. negation only occurs in front of atoms)   *)
   134 (*      negation normal form (i.e. negation only occurs in front of atoms)   *)
   135 (*      of t; implications ("-->") and equivalences ("=" on bool) are        *)
   135 (*      of t; implications ("-->") and equivalences ("=" on bool) are        *)
   136 (*      eliminated (possibly causing an exponential blowup)                  *)
   136 (*      eliminated (possibly causing an exponential blowup)                  *)
   137 (* ------------------------------------------------------------------------- *)
   137 (* ------------------------------------------------------------------------- *)
   138 
   138 
   139 fun make_nnf_thm thy (Const (\<^const_name>\<open>HOL.conj\<close>, _) $ x $ y) =
   139 fun make_nnf_thm thy \<^Const_>\<open>conj for x y\<close> =
   140       let
   140       let
   141         val thm1 = make_nnf_thm thy x
   141         val thm1 = make_nnf_thm thy x
   142         val thm2 = make_nnf_thm thy y
   142         val thm2 = make_nnf_thm thy y
   143       in
   143       in
   144         @{thm cnf.conj_cong} OF [thm1, thm2]
   144         @{thm cnf.conj_cong} OF [thm1, thm2]
   145       end
   145       end
   146   | make_nnf_thm thy (Const (\<^const_name>\<open>HOL.disj\<close>, _) $ x $ y) =
   146   | make_nnf_thm thy \<^Const_>\<open>disj for x y\<close> =
   147       let
   147       let
   148         val thm1 = make_nnf_thm thy x
   148         val thm1 = make_nnf_thm thy x
   149         val thm2 = make_nnf_thm thy y
   149         val thm2 = make_nnf_thm thy y
   150       in
   150       in
   151         @{thm cnf.disj_cong} OF [thm1, thm2]
   151         @{thm cnf.disj_cong} OF [thm1, thm2]
   152       end
   152       end
   153   | make_nnf_thm thy (Const (\<^const_name>\<open>HOL.implies\<close>, _) $ x $ y) =
   153   | make_nnf_thm thy \<^Const_>\<open>implies for x y\<close> =
   154       let
   154       let
   155         val thm1 = make_nnf_thm thy (HOLogic.Not $ x)
   155         val thm1 = make_nnf_thm thy \<^Const>\<open>Not for x\<close>
   156         val thm2 = make_nnf_thm thy y
   156         val thm2 = make_nnf_thm thy y
   157       in
   157       in
   158         @{thm cnf.make_nnf_imp} OF [thm1, thm2]
   158         @{thm cnf.make_nnf_imp} OF [thm1, thm2]
   159       end
   159       end
   160   | make_nnf_thm thy (Const (\<^const_name>\<open>HOL.eq\<close>, Type ("fun", \<^typ>\<open>bool\<close> :: _)) $ x $ y) =
   160   | make_nnf_thm thy \<^Const_>\<open>HOL.eq \<^Type>\<open>bool\<close> for x y\<close> =
   161       let
   161       let
   162         val thm1 = make_nnf_thm thy x
   162         val thm1 = make_nnf_thm thy x
   163         val thm2 = make_nnf_thm thy (HOLogic.Not $ x)
   163         val thm2 = make_nnf_thm thy \<^Const>\<open>Not for x\<close>
   164         val thm3 = make_nnf_thm thy y
   164         val thm3 = make_nnf_thm thy y
   165         val thm4 = make_nnf_thm thy (HOLogic.Not $ y)
   165         val thm4 = make_nnf_thm thy \<^Const>\<open>Not for y\<close>
   166       in
   166       in
   167         @{thm cnf.make_nnf_iff} OF [thm1, thm2, thm3, thm4]
   167         @{thm cnf.make_nnf_iff} OF [thm1, thm2, thm3, thm4]
   168       end
   168       end
   169   | make_nnf_thm _ (Const (\<^const_name>\<open>Not\<close>, _) $ Const (\<^const_name>\<open>False\<close>, _)) =
   169   | make_nnf_thm _ \<^Const_>\<open>Not for \<^Const_>\<open>False\<close>\<close> =
   170       @{thm cnf.make_nnf_not_false}
   170       @{thm cnf.make_nnf_not_false}
   171   | make_nnf_thm _ (Const (\<^const_name>\<open>Not\<close>, _) $ Const (\<^const_name>\<open>True\<close>, _)) =
   171   | make_nnf_thm _ \<^Const_>\<open>Not for \<^Const_>\<open>True\<close>\<close> =
   172       @{thm cnf.make_nnf_not_true}
   172       @{thm cnf.make_nnf_not_true}
   173   | make_nnf_thm thy (Const (\<^const_name>\<open>Not\<close>, _) $ (Const (\<^const_name>\<open>HOL.conj\<close>, _) $ x $ y)) =
   173   | make_nnf_thm thy \<^Const_>\<open>Not for \<^Const_>\<open>conj for x y\<close>\<close> =
   174       let
   174       let
   175         val thm1 = make_nnf_thm thy (HOLogic.Not $ x)
   175         val thm1 = make_nnf_thm thy \<^Const>\<open>Not for x\<close>
   176         val thm2 = make_nnf_thm thy (HOLogic.Not $ y)
   176         val thm2 = make_nnf_thm thy \<^Const>\<open>Not for y\<close>
   177       in
   177       in
   178         @{thm cnf.make_nnf_not_conj} OF [thm1, thm2]
   178         @{thm cnf.make_nnf_not_conj} OF [thm1, thm2]
   179       end
   179       end
   180   | make_nnf_thm thy (Const (\<^const_name>\<open>Not\<close>, _) $ (Const (\<^const_name>\<open>HOL.disj\<close>, _) $ x $ y)) =
   180   | make_nnf_thm thy \<^Const_>\<open>Not for \<^Const_>\<open>disj for x y\<close>\<close> =
   181       let
   181       let
   182         val thm1 = make_nnf_thm thy (HOLogic.Not $ x)
   182         val thm1 = make_nnf_thm thy \<^Const>\<open>Not for x\<close>
   183         val thm2 = make_nnf_thm thy (HOLogic.Not $ y)
   183         val thm2 = make_nnf_thm thy \<^Const>\<open>Not for y\<close>
   184       in
   184       in
   185         @{thm cnf.make_nnf_not_disj} OF [thm1, thm2]
   185         @{thm cnf.make_nnf_not_disj} OF [thm1, thm2]
   186       end
   186       end
   187   | make_nnf_thm thy
   187   | make_nnf_thm thy \<^Const_>\<open>Not for \<^Const_>\<open>implies for x y\<close>\<close> =
   188       (Const (\<^const_name>\<open>Not\<close>, _) $ (Const (\<^const_name>\<open>HOL.implies\<close>, _) $ x $ y)) =
       
   189       let
   188       let
   190         val thm1 = make_nnf_thm thy x
   189         val thm1 = make_nnf_thm thy x
   191         val thm2 = make_nnf_thm thy (HOLogic.Not $ y)
   190         val thm2 = make_nnf_thm thy \<^Const>\<open>Not for y\<close>
   192       in
   191       in
   193         @{thm cnf.make_nnf_not_imp} OF [thm1, thm2]
   192         @{thm cnf.make_nnf_not_imp} OF [thm1, thm2]
   194       end
   193       end
   195   | make_nnf_thm thy
   194   | make_nnf_thm thy \<^Const_>\<open>Not for \<^Const_>\<open>HOL.eq \<^Type>\<open>bool\<close> for x y\<close>\<close> =
   196       (Const (\<^const_name>\<open>Not\<close>, _) $
       
   197         (Const (\<^const_name>\<open>HOL.eq\<close>, Type ("fun", \<^typ>\<open>bool\<close> :: _)) $ x $ y)) =
       
   198       let
   195       let
   199         val thm1 = make_nnf_thm thy x
   196         val thm1 = make_nnf_thm thy x
   200         val thm2 = make_nnf_thm thy (HOLogic.Not $ x)
   197         val thm2 = make_nnf_thm thy \<^Const>\<open>Not for x\<close>
   201         val thm3 = make_nnf_thm thy y
   198         val thm3 = make_nnf_thm thy y
   202         val thm4 = make_nnf_thm thy (HOLogic.Not $ y)
   199         val thm4 = make_nnf_thm thy \<^Const>\<open>Not for y\<close>
   203       in
   200       in
   204         @{thm cnf.make_nnf_not_iff} OF [thm1, thm2, thm3, thm4]
   201         @{thm cnf.make_nnf_not_iff} OF [thm1, thm2, thm3, thm4]
   205       end
   202       end
   206   | make_nnf_thm thy (Const (\<^const_name>\<open>Not\<close>, _) $ (Const (\<^const_name>\<open>Not\<close>, _) $ x)) =
   203   | make_nnf_thm thy \<^Const_>\<open>Not for \<^Const_>\<open>Not for x\<close>\<close> =
   207       let
   204       let
   208         val thm1 = make_nnf_thm thy x
   205         val thm1 = make_nnf_thm thy x
   209       in
   206       in
   210         @{thm cnf.make_nnf_not_not} OF [thm1]
   207         @{thm cnf.make_nnf_not_not} OF [thm1]
   211       end
   208       end
   239 (*      Optimization: The right-hand side of a conjunction (disjunction) is  *)
   236 (*      Optimization: The right-hand side of a conjunction (disjunction) is  *)
   240 (*      simplified only if the left-hand side does not simplify to False     *)
   237 (*      simplified only if the left-hand side does not simplify to False     *)
   241 (*      (True, respectively).                                                *)
   238 (*      (True, respectively).                                                *)
   242 (* ------------------------------------------------------------------------- *)
   239 (* ------------------------------------------------------------------------- *)
   243 
   240 
   244 fun simp_True_False_thm thy (Const (\<^const_name>\<open>HOL.conj\<close>, _) $ x $ y) =
   241 fun simp_True_False_thm thy \<^Const_>\<open>conj for x y\<close> =
   245       let
   242       let
   246         val thm1 = simp_True_False_thm thy x
   243         val thm1 = simp_True_False_thm thy x
   247         val x'= (snd o HOLogic.dest_eq o HOLogic.dest_Trueprop o Thm.prop_of) thm1
   244         val x'= (snd o HOLogic.dest_eq o HOLogic.dest_Trueprop o Thm.prop_of) thm1
   248       in
   245       in
   249         if x' = \<^term>\<open>False\<close> then
   246         if x' = \<^Const>\<open>False\<close> then
   250           @{thm cnf.simp_TF_conj_False_l} OF [thm1]  (* (x & y) = False *)
   247           @{thm cnf.simp_TF_conj_False_l} OF [thm1]  (* (x & y) = False *)
   251         else
   248         else
   252           let
   249           let
   253             val thm2 = simp_True_False_thm thy y
   250             val thm2 = simp_True_False_thm thy y
   254             val y' = (snd o HOLogic.dest_eq o HOLogic.dest_Trueprop o Thm.prop_of) thm2
   251             val y' = (snd o HOLogic.dest_eq o HOLogic.dest_Trueprop o Thm.prop_of) thm2
   255           in
   252           in
   256             if x' = \<^term>\<open>True\<close> then
   253             if x' = \<^Const>\<open>True\<close> then
   257               @{thm cnf.simp_TF_conj_True_l} OF [thm1, thm2]  (* (x & y) = y' *)
   254               @{thm cnf.simp_TF_conj_True_l} OF [thm1, thm2]  (* (x & y) = y' *)
   258             else if y' = \<^term>\<open>False\<close> then
   255             else if y' = \<^Const>\<open>False\<close> then
   259               @{thm cnf.simp_TF_conj_False_r} OF [thm2]  (* (x & y) = False *)
   256               @{thm cnf.simp_TF_conj_False_r} OF [thm2]  (* (x & y) = False *)
   260             else if y' = \<^term>\<open>True\<close> then
   257             else if y' = \<^Const>\<open>True\<close> then
   261               @{thm cnf.simp_TF_conj_True_r} OF [thm1, thm2]  (* (x & y) = x' *)
   258               @{thm cnf.simp_TF_conj_True_r} OF [thm1, thm2]  (* (x & y) = x' *)
   262             else
   259             else
   263               @{thm cnf.conj_cong} OF [thm1, thm2]  (* (x & y) = (x' & y') *)
   260               @{thm cnf.conj_cong} OF [thm1, thm2]  (* (x & y) = (x' & y') *)
   264           end
   261           end
   265       end
   262       end
   266   | simp_True_False_thm thy (Const (\<^const_name>\<open>HOL.disj\<close>, _) $ x $ y) =
   263   | simp_True_False_thm thy \<^Const_>\<open>disj for x y\<close> =
   267       let
   264       let
   268         val thm1 = simp_True_False_thm thy x
   265         val thm1 = simp_True_False_thm thy x
   269         val x' = (snd o HOLogic.dest_eq o HOLogic.dest_Trueprop o Thm.prop_of) thm1
   266         val x' = (snd o HOLogic.dest_eq o HOLogic.dest_Trueprop o Thm.prop_of) thm1
   270       in
   267       in
   271         if x' = \<^term>\<open>True\<close> then
   268         if x' = \<^Const>\<open>True\<close> then
   272           @{thm cnf.simp_TF_disj_True_l} OF [thm1]  (* (x | y) = True *)
   269           @{thm cnf.simp_TF_disj_True_l} OF [thm1]  (* (x | y) = True *)
   273         else
   270         else
   274           let
   271           let
   275             val thm2 = simp_True_False_thm thy y
   272             val thm2 = simp_True_False_thm thy y
   276             val y' = (snd o HOLogic.dest_eq o HOLogic.dest_Trueprop o Thm.prop_of) thm2
   273             val y' = (snd o HOLogic.dest_eq o HOLogic.dest_Trueprop o Thm.prop_of) thm2
   277           in
   274           in
   278             if x' = \<^term>\<open>False\<close> then
   275             if x' = \<^Const>\<open>False\<close> then
   279               @{thm cnf.simp_TF_disj_False_l} OF [thm1, thm2]  (* (x | y) = y' *)
   276               @{thm cnf.simp_TF_disj_False_l} OF [thm1, thm2]  (* (x | y) = y' *)
   280             else if y' = \<^term>\<open>True\<close> then
   277             else if y' = \<^Const>\<open>True\<close> then
   281               @{thm cnf.simp_TF_disj_True_r} OF [thm2]  (* (x | y) = True *)
   278               @{thm cnf.simp_TF_disj_True_r} OF [thm2]  (* (x | y) = True *)
   282             else if y' = \<^term>\<open>False\<close> then
   279             else if y' = \<^Const>\<open>False\<close> then
   283               @{thm cnf.simp_TF_disj_False_r} OF [thm1, thm2]  (* (x | y) = x' *)
   280               @{thm cnf.simp_TF_disj_False_r} OF [thm1, thm2]  (* (x | y) = x' *)
   284             else
   281             else
   285               @{thm cnf.disj_cong} OF [thm1, thm2]  (* (x | y) = (x' | y') *)
   282               @{thm cnf.disj_cong} OF [thm1, thm2]  (* (x | y) = (x' | y') *)
   286           end
   283           end
   287       end
   284       end
   294 (* ------------------------------------------------------------------------- *)
   291 (* ------------------------------------------------------------------------- *)
   295 
   292 
   296 fun make_cnf_thm ctxt t =
   293 fun make_cnf_thm ctxt t =
   297   let
   294   let
   298     val thy = Proof_Context.theory_of ctxt
   295     val thy = Proof_Context.theory_of ctxt
   299     fun make_cnf_thm_from_nnf (Const (\<^const_name>\<open>HOL.conj\<close>, _) $ x $ y) =
   296     fun make_cnf_thm_from_nnf \<^Const_>\<open>conj for x y\<close> =
   300           let
   297           let
   301             val thm1 = make_cnf_thm_from_nnf x
   298             val thm1 = make_cnf_thm_from_nnf x
   302             val thm2 = make_cnf_thm_from_nnf y
   299             val thm2 = make_cnf_thm_from_nnf y
   303           in
   300           in
   304             @{thm cnf.conj_cong} OF [thm1, thm2]
   301             @{thm cnf.conj_cong} OF [thm1, thm2]
   305           end
   302           end
   306       | make_cnf_thm_from_nnf (Const (\<^const_name>\<open>HOL.disj\<close>, _) $ x $ y) =
   303       | make_cnf_thm_from_nnf \<^Const_>\<open>disj for x y\<close> =
   307           let
   304           let
   308             (* produces a theorem "(x' | y') = t'", where x', y', and t' are in CNF *)
   305             (* produces a theorem "(x' | y') = t'", where x', y', and t' are in CNF *)
   309             fun make_cnf_disj_thm (Const (\<^const_name>\<open>HOL.conj\<close>, _) $ x1 $ x2) y' =
   306             fun make_cnf_disj_thm \<^Const_>\<open>conj for x1 x2\<close> y' =
   310                   let
   307                   let
   311                     val thm1 = make_cnf_disj_thm x1 y'
   308                     val thm1 = make_cnf_disj_thm x1 y'
   312                     val thm2 = make_cnf_disj_thm x2 y'
   309                     val thm2 = make_cnf_disj_thm x2 y'
   313                   in
   310                   in
   314                     @{thm cnf.make_cnf_disj_conj_l} OF [thm1, thm2]  (* ((x1 & x2) | y') = ((x1 | y')' & (x2 | y')') *)
   311                     @{thm cnf.make_cnf_disj_conj_l} OF [thm1, thm2]  (* ((x1 & x2) | y') = ((x1 | y')' & (x2 | y')') *)
   315                   end
   312                   end
   316               | make_cnf_disj_thm x' (Const (\<^const_name>\<open>HOL.conj\<close>, _) $ y1 $ y2) =
   313               | make_cnf_disj_thm x' \<^Const_>\<open>conj for y1 y2\<close> =
   317                   let
   314                   let
   318                     val thm1 = make_cnf_disj_thm x' y1
   315                     val thm1 = make_cnf_disj_thm x' y1
   319                     val thm2 = make_cnf_disj_thm x' y2
   316                     val thm2 = make_cnf_disj_thm x' y2
   320                   in
   317                   in
   321                     @{thm cnf.make_cnf_disj_conj_r} OF [thm1, thm2]  (* (x' | (y1 & y2)) = ((x' | y1)' & (x' | y2)') *)
   318                     @{thm cnf.make_cnf_disj_conj_r} OF [thm1, thm2]  (* (x' | (y1 & y2)) = ((x' | y1)' & (x' | y2)') *)
   322                   end
   319                   end
   323               | make_cnf_disj_thm x' y' =
   320               | make_cnf_disj_thm x' y' =
   324                   inst_thm thy [HOLogic.mk_disj (x', y')] @{thm cnf.iff_refl}  (* (x' | y') = (x' | y') *)
   321                   inst_thm thy [\<^Const>\<open>disj for x' y'\<close>] @{thm cnf.iff_refl}  (* (x' | y') = (x' | y') *)
   325             val thm1 = make_cnf_thm_from_nnf x
   322             val thm1 = make_cnf_thm_from_nnf x
   326             val thm2 = make_cnf_thm_from_nnf y
   323             val thm2 = make_cnf_thm_from_nnf y
   327             val x' = (snd o HOLogic.dest_eq o HOLogic.dest_Trueprop o Thm.prop_of) thm1
   324             val x' = (snd o HOLogic.dest_eq o HOLogic.dest_Trueprop o Thm.prop_of) thm1
   328             val y' = (snd o HOLogic.dest_eq o HOLogic.dest_Trueprop o Thm.prop_of) thm2
   325             val y' = (snd o HOLogic.dest_eq o HOLogic.dest_Trueprop o Thm.prop_of) thm2
   329             val disj_thm = @{thm cnf.disj_cong} OF [thm1, thm2]  (* (x | y) = (x' | y') *)
   326             val disj_thm = @{thm cnf.disj_cong} OF [thm1, thm2]  (* (x | y) = (x' | y') *)
   366 fun make_cnfx_thm ctxt t =
   363 fun make_cnfx_thm ctxt t =
   367   let
   364   let
   368     val thy = Proof_Context.theory_of ctxt
   365     val thy = Proof_Context.theory_of ctxt
   369     val var_id = Unsynchronized.ref 0  (* properly initialized below *)
   366     val var_id = Unsynchronized.ref 0  (* properly initialized below *)
   370     fun new_free () =
   367     fun new_free () =
   371       Free ("cnfx_" ^ string_of_int (Unsynchronized.inc var_id), HOLogic.boolT)
   368       Free ("cnfx_" ^ string_of_int (Unsynchronized.inc var_id), \<^Type>\<open>bool\<close>)
   372     fun make_cnfx_thm_from_nnf (Const (\<^const_name>\<open>HOL.conj\<close>, _) $ x $ y) : thm =
   369     fun make_cnfx_thm_from_nnf \<^Const_>\<open>conj for x y\<close> =
   373           let
   370           let
   374             val thm1 = make_cnfx_thm_from_nnf x
   371             val thm1 = make_cnfx_thm_from_nnf x
   375             val thm2 = make_cnfx_thm_from_nnf y
   372             val thm2 = make_cnfx_thm_from_nnf y
   376           in
   373           in
   377             @{thm cnf.conj_cong} OF [thm1, thm2]
   374             @{thm cnf.conj_cong} OF [thm1, thm2]
   378           end
   375           end
   379       | make_cnfx_thm_from_nnf (Const (\<^const_name>\<open>HOL.disj\<close>, _) $ x $ y) =
   376       | make_cnfx_thm_from_nnf \<^Const_>\<open>disj for x y\<close> =
   380           if is_clause x andalso is_clause y then
   377           if is_clause x andalso is_clause y then
   381             inst_thm thy [HOLogic.mk_disj (x, y)] @{thm cnf.iff_refl}
   378             inst_thm thy [\<^Const>\<open>disj for x y\<close>] @{thm cnf.iff_refl}
   382           else if is_literal y orelse is_literal x then
   379           else if is_literal y orelse is_literal x then
   383             let
   380             let
   384               (* produces a theorem "(x' | y') = t'", where x', y', and t' are *)
   381               (* produces a theorem "(x' | y') = t'", where x', y', and t' are *)
   385               (* almost in CNF, and x' or y' is a literal                      *)
   382               (* almost in CNF, and x' or y' is a literal                      *)
   386               fun make_cnfx_disj_thm (Const (\<^const_name>\<open>HOL.conj\<close>, _) $ x1 $ x2) y' =
   383               fun make_cnfx_disj_thm \<^Const_>\<open>conj for x1 x2\<close> y' =
   387                     let
   384                     let
   388                       val thm1 = make_cnfx_disj_thm x1 y'
   385                       val thm1 = make_cnfx_disj_thm x1 y'
   389                       val thm2 = make_cnfx_disj_thm x2 y'
   386                       val thm2 = make_cnfx_disj_thm x2 y'
   390                     in
   387                     in
   391                       @{thm cnf.make_cnf_disj_conj_l} OF [thm1, thm2]  (* ((x1 & x2) | y') = ((x1 | y')' & (x2 | y')') *)
   388                       @{thm cnf.make_cnf_disj_conj_l} OF [thm1, thm2]  (* ((x1 & x2) | y') = ((x1 | y')' & (x2 | y')') *)
   392                     end
   389                     end
   393                 | make_cnfx_disj_thm x' (Const (\<^const_name>\<open>HOL.conj\<close>, _) $ y1 $ y2) =
   390                 | make_cnfx_disj_thm x' \<^Const_>\<open>conj for y1 y2\<close> =
   394                     let
   391                     let
   395                       val thm1 = make_cnfx_disj_thm x' y1
   392                       val thm1 = make_cnfx_disj_thm x' y1
   396                       val thm2 = make_cnfx_disj_thm x' y2
   393                       val thm2 = make_cnfx_disj_thm x' y2
   397                     in
   394                     in
   398                       @{thm cnf.make_cnf_disj_conj_r} OF [thm1, thm2]  (* (x' | (y1 & y2)) = ((x' | y1)' & (x' | y2)') *)
   395                       @{thm cnf.make_cnf_disj_conj_r} OF [thm1, thm2]  (* (x' | (y1 & y2)) = ((x' | y1)' & (x' | y2)') *)
   399                     end
   396                     end
   400                 | make_cnfx_disj_thm (\<^term>\<open>Ex :: (bool \<Rightarrow> bool) \<Rightarrow> bool\<close> $ x') y' =
   397                 | make_cnfx_disj_thm \<^Const_>\<open>Ex \<^Type>\<open>bool\<close> for x'\<close> y' =
   401                     let
   398                     let
   402                       val thm1 = inst_thm thy [x', y'] @{thm cnf.make_cnfx_disj_ex_l}   (* ((Ex x') | y') = (Ex (x' | y')) *)
   399                       val thm1 = inst_thm thy [x', y'] @{thm cnf.make_cnfx_disj_ex_l}   (* ((Ex x') | y') = (Ex (x' | y')) *)
   403                       val var = new_free ()
   400                       val var = new_free ()
   404                       val thm2 = make_cnfx_disj_thm (betapply (x', var)) y'  (* (x' | y') = body' *)
   401                       val thm2 = make_cnfx_disj_thm (betapply (x', var)) y'  (* (x' | y') = body' *)
   405                       val thm3 = Thm.forall_intr (Thm.global_cterm_of thy var) thm2 (* !!v. (x' | y') = body' *)
   402                       val thm3 = Thm.forall_intr (Thm.global_cterm_of thy var) thm2 (* !!v. (x' | y') = body' *)
   406                       val thm4 = Thm.strip_shyps (thm3 COMP allI)            (* ALL v. (x' | y') = body' *)
   403                       val thm4 = Thm.strip_shyps (thm3 COMP allI)            (* ALL v. (x' | y') = body' *)
   407                       val thm5 = Thm.strip_shyps (thm4 RS @{thm cnf.make_cnfx_ex_cong}) (* (EX v. (x' | y')) = (EX v. body') *)
   404                       val thm5 = Thm.strip_shyps (thm4 RS @{thm cnf.make_cnfx_ex_cong}) (* (EX v. (x' | y')) = (EX v. body') *)
   408                     in
   405                     in
   409                       @{thm cnf.iff_trans} OF [thm1, thm5]  (* ((Ex x') | y') = (Ex v. body') *)
   406                       @{thm cnf.iff_trans} OF [thm1, thm5]  (* ((Ex x') | y') = (Ex v. body') *)
   410                     end
   407                     end
   411                 | make_cnfx_disj_thm x' (\<^term>\<open>Ex :: (bool \<Rightarrow> bool) \<Rightarrow> bool\<close> $ y') =
   408                 | make_cnfx_disj_thm x' \<^Const_>\<open>Ex \<^Type>\<open>bool\<close> for y'\<close> =
   412                     let
   409                     let
   413                       val thm1 = inst_thm thy [x', y'] @{thm cnf.make_cnfx_disj_ex_r}   (* (x' | (Ex y')) = (Ex (x' | y')) *)
   410                       val thm1 = inst_thm thy [x', y'] @{thm cnf.make_cnfx_disj_ex_r}   (* (x' | (Ex y')) = (Ex (x' | y')) *)
   414                       val var = new_free ()
   411                       val var = new_free ()
   415                       val thm2 = make_cnfx_disj_thm x' (betapply (y', var))  (* (x' | y') = body' *)
   412                       val thm2 = make_cnfx_disj_thm x' (betapply (y', var))  (* (x' | y') = body' *)
   416                       val thm3 = Thm.forall_intr (Thm.global_cterm_of thy var) thm2 (* !!v. (x' | y') = body' *)
   413                       val thm3 = Thm.forall_intr (Thm.global_cterm_of thy var) thm2 (* !!v. (x' | y') = body' *)
   418                       val thm5 = Thm.strip_shyps (thm4 RS @{thm cnf.make_cnfx_ex_cong}) (* (EX v. (x' | y')) = (EX v. body') *)
   415                       val thm5 = Thm.strip_shyps (thm4 RS @{thm cnf.make_cnfx_ex_cong}) (* (EX v. (x' | y')) = (EX v. body') *)
   419                     in
   416                     in
   420                       @{thm cnf.iff_trans} OF [thm1, thm5]  (* (x' | (Ex y')) = (EX v. body') *)
   417                       @{thm cnf.iff_trans} OF [thm1, thm5]  (* (x' | (Ex y')) = (EX v. body') *)
   421                     end
   418                     end
   422                 | make_cnfx_disj_thm x' y' =
   419                 | make_cnfx_disj_thm x' y' =
   423                     inst_thm thy [HOLogic.mk_disj (x', y')] @{thm cnf.iff_refl}  (* (x' | y') = (x' | y') *)
   420                     inst_thm thy [\<^Const>\<open>disj for x' y'\<close>] @{thm cnf.iff_refl}  (* (x' | y') = (x' | y') *)
   424               val thm1 = make_cnfx_thm_from_nnf x
   421               val thm1 = make_cnfx_thm_from_nnf x
   425               val thm2 = make_cnfx_thm_from_nnf y
   422               val thm2 = make_cnfx_thm_from_nnf y
   426               val x' = (snd o HOLogic.dest_eq o HOLogic.dest_Trueprop o Thm.prop_of) thm1
   423               val x' = (snd o HOLogic.dest_eq o HOLogic.dest_Trueprop o Thm.prop_of) thm1
   427               val y' = (snd o HOLogic.dest_eq o HOLogic.dest_Trueprop o Thm.prop_of) thm2
   424               val y' = (snd o HOLogic.dest_eq o HOLogic.dest_Trueprop o Thm.prop_of) thm2
   428               val disj_thm = @{thm cnf.disj_cong} OF [thm1, thm2]  (* (x | y) = (x' | y') *)
   425               val disj_thm = @{thm cnf.disj_cong} OF [thm1, thm2]  (* (x | y) = (x' | y') *)
   431             end
   428             end
   432           else
   429           else
   433             let  (* neither 'x' nor 'y' is a literal: introduce a fresh variable *)
   430             let  (* neither 'x' nor 'y' is a literal: introduce a fresh variable *)
   434               val thm1 = inst_thm thy [x, y] @{thm cnf.make_cnfx_newlit}     (* (x | y) = EX v. (x | v) & (y | ~v) *)
   431               val thm1 = inst_thm thy [x, y] @{thm cnf.make_cnfx_newlit}     (* (x | y) = EX v. (x | v) & (y | ~v) *)
   435               val var = new_free ()
   432               val var = new_free ()
   436               val body = HOLogic.mk_conj (HOLogic.mk_disj (x, var), HOLogic.mk_disj (y, HOLogic.Not $ var))
   433               val body = \<^Const>\<open>conj for \<^Const>\<open>disj for x var\<close> \<^Const>\<open>disj for y \<^Const>\<open>Not for var\<close>\<close>\<close>
   437               val thm2 = make_cnfx_thm_from_nnf body              (* (x | v) & (y | ~v) = body' *)
   434               val thm2 = make_cnfx_thm_from_nnf body              (* (x | v) & (y | ~v) = body' *)
   438               val thm3 = Thm.forall_intr (Thm.global_cterm_of thy var) thm2 (* !!v. (x | v) & (y | ~v) = body' *)
   435               val thm3 = Thm.forall_intr (Thm.global_cterm_of thy var) thm2 (* !!v. (x | v) & (y | ~v) = body' *)
   439               val thm4 = Thm.strip_shyps (thm3 COMP allI)         (* ALL v. (x | v) & (y | ~v) = body' *)
   436               val thm4 = Thm.strip_shyps (thm3 COMP allI)         (* ALL v. (x | v) & (y | ~v) = body' *)
   440               val thm5 = Thm.strip_shyps (thm4 RS @{thm cnf.make_cnfx_ex_cong})  (* (EX v. (x | v) & (y | ~v)) = (EX v. body') *)
   437               val thm5 = Thm.strip_shyps (thm4 RS @{thm cnf.make_cnfx_ex_cong})  (* (EX v. (x | v) & (y | ~v)) = (EX v. body') *)
   441             in
   438             in