walther@59603
|
1 |
(* Title: ProgLang/Auto_Prog
|
walther@59603
|
2 |
Author: Walther Neuper, Aug.2019
|
walther@59603
|
3 |
(c) due to copyright terms
|
walther@59603
|
4 |
*)
|
walther@59603
|
5 |
|
walther@59767
|
6 |
theory Auto_Prog imports Prog_Tac Tactical begin
|
walther@59603
|
7 |
|
walther@59603
|
8 |
text \<open>Abstract:
|
walther@59619
|
9 |
The tactics Rewrite_Set* create ONE step in a calculation by application of usually
|
walther@59619
|
10 |
MORE than one theorem (here called "rule").
|
walther@59619
|
11 |
However, students can request details of rewriting down to single applications of theorems.
|
walther@59619
|
12 |
For accomplishing such requests, a program is auto-generated from the items of a rule-set.
|
walther@59603
|
13 |
\<close>
|
walther@59603
|
14 |
|
walther@59603
|
15 |
subsection \<open>consts for programs automatically built from rules\<close>
|
walther@59603
|
16 |
|
walther@59603
|
17 |
partial_function (tailrec) auto_generated :: "'z \<Rightarrow> 'z"
|
walther@59603
|
18 |
where "auto_generated t_t = t_t"
|
walther@59603
|
19 |
partial_function (tailrec) auto_generated_inst :: "'z \<Rightarrow> real \<Rightarrow> 'z"
|
walther@59603
|
20 |
where "auto_generated_inst t_t v = t_t"
|
walther@59603
|
21 |
|
walther@59603
|
22 |
|
walther@59603
|
23 |
subsection \<open>TODO: code for above\<close>
|
walther@59603
|
24 |
ML \<open>
|
walther@59603
|
25 |
\<close> ML \<open>
|
walther@59618
|
26 |
signature AUTO_GERNERATE_PROGRAM =
|
walther@59618
|
27 |
sig
|
walther@59618
|
28 |
val contain_bdv: Rule.rule list -> bool
|
walther@59618
|
29 |
val contains_bdv: thm -> bool
|
walther@59636
|
30 |
val subst_typs: term -> typ -> typ -> term
|
walther@59618
|
31 |
val pblterm: Rule.domID -> Celem.pblID -> term
|
walther@59618
|
32 |
val subpbl: string -> string list -> term
|
walther@59618
|
33 |
val stacpbls: term -> term list
|
walther@59618
|
34 |
val op_of_calc: term -> string
|
walther@59618
|
35 |
val get_calcs: theory -> term -> (Rule.prog_calcID * (Rule.calID * Rule.eval_fn)) list
|
walther@59618
|
36 |
val prep_rls: theory -> Rule.rls -> Rule.rls (*ren insert*)
|
walther@59802
|
37 |
val gen: theory -> term -> Rule.rls -> term
|
walther@59618
|
38 |
(* ---- for tests only: shifted from below to remove the Warning "unused" at fun.def. --------- *)
|
walther@59618
|
39 |
(* NONE *)
|
walther@59785
|
40 |
(*/-------------------------------------------------------- ! aktivate for Test_Isac BEGIN ---\* )
|
walther@59636
|
41 |
val subst_typ: string -> typ -> term list -> (typ * typ) list
|
walther@59618
|
42 |
val is_calc: term -> bool
|
walther@59618
|
43 |
val rule2stac: theory -> Rule.rule -> term
|
walther@59618
|
44 |
val rule2stac_inst: theory -> Rule.rule -> term
|
walther@59637
|
45 |
val #> : term list -> term
|
walther@59618
|
46 |
val rules2scr_Rls : theory -> Rule.rule list -> term
|
walther@59618
|
47 |
val rules2scr_Seq : theory -> Rule.rule list -> term
|
walther@59785
|
48 |
( *\--- ! aktivate for Test_Isac END ----------------------------------------------------------/*)
|
walther@59618
|
49 |
end
|
walther@59618
|
50 |
(**)
|
walther@59618
|
51 |
structure Auto_Prog(**): AUTO_GERNERATE_PROGRAM(**) =
|
walther@59618
|
52 |
struct
|
walther@59618
|
53 |
(**)
|
walther@59618
|
54 |
|
walther@59618
|
55 |
(** build up a program from rules **)
|
walther@59618
|
56 |
|
walther@59618
|
57 |
(* make the term 'Subproblem (domID, pblID)' to a formula for frontend;
|
walther@59618
|
58 |
needs to be here after def. Subproblem in Prog_Tac.thy *)
|
walther@59618
|
59 |
val subpbl_t $ (pair_t $ _ $ _) = (Thm.term_of o the o (TermC.parse @{theory Prog_Tac}))
|
walther@59618
|
60 |
"Subproblem (''Isac_Knowledge'',[''equation'',''univar''])"
|
walther@59618
|
61 |
val pbl_t $ _ =
|
walther@59618
|
62 |
(Thm.term_of o the o (TermC.parse @{theory Prog_Tac})) "Problem (''Isac_Knowledge'',[''equation'',''univar''])"
|
walther@59618
|
63 |
|
walther@59618
|
64 |
fun subpbl domID pblID =
|
walther@59618
|
65 |
subpbl_t $ (pair_t $ HOLogic.mk_string domID $
|
walther@59618
|
66 |
list_comb (Syntax.const @{const_syntax Char}, map HOLogic.mk_string pblID));
|
walther@59618
|
67 |
fun pblterm domID pblID =
|
walther@59618
|
68 |
pbl_t $ (pair_t $ HOLogic.mk_string domID $
|
walther@59618
|
69 |
list_comb (Syntax.const @{const_syntax Char}, map HOLogic.mk_string pblID));
|
walther@59618
|
70 |
|
walther@59618
|
71 |
(* fetch tactics from a program omitting tacticals like While, Repeat,.. *)
|
walther@59618
|
72 |
fun stacpbls (_ $ body) =
|
walther@59618
|
73 |
let
|
walther@59618
|
74 |
fun scan (Const ("HOL.Let", _) $ e $ (Abs (_, _, b))) = (scan e) @ (scan b)
|
walther@59618
|
75 |
| scan (Const ("Tactical.If", _) $ _ $ e1 $ e2) = (scan e1) @ (scan e2)
|
walther@59618
|
76 |
| scan (Const ("Tactical.While", _) $ _ $ e $ _) = scan e
|
walther@59618
|
77 |
| scan (Const ("Tactical.While", _) $ _ $ e) = scan e
|
walther@59618
|
78 |
| scan (Const ("Tactical.Repeat", _) $ e $ _) = scan e
|
walther@59618
|
79 |
| scan (Const ("Tactical.Repeat", _) $ e) = scan e
|
walther@59618
|
80 |
| scan (Const ("Tactical.Try", _) $ e $ _) = scan e
|
walther@59618
|
81 |
| scan (Const ("Tactical.Try", _) $ e) = scan e
|
walther@59618
|
82 |
| scan (Const ("Tactical.Or", _) $ e1 $ e2 $ _) = (scan e1) @ (scan e2)
|
walther@59618
|
83 |
| scan (Const ("Tactical.Or", _) $ e1 $ e2) = (scan e1) @ (scan e2)
|
walther@59688
|
84 |
| scan (Const ("Tactical.Chain", _) $ e1 $ e2 $ _) = (scan e1) @ (scan e2)
|
walther@59688
|
85 |
| scan (Const ("Tactical.Chain", _) $ e1 $ e2) = (scan e1) @ (scan e2)
|
walther@59718
|
86 |
| scan t = case Prog_Tac.eval_leaf [] NONE Rule.e_term t of
|
walther@59729
|
87 |
(Program.Tac _, _) => [t] | (Program.Expr _, _) => []
|
walther@59618
|
88 |
in (distinct o scan) body end
|
walther@59618
|
89 |
| stacpbls t = raise ERROR ("fun stacpbls not applicable to '" ^ Rule.term2str t ^ "'")
|
walther@59618
|
90 |
|
walther@59618
|
91 |
(* get operators out of a program *)
|
walther@59618
|
92 |
fun is_calc (Const ("Prog_Tac.Calculate",_) $ _) = true
|
walther@59618
|
93 |
| is_calc (Const ("Prog_Tac.Calculate",_) $ _ $ _) = true
|
walther@59618
|
94 |
| is_calc _ = false;
|
walther@59618
|
95 |
fun op_of_calc (Const ("Prog_Tac.Calculate",_) $ op_) = HOLogic.dest_string op_
|
walther@59618
|
96 |
| op_of_calc (Const ("Prog_Tac.Calculate",_) $ op_ $ _) = HOLogic.dest_string op_
|
walther@59618
|
97 |
| op_of_calc t = error ("op_of_calc called with " ^ Rule.term2str t);
|
walther@59618
|
98 |
fun get_calcs thy sc =
|
walther@59618
|
99 |
sc
|
walther@59618
|
100 |
|> stacpbls
|
walther@59618
|
101 |
|> filter is_calc
|
walther@59618
|
102 |
|> map op_of_calc
|
walther@59618
|
103 |
|> (assoc_calc' thy |> map);
|
walther@59618
|
104 |
|
walther@59603
|
105 |
(** build up a program from rules **)
|
walther@59603
|
106 |
|
walther@59603
|
107 |
(* transform type rule to a term *)
|
walther@59603
|
108 |
(*WN060605 script-arg (t_::'z) and "Free (t_, 'a)" at end of body are inconsistent !!!*)
|
walther@59618
|
109 |
val (FunID_Term $ _) = Program.prep_program @{thm auto_generated.simps}
|
walther@59618
|
110 |
val (FunID_Term_Bdv $ _) = Program.prep_program @{thm auto_generated_inst.simps}
|
walther@59603
|
111 |
val Repeat $ _ = (TermC.inst_abs o Thm.term_of o the o (TermC.parseN @{theory}))
|
walther@59635
|
112 |
"Repeat (Rewrite ''real_diff_minus'' t)";
|
walther@59603
|
113 |
val Try $ _ = (TermC.inst_abs o Thm.term_of o the o (TermC.parseN @{theory}))
|
walther@59635
|
114 |
"Try (Rewrite ''real_diff_minus'' t)";
|
walther@59603
|
115 |
val Cal $ _ = (TermC.inst_abs o Thm.term_of o the o (TermC.parseN @{theory}))
|
walther@59603
|
116 |
"Calculate ''PLUS''";
|
walther@59603
|
117 |
val Ca1 $ _ = (TermC.inst_abs o Thm.term_of o the o (TermC.parseN @{theory}))
|
walther@59603
|
118 |
"Calculate1 ''PLUS''";
|
walther@59635
|
119 |
val Rew $ _ $ _ = (TermC.inst_abs o Thm.term_of o the o (TermC.parseN @{theory}))
|
walther@59635
|
120 |
"Rewrite ''real_diff_minus'' t";
|
walther@59603
|
121 |
(*this is specific to FunHead_inst ...*)
|
walther@59635
|
122 |
val Rew_Inst $ Subs $ _ = (TermC.inst_abs o Thm.term_of o the o (TermC.parseN @{theory}))
|
walther@59635
|
123 |
"Rewrite_Inst [(''bdv'',v)] ''real_diff_minus''";
|
walther@59635
|
124 |
val Rew_Set $ _ = (TermC.inst_abs o Thm.term_of o the o (TermC.parseN @{theory}))
|
walther@59635
|
125 |
"Rewrite_Set ''real_diff_minus''";
|
walther@59635
|
126 |
val Rew_Set_Inst $ _ $ _ = (TermC.inst_abs o Thm.term_of o the o (TermC.parseN @{theory}))
|
walther@59635
|
127 |
"Rewrite_Set_Inst [(''bdv'',v)] ''real_diff_minus''";
|
walther@59603
|
128 |
val SEq $ _ $ _ $ _ = (TermC.inst_abs o Thm.term_of o the o (TermC.parseN @{theory}))
|
walther@59637
|
129 |
" ((Try (Repeat (Rewrite ''real_diff_minus''))) #> \
|
walther@59637
|
130 |
\ (Try (Repeat (Rewrite ''add_commute''))) #> \
|
walther@59635
|
131 |
\ (Try (Repeat (Rewrite ''mult_commute'')))) t";
|
walther@59618
|
132 |
|
walther@59635
|
133 |
fun rule2stac _ (Rule.Thm (thmID, _)) = Try $ (Repeat $ (Rew $ HOLogic.mk_string thmID))
|
walther@59773
|
134 |
| rule2stac thy (Rule.Num_Calc (c, _)) = Try $ (Repeat $ (Cal $ HOLogic.mk_string (assoc_calc thy c)))
|
walther@59603
|
135 |
| rule2stac thy (Rule.Cal1 (c, _)) = Try $ (Repeat $ (Ca1 $ HOLogic.mk_string (assoc_calc thy c)))
|
walther@59635
|
136 |
| rule2stac _ (Rule.Rls_ rls) = Try $ (Rew_Set $ HOLogic.mk_string (Rule.id_rls rls))
|
walther@59603
|
137 |
| rule2stac _ r = raise ERROR ("rule2stac: not applicable to \"" ^ Rule.rule2str r ^ "\"");
|
walther@59603
|
138 |
fun rule2stac_inst _ (Rule.Thm (thmID, _)) =
|
walther@59635
|
139 |
Try $ (Repeat $ (Rew_Inst $ Subs $ HOLogic.mk_string thmID))
|
walther@59773
|
140 |
| rule2stac_inst thy (Rule.Num_Calc (c, _)) =
|
walther@59603
|
141 |
Try $ (Repeat $ (Cal $ HOLogic.mk_string (assoc_calc thy c)))
|
walther@59603
|
142 |
| rule2stac_inst thy (Rule.Cal1 (c, _)) =
|
walther@59603
|
143 |
Try $ (Repeat $ (Cal $ HOLogic.mk_string (assoc_calc thy c)))
|
walther@59603
|
144 |
| rule2stac_inst _ (Rule.Rls_ rls) =
|
walther@59635
|
145 |
Try $ (Rew_Set_Inst $ Subs $ HOLogic.mk_string (Rule.id_rls rls))
|
walther@59603
|
146 |
| rule2stac_inst _ r = raise ERROR ("rule2stac_inst: not applicable to \"" ^ Rule.rule2str r ^ "\"");
|
walther@59603
|
147 |
|
walther@59603
|
148 |
(*for appropriate nesting take stacs in _reverse_ order*)
|
walther@59637
|
149 |
fun op #>@ sts [s] = SEq $ s $ sts
|
walther@59637
|
150 |
| op #>@ sts (s::ss) = op #>@ (SEq $ s $ sts) ss
|
walther@59637
|
151 |
| op #>@ t ts =
|
walther@59637
|
152 |
raise ERROR ("fun #>@ not applicable to \"" ^ Rule.term2str t ^ "\" \"" ^ Rule.terms2str ts ^ "\"");
|
walther@59637
|
153 |
fun #> [stac] = stac
|
walther@59637
|
154 |
| #> [s1, s2] = SEq $ s1 $ s2
|
walther@59637
|
155 |
| #> stacs = case rev stacs of
|
walther@59637
|
156 |
s3 :: s2 :: ss => op #>@ (SEq $ s2 $ s3) ss
|
walther@59637
|
157 |
| ts => raise ERROR ("fun #> not applicable to \"" ^ Rule.terms2str ts ^ "\"")
|
walther@59618
|
158 |
|
walther@59618
|
159 |
val contains_bdv = (not o null o (filter TermC.is_bdv) o TermC.ids2str o #prop o Thm.rep_thm);
|
walther@59618
|
160 |
|
walther@59618
|
161 |
(* does a rule contain a 'bdv'; descend recursively into Rls_ *)
|
walther@59618
|
162 |
fun contain_bdv [] = false
|
walther@59618
|
163 |
| contain_bdv (Rule.Thm (_, thm) :: rs) =
|
walther@59618
|
164 |
if (not o contains_bdv) thm
|
walther@59618
|
165 |
then contain_bdv rs
|
walther@59618
|
166 |
else true
|
walther@59773
|
167 |
| contain_bdv (Rule.Num_Calc _ :: rs) = contain_bdv rs
|
walther@59618
|
168 |
| contain_bdv (Rule.Cal1 _ :: rs) = contain_bdv rs
|
walther@59618
|
169 |
| contain_bdv (Rule.Rls_ rls :: rs) =
|
walther@59618
|
170 |
contain_bdv (Rule.get_rules rls) orelse contain_bdv rs
|
walther@59618
|
171 |
| contain_bdv (r :: _) =
|
walther@59618
|
172 |
error ("contain_bdv called with [" ^ Rule.id_rule r ^ ",...]");
|
walther@59618
|
173 |
|
walther@59636
|
174 |
(* filter Frees for free_str and pair their respective types with typ *)
|
walther@59636
|
175 |
fun subst_typ free_str typ frees =
|
walther@59636
|
176 |
let
|
walther@59636
|
177 |
val vars_v = filter (fn t => curry op = (t |> dest_Free |> fst) free_str) frees
|
walther@59636
|
178 |
val typs_v = map (fn t => (t |> dest_Free |> snd)) vars_v
|
walther@59636
|
179 |
in
|
walther@59636
|
180 |
map (fn T => (T, typ)) typs_v
|
walther@59636
|
181 |
end
|
walther@59636
|
182 |
(* instantiate typs in Prog auto_generated or auto_generated_ins for args "t_t", "v" *)
|
walther@59636
|
183 |
fun subst_typs prog typ_t typ_bdv =
|
walther@59636
|
184 |
let
|
walther@59636
|
185 |
val args = Program.formal_args prog
|
walther@59636
|
186 |
val frees = TermC.vars prog
|
walther@59636
|
187 |
val prog' = subst_atomic_types (subst_typ "t_t" typ_t frees) prog
|
walther@59636
|
188 |
in
|
walther@59636
|
189 |
if length args <= 1
|
walther@59636
|
190 |
then
|
walther@59636
|
191 |
prog'
|
walther@59636
|
192 |
else (* auto_generated_inst has second argument "v" *)
|
walther@59636
|
193 |
subst_atomic_types (subst_typ "v" typ_bdv frees) prog'
|
walther@59636
|
194 |
end
|
walther@59636
|
195 |
|
walther@59618
|
196 |
fun rules2scr_Rls thy rules =
|
walther@59618
|
197 |
if contain_bdv rules
|
walther@59831
|
198 |
then FunID_Term_Bdv $ (Repeat $ (((op #> o (map (rule2stac_inst thy))) rules) $ Rule.e_term))
|
walther@59831
|
199 |
else FunID_Term $ (Repeat $ (((op #> o (map (rule2stac thy))) rules) $ Rule.e_term));
|
walther@59618
|
200 |
fun rules2scr_Seq thy rules =
|
walther@59618
|
201 |
if contain_bdv rules
|
walther@59831
|
202 |
then FunID_Term_Bdv $ (((op #> o (map (rule2stac_inst thy))) rules) $ Rule.e_term)
|
walther@59831
|
203 |
else FunID_Term $ (((op #> o (map (rule2stac thy))) rules) $ Rule.e_term);
|
walther@59618
|
204 |
|
walther@59802
|
205 |
(* REPLACED BY Auto_Prog.gen:
|
walther@59802
|
206 |
prepare the input for an rls for use:
|
walther@59802
|
207 |
# generate a program for stepwise execution of the rls
|
walther@59773
|
208 |
# filter the operators for Num_Calc out of the script ?WN111014?
|
walther@59802
|
209 |
use this function while storing (TODO integrate..) into KEStore_Elems.add_rlss
|
walther@59802
|
210 |
*)
|
walther@59618
|
211 |
fun prep_rls _ Rule.Erls = error "prep_rls: not required for Erls"
|
walther@59618
|
212 |
| prep_rls thy (Rule.Rls {id, preconds, rew_ord, erls, srls, rules, errpatts, ...}) =
|
walther@59802
|
213 |
let
|
walther@59802
|
214 |
val sc = (rules2scr_Rls thy rules)
|
walther@59802
|
215 |
in
|
walther@59802
|
216 |
Rule.Rls {id = id, preconds = preconds, rew_ord = rew_ord, erls = erls, srls = srls,
|
walther@59802
|
217 |
calc = get_calcs thy sc,
|
walther@59802
|
218 |
rules = rules, errpatts = errpatts,
|
walther@59802
|
219 |
scr = Rule.EmptyScr (*Rule.Prog sc AD-HOC REPLACED BY Auto_Prog.gen*)} end
|
walther@59618
|
220 |
| prep_rls thy (Rule.Seq {id, preconds, rew_ord, erls, srls, rules, errpatts, ...}) =
|
walther@59802
|
221 |
let
|
walther@59802
|
222 |
val sc = (rules2scr_Seq thy rules)
|
walther@59802
|
223 |
in
|
walther@59802
|
224 |
Rule.Seq {id = id, preconds = preconds, rew_ord = rew_ord, erls = erls, srls = srls,
|
walther@59802
|
225 |
calc = get_calcs thy sc,
|
walther@59802
|
226 |
rules = rules, errpatts = errpatts,
|
walther@59802
|
227 |
scr = Rule.EmptyScr (*Rule.Prog sc AD-HOC REPLACED BY Auto_Prog.gen*)} end
|
walther@59618
|
228 |
| prep_rls _ (Rule.Rrls {id, ...}) =
|
walther@59618
|
229 |
error ("prep_rls: not required for Rrls \"" ^ id ^ "\"");
|
walther@59618
|
230 |
|
walther@59802
|
231 |
(* on the fly generate a Prog from an rls for Math_Engine.detailstep.
|
walther@59816
|
232 |
Types are not precise, but these are not required by LI.
|
walther@59831
|
233 |
Argument "thy" is only required for lookup in KEStore.
|
walther@59802
|
234 |
*)
|
walther@59802
|
235 |
fun gen thy t rls =
|
walther@59802
|
236 |
let
|
walther@59802
|
237 |
val prog = case rls of
|
walther@59802
|
238 |
Rule.Rls {rules, ...} => rules2scr_Rls thy rules
|
walther@59802
|
239 |
| Rule.Seq {rules, ...} => rules2scr_Seq thy rules
|
walther@59802
|
240 |
| _ => raise ERROR ("Auto_Prog.gen: not for rule-set \"" ^ Rule.id_rls rls ^ "\"")
|
walther@59802
|
241 |
in
|
walther@59802
|
242 |
subst_typs prog (type_of t) (TermC.guess_bdv_typ t)
|
walther@59802
|
243 |
end
|
walther@59802
|
244 |
|
walther@59618
|
245 |
(**)end(**)
|
walther@59603
|
246 |
\<close> ML \<open>
|
walther@59603
|
247 |
\<close> ML \<open>
|
walther@59603
|
248 |
\<close>
|
walther@59603
|
249 |
end
|