src/Tools/isac/ProgLang/Atools.thy
changeset 59424 406681ebe781
parent 59416 229e5c9cf78b
child 59429 c0fe04973189
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/Tools/isac/ProgLang/Atools.thy	Tue Apr 03 14:50:58 2018 +0200
     1.3 @@ -0,0 +1,703 @@
     1.4 +(* Title:  tools for arithmetic
     1.5 +   Author: Walther Neuper 010308
     1.6 +   (c) due to copyright terms
     1.7 +*)
     1.8 +
     1.9 +theory Atools imports Descript Script
    1.10 +begin
    1.11 +
    1.12 +ML_file "~~/src/Tools/isac/ProgLang/scrtools.sml"
    1.13 +
    1.14 +consts
    1.15 +
    1.16 +  Arbfix           :: "real"
    1.17 +  Undef            :: "real"
    1.18 +  dummy            :: "real"
    1.19 +
    1.20 +  some'_occur'_in  :: "[real list, 'a] => bool" ("some'_of _ occur'_in _")
    1.21 +  occurs'_in       :: "[real     , 'a] => bool" ("_ occurs'_in _")
    1.22 +
    1.23 +  pow              :: "[real, real] => real"    (infixr "^^^" 80)
    1.24 +(* ~~~ power doesn't allow Free("2",real) ^ Free("2",nat)
    1.25 +                           ~~~~     ~~~~    ~~~~     ~~~*)
    1.26 +(*WN0603 at FE-interface encoded strings to '^', 
    1.27 +	see 'fun encode', fun 'decode'*)
    1.28 +
    1.29 +  abs              :: "real => real"            ("(|| _ ||)")
    1.30 +(* ~~~ FIXXXME Isabelle2002 has abs already !!!*)
    1.31 +  absset           :: "real set => real"        ("(||| _ |||)")
    1.32 +  (*is numeral constant ?*)
    1.33 +  is'_const        :: "real => bool"            ("_ is'_const" 10)
    1.34 +  (*is_const rename to is_num FIXXXME.WN.16.5.03 *)
    1.35 +  is'_atom         :: "real => bool"            ("_ is'_atom" 10)
    1.36 +  is'_even         :: "real => bool"            ("_ is'_even" 10)
    1.37 +		
    1.38 +  (* identity on term level*)
    1.39 +  ident            :: "['a, 'a] => bool"        ("(_ =!=/ _)" [51, 51] 50)
    1.40 +
    1.41 +  argument'_in     :: "real => real"            ("argument'_in _" 10)
    1.42 +  sameFunId        :: "[real, bool] => bool"    (**"same'_funid _ _" 10
    1.43 +	WN0609 changed the id, because ".. _ _" inhibits currying**)
    1.44 +  filter'_sameFunId:: "[real, bool list] => bool list" 
    1.45 +					        ("filter'_sameFunId _ _" 10)
    1.46 +  boollist2sum     :: "bool list => real"
    1.47 +
    1.48 +axiomatization where (*for evaluating the assumptions of conditional rules*)
    1.49 +
    1.50 +  last_thmI:	      "lastI (x#xs) = (if xs =!= [] then x else lastI xs)" and
    1.51 +  real_unari_minus:   "- a = (-1) * a" and
    1.52 +
    1.53 +  rle_refl:           "(n::real) <= n" and
    1.54 +  radd_left_cancel_le:"((k::real) + m <= k + n) = (m <= n)" and
    1.55 +  not_true:           "(~ True) = False" and
    1.56 +  not_false:          "(~ False) = True"
    1.57 +
    1.58 +axiomatization where (*..if replaced by "and" we get error:
    1.59 +Type unification failed: No type arity bool :: zero ...*)
    1.60 +  and_true:           "(a & True) = a" and
    1.61 +  and_false:          "(a & False) = False" and
    1.62 +  or_true:            "(a | True) = True" and
    1.63 +  or_false:           "(a | False) = a" and
    1.64 +  and_commute:        "(a & b) = (b & a)" and
    1.65 +  or_commute:         "(a | b) = (b | a)" 
    1.66 +
    1.67 +  (*.should be in Rational.thy, but: 
    1.68 +   needed for asms in e.g. d2_pqformula1 in PolyEq.ML, RootEq.ML.*)
    1.69 +axiomatization where (*..if replaced by "and" we get error:
    1.70 +Type unification failed: No type arity bool :: zero ...*)
    1.71 +  rat_leq1:	      "[| b ~= 0; d ~= 0 |] ==>
    1.72 +		       ((a / b) <= (c / d)) = ((a*d) <= (b*c))"(*Isa?*) and
    1.73 +  rat_leq2:	      "d ~= 0 ==>
    1.74 +		       ( a      <= (c / d)) = ((a*d) <=    c )"(*Isa?*) and
    1.75 +  rat_leq3:	      "b ~= 0 ==>
    1.76 +		       ((a / b) <=  c     ) = ( a    <= (b*c))"(*Isa?*)
    1.77 +
    1.78 +
    1.79 +text {*copy from doc/math-eng.tex WN.28.3.03
    1.80 +WN071228 extended *}
    1.81 +
    1.82 +section {*Coding standards*}
    1.83 +subsection {*Identifiers*}
    1.84 +text {*Naming is particularily crucial, because Isabelles name space is global, and isac does not yet use the novel locale features introduces by Isar. For instance, {\tt probe} sounds reasonable as (1) a description in the model of a problem-pattern, (2) as an element of the problem hierarchies key, (3) as a socalled CAS-command, (4) as the name of a related script etc. However, all the cases (1)..(4) require different typing for one and the same identifier {\tt probe} which is impossible, and actually leads to strange errors (for instance (1) is used as string, except in a script addressing a Subproblem).
    1.85 +
    1.86 +This are the preliminary rules for naming identifiers>
    1.87 +\begin{description}
    1.88 +\item [elements of a key] into the hierarchy of problems or methods must not contain capital letters and may contain underscrores, e.g. {\tt probe, for_polynomials}.
    1.89 +\item [descriptions in problem-patterns] must contain at least 1 capital letter and must not contain underscores, e.g. {\tt Probe, forPolynomials}.
    1.90 +\item [CAS-commands] follow the same rules as descriptions in problem-patterns above, thus beware of conflicts~!
    1.91 +\item [script identifiers] always end with {\tt Script}, e.g. {\tt ProbeScript}.
    1.92 +\item [???] ???
    1.93 +\item [???] ???
    1.94 +\end{description}
    1.95 +%WN071228 extended *}
    1.96 +
    1.97 +subsection {*Rule sets*}
    1.98 +text {*The actual version of the coding standards for rulesets is in {\tt /IsacKnowledge/Atools.ML where it can be viewed using the knowledge browsers.
    1.99 +
   1.100 +There are rulesets visible to the student, and there are rulesets visible (in general) only for math authors. There are also rulesets which {\em must} exist for {\em each} theory; these contain the identifier of the respective theory (including all capital letters) as indicated by {\it Thy} below.
   1.101 +\begin{description}
   1.102 +
   1.103 +\item [norm\_{\it Thy}] exists for each theory, and {\em efficiently} calculates a normalform for all terms which can be expressed by the definitions of the respective theory (and the respective parents).
   1.104 +
   1.105 +\item [simplify\_{\it Thy}] exists for each theory, and calculates a normalform for all terms which can be expressed by the definitions of the respective theory (and the respective parents) such, that the rewrites can be presented to the student.
   1.106 +
   1.107 +\item [calculate\_{\it Thy}] exists for each theory, and evaluates terms with numerical constants only (i.e. all terms which can be expressed by the definitions of the respective theory and the respective parent theories). In particular, this ruleset includes evaluating in/equalities with numerical constants only.
   1.108 +WN.3.7.03: may be dropped due to more generality: numericals and non-numericals are logically equivalent, where the latter often add to the assumptions (e.g. in Check_elementwise).
   1.109 +\end{description}
   1.110 +
   1.111 +The above rulesets are all visible to the user, and also may be input; 
   1.112 +thus they must be contained in {\tt Theory_Data} (KEStore_Elems.add_rlss,
   1.113 +KEStore_Elems.get_rlss). All these rulesets must undergo a preparation
   1.114 +using the function {\tt prep_rls'}, which generates a script for stepwise rewriting etc.
   1.115 +The following rulesets are used for internal purposes and usually invisible to the (naive) user:
   1.116 +\begin{description}
   1.117 +
   1.118 +\item [*\_erls] TODO
   1.119 +\item [*\_prls] 
   1.120 +\item [*\_srls] 
   1.121 +
   1.122 +\end{description}
   1.123 +{\tt Rule.append_rls, Rule.merge_rls, remove_rls} TODO
   1.124 +*}
   1.125 +
   1.126 +ML {*
   1.127 +val thy = @{theory};
   1.128 +
   1.129 +(** evaluation of numerals and special predicates on the meta-level **)
   1.130 +(*-------------------------functions---------------------*)
   1.131 +local (* rlang 09.02 *)
   1.132 +    (*.a 'c is coefficient of v' if v does occur in c.*)
   1.133 +    fun coeff_in v c = member op = (TermC.vars c) v;
   1.134 +in
   1.135 +    fun occurs_in v t = coeff_in v t;
   1.136 +end;
   1.137 +
   1.138 +(*("occurs_in", ("Atools.occurs'_in", eval_occurs_in ""))*)
   1.139 +fun eval_occurs_in _ "Atools.occurs'_in"
   1.140 +	     (p as (Const ("Atools.occurs'_in",_) $ v $ t)) _ =
   1.141 +    ((*tracing("@@@ eval_occurs_in: v= "^(Rule.term2str v));
   1.142 +     tracing("@@@ eval_occurs_in: t= "^(Rule.term2str t));*)
   1.143 +     if occurs_in v t
   1.144 +    then SOME ((Rule.term2str p) ^ " = True",
   1.145 +	  HOLogic.Trueprop $ (TermC.mk_equality (p, @{term True})))
   1.146 +    else SOME ((Rule.term2str p) ^ " = False",
   1.147 +	  HOLogic.Trueprop $ (TermC.mk_equality (p, @{term False}))))
   1.148 +  | eval_occurs_in _ _ _ _ = NONE;
   1.149 +
   1.150 +(*some of the (bound) variables (eg. in an eqsys) "vs" occur in term "t"*)   
   1.151 +fun some_occur_in vs t = 
   1.152 +    let fun occurs_in' a b = occurs_in b a
   1.153 +    in foldl or_ (false, map (occurs_in' t) vs) end;
   1.154 +
   1.155 +(*("some_occur_in", ("Atools.some'_occur'_in", 
   1.156 +			eval_some_occur_in "#eval_some_occur_in_"))*)
   1.157 +fun eval_some_occur_in _ "Atools.some'_occur'_in"
   1.158 +			  (p as (Const ("Atools.some'_occur'_in",_) 
   1.159 +				       $ vs $ t)) _ =
   1.160 +    if some_occur_in (TermC.isalist2list vs) t
   1.161 +    then SOME ((Rule.term2str p) ^ " = True",
   1.162 +	       HOLogic.Trueprop $ (TermC.mk_equality (p, @{term True})))
   1.163 +    else SOME ((Rule.term2str p) ^ " = False",
   1.164 +	       HOLogic.Trueprop $ (TermC.mk_equality (p, @{term False})))
   1.165 +  | eval_some_occur_in _ _ _ _ = NONE;
   1.166 +
   1.167 +
   1.168 +
   1.169 +
   1.170 +(*evaluate 'is_atom'*)
   1.171 +(*("is_atom",("Atools.is'_atom",eval_is_atom "#is_atom_"))*)
   1.172 +fun eval_is_atom (thmid:string) "Atools.is'_atom"
   1.173 +		 (t as (Const(op0,_) $ arg)) thy = 
   1.174 +    (case arg of 
   1.175 +	 Free (n,_) => SOME (TermC.mk_thmid thmid n "", 
   1.176 +			      HOLogic.Trueprop $ (TermC.mk_equality (t, @{term True})))
   1.177 +       | _ => SOME (TermC.mk_thmid thmid "" "", 
   1.178 +		    HOLogic.Trueprop $ (TermC.mk_equality (t, @{term False}))))
   1.179 +  | eval_is_atom _ _ _ _ = NONE;
   1.180 +
   1.181 +(*evaluate 'is_even'*)
   1.182 +fun even i = (i div 2) * 2 = i;
   1.183 +(*("is_even",("Atools.is'_even",eval_is_even "#is_even_"))*)
   1.184 +fun eval_is_even (thmid:string) "Atools.is'_even"
   1.185 +		 (t as (Const(op0,_) $ arg)) thy = 
   1.186 +    (case arg of 
   1.187 +	Free (n,_) =>
   1.188 +	 (case TermC.int_of_str_opt n of
   1.189 +	      SOME i =>
   1.190 +	      if even i then SOME (TermC.mk_thmid thmid n "", 
   1.191 +				   HOLogic.Trueprop $ (TermC.mk_equality (t, @{term True})))
   1.192 +	      else SOME (TermC.mk_thmid thmid "" "", 
   1.193 +			 HOLogic.Trueprop $ (TermC.mk_equality (t, @{term False})))
   1.194 +	    | _ => NONE)
   1.195 +       | _ => NONE)
   1.196 +  | eval_is_even _ _ _ _ = NONE; 
   1.197 +
   1.198 +(*evaluate 'is_const'*)
   1.199 +(*("is_const",("Atools.is'_const",eval_const "#is_const_"))*)
   1.200 +fun eval_const (thmid:string) _(*"Atools.is'_const" WN050820 diff.beh. rooteq*)
   1.201 +	       (t as (Const(op0,t0) $ arg)) (thy:theory) = 
   1.202 +    (*eval_const FIXXXXXME.WN.16.5.03 still forgets ComplexI*)
   1.203 +    (case arg of 
   1.204 +       Const (n1,_) =>
   1.205 +	 SOME (TermC.mk_thmid thmid n1 "", 
   1.206 +	       HOLogic.Trueprop $ (TermC.mk_equality (t, @{term False})))
   1.207 +     | Free (n1,_) =>
   1.208 +	 if TermC.is_num' n1
   1.209 +	   then SOME (TermC.mk_thmid thmid n1 "", 
   1.210 +		      HOLogic.Trueprop $ (TermC.mk_equality (t, @{term True})))
   1.211 +	 else SOME (TermC.mk_thmid thmid n1 "", 
   1.212 +		    HOLogic.Trueprop $ (TermC.mk_equality (t, @{term False})))
   1.213 +     | Const ("Float.Float",_) =>
   1.214 +       SOME (TermC.mk_thmid thmid (Rule.term2str arg) "", 
   1.215 +	     HOLogic.Trueprop $ (TermC.mk_equality (t, @{term True})))
   1.216 +     | _ => (*NONE*)
   1.217 +       SOME (TermC.mk_thmid thmid (Rule.term2str arg) "", 
   1.218 +		    HOLogic.Trueprop $ (TermC.mk_equality (t, @{term False}))))
   1.219 +  | eval_const _ _ _ _ = NONE; 
   1.220 +
   1.221 +(*. evaluate binary, associative, commutative operators: *,+,^ .*)
   1.222 +(*("PLUS"    ,("Groups.plus_class.plus"        ,eval_binop "#add_")),
   1.223 +  ("TIMES"   ,("Groups.times_class.times"        ,eval_binop "#mult_")),
   1.224 +  ("POWER"  ,("Atools.pow"  ,eval_binop "#power_"))*)
   1.225 +
   1.226 +(* val (thmid,op_,t as(Const (op0,t0) $ Free (n1,t1) $ Free(n2,t2)),thy) =
   1.227 +       ("xxxxxx",op_,t,thy);
   1.228 +   *)
   1.229 +fun mk_thmid_f thmid ((v11, v12), (p11, p12)) ((v21, v22), (p21, p22)) = (* dropped *)
   1.230 +  thmid ^ "Float ((" ^ 
   1.231 +  (string_of_int v11)^","^(string_of_int v12)^"), ("^
   1.232 +  (string_of_int p11)^","^(string_of_int p12)^")) __ (("^
   1.233 +  (string_of_int v21)^","^(string_of_int v22)^"), ("^
   1.234 +  (string_of_int p21)^","^(string_of_int p22)^"))";
   1.235 +
   1.236 +(*.convert int and float to internal floatingpoint prepresentation.*)
   1.237 +fun numeral (Free (str, T)) = 
   1.238 +    (case TermC.int_of_str_opt str of
   1.239 +	 SOME i => SOME ((i, 0), (0, 0))
   1.240 +       | NONE => NONE)
   1.241 +  | numeral (Const ("Float.Float", _) $
   1.242 +		   (Const ("Product_Type.Pair", _) $
   1.243 +			  (Const ("Product_Type.Pair", T) $ Free (v1, _) $ Free (v2,_)) $
   1.244 +			  (Const ("Product_Type.Pair", _) $ Free (p1, _) $ Free (p2,_))))=
   1.245 +    (case (TermC.int_of_str_opt v1, TermC.int_of_str_opt v2, TermC.int_of_str_opt p1, TermC.int_of_str_opt p2) of
   1.246 +	(SOME v1', SOME v2', SOME p1', SOME p2') =>
   1.247 +	SOME ((v1', v2'), (p1', p2'))
   1.248 +      | _ => NONE)
   1.249 +  | numeral _ = NONE;
   1.250 +
   1.251 +(* evaluate binary associative operations *)
   1.252 +fun eval_binop (thmid : string) (op_: string) 
   1.253 +      (t as (Const (op0, t0) $ (Const (op0', _) $ v $ t1) $ t2)) _ =  (* binary . (v.n1).n2 *)
   1.254 +    if op0 = op0' then
   1.255 +      case (numeral t1, numeral t2) of
   1.256 +        (SOME n1, SOME n2) =>
   1.257 +          let 
   1.258 +            val (T1, _, _) = TermC.dest_binop_typ t0
   1.259 +            val res = 
   1.260 +              calcul (if op0 = "Groups.minus_class.minus" then "Groups.plus_class.plus" else op0)n1 n2
   1.261 +              (*WN071229 "Rings.divide_class.divide" never tried*)
   1.262 +            val rhs = var_op_float v op_ t0 T1 res
   1.263 +            val prop = HOLogic.Trueprop $ (TermC.mk_equality (t, rhs))
   1.264 +          in SOME ("#: " ^ Rule.term2str prop, prop) end
   1.265 +      | _ => NONE
   1.266 +    else NONE
   1.267 +  | eval_binop (thmid : string) (op_ : string) 
   1.268 +      (t as (Const (op0, t0) $ t1 $ (Const (op0', _) $ t2 $ v))) _ =  (* binary . n1.(n2.v) *)
   1.269 +    if op0 = op0' then
   1.270 +      case (numeral t1, numeral t2) of
   1.271 +        (SOME n1, SOME n2) =>
   1.272 +          if op0 = "Groups.minus_class.minus" then NONE 
   1.273 +          else let 
   1.274 +            val (T1, _, _) = TermC.dest_binop_typ t0
   1.275 +            val res = calcul op0 n1 n2
   1.276 +            val rhs = float_op_var v op_ t0 T1 res
   1.277 +            val prop = HOLogic.Trueprop $ (TermC.mk_equality (t, rhs))
   1.278 +          in SOME ("#: " ^ Rule.term2str prop, prop) end
   1.279 +      | _ => NONE
   1.280 +    else NONE
   1.281 +  | eval_binop (thmid : string) _ (t as (Const (op0, t0) $ t1 $ t2)) _ =   (* binary . n1.n2 *)
   1.282 +    (case (numeral t1, numeral t2) of
   1.283 +      (SOME n1, SOME n2) =>
   1.284 +        let 
   1.285 +          val (_, _, Trange) = TermC.dest_binop_typ t0;
   1.286 +          val res = calcul op0 n1 n2;
   1.287 +          val rhs = term_of_float Trange res;
   1.288 +          val prop = HOLogic.Trueprop $ (TermC.mk_equality (t, rhs));
   1.289 +        in SOME ("#: " ^ Rule.term2str prop, prop) end
   1.290 +    | _ => NONE)
   1.291 +  | eval_binop _ _ _ _ = NONE; 
   1.292 +(*
   1.293 +> val SOME (thmid, t) = eval_binop "#add_" "Groups.plus_class.plus" (str2term "-1 + 2") thy;
   1.294 +> Rule.term2str t;
   1.295 +val it = "-1 + 2 = 1"
   1.296 +> val t = str2term "-1 * (-1 * a)";
   1.297 +> val SOME (thmid, t) = eval_binop "#mult_" "Groups.times_class.times" t thy;
   1.298 +> Rule.term2str t;
   1.299 +val it = "-1 * (-1 * a) = 1 * a"*)
   1.300 +
   1.301 +
   1.302 +
   1.303 +(*.evaluate < and <= for numerals.*)
   1.304 +(*("le"      ,("Orderings.ord_class.less"        ,eval_equ "#less_")),
   1.305 +  ("leq"     ,("Orderings.ord_class.less_eq"       ,eval_equ "#less_equal_"))*)
   1.306 +fun eval_equ (thmid:string) (op_:string) (t as 
   1.307 +	       (Const (op0,t0) $ Free (n1,t1) $ Free(n2,t2))) thy = 
   1.308 +    (case (TermC.int_of_str_opt n1, TermC.int_of_str_opt n2) of
   1.309 +	 (SOME n1', SOME n2') =>
   1.310 +  if Calc.calc_equ (strip_thy op0) (n1', n2')
   1.311 +    then SOME (TermC.mk_thmid thmid n1 n2, 
   1.312 +	  HOLogic.Trueprop $ (TermC.mk_equality (t, @{term True})))
   1.313 +  else SOME (TermC.mk_thmid thmid n1 n2,  
   1.314 +	  HOLogic.Trueprop $ (TermC.mk_equality (t, @{term False})))
   1.315 +       | _ => NONE)
   1.316 +    
   1.317 +  | eval_equ _ _ _ _ = NONE;
   1.318 +
   1.319 +
   1.320 +(*evaluate identity
   1.321 +> reflI;
   1.322 +val it = "(?t = ?t) = True"
   1.323 +> val t = str2term "x = 0";
   1.324 +> val NONE = rewrite_ thy Rule.dummy_ord Rule.e_rls false reflI t;
   1.325 +
   1.326 +> val t = str2term "1 = 0";
   1.327 +> val NONE = rewrite_ thy Rule.dummy_ord Rule.e_rls false reflI t;
   1.328 +----------- thus needs Rule.Calc !
   1.329 +> val t = str2term "0 = 0";
   1.330 +> val SOME (t',_) = rewrite_ thy Rule.dummy_ord Rule.e_rls false reflI t;
   1.331 +> Rule.term2str t';
   1.332 +val it = "HOL.True"
   1.333 +
   1.334 +val t = str2term "Not (x = 0)";
   1.335 +atomt t; Rule.term2str t;
   1.336 +*** -------------
   1.337 +*** Const ( Not)
   1.338 +*** . Const ( op =)
   1.339 +*** . . Free ( x, )
   1.340 +*** . . Free ( 0, )
   1.341 +val it = "x ~= 0" : string*)
   1.342 +
   1.343 +(*.evaluate identity on the term-level, =!= ,i.e. without evaluation of 
   1.344 +  the arguments: thus special handling by 'fun eval_binop'*)
   1.345 +(*("ident"   ,("Atools.ident",eval_ident "#ident_")):calc*)
   1.346 +fun eval_ident (thmid:string) "Atools.ident" (t as 
   1.347 +	       (Const (op0,t0) $ t1 $ t2 )) thy = 
   1.348 +  if t1 = t2
   1.349 +  then SOME (TermC.mk_thmid thmid 
   1.350 +	              ("(" ^ (Rule.term_to_string''' thy t1) ^ ")")
   1.351 +	              ("(" ^ (Rule.term_to_string''' thy t2) ^ ")"), 
   1.352 +	     HOLogic.Trueprop $ (TermC.mk_equality (t, @{term True})))
   1.353 +  else SOME (TermC.mk_thmid thmid  
   1.354 +	              ("(" ^ (Rule.term_to_string''' thy t1) ^ ")")
   1.355 +	              ("(" ^ (Rule.term_to_string''' thy t2) ^ ")"),  
   1.356 +	     HOLogic.Trueprop $ (TermC.mk_equality (t, @{term False})))
   1.357 +  | eval_ident _ _ _ _ = NONE;
   1.358 +(* TODO
   1.359 +> val t = str2term "x =!= 0";
   1.360 +> val SOME (str, t') = eval_ident "ident_" "b" t thy;
   1.361 +> Rule.term2str t';
   1.362 +val str = "ident_(x)_(0)" : string
   1.363 +val it = "(x =!= 0) = False" : string                                
   1.364 +> val t = str2term "1 =!= 0";
   1.365 +> val SOME (str, t') = eval_ident "ident_" "b" t thy;
   1.366 +> Rule.term2str t';
   1.367 +val str = "ident_(1)_(0)" : string 
   1.368 +val it = "(1 =!= 0) = False" : string                                       
   1.369 +> val t = str2term "0 =!= 0";
   1.370 +> val SOME (str, t') = eval_ident "ident_" "b" t thy;
   1.371 +> Rule.term2str t';
   1.372 +val str = "ident_(0)_(0)" : string
   1.373 +val it = "(0 =!= 0) = True" : string
   1.374 +*)
   1.375 +
   1.376 +(*.evaluate identity of terms, which stay ready for evaluation in turn;
   1.377 +  thus returns False only for atoms.*)
   1.378 +(*("equal"   ,("HOL.eq",eval_equal "#equal_")):calc*)
   1.379 +fun eval_equal (thmid : string) "HOL.eq" (t as (Const (op0,t0) $ t1 $ t2 )) thy = 
   1.380 +  if t1 = t2
   1.381 +  then SOME (TermC.mk_thmid thmid 
   1.382 +                ("(" ^ Rule.term_to_string''' thy t1 ^ ")")
   1.383 +                ("(" ^ Rule.term_to_string''' thy t2 ^ ")"), 
   1.384 +       HOLogic.Trueprop $ (TermC.mk_equality (t, @{term True})))
   1.385 +  else (case (TermC.is_atom t1, TermC.is_atom t2) of
   1.386 +      (true, true) => 
   1.387 +      SOME (TermC.mk_thmid thmid  
   1.388 +         ("(" ^ Rule.term_to_string''' thy t1 ^ ")")
   1.389 +         ("(" ^ Rule.term_to_string''' thy t2 ^ ")"),
   1.390 +      HOLogic.Trueprop $ (TermC.mk_equality (t, @{term False})))
   1.391 +    | _ => NONE)                             (* NOT is_atom t1,t2 --> rew_sub *)
   1.392 +  | eval_equal _ _ _ _ = NONE;                                  (* error-exit *)
   1.393 +(*
   1.394 +val t = str2term "x ~= 0";
   1.395 +val NONE = eval_equal "equal_" "b" t thy;
   1.396 +
   1.397 +
   1.398 +> val t = str2term "(x + 1) = (x + 1)";
   1.399 +> val SOME (str, t') = eval_equal "equal_" "b" t thy;
   1.400 +> Rule.term2str t';
   1.401 +val str = "equal_(x + 1)_(x + 1)" : string
   1.402 +val it = "(x + 1 = x + 1) = True" : string
   1.403 +> val t = str2term "x = 0";
   1.404 +> val NONE = eval_equal "equal_" "b" t thy;
   1.405 +
   1.406 +> val t = str2term "1 = 0";
   1.407 +> val SOME (str, t') = eval_equal "equal_" "b" t thy;
   1.408 +> Rule.term2str t';
   1.409 +val str = "equal_(1)_(0)" : string 
   1.410 +val it = "(1 = 0) = False" : string
   1.411 +> val t = str2term "0 = 0";
   1.412 +> val SOME (str, t') = eval_equal "equal_" "b" t thy;
   1.413 +> Rule.term2str t';
   1.414 +val str = "equal_(0)_(0)" : string
   1.415 +val it = "(0 = 0) = True" : string
   1.416 +*)
   1.417 +
   1.418 +
   1.419 +*}
   1.420 +
   1.421 +ML {*
   1.422 +(** evaluation on the metalevel **)
   1.423 +
   1.424 +(*. evaluate HOL.divide .*)
   1.425 +(*("DIVIDE" ,("Rings.divide_class.divide"  ,eval_cancel "#divide_e"))*)
   1.426 +fun eval_cancel (thmid:string) "Rings.divide_class.divide" (t as 
   1.427 +	       (Const (op0,t0) $ Free (n1,t1) $ Free(n2,t2))) thy = 
   1.428 +    (case (TermC.int_of_str_opt n1, TermC.int_of_str_opt n2) of
   1.429 +	 (SOME n1', SOME n2') =>
   1.430 +  let 
   1.431 +    val sg = Calc.sign_mult n1' n2';
   1.432 +    val (T1,T2,Trange) = TermC.dest_binop_typ t0;
   1.433 +    val gcd' = Calc.gcd (abs n1') (abs n2');
   1.434 +  in if gcd' = abs n2' 
   1.435 +     then let val rhs = TermC.term_of_num Trange (sg * (abs n1') div gcd')
   1.436 +	      val prop = HOLogic.Trueprop $ (TermC.mk_equality (t, rhs))
   1.437 +	  in SOME (TermC.mk_thmid thmid n1 n2, prop) end     
   1.438 +     else if 0 < n2' andalso gcd' = 1 then NONE
   1.439 +     else let val rhs = TermC.mk_num_op_num T1 T2 (op0,t0) (sg * (abs n1') div gcd')
   1.440 +				   ((abs n2') div gcd')
   1.441 +	      val prop = HOLogic.Trueprop $ (TermC.mk_equality (t, rhs))
   1.442 +	  in SOME (TermC.mk_thmid thmid n1 n2, prop) end
   1.443 +  end
   1.444 +       | _ => ((*tracing"@@@ eval_cancel NONE";*)NONE))
   1.445 +
   1.446 +  | eval_cancel _ _ _ _ = NONE;
   1.447 +
   1.448 +(*. get the argument from a function-definition.*)
   1.449 +(*("argument_in" ,("Atools.argument'_in",
   1.450 +		   eval_argument_in "Atools.argument'_in"))*)
   1.451 +fun eval_argument_in _ "Atools.argument'_in" 
   1.452 +		     (t as (Const ("Atools.argument'_in", _) $ (f $ arg))) _ =
   1.453 +    if is_Free arg (*could be something to be simplified before*)
   1.454 +    then SOME (Rule.term2str t ^ " = " ^ Rule.term2str arg,
   1.455 +	       HOLogic.Trueprop $ (TermC.mk_equality (t, arg)))
   1.456 +    else NONE
   1.457 +  | eval_argument_in _ _ _ _ = NONE;
   1.458 +
   1.459 +(*.check if the function-identifier of the first argument matches 
   1.460 +   the function-identifier of the lhs of the second argument.*)
   1.461 +(*("sameFunId" ,("Atools.sameFunId",
   1.462 +		   eval_same_funid "Atools.sameFunId"))*)
   1.463 +fun eval_sameFunId _ "Atools.sameFunId" 
   1.464 +		     (p as Const ("Atools.sameFunId",_) $ 
   1.465 +			(f1 $ _) $ 
   1.466 +			(Const ("HOL.eq", _) $ (f2 $ _) $ _)) _ =
   1.467 +    if f1 = f2 
   1.468 +    then SOME ((Rule.term2str p) ^ " = True",
   1.469 +	       HOLogic.Trueprop $ (TermC.mk_equality (p, @{term True})))
   1.470 +    else SOME ((Rule.term2str p) ^ " = False",
   1.471 +	       HOLogic.Trueprop $ (TermC.mk_equality (p, @{term False})))
   1.472 +| eval_sameFunId _ _ _ _ = NONE;
   1.473 +
   1.474 +
   1.475 +(*.from a list of fun-definitions "f x = ..." as 2nd argument
   1.476 +   filter the elements with the same fun-identfier in "f y"
   1.477 +   as the fst argument;
   1.478 +   this is, because Isabelles filter takes more than 1 sec.*)
   1.479 +fun same_funid f1 (Const ("HOL.eq", _) $ (f2 $ _) $ _) = f1 = f2
   1.480 +  | same_funid f1 t = error ("same_funid called with t = ("
   1.481 +				   ^Rule.term2str f1^") ("^Rule.term2str t^")");
   1.482 +(*("filter_sameFunId" ,("Atools.filter'_sameFunId",
   1.483 +		   eval_filter_sameFunId "Atools.filter'_sameFunId"))*)
   1.484 +fun eval_filter_sameFunId _ "Atools.filter'_sameFunId" 
   1.485 +		     (p as Const ("Atools.filter'_sameFunId",_) $ 
   1.486 +			(fid $ _) $ fs) _ =
   1.487 +    let val fs' = ((TermC.list2isalist HOLogic.boolT) o 
   1.488 +		   (filter (same_funid fid))) (TermC.isalist2list fs)
   1.489 +    in SOME (Rule.term2str (TermC.mk_equality (p, fs')),
   1.490 +	       HOLogic.Trueprop $ (TermC.mk_equality (p, fs'))) end
   1.491 +| eval_filter_sameFunId _ _ _ _ = NONE;
   1.492 +
   1.493 +
   1.494 +(*make a list of terms to a sum*)
   1.495 +fun list2sum [] = error ("list2sum called with []")
   1.496 +  | list2sum [s] = s
   1.497 +  | list2sum (s::ss) = 
   1.498 +    let fun sum su [s'] = 
   1.499 +	    Const ("Groups.plus_class.plus", [HOLogic.realT,HOLogic.realT]--->HOLogic.realT)
   1.500 +		  $ su $ s'
   1.501 +	  | sum su (s'::ss') = 
   1.502 +	    sum (Const ("Groups.plus_class.plus", [HOLogic.realT,HOLogic.realT]--->HOLogic.realT)
   1.503 +		  $ su $ s') ss'
   1.504 +    in sum s ss end;
   1.505 +
   1.506 +(*make a list of equalities to the sum of the lhs*)
   1.507 +(*("boollist2sum"    ,("Atools.boollist2sum"    ,eval_boollist2sum "")):calc*)
   1.508 +fun eval_boollist2sum _ "Atools.boollist2sum" 
   1.509 +		      (p as Const ("Atools.boollist2sum", _) $ 
   1.510 +			 (l as Const ("List.list.Cons", _) $ _ $ _)) _ =
   1.511 +    let val isal = TermC.isalist2list l
   1.512 +	val lhss = map lhs isal
   1.513 +	val sum = list2sum lhss
   1.514 +    in SOME ((Rule.term2str p) ^ " = " ^ (Rule.term2str sum),
   1.515 +	  HOLogic.Trueprop $ (TermC.mk_equality (p, sum)))
   1.516 +    end
   1.517 +| eval_boollist2sum _ _ _ _ = NONE;
   1.518 +
   1.519 +
   1.520 +
   1.521 +local
   1.522 +
   1.523 +open Term;
   1.524 +
   1.525 +in
   1.526 +fun termlessI (_: Rule.subst) uv = Term_Ord.termless uv;
   1.527 +fun term_ordI (_: Rule.subst) uv = Term_Ord.term_ord uv;
   1.528 +end;
   1.529 +
   1.530 +
   1.531 +(** rule set, for evaluating list-expressions in scripts 8.01.02 **)
   1.532 +
   1.533 +
   1.534 +val list_rls = Rule.append_rls "list_rls" list_rls
   1.535 +	 [Rule.Calc ("Groups.times_class.times",eval_binop "#mult_"),
   1.536 +		Rule.Calc ("Groups.plus_class.plus", eval_binop "#add_"), 
   1.537 +		Rule.Calc ("Orderings.ord_class.less",eval_equ "#less_"),
   1.538 +		Rule.Calc ("Orderings.ord_class.less_eq",eval_equ "#less_equal_"),
   1.539 +		Rule.Calc ("Atools.ident",eval_ident "#ident_"),
   1.540 +		Rule.Calc ("HOL.eq",eval_equal "#equal_"),(*atom <> atom -> False*)
   1.541 +       
   1.542 +		Rule.Calc ("Tools.Vars",eval_var "#Vars_"),
   1.543 +		
   1.544 +		Rule.Thm ("if_True",TermC.num_str @{thm if_True}),
   1.545 +		Rule.Thm ("if_False",TermC.num_str @{thm if_False})
   1.546 +		];
   1.547 +*}
   1.548 +ML {*
   1.549 +
   1.550 +(*TODO.WN0509 reduce ids: tless_true = e_rew_ord' = Rule.e_rew_ord = Rule.dummy_ord*)
   1.551 +val tless_true = Rule.dummy_ord;
   1.552 +Rule.rew_ord' := overwritel (! Rule.rew_ord',
   1.553 +			[("tless_true", tless_true),
   1.554 +			 ("e_rew_ord'", tless_true),
   1.555 +			 ("dummy_ord", Rule.dummy_ord)]);
   1.556 +
   1.557 +val calculate_Base_Tools = 
   1.558 +    Rule.append_rls "calculate_Atools" Rule.e_rls
   1.559 +               [Rule.Calc ("Orderings.ord_class.less",eval_equ "#less_"),
   1.560 +		Rule.Calc ("Orderings.ord_class.less_eq",eval_equ "#less_equal_"),
   1.561 +		Rule.Calc ("HOL.eq",eval_equal "#equal_"),
   1.562 +
   1.563 +		Rule.Thm  ("real_unari_minus",TermC.num_str @{thm real_unari_minus}),
   1.564 +		Rule.Calc ("Groups.plus_class.plus",eval_binop "#add_"),
   1.565 +		Rule.Calc ("Groups.minus_class.minus",eval_binop "#sub_"),
   1.566 +		Rule.Calc ("Groups.times_class.times",eval_binop "#mult_")
   1.567 +		];
   1.568 +
   1.569 +*}
   1.570 +
   1.571 +find_theorems (9) "?n <= ?n"
   1.572 +
   1.573 +ML {*
   1.574 +val Atools_erls = 
   1.575 +    Rule.append_rls "Atools_erls" Rule.e_rls
   1.576 +               [Rule.Calc ("HOL.eq",eval_equal "#equal_"),
   1.577 +                Rule.Thm ("not_true",TermC.num_str @{thm not_true}),
   1.578 +		(*"(~ True) = False"*)
   1.579 +		Rule.Thm ("not_false",TermC.num_str @{thm not_false}),
   1.580 +		(*"(~ False) = True"*)
   1.581 +		Rule.Thm ("and_true",TermC.num_str @{thm and_true}),
   1.582 +		(*"(?a & True) = ?a"*)
   1.583 +		Rule.Thm ("and_false",TermC.num_str @{thm and_false}),
   1.584 +		(*"(?a & False) = False"*)
   1.585 +		Rule.Thm ("or_true",TermC.num_str @{thm or_true}),
   1.586 +		(*"(?a | True) = True"*)
   1.587 +		Rule.Thm ("or_false",TermC.num_str @{thm or_false}),
   1.588 +		(*"(?a | False) = ?a"*)
   1.589 +               
   1.590 +		Rule.Thm ("rat_leq1",TermC.num_str @{thm rat_leq1}),
   1.591 +		Rule.Thm ("rat_leq2",TermC.num_str @{thm rat_leq2}),
   1.592 +		Rule.Thm ("rat_leq3",TermC.num_str @{thm rat_leq3}),
   1.593 +                Rule.Thm ("refl",TermC.num_str @{thm refl}),
   1.594 +		Rule.Thm ("order_refl",TermC.num_str @{thm order_refl}),
   1.595 +		Rule.Thm ("radd_left_cancel_le",TermC.num_str @{thm radd_left_cancel_le}),
   1.596 +		
   1.597 +		Rule.Calc ("Orderings.ord_class.less",eval_equ "#less_"),
   1.598 +		Rule.Calc ("Orderings.ord_class.less_eq",eval_equ "#less_equal_"),
   1.599 +		
   1.600 +		Rule.Calc ("Atools.ident",eval_ident "#ident_"),    
   1.601 +		Rule.Calc ("Atools.is'_const",eval_const "#is_const_"),
   1.602 +		Rule.Calc ("Atools.occurs'_in",eval_occurs_in ""),    
   1.603 +		Rule.Calc ("Tools.matches",eval_matches "")
   1.604 +		];
   1.605 +
   1.606 +*}
   1.607 +
   1.608 +ML {*
   1.609 +val Atools_crls = 
   1.610 +    Rule.append_rls "Atools_crls" Rule.e_rls
   1.611 +               [Rule.Calc ("HOL.eq",eval_equal "#equal_"),
   1.612 +                Rule.Thm ("not_true",TermC.num_str @{thm not_true}),
   1.613 +		Rule.Thm ("not_false",TermC.num_str @{thm not_false}),
   1.614 +		Rule.Thm ("and_true",TermC.num_str @{thm and_true}),
   1.615 +		Rule.Thm ("and_false",TermC.num_str @{thm and_false}),
   1.616 +		Rule.Thm ("or_true",TermC.num_str @{thm or_true}),
   1.617 +		Rule.Thm ("or_false",TermC.num_str @{thm or_false}),
   1.618 +               
   1.619 +		Rule.Thm ("rat_leq1",TermC.num_str @{thm rat_leq1}),
   1.620 +		Rule.Thm ("rat_leq2",TermC.num_str @{thm rat_leq2}),
   1.621 +		Rule.Thm ("rat_leq3",TermC.num_str @{thm rat_leq3}),
   1.622 +                Rule.Thm ("refl",TermC.num_str @{thm refl}),
   1.623 +		Rule.Thm ("order_refl",TermC.num_str @{thm order_refl}),
   1.624 +		Rule.Thm ("radd_left_cancel_le",TermC.num_str @{thm radd_left_cancel_le}),
   1.625 +		
   1.626 +		Rule.Calc ("Orderings.ord_class.less",eval_equ "#less_"),
   1.627 +		Rule.Calc ("Orderings.ord_class.less_eq",eval_equ "#less_equal_"),
   1.628 +		
   1.629 +		Rule.Calc ("Atools.ident",eval_ident "#ident_"),    
   1.630 +		Rule.Calc ("Atools.is'_const",eval_const "#is_const_"),
   1.631 +		Rule.Calc ("Atools.occurs'_in",eval_occurs_in ""),    
   1.632 +		Rule.Calc ("Tools.matches",eval_matches "")
   1.633 +		];
   1.634 +
   1.635 +(*val atools_erls = ... waere zu testen ...
   1.636 +    Rule.merge_rls calculate_Atools
   1.637 +	      (Rule.append_rls Atools_erls (*i.A. zu viele rules*)
   1.638 +			  [Rule.Calc ("Atools.ident",eval_ident "#ident_"),    
   1.639 +			   Rule.Calc ("Atools.is'_const",eval_const "#is_const_"),
   1.640 +			   Rule.Calc ("Atools.occurs'_in",
   1.641 +				 eval_occurs_in "#occurs_in"),    
   1.642 +			   Rule.Calc ("Tools.matches",eval_matches "#matches")
   1.643 +			   ] (*i.A. zu viele rules*)
   1.644 +			  );*)
   1.645 +(* val atools_erls = prep_rls'(     (*outcommented*)
   1.646 +  Rule.Rls {id="atools_erls",preconds = [], rew_ord = ("termlessI",termlessI), 
   1.647 +      erls = Rule.e_rls, srls = Rule.Erls, calc = [], errpatts = [],
   1.648 +      rules = [Rule.Thm ("refl",num_str @{thm refl}),
   1.649 +		Rule.Thm ("order_refl",num_str @{thm order_refl}),
   1.650 +		Rule.Thm ("radd_left_cancel_le",num_str @{thm radd_left_cancel_le}),
   1.651 +		Rule.Thm ("not_true",num_str @{thm not_true}),
   1.652 +		Rule.Thm ("not_false",num_str @{thm not_false}),
   1.653 +		Rule.Thm ("and_true",num_str @{thm and_true}),
   1.654 +		Rule.Thm ("and_false",num_str @{thm and_false}),
   1.655 +		Rule.Thm ("or_true",num_str @{thm or_true}),
   1.656 +		Rule.Thm ("or_false",num_str @{thm or_false}),
   1.657 +		Rule.Thm ("and_commute",num_str @{thm and_commute}),
   1.658 +		Rule.Thm ("or_commute",num_str @{thm or_commute}),
   1.659 +		
   1.660 +		Rule.Calc ("Orderings.ord_class.less",eval_equ "#less_"),
   1.661 +		Rule.Calc ("Orderings.ord_class.less_eq",eval_equ "#less_equal_"),
   1.662 +		
   1.663 +		Rule.Calc ("Atools.ident",eval_ident "#ident_"),    
   1.664 +		Rule.Calc ("Atools.is'_const",eval_const "#is_const_"),
   1.665 +		Rule.Calc ("Atools.occurs'_in",eval_occurs_in ""),    
   1.666 +		Rule.Calc ("Tools.matches",eval_matches "")
   1.667 +	       ],
   1.668 +      scr = Rule.Prog ((Thm.term_of o the o (parse @{theory})) "empty_script")
   1.669 +      });
   1.670 +*)
   1.671 +"******* Atools.ML end *******";
   1.672 +*}
   1.673 +setup {* KEStore_Elems.add_calcs
   1.674 +  [("occurs_in",("Atools.occurs'_in", eval_occurs_in "#occurs_in_")),
   1.675 +    ("some_occur_in",
   1.676 +      ("Atools.some'_occur'_in", eval_some_occur_in "#some_occur_in_")),
   1.677 +    ("is_atom"  ,("Atools.is'_atom", eval_is_atom "#is_atom_")),
   1.678 +    ("is_even"  ,("Atools.is'_even", eval_is_even "#is_even_")),
   1.679 +    ("is_const" ,("Atools.is'_const", eval_const "#is_const_")),
   1.680 +    ("le"       ,("Orderings.ord_class.less", eval_equ "#less_")),
   1.681 +    ("leq"      ,("Orderings.ord_class.less_eq", eval_equ "#less_equal_")),
   1.682 +    ("ident"    ,("Atools.ident", eval_ident "#ident_")),
   1.683 +    ("equal"    ,("HOL.eq", eval_equal "#equal_")),
   1.684 +    ("PLUS"     ,("Groups.plus_class.plus", eval_binop "#add_")),
   1.685 +    ("MINUS"    ,("Groups.minus_class.minus", eval_binop "#sub_")),
   1.686 +    ("TIMES"    ,("Groups.times_class.times", eval_binop "#mult_")),
   1.687 +    ("DIVIDE"  ,("Rings.divide_class.divide", eval_cancel "#divide_e")),
   1.688 +    ("POWER"   ,("Atools.pow", eval_binop "#power_")),
   1.689 +    ("boollist2sum",("Atools.boollist2sum", eval_boollist2sum ""))] *}
   1.690 +ML {*
   1.691 +val list_rls = LTool.prep_rls @{theory} (Rule.merge_rls "list_erls"
   1.692 +	(Rule.Rls {id = "replaced", preconds = [], rew_ord = ("termlessI", termlessI),
   1.693 +    erls = Rule.Rls {id = "list_elrs", preconds = [], rew_ord = ("termlessI", termlessI), 
   1.694 +      erls = Rule.e_rls, srls = Rule.Erls, calc = [], errpatts = [],
   1.695 +      rules = [Rule.Calc ("Groups.plus_class.plus", eval_binop "#add_"),
   1.696 +        Rule.Calc ("Orderings.ord_class.less", eval_equ "#less_")
   1.697 +        (*    ~~~~~~ for nth_Cons_*)],
   1.698 +      scr = Rule.EmptyScr},
   1.699 +    srls = Rule.Erls, calc = [], errpatts = [],
   1.700 +    rules = [], scr = Rule.EmptyScr})
   1.701 +  list_rls);
   1.702 +*}
   1.703 +setup {* KEStore_Elems.add_rlss
   1.704 +  [("list_rls", (Context.theory_name @{theory}, LTool.prep_rls @{theory} list_rls))] *}
   1.705 +
   1.706 +end