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