src/Tools/isac/Specify/o-model.sml
author wneuper <Walther.Neuper@jku.at>
Fri, 24 Nov 2023 15:34:07 +0100
changeset 60766 2e0603ca18a4
parent 60763 2121f1a39a64
child 60778 41abd196342a
permissions -rw-r--r--
followup 3: repair new fill_from_o, uncomment maximum of tests
     1 (* Title:  Specify/o-model.sml
     2    Author: Walther Neuper 110226
     3    (c) due to copyright terms
     4 
     5 An \<open>O_Model\<close> holds \<open>O\<close>riginal data, \<open>descriptor\<close> and \<open>values\<close> parsed from \<open>Formalise.model\<close>
     6 selected with respect to a \<open>Model_Pattern\<close> and combined with respective \<open>m_field\<close>s.
     7 \<open>complete_for\<close> a \<open>Model_Pattern\<close> is done by \<open>Tactic.Model_Problem\<close>
     8 (with defaults from \<open>Formalise\<close>refs), by \<open>Tactic.Specify_Problem\<close> and \<open>Tactic.Specify_Method\<close>
     9 
    10 \<open>O_Model\<close> serves efficiency of student's interactive modelling via \<open>I_Model\<close>.
    11 
    12 \<open>O_Model\<close> marks elements with  \<open>m_field\<close> \<open>#undef\<close>, which are not required by the \<open>Model_Pattern\<close>
    13 of the \<open>Problem\<close> or the \<open>MethodC\<close> .. TODO redes: \<open>m_field\<close> probably different in root..Subproblem
    14 
    15 TODO: revise with an example with more than 1 variant.
    16     + consider: drop m_field ?
    17 *)
    18 
    19 signature ORIGINAL_MODEL =
    20 sig
    21   type T
    22   val empty: T
    23   type single
    24   type variant
    25   type variants
    26   type m_field
    27   type descriptor
    28   type values
    29   type message
    30   val to_string: Proof.context -> T -> string
    31   val single_to_string: Proof.context -> single -> string
    32   val single_empty: single
    33 
    34   val init: theory -> Formalise.model -> Model_Pattern.T -> T * Proof.context
    35   val values : T -> term list
    36   val values': Proof.context -> T -> Formalise.model * term list
    37   val complete_for: Model_Pattern.T -> T -> T * Proof.context -> T * Proof.context
    38   val associate_input: Proof.context -> m_field(*del?*) -> descriptor * values -> T -> message * single * values
    39   val associate_input': Proof.context -> m_field -> values -> T -> message * single * values
    40   val contains: Proof.context -> m_field -> T -> term -> message * single * values
    41   val make_typeless: term -> term
    42   val test_types: Proof.context -> descriptor * values -> string
    43 
    44   val add_enumerate: 'a list -> (int * 'a) list
    45   type preori
    46   val copy_name: Model_Pattern.T -> preori list -> Model_Pattern.single -> preori
    47   val is_copy_named: Model_Pattern.single -> bool
    48   val is_copy_named': string -> bool
    49   val is_copy_named_generating: Model_Pattern.single -> bool
    50 
    51   val get_field_term: theory -> single -> m_field * UnparseC.term_as_string
    52 
    53 \<^isac_test>\<open>
    54   val is_copy_named_generating_idstr: string -> bool
    55   val string_of_preoris : preori list -> string
    56   val add_field: theory -> Model_Pattern.T -> descriptor * values -> m_field * descriptor * values
    57 
    58   val add_variants: ('a * ''b * 'c) list -> (int * ('a * ''b * 'c)) list
    59   val get_max_variant: variants -> variant
    60   val partition_variants: ('a * 'a -> bool) -> 'a list -> (int * 'a) list
    61   val collect_variants: ('a * ''b) list -> ('a list * ''b) list
    62 
    63   val replace_0: int -> int list -> int list
    64   val flattup: 'a * ('b * ('c * 'd * 'e)) -> 'a * 'b * 'c * 'd * 'e
    65 \<close>
    66 end
    67 
    68 (**)
    69 structure O_Model(**) : ORIGINAL_MODEL(**) =
    70 struct
    71 (**)
    72 
    73 (** types **)
    74 
    75 type variant =  Model_Def.variant;
    76 type variants =  Model_Def.variants;
    77 type m_field = Model_Def.m_field;
    78 type descriptor = Model_Def.descriptor;
    79 type values = Model_Def.values;
    80 type message = string;
    81 
    82 type T = Model_Def.o_model;
    83 val empty = [] : Model_Def.o_model;
    84 type single = Model_Def.o_model_single
    85 val single_empty = Model_Def.o_model_empty;
    86 
    87 val single_to_string = Model_Def.o_model_single_to_string;
    88 val to_string = Model_Def.o_model_to_string;
    89 
    90 (* O_Model.single without leading integer *)
    91 type preori = (variants * m_field * term * term list);
    92 \<^isac_test>\<open>
    93 fun preori2str (vs, fi, t, ts) = 
    94   "(" ^ (strs2str o (map string_of_int)) vs ^ ", " ^ fi ^ ", " ^
    95     UnparseC.term (ContextC.for_ERROR ()) t ^ ", " ^ 
    96       (strs2str o (map (UnparseC.term (ContextC.for_ERROR ())) ) ) ts ^ ")";
    97 val string_of_preoris = (strs2str' o (map (linefeed o preori2str)));
    98 \<close>
    99 
   100 (* get the first term in ts from ori *)
   101 fun get_field_term thy (_, _, fd, d, ts) =
   102   (fd, ((UnparseC.term_in_thy thy) o Input_Descript.join) (d,[hd ts]))
   103 
   104 
   105 (** initialise O_Model **)
   106 
   107 (* compare d and dsc in pbt and transfer field to where_-ori *)
   108 fun add_field thy pbt (d,ts) = 
   109   let fun eq d pt = (d = (fst o snd) pt);
   110   in case filter (eq d) pbt of
   111        [(fi, (_, _))] => (fi, d, ts)
   112      | [] => ("#undef", d, ts)   (*may come with met.model*)
   113      | _ => raise ERROR ("add_field: " ^ UnparseC.term_in_thy thy d ^ " more than once in pbt")
   114   end;
   115 
   116 (*
   117   mark an element with the position within a plateau;
   118   a plateau with length 1 is marked with 0
   119 *)
   120 fun partition_variants _ [] = raise ERROR "partition_variants []"
   121   | partition_variants eq xs =
   122     let
   123       fun mar xx _ [x] n = xx @ [(if n = 1 then 0 else n, x)]
   124         | mar _ _ [] _ = raise ERROR "partition_variants []"
   125         | mar xx eq (x :: x' :: xs) n = 
   126         if eq (x, x') then mar (xx @ [(n, x)]) eq (x' :: xs) (n + 1)
   127         else mar (xx @ [(if n = 1 then 0 else n, x)]) eq (x' :: xs) 1;
   128     in mar [] eq xs 1 end;
   129 
   130 (*
   131   assumes equal descriptions to be in adjacent 'plateaus',
   132   items at a certain position within the plateaus form a variant;
   133   length = 1 ... marked with 0: covers all variants
   134 *)
   135 fun add_variants fdts = 
   136   let 
   137     fun eq (a, b) = curry op= (snd3 a) (snd3 b);
   138   in partition_variants eq fdts end;
   139 
   140 fun get_max_variant [] = raise ERROR "get_max_variant of []"
   141   | get_max_variant (y :: ys) =
   142   let fun mx x [] = x
   143 	| mx x (y :: ys) = if x < y then mx y ys else mx x ys;
   144 in mx y ys end;
   145 
   146 fun collect_variants (((v,x) :: vxs)) =
   147     let
   148       fun col xs (vs, x) [] = xs @ [(vs, x)]
   149         | col xs (vs, x) ((v', x') :: vxs') = 
   150         if x = x' then col xs (vs @ [v'], x') vxs'
   151         else col (xs @ [(vs, x)]) ([v'], x') vxs';
   152     in col [] ([v], x) vxs end
   153   | collect_variants _ = raise ERROR "collect_variants: called with []";
   154 
   155 fun replace_0 vm [0] = intsto vm
   156   | replace_0 _ vs = vs;
   157 
   158 fun add_enumerate [] = raise ERROR "O_Model.add_enumerate []"
   159   | add_enumerate xs =
   160     let
   161       fun add _ [] = []
   162         | add n (x :: xs) = (n, x) :: add (n + 1) xs;
   163     in add 1 xs end;
   164 
   165 fun flattup (a, (b, (c, d, e))) = (a, b, c, d, e);
   166 
   167 fun init _ []  _ = ([], ContextC.empty)
   168   | init thy fmz pbt =
   169     let
   170       val (ts, ctxt) = ContextC.init_while_parsing fmz thy
   171       val model =
   172         (map (fn t => t
   173           |> Input_Descript.split
   174           |> add_field thy pbt) ts)
   175         |> add_variants;
   176       val maxv = model |> map fst |> get_max_variant;
   177       val maxv = if maxv = 0 then 1 else maxv;
   178       val model' = model
   179         |> collect_variants
   180         |> map (replace_0 maxv |> apfst)
   181         |> add_enumerate
   182         |> map flattup
   183     in (model', ctxt) end
   184 
   185 (** get the values **)
   186 
   187 fun mkval _(*dsc*) [] = raise ERROR "mkval called with []"
   188   | mkval _ [t] = t
   189   | mkval _ ts = TermC.list2isalist ((type_of o hd) ts) ts;
   190 fun mkval' x = mkval TermC.empty x;
   191 (* from an O_Model create values for ctxt *)
   192 fun values oris =
   193   ((map (mkval' o (#5))) o (filter ((member_swap op= 1) o (#2)))) oris
   194 
   195 (* from an O_Model create (Formalise.model, values)
   196   e.g. Subproblem ["BOOL (1+x=2)", "REAL x"] 
   197                  --match_ags--> O_Model.T
   198        O_Model.T --values'--> (["equality (1+x=2)", "boundVariable x", "solutions L"], values)
   199 *)
   200 fun values' ctxt oris =
   201   let
   202     fun ori2fmz_vals (_, _, _, dsc, ts) = 
   203       case \<^try>\<open>(((UnparseC.term ctxt) o Input_Descript.join') (dsc, ts), last_elem ts)\<close> of
   204         SOME x => x
   205       | NONE => raise ERROR ("O_Model.values' called with " ^ UnparseC.terms ctxt ts)
   206   in (split_list o (map ori2fmz_vals)) oris end
   207 
   208 
   209 (** complete wrt. Model_Pattern.T by use of root's O_Model.T **)
   210 
   211 fun complete_for m_patt root_model (o_model, ctxt) =
   212   let
   213     val  missing = m_patt |> filter_out
   214       (fn (_, (descriptor, _)) => (member op = (map #4 o_model) descriptor))
   215     val add = (root_model
   216       |> filter
   217         (fn (_, _, _, descriptor, _) => (member op = (map (fst o snd) missing)) descriptor))
   218   in
   219     ((o_model @ add)
   220       |> map (fn (a, b, _, descr, e) =>
   221                case Model_Pattern.get_field descr m_patt of
   222                  SOME m_field => (a, b, m_field, descr, e)
   223                | NONE => (a, b, "#undef", descr, e))
   224       |> map (fn (_, b, c, d, e) => (b, c, d, e))       (* for correct enumeration *)
   225       |> add_enumerate                                  (* for correct enumeration *)
   226       |> map (fn (a, (b, c, d, e)) => (a, b, c, d, e)), (* for correct enumeration *)
   227     ctxt |> ContextC.add_constraints (add |> values |> TermC.vars'))
   228   end
   229 
   230 
   231 (** ? ? ? **)
   232 
   233 (* make oris from args of the stac SubProblem and from pbt.
   234    can this formal argument (of a model-pattern) be omitted in the arg-list
   235    of a SubProblem ? see calcelems.sml 'type met '                        *)
   236 fun is_copy_named' str =
   237   case (rev o Symbol.explode) str of
   238 	  "'" :: _ :: "'" :: _ => true
   239   | _ => false
   240 fun is_copy_named (_, (_, t)) = (is_copy_named' o TermC.free2str) t
   241 
   242 (* should this formal argument (of a model-pattern) create a new identifier? *)
   243 fun is_copy_named_generating_idstr str =
   244   if is_copy_named' str
   245   then
   246     case (rev o Symbol.explode) str of
   247 	    "'" :: "'" :: "'" :: _ => false
   248     | _ => true
   249   else false
   250 fun is_copy_named_generating (_, (_, t)) = (is_copy_named_generating_idstr o TermC.free2str) t
   251 
   252 (* generate a new variable "x_i" name from a related given one "x"
   253    by use of oris relating "v_v'i'" (is_copy_named!) to "v_v"
   254    e.g. (v_v, x) & (v_v'i', ?) --> (v_v'i', x_i),
   255    but leave is_copy_named_generating as is, e.t. ss''' *)
   256 fun copy_name pbt oris (p as (field, (dsc, t))) =
   257   case \<^try>\<open>
   258     if is_copy_named_generating p
   259     then (*WN051014 kept strange old code ...*)
   260       let fun sel (_,_,d,ts) = Input_Descript.join'''' (d, ts) 
   261         val cy' = (implode o (drop_last_n 3) o Symbol.explode o TermC.free2str) t
   262         val ext = (last_elem o drop_last o Symbol.explode o TermC.free2str) t
   263         val vars' = map (Term.term_name o snd o snd) pbt (*cpy-nam filtered_out*)
   264         val vals = map sel oris
   265         val cy_ext = (Term.term_name o the) (assoc (vars' ~~ vals, cy')) ^ "_" ^ ext
   266       in ([1], field, dsc, [TermC.mk_free (type_of t) cy_ext]) end
   267     else ([1], field, dsc, [t])
   268 	\<close> of
   269     SOME x => x
   270   | NONE => raise ERROR ("copy_name: for " ^ UnparseC.term (ContextC.for_ERROR ()) t)
   271 
   272 
   273 (** tools for I_Model **)
   274 
   275 (* to an input (_ $ values) find the according O_Model.single and insert the values *)
   276 fun associate_input ctxt m_field (descript, vals) [] =
   277     ("associate_input: input ('" ^
   278         (UnparseC.term ctxt (Input_Descript.join (descript, vals))) ^
   279           "') not found in oris (typed)", (0, [], m_field, descript, vals), [])
   280   | associate_input ctxt sel (d, ts) ((id, vat, sel', d', ts') :: oris) =
   281     if sel = sel' andalso d = d' andalso (inter op = ts ts') <> []
   282     then ("", (id, vat, sel, d, inter op = ts ts'), ts')
   283     else associate_input ctxt sel (d, ts) oris
   284 
   285 (* to an input (_ $ values) find the according O_Model.single and insert the values *)
   286 fun associate_input' ctxt _ vals [] = 
   287     ("associate_input': input (_, '" ^ strs2str (map (UnparseC.term ctxt) vals) ^
   288       "') not found in oris (typed)", single_empty, [])
   289   | associate_input' ctxt m_field vals ((id, vat, m_field', descr, vals') :: oris) =
   290     if m_field = m_field' andalso (inter op = vals vals') <> [] 
   291     then
   292       if m_field = m_field' 
   293       then ("", (id, vat, m_field, descr, inter op = vals vals'), vals')
   294       else ((strs2str' o map (UnparseC.term ctxt)) vals ^
   295         " not for " ^ m_field, single_empty, [])
   296     else associate_input' ctxt m_field vals oris
   297 
   298 fun test_types ctxt (d,ts) =
   299   let 
   300     val opt = (try Input_Descript.join) (d, ts)
   301     val msg = case opt of 
   302       SOME _ => "" 
   303     | NONE => (UnparseC.term ctxt d ^ " " ^
   304 	    (strs2str' o map (UnparseC.term ctxt)) ts ^ " is illtyped")
   305   in msg end
   306 
   307 (* make a term 'typeless' for comparing with another 'typeless' term;
   308    'type-less' usually is illtyped                                  *)
   309 fun make_typeless (Const (s, _)) = (Const (s, TermC.typ_empty)) 
   310   | make_typeless (Free (s, _)) = (Free (s, TermC.typ_empty))
   311   | make_typeless (Var (n, _)) = (Var (n, TermC.typ_empty))
   312   | make_typeless (Bound i) = (Bound i)
   313   | make_typeless (Abs (s, _,t)) = Abs(s, TermC.typ_empty, make_typeless t)
   314   | make_typeless (t1 $ t2) = (make_typeless t1) $ (make_typeless t2)
   315 
   316 (* is the term t input (or taken from fmz) known in O_Model ?
   317    give feedback on all(?) strange input;
   318    return _all_ terms already input to this item (e.g. valuesFor a,b) *)
   319 fun contains ctxt sel ori t =
   320   let
   321     val ots = ((distinct op =) o flat o (map #5)) ori
   322     val oids = ((map (fst o dest_Free)) o (distinct op =) o flat o (map TermC.vars)) ots
   323     val (d, ts) = Input_Descript.split t
   324     val ids = map (fst o dest_Free) (((distinct op =) o (flat o (map TermC.vars))) ts)
   325   in
   326     if (subtract op = oids ids) <> []
   327     then ("identifiers " ^ strs2str' (subtract op = oids ids) ^ " not in example", single_empty, [])
   328     else 
   329 	    if d = TermC.empty
   330 	    then 
   331 	      if not (subset op = (map make_typeless ts, map make_typeless ots))
   332 	      then ("terms '" ^ (strs2str' o (map (UnparseC.term ctxt))) ts ^
   333 		      "' not in example (make_typeless)", single_empty, [])
   334 	      else 
   335           (case associate_input' ctxt sel ts(*..values*) ori of
   336 		         ("", ori_ as (_, _, _, d, ts), all) =>
   337 		            (case test_types ctxt (d,ts) of
   338 		              "" => ("", ori_, all)
   339 		            | msg => (msg, single_empty, []))
   340 		       | (msg, _, _) => (msg, single_empty, []))
   341 	    else 
   342 	      if member op = (map #4 ori) d
   343 	      then associate_input ctxt sel (d, ts) ori
   344 	      else (UnparseC.term ctxt d ^ " not in example", (0, [], sel, d, ts), [])
   345   end
   346 
   347 (**)end(**);