src/HOL/Tools/SMT/z3_proof_literals.ML
changeset 41328 6792a5c92a58
parent 41172 a17c2d669c40
child 44890 22f665a2e91c
equal deleted inserted replaced
41327:49feace87649 41328:6792a5c92a58
    31 end
    31 end
    32 
    32 
    33 structure Z3_Proof_Literals: Z3_PROOF_LITERALS =
    33 structure Z3_Proof_Literals: Z3_PROOF_LITERALS =
    34 struct
    34 struct
    35 
    35 
    36 structure U = SMT_Utils
       
    37 structure T = Z3_Proof_Tools
       
    38 
       
    39 
    36 
    40 
    37 
    41 (* literal table *)
    38 (* literal table *)
    42 
    39 
    43 type littab = thm Termtab.table
    40 type littab = thm Termtab.table
    44 
    41 
    45 fun make_littab thms = fold (Termtab.update o `U.prop_of) thms Termtab.empty
    42 fun make_littab thms =
    46 
    43   fold (Termtab.update o `SMT_Utils.prop_of) thms Termtab.empty
    47 fun insert_lit thm = Termtab.update (`U.prop_of thm)
    44 
    48 fun delete_lit thm = Termtab.delete (U.prop_of thm)
    45 fun insert_lit thm = Termtab.update (`SMT_Utils.prop_of thm)
       
    46 fun delete_lit thm = Termtab.delete (SMT_Utils.prop_of thm)
    49 fun lookup_lit lits = Termtab.lookup lits
    47 fun lookup_lit lits = Termtab.lookup lits
    50 fun get_first_lit f =
    48 fun get_first_lit f =
    51   Termtab.get_first (fn (t, thm) => if f t then SOME thm else NONE)
    49   Termtab.get_first (fn (t, thm) => if f t then SOME thm else NONE)
    52 
    50 
    53 
    51 
    91 (* proof tools *)
    89 (* proof tools *)
    92 
    90 
    93 (** explosion of conjunctions and disjunctions **)
    91 (** explosion of conjunctions and disjunctions **)
    94 
    92 
    95 local
    93 local
       
    94   val precomp = Z3_Proof_Tools.precompose2
       
    95 
    96   fun destc ct = Thm.dest_binop (Thm.dest_arg ct)
    96   fun destc ct = Thm.dest_binop (Thm.dest_arg ct)
    97   val dest_conj1 = T.precompose2 destc @{thm conjunct1}
    97   val dest_conj1 = precomp destc @{thm conjunct1}
    98   val dest_conj2 = T.precompose2 destc @{thm conjunct2}
    98   val dest_conj2 = precomp destc @{thm conjunct2}
    99   fun dest_conj_rules t =
    99   fun dest_conj_rules t =
   100     dest_conj_term t |> Option.map (K (dest_conj1, dest_conj2))
   100     dest_conj_term t |> Option.map (K (dest_conj1, dest_conj2))
   101     
   101     
   102   fun destd f ct = f (Thm.dest_binop (Thm.dest_arg (Thm.dest_arg ct)))
   102   fun destd f ct = f (Thm.dest_binop (Thm.dest_arg (Thm.dest_arg ct)))
   103   val dn1 = apfst Thm.dest_arg and dn2 = apsnd Thm.dest_arg
   103   val dn1 = apfst Thm.dest_arg and dn2 = apsnd Thm.dest_arg
   104   val dest_disj1 = T.precompose2 (destd I) @{lemma "~(P | Q) ==> ~P" by fast}
   104   val dest_disj1 = precomp (destd I) @{lemma "~(P | Q) ==> ~P" by fast}
   105   val dest_disj2 = T.precompose2 (destd dn1) @{lemma "~(~P | Q) ==> P" by fast}
   105   val dest_disj2 = precomp (destd dn1) @{lemma "~(~P | Q) ==> P" by fast}
   106   val dest_disj3 = T.precompose2 (destd I) @{lemma "~(P | Q) ==> ~Q" by fast}
   106   val dest_disj3 = precomp (destd I) @{lemma "~(P | Q) ==> ~Q" by fast}
   107   val dest_disj4 = T.precompose2 (destd dn2) @{lemma "~(P | ~Q) ==> Q" by fast}
   107   val dest_disj4 = precomp (destd dn2) @{lemma "~(P | ~Q) ==> Q" by fast}
   108 
   108 
   109   fun dest_disj_rules t =
   109   fun dest_disj_rules t =
   110     (case dest_disj_term' is_neg t of
   110     (case dest_disj_term' is_neg t of
   111       SOME (true, true) => SOME (dest_disj2, dest_disj4)
   111       SOME (true, true) => SOME (dest_disj2, dest_disj4)
   112     | SOME (true, false) => SOME (dest_disj2, dest_disj3)
   112     | SOME (true, false) => SOME (dest_disj2, dest_disj3)
   113     | SOME (false, true) => SOME (dest_disj1, dest_disj4)
   113     | SOME (false, true) => SOME (dest_disj1, dest_disj4)
   114     | SOME (false, false) => SOME (dest_disj1, dest_disj3)
   114     | SOME (false, false) => SOME (dest_disj1, dest_disj3)
   115     | NONE => NONE)
   115     | NONE => NONE)
   116 
   116 
   117   fun destn ct = [Thm.dest_arg (Thm.dest_arg (Thm.dest_arg ct))]
   117   fun destn ct = [Thm.dest_arg (Thm.dest_arg (Thm.dest_arg ct))]
   118   val dneg_rule = T.precompose destn @{thm notnotD}
   118   val dneg_rule = Z3_Proof_Tools.precompose destn @{thm notnotD}
   119 in
   119 in
   120 
   120 
   121 (*
   121 (*
   122   explode a term into literals and collect all rules to be able to deduce
   122   explode a term into literals and collect all rules to be able to deduce
   123   particular literals afterwards
   123   particular literals afterwards
   148   in explode0 end
   148   in explode0 end
   149 
   149 
   150 (*
   150 (*
   151   extract a literal by applying previously collected rules
   151   extract a literal by applying previously collected rules
   152 *)
   152 *)
   153 fun extract_lit thm rules = fold T.compose rules thm
   153 fun extract_lit thm rules = fold Z3_Proof_Tools.compose rules thm
   154 
   154 
   155 
   155 
   156 (*
   156 (*
   157   explode a theorem into its literals
   157   explode a theorem into its literals
   158 *)
   158 *)
   160   let
   160   let
   161     val dest_rules = if is_conj then dest_conj_rules else dest_disj_rules
   161     val dest_rules = if is_conj then dest_conj_rules else dest_disj_rules
   162     val tab = fold (Termtab.update o rpair ()) stop_lits Termtab.empty
   162     val tab = fold (Termtab.update o rpair ()) stop_lits Termtab.empty
   163 
   163 
   164     fun explode1 thm =
   164     fun explode1 thm =
   165       if Termtab.defined tab (U.prop_of thm) then cons thm
   165       if Termtab.defined tab (SMT_Utils.prop_of thm) then cons thm
   166       else
   166       else
   167         (case dest_rules (U.prop_of thm) of
   167         (case dest_rules (SMT_Utils.prop_of thm) of
   168           SOME (rule1, rule2) =>
   168           SOME (rule1, rule2) =>
   169             explode2 rule1 thm #>
   169             explode2 rule1 thm #>
   170             explode2 rule2 thm #>
   170             explode2 rule2 thm #>
   171             keep_intermediate ? cons thm
   171             keep_intermediate ? cons thm
   172         | NONE => cons thm)
   172         | NONE => cons thm)
   173 
   173 
   174     and explode2 dest_rule thm =
   174     and explode2 dest_rule thm =
   175       if full orelse exists_lit is_conj (Termtab.defined tab) (U.prop_of thm)
   175       if full orelse
   176       then explode1 (T.compose dest_rule thm)
   176         exists_lit is_conj (Termtab.defined tab) (SMT_Utils.prop_of thm)
   177       else cons (T.compose dest_rule thm)
   177       then explode1 (Z3_Proof_Tools.compose dest_rule thm)
       
   178       else cons (Z3_Proof_Tools.compose dest_rule thm)
   178 
   179 
   179     fun explode0 thm =
   180     fun explode0 thm =
   180       if not is_conj andalso is_dneg (U.prop_of thm)
   181       if not is_conj andalso is_dneg (SMT_Utils.prop_of thm)
   181       then [T.compose dneg_rule thm]
   182       then [Z3_Proof_Tools.compose dneg_rule thm]
   182       else explode1 thm []
   183       else explode1 thm []
   183 
   184 
   184   in explode0 end
   185   in explode0 end
   185 
   186 
   186 end
   187 end
   193   fun on_cprem i f thm = f (Thm.cprem_of thm i)
   194   fun on_cprem i f thm = f (Thm.cprem_of thm i)
   194   fun on_cprop f thm = f (Thm.cprop_of thm)
   195   fun on_cprop f thm = f (Thm.cprop_of thm)
   195   fun precomp2 f g thm = (on_cprem 1 f thm, on_cprem 2 g thm, f, g, thm)
   196   fun precomp2 f g thm = (on_cprem 1 f thm, on_cprem 2 g thm, f, g, thm)
   196   fun comp2 (cv1, cv2, f, g, rule) thm1 thm2 =
   197   fun comp2 (cv1, cv2, f, g, rule) thm1 thm2 =
   197     Thm.instantiate ([], [(cv1, on_cprop f thm1), (cv2, on_cprop g thm2)]) rule
   198     Thm.instantiate ([], [(cv1, on_cprop f thm1), (cv2, on_cprop g thm2)]) rule
   198     |> T.discharge thm1 |> T.discharge thm2
   199     |> Z3_Proof_Tools.discharge thm1 |> Z3_Proof_Tools.discharge thm2
   199 
   200 
   200   fun d1 ct = Thm.dest_arg ct and d2 ct = Thm.dest_arg (Thm.dest_arg ct)
   201   fun d1 ct = Thm.dest_arg ct and d2 ct = Thm.dest_arg (Thm.dest_arg ct)
   201 
   202 
   202   val conj_rule = precomp2 d1 d1 @{thm conjI}
   203   val conj_rule = precomp2 d1 d1 @{thm conjI}
   203   fun comp_conj ((_, thm1), (_, thm2)) = comp2 conj_rule thm1 thm2
   204   fun comp_conj ((_, thm1), (_, thm2)) = comp2 conj_rule thm1 thm2
   217 
   218 
   218   val neg = (fn @{const Not} $ t => (true, t) | t => (false, @{const Not} $ t))
   219   val neg = (fn @{const Not} $ t => (true, t) | t => (false, @{const Not} $ t))
   219   fun dest_disj (@{const Not} $ (@{const HOL.disj} $ t $ u)) = (neg t, neg u)
   220   fun dest_disj (@{const Not} $ (@{const HOL.disj} $ t $ u)) = (neg t, neg u)
   220     | dest_disj t = raise TERM ("dest_disj", [t])
   221     | dest_disj t = raise TERM ("dest_disj", [t])
   221 
   222 
   222   val dnegE = T.precompose (single o d2 o d1) @{thm notnotD}
   223   val precomp = Z3_Proof_Tools.precompose
   223   val dnegI = T.precompose (single o d1) @{lemma "P ==> ~~P" by fast}
   224   val dnegE = precomp (single o d2 o d1) @{thm notnotD}
       
   225   val dnegI = precomp (single o d1) @{lemma "P ==> ~~P" by fast}
   224   fun as_dneg f t = f (@{const Not} $ (@{const Not} $ t))
   226   fun as_dneg f t = f (@{const Not} $ (@{const Not} $ t))
   225 
   227 
       
   228   val precomp2 = Z3_Proof_Tools.precompose2
   226   fun dni f = apsnd f o Thm.dest_binop o f o d1
   229   fun dni f = apsnd f o Thm.dest_binop o f o d1
   227   val negIffE = T.precompose2 (dni d1) @{lemma "~(P = (~Q)) ==> Q = P" by fast}
   230   val negIffE = precomp2 (dni d1) @{lemma "~(P = (~Q)) ==> Q = P" by fast}
   228   val negIffI = T.precompose2 (dni I) @{lemma "P = Q ==> ~(Q = (~P))" by fast}
   231   val negIffI = precomp2 (dni I) @{lemma "P = Q ==> ~(Q = (~P))" by fast}
   229   val iff_const = @{const HOL.eq (bool)}
   232   val iff_const = @{const HOL.eq (bool)}
   230   fun as_negIff f (@{const HOL.eq (bool)} $ t $ u) =
   233   fun as_negIff f (@{const HOL.eq (bool)} $ t $ u) =
   231         f (@{const Not} $ (iff_const $ u $ (@{const Not} $ t)))
   234         f (@{const Not} $ (iff_const $ u $ (@{const Not} $ t)))
   232     | as_negIff _ _ = NONE
   235     | as_negIff _ _ = NONE
   233 in
   236 in
   239 
   242 
   240     val lookup = lookup_lit littab
   243     val lookup = lookup_lit littab
   241 
   244 
   242     fun lookup_rule t =
   245     fun lookup_rule t =
   243       (case t of
   246       (case t of
   244         @{const Not} $ (@{const Not} $ t) => (T.compose dnegI, lookup t)
   247         @{const Not} $ (@{const Not} $ t) =>
       
   248           (Z3_Proof_Tools.compose dnegI, lookup t)
   245       | @{const Not} $ (@{const HOL.eq (bool)} $ t $ (@{const Not} $ u)) =>
   249       | @{const Not} $ (@{const HOL.eq (bool)} $ t $ (@{const Not} $ u)) =>
   246             (T.compose negIffI, lookup (iff_const $ u $ t))
   250           (Z3_Proof_Tools.compose negIffI, lookup (iff_const $ u $ t))
   247       | @{const Not} $ ((eq as Const (@{const_name HOL.eq}, _)) $ t $ u) =>
   251       | @{const Not} $ ((eq as Const (@{const_name HOL.eq}, _)) $ t $ u) =>
   248           let fun rewr lit = lit COMP @{thm not_sym}
   252           let fun rewr lit = lit COMP @{thm not_sym}
   249           in (rewr, lookup (@{const Not} $ (eq $ u $ t))) end
   253           in (rewr, lookup (@{const Not} $ (eq $ u $ t))) end
   250       | _ =>
   254       | _ =>
   251           (case as_dneg lookup t of
   255           (case as_dneg lookup t of
   252             NONE => (T.compose negIffE, as_negIff lookup t)
   256             NONE => (Z3_Proof_Tools.compose negIffE, as_negIff lookup t)
   253           | x => (T.compose dnegE, x)))
   257           | x => (Z3_Proof_Tools.compose dnegE, x)))
   254 
   258 
   255     fun join1 (s, t) =
   259     fun join1 (s, t) =
   256       (case lookup t of
   260       (case lookup t of
   257         SOME lit => (s, lit)
   261         SOME lit => (s, lit)
   258       | NONE => 
   262       | NONE => 
   283 
   287 
   284 local
   288 local
   285   val contra_rule = @{lemma "P ==> ~P ==> False" by (rule notE)}
   289   val contra_rule = @{lemma "P ==> ~P ==> False" by (rule notE)}
   286   fun contra_left conj thm =
   290   fun contra_left conj thm =
   287     let
   291     let
   288       val rules = explode_term conj (U.prop_of thm)
   292       val rules = explode_term conj (SMT_Utils.prop_of thm)
   289       fun contra_lits (t, rs) =
   293       fun contra_lits (t, rs) =
   290         (case t of
   294         (case t of
   291           @{const Not} $ u => Termtab.lookup rules u |> Option.map (pair rs)
   295           @{const Not} $ u => Termtab.lookup rules u |> Option.map (pair rs)
   292         | _ => NONE)
   296         | _ => NONE)
   293     in
   297     in
   301 
   305 
   302   val falseE_v = Thm.dest_arg (Thm.dest_arg (Thm.cprop_of @{thm FalseE}))
   306   val falseE_v = Thm.dest_arg (Thm.dest_arg (Thm.cprop_of @{thm FalseE}))
   303   fun contra_right ct = Thm.instantiate ([], [(falseE_v, ct)]) @{thm FalseE}
   307   fun contra_right ct = Thm.instantiate ([], [(falseE_v, ct)]) @{thm FalseE}
   304 in
   308 in
   305 fun contradict conj ct =
   309 fun contradict conj ct =
   306   iff_intro (T.under_assumption (contra_left conj) ct) (contra_right ct)
   310   iff_intro (Z3_Proof_Tools.under_assumption (contra_left conj) ct)
       
   311     (contra_right ct)
   307 end
   312 end
   308 
   313 
   309 
   314 
   310 local
   315 local
   311   fun prove_eq l r (cl, cr) =
   316   fun prove_eq l r (cl, cr) =
   312     let
   317     let
   313       fun explode' is_conj = explode is_conj true (l <> r) []
   318       fun explode' is_conj = explode is_conj true (l <> r) []
   314       fun make_tab is_conj thm = make_littab (true_thm :: explode' is_conj thm)
   319       fun make_tab is_conj thm = make_littab (true_thm :: explode' is_conj thm)
   315       fun prove is_conj ct tab = join is_conj tab (Thm.term_of ct)
   320       fun prove is_conj ct tab = join is_conj tab (Thm.term_of ct)
   316 
   321 
   317       val thm1 = T.under_assumption (prove r cr o make_tab l) cl
   322       val thm1 = Z3_Proof_Tools.under_assumption (prove r cr o make_tab l) cl
   318       val thm2 = T.under_assumption (prove l cl o make_tab r) cr
   323       val thm2 = Z3_Proof_Tools.under_assumption (prove l cl o make_tab r) cr
   319     in iff_intro thm1 thm2 end
   324     in iff_intro thm1 thm2 end
   320 
   325 
   321   datatype conj_disj = CONJ | DISJ | NCON | NDIS
   326   datatype conj_disj = CONJ | DISJ | NCON | NDIS
   322   fun kind_of t =
   327   fun kind_of t =
   323     if is_conj t then SOME CONJ
   328     if is_conj t then SOME CONJ