src/HOL/Tools/SMT2/verit_proof.ML
changeset 57762 1649841f3b38
parent 57747 816f96fff418
equal deleted inserted replaced
57761:dafecf8fa266 57762:1649841f3b38
    19   val parse: typ Symtab.table -> term Symtab.table -> string list ->
    19   val parse: typ Symtab.table -> term Symtab.table -> string list ->
    20     Proof.context -> veriT_step list * Proof.context
    20     Proof.context -> veriT_step list * Proof.context
    21 
    21 
    22   val veriT_step_prefix : string
    22   val veriT_step_prefix : string
    23   val veriT_input_rule: string
    23   val veriT_input_rule: string
       
    24   val veriT_la_generic_rule : string
    24   val veriT_rewrite_rule : string
    25   val veriT_rewrite_rule : string
       
    26   val veriT_simp_arith_rule : string
       
    27   val veriT_tmp_ite_elim_rule : string
    25   val veriT_tmp_skolemize_rule : string
    28   val veriT_tmp_skolemize_rule : string
    26   val veriT_tmp_ite_elim_rule : string
       
    27 end;
    29 end;
    28 
    30 
    29 structure VeriT_Proof: VERIT_PROOF =
    31 structure VeriT_Proof: VERIT_PROOF =
    30 struct
    32 struct
    31 
    33 
    50 
    52 
    51 fun mk_step id rule prems concl fixes =
    53 fun mk_step id rule prems concl fixes =
    52   VeriT_Step {id = id, rule = rule, prems = prems, concl = concl, fixes = fixes}
    54   VeriT_Step {id = id, rule = rule, prems = prems, concl = concl, fixes = fixes}
    53 
    55 
    54 val veriT_step_prefix = ".c"
    56 val veriT_step_prefix = ".c"
       
    57 val veriT_alpha_conv_rule = "tmp_alphaconv"
    55 val veriT_input_rule = "input"
    58 val veriT_input_rule = "input"
    56 val veriT_rewrite_rule = "__rewrite" (*arbitrary*)
    59 val veriT_la_generic_rule = "la_generic"
       
    60 val veriT_rewrite_rule = "__rewrite" (* arbitrary *)
       
    61 val veriT_simp_arith_rule = "simp_arith"
    57 val veriT_tmp_ite_elim_rule = "tmp_ite_elim"
    62 val veriT_tmp_ite_elim_rule = "tmp_ite_elim"
    58 val veriT_tmp_skolemize_rule = "tmp_skolemize"
    63 val veriT_tmp_skolemize_rule = "tmp_skolemize"
    59 val veriT_alpha_conv_rule = "tmp_alphaconv"
       
    60 
    64 
    61 (* proof parser *)
    65 (* proof parser *)
    62 
    66 
    63 fun node_of p cx =
    67 fun node_of p cx =
    64   ([], cx)
    68   ([], cx)
    65   ||>> `(with_fresh_names (term_of p))
    69   ||>> `(with_fresh_names (term_of p))
    66   |>> snd
    70   |>> snd
    67 
    71 
    68 (*in order to get Z3-style quantification*)
    72 (*in order to get Z3-style quantification*)
    69 fun fix_quantification (SMTLIB2.S (SMTLIB2.Sym "forall" :: l)) =
    73 fun repair_quantification (SMTLIB2.S (SMTLIB2.Sym "forall" :: l)) =
    70     let val (quantified_vars, t) = split_last (map fix_quantification l)
    74     let val (quantified_vars, t) = split_last (map repair_quantification l)
    71     in
    75     in
    72       SMTLIB2.S (SMTLIB2.Sym "forall" :: SMTLIB2.S quantified_vars :: t :: [])
    76       SMTLIB2.S (SMTLIB2.Sym "forall" :: SMTLIB2.S quantified_vars :: t :: [])
    73     end
    77     end
    74   | fix_quantification (SMTLIB2.S (SMTLIB2.Sym "exists" :: l)) =
    78   | repair_quantification (SMTLIB2.S (SMTLIB2.Sym "exists" :: l)) =
    75     let val (quantified_vars, t) = split_last (map fix_quantification l)
    79     let val (quantified_vars, t) = split_last (map repair_quantification l)
    76     in
    80     in
    77       SMTLIB2.S (SMTLIB2.Sym "exists" :: SMTLIB2.S quantified_vars :: t :: [])
    81       SMTLIB2.S (SMTLIB2.Sym "exists" :: SMTLIB2.S quantified_vars :: t :: [])
    78     end
    82     end
    79   | fix_quantification (SMTLIB2.S l) = SMTLIB2.S (map fix_quantification l)
    83   | repair_quantification (SMTLIB2.S l) = SMTLIB2.S (map repair_quantification l)
    80   | fix_quantification x = x
    84   | repair_quantification x = x
    81 
    85 
    82 fun replace_bound_var_by_free_var (q $ Abs (var, ty, u)) free_var =
    86 fun replace_bound_var_by_free_var (q $ Abs (var, ty, u)) free_var =
    83     (case List.find (fn v => String.isPrefix v var) free_var of
    87     (case List.find (fn v => String.isPrefix v var) free_var of
    84       NONE => q $ Abs (var, ty, replace_bound_var_by_free_var u free_var)
    88       NONE => q $ Abs (var, ty, replace_bound_var_by_free_var u free_var)
    85     | SOME _ => replace_bound_var_by_free_var (Term.subst_bound (Free (var, ty), u)) free_var)
    89     | SOME _ => replace_bound_var_by_free_var (Term.subst_bound (Free (var, ty), u)) free_var)
   186     #> rotate_pair
   190     #> rotate_pair
   187     ##> skip_args
   191     ##> skip_args
   188     #> (fn (((id, rule), prems), sub) => (((id, rule), prems), parse_subproof cx id sub))
   192     #> (fn (((id, rule), prems), sub) => (((id, rule), prems), parse_subproof cx id sub))
   189     #> rotate_pair
   193     #> rotate_pair
   190     ##> parse_conclusion
   194     ##> parse_conclusion
   191     ##> map fix_quantification
   195     ##> map repair_quantification
   192     #> (fn ((((id, rule), prems), (subproof, cx)), terms) =>
   196     #> (fn ((((id, rule), prems), (subproof, cx)), terms) =>
   193          (((((id, rule), prems), subproof), fold_map (fn t => fn cx => node_of t cx) terms cx)))
   197          (((((id, rule), prems), subproof), fold_map (fn t => fn cx => node_of t cx) terms cx)))
   194     (*the conclusion is the empty list, ie no false is written, we have to add it.*)
   198     ##> apfst (fn [] => (@{const False}, []) | concls => make_or_from_clausification concls)
   195     ##> (apfst (fn [] => (@{const False}, [])
       
   196                  | concls => make_or_from_clausification concls))
       
   197     #> fix_subproof_steps
   199     #> fix_subproof_steps
   198     ##> to_node
   200     ##> to_node
   199     #> (fn (subproof, (step, cx)) => (subproof @ [step], cx))
   201     #> (fn (subproof, (step, cx)) => (subproof @ [step], cx))
   200     #-> (fold_map update_step_and_cx)
   202     #-> fold_map update_step_and_cx
   201   end
   203   end
   202 
       
   203 
       
   204 (*function related to parsing and general transformation*)
       
   205 
   204 
   206 (*subproofs are written on multiple lines: SMTLIB can not parse then, because parentheses are
   205 (*subproofs are written on multiple lines: SMTLIB can not parse then, because parentheses are
   207 unbalanced on each line*)
   206 unbalanced on each line*)
   208 fun seperate_into_steps lines =
   207 fun seperate_into_steps lines =
   209   let
   208   let
   220       | seperate [] _ 0 = []
   219       | seperate [] _ 0 = []
   221   in
   220   in
   222     seperate lines "" 0
   221     seperate lines "" 0
   223   end
   222   end
   224 
   223 
   225  (*VeriT adds @ before every variable.*)
   224  (* VeriT adds @ before every variable. *)
   226 fun remove_all_at (SMTLIB2.Sym v :: l) =
   225 fun remove_all_at (SMTLIB2.Sym v :: l) = SMTLIB2.Sym (perhaps (try (unprefix "@")) v) :: remove_all_at l
   227     SMTLIB2.Sym (if nth_string v 0 = "@" then String.extract (v, 1, NONE) else v) :: remove_all_at l
       
   228   | remove_all_at (SMTLIB2.S l :: l') = SMTLIB2.S (remove_all_at l) :: remove_all_at l'
   226   | remove_all_at (SMTLIB2.S l :: l') = SMTLIB2.S (remove_all_at l) :: remove_all_at l'
   229   | remove_all_at (SMTLIB2.Key v :: l) = SMTLIB2.Key v :: remove_all_at l
   227   | remove_all_at (SMTLIB2.Key v :: l) = SMTLIB2.Key v :: remove_all_at l
   230   | remove_all_at (v :: l) = v :: remove_all_at l
   228   | remove_all_at (v :: l) = v :: remove_all_at l
   231   | remove_all_at [] = []
   229   | remove_all_at [] = []
   232 
   230 
   276       NONE => find_ite_var_in_term q
   274       NONE => find_ite_var_in_term q
   277     | x => x)
   275     | x => x)
   278   | find_ite_var_in_term (Abs (_, _, body)) = find_ite_var_in_term body
   276   | find_ite_var_in_term (Abs (_, _, body)) = find_ite_var_in_term body
   279   | find_ite_var_in_term _ = NONE
   277   | find_ite_var_in_term _ = NONE
   280 
   278 
   281 
       
   282 fun correct_veriT_step steps (st as VeriT_Node {id, rule, prems, concl, bounds}) =
   279 fun correct_veriT_step steps (st as VeriT_Node {id, rule, prems, concl, bounds}) =
   283   if rule = veriT_tmp_ite_elim_rule then
   280   if rule = veriT_tmp_ite_elim_rule then
   284     if bounds = [] then
   281     if bounds = [] then
   285       (*if the introduced var has already been defined,
   282       (*if the introduced var has already been defined, adding the definition as a dependency*)
   286         adding the definition as a dependency*)
       
   287       let
   283       let
   288         val new_prems =
   284         val new_prems =
   289           (case find_ite_var_in_term concl of
   285           (case find_ite_var_in_term concl of
   290             NONE => prems
   286             NONE => prems
   291           | SOME var => find_in_which_step_defined var steps :: prems)
   287           | SOME var => find_in_which_step_defined var steps :: prems)
   300         mk_node id rule prems concl' []
   296         mk_node id rule prems concl' []
   301       end
   297       end
   302   else
   298   else
   303     st
   299     st
   304 
   300 
   305 (*remove alpha conversion step, that just renames the variables*)
       
   306 fun remove_alpha_conversion _ [] = []
   301 fun remove_alpha_conversion _ [] = []
   307   | remove_alpha_conversion replace_table (VeriT_Node {id, rule, prems, concl, bounds} :: steps) =
   302   | remove_alpha_conversion replace_table (VeriT_Node {id, rule, prems, concl, bounds} :: steps) =
   308     let
   303     let
   309       fun correct_dependency prems =
   304       fun correct_dependency prems =
   310         map (fn x => perhaps (Symtab.lookup replace_table) x) prems
   305         map (fn x => perhaps (Symtab.lookup replace_table) x) prems
   321 fun correct_veriT_steps steps =
   316 fun correct_veriT_steps steps =
   322   steps
   317   steps
   323   |> map (correct_veriT_step steps)
   318   |> map (correct_veriT_step steps)
   324   |> remove_alpha_conversion Symtab.empty
   319   |> remove_alpha_conversion Symtab.empty
   325 
   320 
   326 (* overall proof parser *)
       
   327 fun parse typs funs lines ctxt =
   321 fun parse typs funs lines ctxt =
   328   let
   322   let
   329     val smtlib2_lines_without_at =
   323     val smtlib2_lines_without_at =
   330       remove_all_at (map SMTLIB2.parse (seperate_into_steps lines))
   324       remove_all_at (map SMTLIB2.parse (seperate_into_steps lines))
   331     val (u, env) = apfst flat (fold_map (fn l => fn cx => parse_proof_step cx l)
   325     val (u, env) = apfst flat (fold_map (fn l => fn cx => parse_proof_step cx l)