src/Tools/isac/Knowledge/Rational.thy
author Walther Neuper <neuper@ist.tugraz.at>
Mon, 16 Sep 2013 12:20:00 +0200
changeset 52105 2786cc9704c8
parent 52103 0d13f07d8e2a
child 52125 6f1d3415dc68
permissions -rwxr-xr-x
Test_Isac works again, perfectly ..

# the same tests works as in 8df4b6196660 (the *child* of "Test_Isac works...")
# ..EXCEPT those marked with "exception Div raised"
# for general state of tests see Test_Isac section {* history of tests *}.
     1 (* rationals, fractions of multivariate polynomials over the real field
     2    author: isac team
     3    Copyright (c) isac team 2002, 2013
     4    Use is subject to license terms.
     5 
     6    depends on Poly (and not on Atools), because 
     7    fractions with _normalized_ polynomials are canceled, added, etc.
     8 *)
     9 
    10 theory Rational 
    11 imports Poly "~~/src/Tools/isac/Knowledge/GCD_Poly_ML"
    12 begin
    13 
    14 section {* Constants for evaluation by "Calc" *}
    15 consts
    16 
    17   is'_expanded    :: "real => bool" ("_ is'_expanded")     (*RL->Poly.thy*)
    18   is'_ratpolyexp  :: "real => bool" ("_ is'_ratpolyexp") 
    19   get_denominator :: "real => real"
    20   get_numerator   :: "real => real"
    21 
    22 ML {*
    23 (*.the expression contains + - * ^ / only ?.*)
    24 fun is_ratpolyexp (Free _) = true
    25   | is_ratpolyexp (Const ("Groups.plus_class.plus",_) $ Free _ $ Free _) = true
    26   | is_ratpolyexp (Const ("Groups.minus_class.minus",_) $ Free _ $ Free _) = true
    27   | is_ratpolyexp (Const ("Groups.times_class.times",_) $ Free _ $ Free _) = true
    28   | is_ratpolyexp (Const ("Atools.pow",_) $ Free _ $ Free _) = true
    29   | is_ratpolyexp (Const ("Fields.inverse_class.divide",_) $ Free _ $ Free _) = true
    30   | is_ratpolyexp (Const ("Groups.plus_class.plus",_) $ t1 $ t2) = 
    31                ((is_ratpolyexp t1) andalso (is_ratpolyexp t2))
    32   | is_ratpolyexp (Const ("Groups.minus_class.minus",_) $ t1 $ t2) = 
    33                ((is_ratpolyexp t1) andalso (is_ratpolyexp t2))
    34   | is_ratpolyexp (Const ("Groups.times_class.times",_) $ t1 $ t2) = 
    35                ((is_ratpolyexp t1) andalso (is_ratpolyexp t2))
    36   | is_ratpolyexp (Const ("Atools.pow",_) $ t1 $ t2) = 
    37                ((is_ratpolyexp t1) andalso (is_ratpolyexp t2))
    38   | is_ratpolyexp (Const ("Fields.inverse_class.divide",_) $ t1 $ t2) = 
    39                ((is_ratpolyexp t1) andalso (is_ratpolyexp t2))
    40   | is_ratpolyexp _ = false;
    41 
    42 (*("is_ratpolyexp", ("Rational.is'_ratpolyexp", eval_is_ratpolyexp ""))*)
    43 fun eval_is_ratpolyexp (thmid:string) _ 
    44 		       (t as (Const("Rational.is'_ratpolyexp", _) $ arg)) thy =
    45     if is_ratpolyexp arg
    46     then SOME (mk_thmid thmid "" (term_to_string''' thy arg) "", 
    47 	         Trueprop $ (mk_equality (t, @{term True})))
    48     else SOME (mk_thmid thmid "" (term_to_string''' thy arg) "", 
    49 	         Trueprop $ (mk_equality (t, @{term False})))
    50   | eval_is_ratpolyexp _ _ _ _ = NONE; 
    51 
    52 (*("get_denominator", ("Rational.get_denominator", eval_get_denominator ""))*)
    53 fun eval_get_denominator (thmid:string) _ 
    54 		      (t as Const ("Rational.get_denominator", _) $
    55               (Const ("Fields.inverse_class.divide", _) $ num $
    56                 denom)) thy = 
    57       SOME (mk_thmid thmid "" (term_to_string''' thy denom) "", 
    58 	            Trueprop $ (mk_equality (t, denom)))
    59   | eval_get_denominator _ _ _ _ = NONE; 
    60 
    61 (*("get_numerator", ("Rational.get_numerator", eval_get_numerator ""))*)
    62 fun eval_get_numerator (thmid:string) _ 
    63       (t as Const ("Rational.get_numerator", _) $
    64           (Const ("Fields.inverse_class.divide", _) $num
    65             $denom )) thy = 
    66     SOME (mk_thmid thmid "" (term_to_string''' thy num) "", 
    67 	    Trueprop $ (mk_equality (t, num)))
    68   | eval_get_numerator _ _ _ _ = NONE; 
    69 *}
    70 
    71 section {* Theorems for rewriting *}
    72 
    73 axiomatization (* naming due to Isabelle2002, but not contained in Isabelle2002; 
    74                   many thms are due to RL and can be removed with updating the equation solver;
    75                   TODO: replace by equivalent thms in recent Isabelle201x *) 
    76 where
    77   mult_cross:      "[| b ~= 0; d ~= 0 |] ==> (a / b = c / d) = (a * d = b * c)" and
    78   mult_cross1:     "   b ~= 0            ==> (a / b = c    ) = (a     = b * c)" and
    79   mult_cross2:     "           d ~= 0    ==> (a     = c / d) = (a * d =     c)" and
    80                   
    81   add_minus:       "a + b - b = a"(*RL->Poly.thy*) and
    82   add_minus1:      "a - b + b = a"(*RL->Poly.thy*) and
    83                   
    84   rat_mult:        "a / b * (c / d) = a * c / (b * d)"(*?Isa02*)  and
    85   rat_mult2:       "a / b *  c      = a * c /  b     "(*?Isa02*) and
    86 
    87   rat_mult_poly_l: "c is_polyexp ==> c * (a / b) = c * a /  b" and
    88   rat_mult_poly_r: "c is_polyexp ==> (a / b) * c = a * c /  b" and
    89 
    90 (*real_times_divide1_eq .. Isa02*) 
    91   real_times_divide_1_eq:  "-1 * (c / d) = -1 * c / d " and
    92   real_times_divide_num:   "a is_const ==> a * (c / d) = a * c / d " and
    93 
    94   real_mult_div_cancel2:   "k ~= 0 ==> m * k / (n * k) = m / n" and
    95 (*real_mult_div_cancel1:   "k ~= 0 ==> k * m / (k * n) = m / n"..Isa02*)
    96 			  
    97   real_divide_divide1:     "y ~= 0 ==> (u / v) / (y / z) = (u / v) * (z / y)" and
    98   real_divide_divide1_mg:  "y ~= 0 ==> (u / v) / (y / z) = (u * z) / (y * v)" and
    99 (*real_divide_divide2_eq:  "x / y / z = x / (y * z)"..Isa02*)
   100 			  
   101   rat_power:               "(a / b)^^^n = (a^^^n) / (b^^^n)" and
   102 
   103   rat_add:         "[| a is_const; b is_const; c is_const; d is_const |] ==> 
   104 	           a / c + b / d = (a * d + b * c) / (c * d)" and
   105   rat_add_assoc:   "[| a is_const; b is_const; c is_const; d is_const |] ==> 
   106 	           a / c +(b / d + e) = (a * d + b * c)/(d * c) + e" and
   107   rat_add1:        "[| a is_const; b is_const; c is_const |] ==> 
   108 	           a / c + b / c = (a + b) / c" and
   109   rat_add1_assoc:   "[| a is_const; b is_const; c is_const |] ==> 
   110 	           a / c + (b / c + e) = (a + b) / c + e" and
   111   rat_add2:        "[| a is_const; b is_const; c is_const |] ==> 
   112 	           a / c + b = (a + b * c) / c" and
   113   rat_add2_assoc:  "[| a is_const; b is_const; c is_const |] ==> 
   114 	           a / c + (b + e) = (a + b * c) / c + e" and
   115   rat_add3:        "[| a is_const; b is_const; c is_const |] ==> 
   116 	           a + b / c = (a * c + b) / c" and
   117   rat_add3_assoc:   "[| a is_const; b is_const; c is_const |] ==> 
   118 	           a + (b / c + e) = (a * c + b) / c + e"
   119 
   120 section {* Cancellation and addition of fractions *}
   121 subsection {* Conversion term <--> poly *}
   122 subsubsection {* Convert a term to the internal representation of a multivariate polynomial *}
   123 ML {*
   124 fun monom_of_term  vs (c, es) (Free (id, _)) =
   125     if is_numeral id 
   126     then (id |> int_of_str |> the |> curry op * c, es) (*several numerals in one monom*)
   127     else (c, list_update es (find_index (curry op = id) vs) 1)
   128   | monom_of_term  vs (c, es) (Const ("Atools.pow", _) $ Free (id, _) $ Free (e, _)) =
   129     (c, list_update es (find_index (curry op = id) vs) (the (int_of_str e)))
   130   | monom_of_term vs (c, es) (Const ("Groups.times_class.times", _) $ m1 $ m2) =
   131     let val (c', es') = monom_of_term vs (c, es) m1
   132     in monom_of_term vs (c', es') m2 end
   133   | monom_of_term _ _ t = raise ERROR ("poly malformed with " ^ term2str t)
   134 
   135 fun monoms_of_term vs (t as Free _) =
   136     [monom_of_term  vs (1, replicate (length vs) 0) t]
   137   | monoms_of_term vs (t as Const ("Atools.pow", _) $ _ $  _) =
   138     [monom_of_term  vs (1, replicate (length vs) 0) t]
   139   | monoms_of_term vs (t as Const ("Groups.times_class.times", _) $ _ $  _) =
   140     [monom_of_term  vs (1, replicate (length vs) 0) t]
   141   | monoms_of_term vs (Const ("Groups.plus_class.plus", _) $ ms1 $ ms2) =
   142     (monoms_of_term vs ms1) @ (monoms_of_term vs ms2)
   143   | monoms_of_term _ t = raise ERROR ("poly malformed with " ^ term2str t)
   144 
   145 (* convert a term to the internal representation of a multivariate polynomial;
   146   the conversion is quite liberal, see test --- fun poly_of_term ---:
   147 * the order of variables and the parentheses within a monomial are arbitrary
   148 * the coefficient may be somewhere
   149 * he order and the parentheses within monomials are arbitrary
   150 But the term must be completely expand + over * (laws of distributivity are not applicable).
   151 
   152 The function requires the free variables as strings already given, 
   153 because the gcd involves 2 polynomials (with the same length for their list of exponents).
   154 *)
   155 fun poly_of_term vs (t as Const ("Groups.plus_class.plus", _) $ _ $ _) =
   156     (SOME (t |> monoms_of_term vs |> order)
   157       handle ERROR _ => NONE)
   158   | poly_of_term vs t =
   159     (SOME [monom_of_term vs (1, replicate (length vs) 0) t]
   160       handle ERROR _ => NONE)
   161 
   162 fun is_poly t =
   163   let 
   164     val vs = t |> vars |> map str_of_free_opt (* tolerate Var in simplification *)
   165       |> filter is_some |> map the |> sort string_ord
   166   in 
   167     case poly_of_term vs t of SOME _ => true | NONE => false
   168   end
   169 val is_expanded = is_poly   (* TODO: check names *)
   170 val is_polynomial = is_poly (* TODO: check names *)
   171 *}
   172 
   173 subsubsection {* Convert internal representation of a multivariate polynomial to a term *}
   174 ML {*
   175 fun term_of_es _ _ _ [] = [] (*assumes same length for vs and es*)
   176   | term_of_es baseT expT (_ :: vs) (0 :: es) =
   177     [] @ term_of_es baseT expT vs es
   178   | term_of_es baseT expT (v :: vs) (1 :: es) =
   179     [(Free (v, baseT))] @ term_of_es baseT expT vs es
   180   | term_of_es baseT expT (v :: vs) (e :: es) =
   181     [Const ("Atools.pow", [baseT, expT] ---> baseT) $ 
   182       (Free (v, baseT)) $  (Free (isastr_of_int e, expT))]
   183     @ term_of_es baseT expT vs es
   184 
   185 fun term_of_monom baseT expT vs ((c, es): monom) =
   186     let val es' = term_of_es baseT expT vs es
   187     in 
   188       if c = 1 
   189       then 
   190         if es' = [] (*if es = [0,0,0,...]*)
   191         then Free (isastr_of_int c, baseT)
   192         else foldl (HOLogic.mk_binop "Groups.times_class.times") (hd es', tl es')
   193       else foldl (HOLogic.mk_binop "Groups.times_class.times") (Free (isastr_of_int c, baseT), es') 
   194     end
   195 
   196 fun term_of_poly baseT expT vs p =
   197   let val monos = map (term_of_monom baseT expT vs) p
   198   in foldl (HOLogic.mk_binop "Groups.plus_class.plus") (hd monos, tl monos) end
   199 *}
   200 
   201 subsection {* Apply gcd_poly for cancelling and adding fractions as terms *}
   202 ML {*
   203 fun mk_noteq_0 baseT t = 
   204   Const ("HOL.Not", HOLogic.boolT --> HOLogic.boolT) $ 
   205     (Const ("HOL.eq", [baseT, baseT] ---> HOLogic.boolT) $ t $ Free ("0", HOLogic.realT))
   206 
   207 fun mk_asms baseT ts =
   208   let val as' = filter_out is_num ts (* asm like "2 ~= 0" is needless *)
   209   in map (mk_noteq_0 baseT) as' end
   210 *}
   211 
   212 subsubsection {* Factor out gcd for cancellation *}
   213 ML {*
   214 fun check_fraction t =
   215   let val Const ("Fields.inverse_class.divide", _) $ numerator $ denominator = t
   216   in SOME (numerator, denominator) end
   217   handle Bind => NONE
   218 
   219 (* prepare a term for cancellation by factoring out the gcd
   220   assumes: is a fraction with outmost "/"*)
   221 fun factout_p_ (thy: theory) t =
   222   let val opt = check_fraction t
   223   in
   224     case opt of 
   225       NONE => NONE
   226     | SOME (numerator, denominator) =>
   227       let 
   228         val vs = t |> vars |> map str_of_free_opt (* tolerate Var in simplification *)
   229           |> filter is_some |> map the |> sort string_ord
   230         val baseT = type_of numerator
   231         val expT = HOLogic.realT
   232       in
   233         case (poly_of_term vs numerator, poly_of_term vs denominator) of
   234           (SOME a, SOME b) =>
   235             let
   236               val ((a', b'), c) = gcd_poly a b
   237               val es = replicate (length vs) 0 
   238             in
   239               if c = [(1, es)] orelse c = [(~1, es)]
   240               then NONE
   241               else 
   242                 let
   243                   val b't = term_of_poly baseT expT vs b'
   244                   val ct = term_of_poly baseT expT vs c
   245                   val t' = 
   246                     HOLogic.mk_binop "Fields.inverse_class.divide" 
   247                       (HOLogic.mk_binop "Groups.times_class.times"
   248                         (term_of_poly baseT expT vs a', ct),
   249                        HOLogic.mk_binop "Groups.times_class.times" (b't, ct))
   250                 in SOME (t', mk_asms baseT [b't, ct]) end
   251             end
   252         | _ => NONE : (term * term list) option
   253       end
   254   end
   255 *}
   256 
   257 subsubsection {* Cancel a fraction *}
   258 ML {*
   259 (* cancel a term by the gcd ("" denote terms with internal algebraic structure)
   260   cancel_p_ :: theory \<Rightarrow> term  \<Rightarrow> (term \<times> term list) option
   261   cancel_p_ thy "a / b" = SOME ("a' / b'", ["b' \<noteq> 0"])
   262   assumes: a is_polynomial  \<and>  b is_polynomial  \<and>  b \<noteq> 0
   263   yields
   264     SOME ("a' / b'", ["b' \<noteq> 0"]). gcd_poly a b \<noteq> 1  \<and>  gcd_poly a b \<noteq> -1  \<and>  
   265       a' * gcd_poly a b = a  \<and>  b' * gcd_poly a b = b
   266     \<or> NONE *)
   267 fun cancel_p_ (_: theory) t =
   268   let val opt = check_fraction t
   269   in
   270     case opt of 
   271       NONE => NONE
   272     | SOME (numerator, denominator) =>
   273       let 
   274         val vs = t |> vars |> map str_of_free_opt (* tolerate Var in simplification *)
   275           |> filter is_some |> map the |> sort string_ord
   276         val baseT = type_of numerator
   277         val expT = HOLogic.realT
   278       in
   279         case (poly_of_term vs numerator, poly_of_term vs denominator) of
   280           (SOME a, SOME b) =>
   281             let
   282               val ((a', b'), c) = gcd_poly a b
   283               val es = replicate (length vs) 0 
   284             in
   285               if c = [(1, es)] orelse c = [(~1, es)]
   286               then NONE
   287               else 
   288                 let
   289                   val bt' = term_of_poly baseT expT vs b'
   290                   val ct = term_of_poly baseT expT vs c
   291                   val t' = 
   292                     HOLogic.mk_binop "Fields.inverse_class.divide" 
   293                       (term_of_poly baseT expT vs a', bt')
   294                   val asm = mk_asms baseT [bt']
   295                 in SOME (t', asm) end
   296             end
   297         | _ => NONE : (term * term list) option
   298       end
   299   end
   300 *}
   301 
   302 subsubsection {* Factor out to a common denominator for addition *}
   303 ML {*
   304 (* addition of fractions allows (at most) one non-fraction (a monomial) *)
   305 fun check_frac_sum 
   306     (Const ("Groups.plus_class.plus", _) $ 
   307       (Const ("Fields.inverse_class.divide", _) $ n1 $ d1) $
   308       (Const ("Fields.inverse_class.divide", _) $ n2 $ d2))
   309     = SOME ((n1, d1), (n2, d2))
   310   | check_frac_sum 
   311     (Const ("Groups.plus_class.plus", _) $ 
   312       nofrac $ 
   313       (Const ("Fields.inverse_class.divide", _) $ n2 $ d2))
   314     = SOME ((nofrac, Free ("1", HOLogic.realT)), (n2, d2))
   315   | check_frac_sum 
   316     (Const ("Groups.plus_class.plus", _) $ 
   317       (Const ("Fields.inverse_class.divide", _) $ n1 $ d1) $ 
   318       nofrac)
   319     = SOME ((n1, d1), (nofrac, Free ("1", HOLogic.realT)))
   320   | check_frac_sum _ = NONE  
   321 
   322 (* prepare a term for addition by providing the least common denominator as a product
   323   assumes: is a term with outmost "+" and at least one outmost "/" in respective summands*)
   324 fun common_nominator_p_ (_: theory) t =
   325   let val opt = check_frac_sum t
   326   in
   327     case opt of 
   328       NONE => NONE
   329     | SOME ((n1, d1), (n2, d2)) =>
   330       let 
   331         val vs = t |> vars |> map str_of_free_opt (* tolerate Var in simplification *)
   332           |> filter is_some |> map the |> sort string_ord
   333       in
   334         case (poly_of_term vs d1, poly_of_term vs d2) of
   335           (SOME a, SOME b) =>
   336             let
   337               val ((a', b'), c) = gcd_poly a b
   338               val (baseT, expT) = (type_of n1, HOLogic.realT)
   339               val [d1', d2', c'] = map (term_of_poly baseT expT vs) [a', b', c]
   340               (*----- minimum of parentheses & nice result, but breaks tests: -------------
   341               val denom = HOLogic.mk_binop "Groups.times_class.times" 
   342                 (HOLogic.mk_binop "Groups.times_class.times" (d1', d2'), c') -------------*)
   343               val denom =
   344                 if c = [(1, replicate (length vs) 0)]
   345                 then HOLogic.mk_binop "Groups.times_class.times" (d1', d2')
   346                 else
   347                   HOLogic.mk_binop "Groups.times_class.times" (c',
   348                   HOLogic.mk_binop "Groups.times_class.times" (d1', d2')) (*--------------*)
   349               val t' =
   350                 HOLogic.mk_binop "Groups.plus_class.plus"
   351                   (HOLogic.mk_binop "Fields.inverse_class.divide"
   352                     (HOLogic.mk_binop "Groups.times_class.times" (n1, d2'), denom),
   353                   HOLogic.mk_binop "Fields.inverse_class.divide" 
   354                     (HOLogic.mk_binop "Groups.times_class.times" (n2, d1'), denom))
   355               val asm = mk_asms baseT [d1', d2', c']
   356             in SOME (t', asm) end
   357         | _ => NONE : (term * term list) option
   358       end
   359   end
   360 
   361 *}
   362 
   363 subsubsection {* Addition of at least one fraction within a sum *}
   364 ML {*
   365 (* add fractions
   366   assumes: is a term with outmost "+" and at least one outmost "/" in respective summands
   367   NOTE: the case "(_ + _) + _" need not be considered due to iterated addition.*)
   368 fun add_fraction_p_ (_: theory) t =
   369   case check_frac_sum t of 
   370     NONE => NONE
   371   | SOME ((n1, d1), (n2, d2)) =>
   372     let 
   373       val vs = t |> vars |> map str_of_free_opt (* tolerate Var in simplification *)
   374         |> filter is_some |> map the |> sort string_ord
   375     in
   376       case (poly_of_term vs n1, poly_of_term vs d1, poly_of_term vs n2, poly_of_term vs d2) of
   377         (SOME _, SOME a, SOME _, SOME b) =>
   378           let
   379             val ((a', b'), c) = gcd_poly a b
   380             val (baseT, expT) = (type_of n1, HOLogic.realT)
   381             val nomin = term_of_poly baseT expT vs 
   382               (((the (poly_of_term vs n1)) %%*%% b') %%+%% ((the (poly_of_term vs n2)) %%*%% a')) 
   383             val denom = term_of_poly baseT expT vs ((c %%*%% a') %%*%% b')
   384             val t' = HOLogic.mk_binop "Fields.inverse_class.divide" (nomin, denom)
   385           in SOME (t', mk_asms baseT [denom]) end
   386       | _ => NONE : (term * term list) option
   387     end
   388 *}
   389 
   390 section {* Embed cancellation and addition into rewriting *}
   391 ML {* val thy = @{theory} *}
   392 subsection {* Rulesets and predicate for embedding *}
   393 ML {*
   394 (* evaluates conditions in calculate_Rational *)
   395 val calc_rat_erls =
   396   prep_rls
   397     (Rls {id = "calc_rat_erls", preconds = [], rew_ord = ("dummy_ord", dummy_ord), 
   398       erls = e_rls, srls = Erls, calc = [], errpatts = [],
   399       rules = 
   400         [Calc ("HOL.eq", eval_equal "#equal_"),
   401         Calc ("Atools.is'_const", eval_const "#is_const_"),
   402         Thm ("not_true", num_str @{thm not_true}),
   403         Thm ("not_false", num_str @{thm not_false})], 
   404       scr = EmptyScr});
   405 
   406 (* simplifies expressions with numerals;
   407    does NOT rearrange the term by AC-rewriting; thus terms with variables 
   408    need to have constants to be commuted together respectively           *)
   409 val calculate_Rational =
   410   prep_rls (merge_rls "calculate_Rational"
   411     (Rls {id = "divide", preconds = [], rew_ord = ("dummy_ord", dummy_ord), 
   412       erls = calc_rat_erls, srls = Erls,
   413       calc = [], errpatts = [],
   414       rules = 
   415         [Calc ("Fields.inverse_class.divide", eval_cancel "#divide_e"),
   416 
   417         Thm ("minus_divide_left", num_str (@{thm minus_divide_left} RS @{thm sym})),
   418           (*SYM - ?x / ?y = - (?x / ?y)  may come from subst*)
   419         Thm ("rat_add", num_str @{thm rat_add}),
   420           (*"[| a is_const; b is_const; c is_const; d is_const |] ==> \
   421           \a / c + b / d = (a * d) / (c * d) + (b * c ) / (d * c)"*)
   422         Thm ("rat_add1", num_str @{thm rat_add1}),
   423           (*"[| a is_const; b is_const; c is_const |] ==> a / c + b / c = (a + b) / c"*)
   424         Thm ("rat_add2", num_str @{thm rat_add2}),
   425           (*"[| ?a is_const; ?b is_const; ?c is_const |] ==> ?a / ?c + ?b = (?a + ?b * ?c) / ?c"*)
   426         Thm ("rat_add3", num_str @{thm rat_add3}),
   427           (*"[| a is_const; b is_const; c is_const |] ==> a + b / c = (a * c) / c + b / c"\
   428           .... is_const to be omitted here FIXME*)
   429         
   430         Thm ("rat_mult", num_str @{thm rat_mult}), 
   431           (*a / b * (c / d) = a * c / (b * d)*)
   432         Thm ("times_divide_eq_right", num_str @{thm times_divide_eq_right}),
   433           (*?x * (?y / ?z) = ?x * ?y / ?z*)
   434         Thm ("times_divide_eq_left", num_str @{thm times_divide_eq_left}),
   435           (*?y / ?z * ?x = ?y * ?x / ?z*)
   436         
   437         Thm ("real_divide_divide1", num_str @{thm real_divide_divide1}),
   438           (*"?y ~= 0 ==> ?u / ?v / (?y / ?z) = ?u / ?v * (?z / ?y)"*)
   439         Thm ("divide_divide_eq_left", num_str @{thm divide_divide_eq_left}),
   440           (*"?x / ?y / ?z = ?x / (?y * ?z)"*)
   441         
   442         Thm ("rat_power", num_str @{thm rat_power}),
   443           (*"(?a / ?b) ^^^ ?n = ?a ^^^ ?n / ?b ^^^ ?n"*)
   444         
   445         Thm ("mult_cross", num_str @{thm mult_cross}),
   446           (*"[| b ~= 0; d ~= 0 |] ==> (a / b = c / d) = (a * d = b * c)*)
   447         Thm ("mult_cross1", num_str @{thm mult_cross1}),
   448           (*"   b ~= 0            ==> (a / b = c    ) = (a     = b * c)*)
   449         Thm ("mult_cross2", num_str @{thm mult_cross2})
   450           (*"           d ~= 0    ==> (a     = c / d) = (a * d =     c)*)], 
   451       scr = EmptyScr})
   452     calculate_Poly);
   453 
   454 (*("is_expanded", ("Rational.is'_expanded", eval_is_expanded ""))*)
   455 fun eval_is_expanded (thmid:string) _ 
   456 		       (t as (Const("Rational.is'_expanded", _) $ arg)) thy = 
   457     if is_expanded arg
   458     then SOME (mk_thmid thmid "" (term_to_string''' thy arg) "", 
   459 	         Trueprop $ (mk_equality (t, @{term True})))
   460     else SOME (mk_thmid thmid "" (term_to_string''' thy arg) "", 
   461 	         Trueprop $ (mk_equality (t, @{term False})))
   462   | eval_is_expanded _ _ _ _ = NONE; 
   463 
   464 calclist':= overwritel (!calclist', 
   465    [("is_expanded", ("Rational.is'_expanded", eval_is_expanded ""))]);
   466 
   467 val rational_erls = 
   468   merge_rls "rational_erls" calculate_Rational 
   469     (append_rls "is_expanded" Atools_erls 
   470       [Calc ("Rational.is'_expanded", eval_is_expanded "")]);
   471 *}
   472 
   473 subsection {* Embed cancellation into rewriting *}
   474 ML {*
   475 local (* cancel_p *)
   476 
   477 val {rules = rules, rew_ord = (_, ro), ...} = rep_rls (assoc_rls "rev_rew_p");
   478 
   479 fun init_state thy eval_rls ro t =
   480   let
   481     val SOME (t', _) = factout_p_ thy t;
   482     val SOME (t'', asm) = cancel_p_ thy t;
   483     val der = reverse_deriv thy eval_rls rules ro NONE t';
   484     val der = der @ 
   485       [(Thm ("real_mult_div_cancel2", num_str @{thm real_mult_div_cancel2}), (t'', asm))]
   486     val rs = (distinct_Thm o (map #1)) der
   487   	val rs = filter_out (eq_Thms 
   488   	  ["sym_real_add_zero_left", "sym_real_mult_0", "sym_real_mult_1"]) rs
   489   in (t, t'', [rs(*one in order to ease locate_rule*)], der) end;
   490 
   491 fun locate_rule thy eval_rls ro [rs] t r =
   492     if member op = ((map (id_of_thm)) rs) (id_of_thm r)
   493     then 
   494       let val ropt = rewrite_ thy ro eval_rls true (thm_of_thm r) t;
   495       in
   496         case ropt of SOME ta => [(r, ta)]
   497 	      | NONE => (tracing 
   498 	          ("### locate_rule:  rewrite " ^ id_of_thm r ^ " " ^ term2str t ^ " = NONE"); []) 
   499 			end
   500     else (tracing ("### locate_rule:  " ^ id_of_thm r ^ " not mem rrls"); [])
   501   | locate_rule _ _ _ _ _ _ = error "locate_rule: doesnt match rev-sets in istate";
   502 
   503 fun next_rule thy eval_rls ro [rs] t =
   504     let
   505       val der = make_deriv thy eval_rls rs ro NONE t;
   506     in case der of (_, r, _) :: _ => SOME r | _ => NONE end
   507   | next_rule _ _ _ _ _ = error ("next_rule: doesnt match rev-sets in istate");
   508 
   509 fun attach_form (_:rule list list) (_:term) (_:term) = 
   510   [(*TODO*)]: (rule * (term * term list)) list;
   511 
   512 in
   513 
   514 val cancel_p = 
   515   Rrls {id = "cancel_p", prepat = [],
   516 	rew_ord=("ord_make_polynomial", ord_make_polynomial false thy),
   517 	erls = rational_erls, 
   518 	calc = 
   519 	  [("PLUS", ("Groups.plus_class.plus", eval_binop "#add_")),
   520 	  ("TIMES" , ("Groups.times_class.times", eval_binop "#mult_")),
   521 	  ("DIVIDE", ("Fields.inverse_class.divide", eval_cancel "#divide_e")),
   522 	  ("POWER", ("Atools.pow", eval_binop "#power_"))],
   523     errpatts = [],
   524 	scr =
   525 	  Rfuns {init_state  = init_state thy Atools_erls ro,
   526 		normal_form = cancel_p_ thy, 
   527 		locate_rule = locate_rule thy Atools_erls ro,
   528 		next_rule   = next_rule thy Atools_erls ro,
   529 		attach_form = attach_form}}
   530 end; (* local cancel_p *)
   531 *}
   532 
   533 subsection {* Embed addition into rewriting *}
   534 ML {*
   535 local (* add_fractions_p *)
   536 
   537 val {rules = rules, rew_ord = (_, ro), ...} = rep_rls (assoc_rls "make_polynomial");
   538 val {rules, rew_ord=(_,ro),...} = rep_rls (assoc_rls "rev_rew_p");
   539 
   540 fun init_state thy eval_rls ro t =
   541   let 
   542     val SOME (t',_) = common_nominator_p_ thy t;
   543     val SOME (t'', asm) = add_fraction_p_ thy t;
   544     val der = reverse_deriv thy eval_rls rules ro NONE t';
   545     val der = der @ 
   546       [(Thm ("real_mult_div_cancel2", num_str @{thm real_mult_div_cancel2}), (t'',asm))]
   547     val rs = (distinct_Thm o (map #1)) der;
   548     val rs = filter_out (eq_Thms 
   549       ["sym_real_add_zero_left", "sym_real_mult_0", "sym_real_mult_1"]) rs;
   550   in (t, t'', [rs(*here only _ONE_*)], der) end;
   551 
   552 fun locate_rule thy eval_rls ro [rs] t r =
   553     if member op = ((map (id_of_thm)) rs) (id_of_thm r)
   554     then 
   555       let val ropt = rewrite_ thy ro eval_rls true (thm_of_thm r) t;
   556       in 
   557         case ropt of
   558           SOME ta => [(r, ta)]
   559 	      | NONE => 
   560 	        (tracing ("### locate_rule:  rewrite " ^ id_of_thm r ^ " " ^ term2str t ^ " = NONE");
   561 	        []) end
   562     else (tracing ("### locate_rule:  " ^ id_of_thm r ^ " not mem rrls"); [])
   563   | locate_rule _ _ _ _ _ _ = error "locate_rule: doesnt match rev-sets in istate";
   564 
   565 fun next_rule thy eval_rls ro [rs] t =
   566     let val der = make_deriv thy eval_rls rs ro NONE t;
   567     in 
   568       case der of
   569 	      (_,r,_)::_ => SOME r
   570 	    | _ => NONE
   571     end
   572   | next_rule _ _ _ _ _ = error ("next_rule: doesnt match rev-sets in istate");
   573 
   574 val pat0 = parse_patt thy "?r/?s+?u/?v :: real";
   575 val pat1 = parse_patt thy "?r/?s+?u    :: real";
   576 val pat2 = parse_patt thy "?r   +?u/?v :: real";
   577 val prepat = [([@{term True}], pat0),
   578 	      ([@{term True}], pat1),
   579 	      ([@{term True}], pat2)];
   580 in
   581 
   582 val add_fractions_p =
   583   Rrls {id = "add_fractions_p", prepat=prepat,
   584     rew_ord = ("ord_make_polynomial", ord_make_polynomial false thy),
   585     erls = rational_erls,
   586     calc = [("PLUS", ("Groups.plus_class.plus", eval_binop "#add_")),
   587       ("TIMES", ("Groups.times_class.times", eval_binop "#mult_")),
   588       ("DIVIDE", ("Fields.inverse_class.divide", eval_cancel "#divide_e")),
   589       ("POWER", ("Atools.pow", eval_binop "#power_"))],
   590     errpatts = [],
   591     scr = Rfuns {init_state  = init_state thy Atools_erls ro,
   592       normal_form = add_fraction_p_ thy,
   593       locate_rule = locate_rule thy Atools_erls ro,
   594       next_rule   = next_rule thy Atools_erls ro,
   595       attach_form = attach_form}}
   596 end; (*local add_fractions_p *)
   597 *}
   598 
   599 subsection {* Cancelling and adding all occurrences in a term /////////////////////////////*}
   600 ML {*
   601 (*copying cancel_p_rls + add her caused error in interface.sml*)
   602 *}
   603 
   604 section {* Rulesets for general simplification *}
   605 ML {* 
   606 
   607 (*-------------------18.3.03 --> struct <-----------vvv--
   608 val add_fractions_p = common_nominator_p; (*FIXXXME:eilig f"ur norm_Rational*)
   609  -------------------18.3.03 --> struct <-----------vvv--*)
   610 
   611 (*erls for calculate_Rational; make local with FIXX@ME result:term *term list*)
   612 val powers_erls = prep_rls(
   613   Rls {id = "powers_erls", preconds = [], rew_ord = ("dummy_ord",dummy_ord), 
   614       erls = e_rls, srls = Erls, calc = [], errpatts = [],
   615       rules = [Calc ("Atools.is'_atom",eval_is_atom "#is_atom_"),
   616 	       Calc ("Atools.is'_even",eval_is_even "#is_even_"),
   617 	       Calc ("Orderings.ord_class.less",eval_equ "#less_"),
   618 	       Thm ("not_false", num_str @{thm not_false}),
   619 	       Thm ("not_true", num_str @{thm not_true}),
   620 	       Calc ("Groups.plus_class.plus",eval_binop "#add_")
   621 	       ],
   622       scr = EmptyScr
   623       }:rls);
   624 (*.all powers over + distributed; atoms over * collected, other distributed
   625    contains absolute minimum of thms for context in norm_Rational .*)
   626 val powers = prep_rls(
   627   Rls {id = "powers", preconds = [], rew_ord = ("dummy_ord",dummy_ord), 
   628       erls = powers_erls, srls = Erls, calc = [], errpatts = [],
   629       rules = [Thm ("realpow_multI", num_str @{thm realpow_multI}),
   630 	       (*"(r * s) ^^^ n = r ^^^ n * s ^^^ n"*)
   631 	       Thm ("realpow_pow",num_str @{thm realpow_pow}),
   632 	       (*"(a ^^^ b) ^^^ c = a ^^^ (b * c)"*)
   633 	       Thm ("realpow_oneI",num_str @{thm realpow_oneI}),
   634 	       (*"r ^^^ 1 = r"*)
   635 	       Thm ("realpow_minus_even",num_str @{thm realpow_minus_even}),
   636 	       (*"n is_even ==> (- r) ^^^ n = r ^^^ n" ?-->discard_minus?*)
   637 	       Thm ("realpow_minus_odd",num_str @{thm realpow_minus_odd}),
   638 	       (*"Not (n is_even) ==> (- r) ^^^ n = -1 * r ^^^ n"*)
   639 	       
   640 	       (*----- collect atoms over * -----*)
   641 	       Thm ("realpow_two_atom",num_str @{thm realpow_two_atom}),	
   642 	       (*"r is_atom ==> r * r = r ^^^ 2"*)
   643 	       Thm ("realpow_plus_1",num_str @{thm realpow_plus_1}),		
   644 	       (*"r is_atom ==> r * r ^^^ n = r ^^^ (n + 1)"*)
   645 	       Thm ("realpow_addI_atom",num_str @{thm realpow_addI_atom}),
   646 	       (*"r is_atom ==> r ^^^ n * r ^^^ m = r ^^^ (n + m)"*)
   647 
   648 	       (*----- distribute none-atoms -----*)
   649 	       Thm ("realpow_def_atom",num_str @{thm realpow_def_atom}),
   650 	       (*"[| 1 < n; not(r is_atom) |]==>r ^^^ n = r * r ^^^ (n + -1)"*)
   651 	       Thm ("realpow_eq_oneI",num_str @{thm realpow_eq_oneI}),
   652 	       (*"1 ^^^ n = 1"*)
   653 	       Calc ("Groups.plus_class.plus",eval_binop "#add_")
   654 	       ],
   655       scr = EmptyScr
   656       }:rls);
   657 (*.contains absolute minimum of thms for context in norm_Rational.*)
   658 val rat_mult_divide = prep_rls(
   659   Rls {id = "rat_mult_divide", preconds = [], 
   660       rew_ord = ("dummy_ord", dummy_ord), 
   661       erls = e_rls, srls = Erls, calc = [], errpatts = [],
   662       rules = [Thm ("rat_mult",num_str @{thm rat_mult}),
   663 	       (*(1)"?a / ?b * (?c / ?d) = ?a * ?c / (?b * ?d)"*)
   664 	       Thm ("times_divide_eq_right",num_str @{thm times_divide_eq_right}),
   665 	       (*(2)"?a * (?c / ?d) = ?a * ?c / ?d" must be [2],
   666 	       otherwise inv.to a / b / c = ...*)
   667 	       Thm ("times_divide_eq_left",num_str @{thm times_divide_eq_left}),
   668 	       (*"?a / ?b * ?c = ?a * ?c / ?b" order weights x^^^n too much
   669 		     and does not commute a / b * c ^^^ 2 !*)
   670 	       
   671 	       Thm ("divide_divide_eq_right", 
   672                      num_str @{thm divide_divide_eq_right}),
   673 	       (*"?x / (?y / ?z) = ?x * ?z / ?y"*)
   674 	       Thm ("divide_divide_eq_left",
   675                      num_str @{thm divide_divide_eq_left}),
   676 	       (*"?x / ?y / ?z = ?x / (?y * ?z)"*)
   677 	       Calc ("Fields.inverse_class.divide"  ,eval_cancel "#divide_e")
   678 	       ],
   679       scr = EmptyScr
   680       }:rls);
   681 
   682 (*.contains absolute minimum of thms for context in norm_Rational.*)
   683 val reduce_0_1_2 = prep_rls(
   684   Rls{id = "reduce_0_1_2", preconds = [], rew_ord = ("dummy_ord", dummy_ord),
   685       erls = e_rls, srls = Erls, calc = [], errpatts = [],
   686       rules = [(*Thm ("divide_1",num_str @{thm divide_1}),
   687 		 "?x / 1 = ?x" unnecess.for normalform*)
   688 	       Thm ("mult_1_left",num_str @{thm mult_1_left}),                 
   689 	       (*"1 * z = z"*)
   690 	       (*Thm ("real_mult_minus1",num_str @{thm real_mult_minus1}),
   691 	       "-1 * z = - z"*)
   692 	       (*Thm ("real_minus_mult_cancel",num_str @{thm real_minus_mult_cancel}),
   693 	       "- ?x * - ?y = ?x * ?y"*)
   694 
   695 	       Thm ("mult_zero_left",num_str @{thm mult_zero_left}),        
   696 	       (*"0 * z = 0"*)
   697 	       Thm ("add_0_left",num_str @{thm add_0_left}),
   698 	       (*"0 + z = z"*)
   699 	       (*Thm ("right_minus",num_str @{thm right_minus}),
   700 	       "?z + - ?z = 0"*)
   701 
   702 	       Thm ("sym_real_mult_2",
   703                      num_str (@{thm real_mult_2} RS @{thm sym})),	
   704 	       (*"z1 + z1 = 2 * z1"*)
   705 	       Thm ("real_mult_2_assoc",num_str @{thm real_mult_2_assoc}),
   706 	       (*"z1 + (z1 + k) = 2 * z1 + k"*)
   707 
   708 	       Thm ("divide_zero_left",num_str @{thm divide_zero_left})
   709 	       (*"0 / ?x = 0"*)
   710 	       ], scr = EmptyScr}:rls);
   711 
   712 (*erls for calculate_Rational; 
   713   make local with FIXX@ME result:term *term list WN0609???SKMG*)
   714 val norm_rat_erls = prep_rls(
   715   Rls {id = "norm_rat_erls", preconds = [], rew_ord = ("dummy_ord",dummy_ord), 
   716       erls = e_rls, srls = Erls, calc = [], errpatts = [],
   717       rules = [Calc ("Atools.is'_const",eval_const "#is_const_")
   718 	       ], scr = EmptyScr}:rls);
   719 
   720 (* consists of rls containing the absolute minimum of thms *)
   721 (*040209: this version has been used by RL for his equations,
   722 which is now replaced by MGs version "norm_Rational" below *)
   723 val norm_Rational_min = prep_rls(
   724   Rls {id = "norm_Rational_min", preconds = [], rew_ord = ("dummy_ord",dummy_ord), 
   725       erls = norm_rat_erls, srls = Erls, calc = [], errpatts = [],
   726       rules = [(*sequence given by operator precedence*)
   727 	       Rls_ discard_minus,
   728 	       Rls_ powers,
   729 	       Rls_ rat_mult_divide,
   730 	       Rls_ expand,
   731 	       Rls_ reduce_0_1_2,
   732 	       Rls_ order_add_mult,
   733 	       Rls_ collect_numerals,
   734 	       Rls_ add_fractions_p,
   735 	       Rls_ cancel_p
   736 	       ],
   737       scr = EmptyScr}:rls);
   738 
   739 val norm_Rational_parenthesized = prep_rls(
   740   Seq {id = "norm_Rational_parenthesized", preconds = []:term list, 
   741        rew_ord = ("dummy_ord", dummy_ord),
   742       erls = Atools_erls, srls = Erls,
   743       calc = [], errpatts = [],
   744       rules = [Rls_  norm_Rational_min,
   745 	       Rls_ discard_parentheses
   746 	       ],
   747       scr = EmptyScr}:rls);      
   748 
   749 (*WN030318???SK: simplifies all but cancel and common_nominator*)
   750 val simplify_rational = 
   751     merge_rls "simplify_rational" expand_binoms
   752     (append_rls "divide" calculate_Rational
   753 		[Thm ("divide_1",num_str @{thm divide_1}),
   754 		 (*"?x / 1 = ?x"*)
   755 		 Thm ("rat_mult",num_str @{thm rat_mult}),
   756 		 (*(1)"?a / ?b * (?c / ?d) = ?a * ?c / (?b * ?d)"*)
   757 		 Thm ("times_divide_eq_right",num_str @{thm times_divide_eq_right}),
   758 		 (*(2)"?a * (?c / ?d) = ?a * ?c / ?d" must be [2],
   759 		 otherwise inv.to a / b / c = ...*)
   760 		 Thm ("times_divide_eq_left",num_str @{thm times_divide_eq_left}),
   761 		 (*"?a / ?b * ?c = ?a * ?c / ?b"*)
   762 		 Thm ("add_minus",num_str @{thm add_minus}),
   763 		 (*"?a + ?b - ?b = ?a"*)
   764 		 Thm ("add_minus1",num_str @{thm add_minus1}),
   765 		 (*"?a - ?b + ?b = ?a"*)
   766 		 Thm ("divide_minus1",num_str @{thm divide_minus1})
   767 		 (*"?x / -1 = - ?x"*)
   768 		 ]);
   769 *}
   770 ML {* 
   771 val add_fractions_p_rls = prep_rls(
   772   Rls {id = "add_fractions_p_rls", preconds = [], rew_ord = ("dummy_ord", dummy_ord), 
   773 	  erls = e_rls, srls = Erls, calc = [], errpatts = [],
   774 	  rules = [Rls_ add_fractions_p], 
   775 	  scr = EmptyScr});
   776 
   777 (* "Rls" causes repeated application of cancel_p to one and the same term *)
   778 val cancel_p_rls = prep_rls(
   779   Rls 
   780     {id = "cancel_p_rls", preconds = [], rew_ord = ("dummy_ord", dummy_ord), 
   781     erls = e_rls, srls = Erls, calc = [], errpatts = [],
   782     rules = [Rls_ cancel_p], 
   783 	  scr = EmptyScr});
   784 
   785 (*. makes 'normal' fractions; 'is_polyexp' inhibits double fractions;
   786     used in initial part norm_Rational_mg, see example DA-M02-main.p.60.*)
   787 val rat_mult_poly = prep_rls(
   788   Rls {id = "rat_mult_poly", preconds = [], rew_ord = ("dummy_ord", dummy_ord), 
   789 	  erls = append_rls "e_rls-is_polyexp" e_rls [Calc ("Poly.is'_polyexp", eval_is_polyexp "")], 
   790 	  srls = Erls, calc = [], errpatts = [],
   791 	  rules = 
   792 	    [Thm ("rat_mult_poly_l",num_str @{thm rat_mult_poly_l}),
   793 	    (*"?c is_polyexp ==> ?c * (?a / ?b) = ?c * ?a / ?b"*)
   794 	    Thm ("rat_mult_poly_r",num_str @{thm rat_mult_poly_r})
   795 	    (*"?c is_polyexp ==> ?a / ?b * ?c = ?a * ?c / ?b"*) ], 
   796 	  scr = EmptyScr});
   797 
   798 (*. makes 'normal' fractions; 'is_polyexp' inhibits double fractions;
   799     used in looping part norm_Rational_rls, see example DA-M02-main.p.60 
   800     .. WHERE THE LATTER DOES ALWAYS WORK, BECAUSE erls = e_rls, 
   801     I.E. THE RESPECTIVE ASSUMPTION IS STORED AND Thm APPLIED; WN051028 
   802     ... WN0609???MG.*)
   803 val rat_mult_div_pow = prep_rls(
   804   Rls {id = "rat_mult_div_pow", preconds = [], rew_ord = ("dummy_ord",dummy_ord), 
   805     erls = e_rls, srls = Erls, calc = [], errpatts = [],
   806     rules = [Thm ("rat_mult", num_str @{thm rat_mult}),
   807       (*"?a / ?b * (?c / ?d) = ?a * ?c / (?b * ?d)"*)
   808       Thm ("rat_mult_poly_l", num_str @{thm rat_mult_poly_l}),
   809       (*"?c is_polyexp ==> ?c * (?a / ?b) = ?c * ?a / ?b"*)
   810       Thm ("rat_mult_poly_r", num_str @{thm rat_mult_poly_r}),
   811       (*"?c is_polyexp ==> ?a / ?b * ?c = ?a * ?c / ?b"*)
   812       
   813       Thm ("real_divide_divide1_mg", num_str @{thm real_divide_divide1_mg}),
   814       (*"y ~= 0 ==> (u / v) / (y / z) = (u * z) / (y * v)"*)
   815       Thm ("divide_divide_eq_right", num_str @{thm divide_divide_eq_right}),
   816       (*"?x / (?y / ?z) = ?x * ?z / ?y"*)
   817       Thm ("divide_divide_eq_left", num_str @{thm divide_divide_eq_left}),
   818       (*"?x / ?y / ?z = ?x / (?y * ?z)"*)
   819       Calc ("Fields.inverse_class.divide", eval_cancel "#divide_e"),
   820       
   821       Thm ("rat_power", num_str @{thm rat_power})
   822       (*"(?a / ?b) ^^^ ?n = ?a ^^^ ?n / ?b ^^^ ?n"*)
   823       ],
   824     scr = EmptyScr}:rls);
   825 
   826 val rat_reduce_1 = prep_rls(
   827   Rls {id = "rat_reduce_1", preconds = [], rew_ord = ("dummy_ord", dummy_ord), 
   828     erls = e_rls, srls = Erls, calc = [], errpatts = [], 
   829     rules = 
   830       [Thm ("divide_1", num_str @{thm divide_1}),
   831       (*"?x / 1 = ?x"*)
   832       Thm ("mult_1_left", num_str @{thm mult_1_left})           
   833       (*"1 * z = z"*)
   834       ],
   835     scr = EmptyScr}:rls);
   836 
   837 (* looping part of norm_Rational *)
   838 val norm_Rational_rls = prep_rls (
   839   Rls {id = "norm_Rational_rls", preconds = [], rew_ord = ("dummy_ord",dummy_ord), 
   840     erls = norm_rat_erls, srls = Erls, calc = [], errpatts = [],
   841     rules = [Rls_ add_fractions_p_rls,
   842       Rls_ rat_mult_div_pow,
   843       Rls_ make_rat_poly_with_parentheses,
   844       Rls_ cancel_p_rls,
   845       Rls_ rat_reduce_1
   846       ],
   847     scr = EmptyScr}:rls);
   848 
   849 val norm_Rational = prep_rls (
   850   Seq 
   851     {id = "norm_Rational", preconds = [], rew_ord = ("dummy_ord", dummy_ord), 
   852     erls = norm_rat_erls, srls = Erls, calc = [], errpatts = [],
   853     rules = [Rls_ discard_minus,
   854       Rls_ rat_mult_poly,             (* removes double fractions like a/b/c *)
   855       Rls_ make_rat_poly_with_parentheses,
   856       Rls_ cancel_p_rls,
   857       Rls_ norm_Rational_rls,         (* the main rls, looping (#) *)
   858       Rls_ discard_parentheses1       (* mult only *)
   859       ],
   860     scr = EmptyScr}:rls);
   861 *}
   862 ML {*
   863 ruleset' := overwritelthy @{theory} (!ruleset',
   864   [("calculate_Rational", calculate_Rational),
   865    ("calc_rat_erls",calc_rat_erls),
   866    ("rational_erls", rational_erls),
   867    ("cancel_p", cancel_p),
   868    ("add_fractions_p", add_fractions_p),
   869    ("add_fractions_p_rls", add_fractions_p_rls),
   870    (*WN120410 ("discard_minus", discard_minus), is defined in Poly.thy*)
   871    ("powers_erls", powers_erls),
   872    ("powers", powers),
   873    ("rat_mult_divide", rat_mult_divide),
   874    ("reduce_0_1_2", reduce_0_1_2),
   875    ("rat_reduce_1", rat_reduce_1),
   876    ("norm_rat_erls", norm_rat_erls),
   877    ("norm_Rational", norm_Rational),
   878    ("norm_Rational_rls", norm_Rational_rls),
   879    ("norm_Rational_parenthesized", norm_Rational_parenthesized),
   880    ("rat_mult_poly", rat_mult_poly),
   881    ("rat_mult_div_pow", rat_mult_div_pow),
   882    ("cancel_p_rls", cancel_p_rls)
   883    ]);
   884 
   885 *}
   886 
   887 section {* A problem for simplification of rationals *}
   888 ML {*
   889 store_pbt
   890  (prep_pbt thy "pbl_simp_rat" [] e_pblID
   891  (["rational","simplification"],
   892   [("#Given" ,["Term t_t"]),
   893    ("#Where" ,["t_t is_ratpolyexp"]),
   894    ("#Find"  ,["normalform n_n"])
   895   ],
   896   append_rls "e_rls" e_rls [(*for preds in where_*)], 
   897   SOME "Simplify t_t", 
   898   [["simplification","of_rationals"]]));
   899 *}
   900 
   901 section {* A methods for simplification of rationals *}
   902 ML {*
   903 (*WN061025 this methods script is copied from (auto-generated) script
   904   of norm_Rational in order to ease repair on inform*)
   905 store_met (prep_met thy "met_simp_rat" [] e_metID (["simplification","of_rationals"],
   906 	  [("#Given" ,["Term t_t"]),
   907 	   ("#Where" ,["t_t is_ratpolyexp"]),
   908 	   ("#Find"  ,["normalform n_n"])],
   909 	  {rew_ord'="tless_true", rls' = e_rls, calc = [], srls = e_rls, 
   910 	   prls = append_rls "simplification_of_rationals_prls" e_rls 
   911 				    [(*for preds in where_*) Calc ("Rational.is'_ratpolyexp", eval_is_ratpolyexp "")],
   912 				   crls = e_rls, errpats = [],
   913    nrls = norm_Rational_rls},
   914    "Script SimplifyScript (t_t::real) =                             " ^
   915    "  ((Try (Rewrite_Set discard_minus False) @@                   " ^
   916    "    Try (Rewrite_Set rat_mult_poly False) @@                    " ^
   917    "    Try (Rewrite_Set make_rat_poly_with_parentheses False) @@   " ^
   918    "    Try (Rewrite_Set cancel_p_rls False) @@                     " ^
   919    "    (Repeat                                                     " ^
   920    "     ((Try (Rewrite_Set add_fractions_p_rls False) @@        " ^
   921    "       Try (Rewrite_Set rat_mult_div_pow False) @@              " ^
   922    "       Try (Rewrite_Set make_rat_poly_with_parentheses False) @@" ^
   923    "       Try (Rewrite_Set cancel_p_rls False) @@                  " ^
   924    "       Try (Rewrite_Set rat_reduce_1 False)))) @@               " ^
   925    "    Try (Rewrite_Set discard_parentheses1 False))               " ^
   926    "   t_t)"));
   927 *}
   928 
   929 end