src/Tools/isac/ProgLang/Auto_Prog.thy
author Walther Neuper <walther.neuper@jku.at>
Wed, 18 Mar 2020 15:23:15 +0100
changeset 59831 edf1643edde5
parent 59816 6871316e75c3
child 59833 9331e61f55dd
permissions -rw-r--r--
prep. cleanup LItool.resume_prog
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