neuper@52105: (* rationals, fractions of multivariate polynomials over the real field neuper@37906: author: isac team neuper@52105: Copyright (c) isac team 2002, 2013 neuper@37906: Use is subject to license terms. neuper@37906: neuper@37906: depends on Poly (and not on Atools), because wneuper@59370: fractions with _normalised_ polynomials are canceled, added, etc. neuper@37906: *) neuper@37906: neuper@48884: theory Rational wneuper@59553: imports Poly GCD_Poly_ML neuper@48884: begin neuper@37906: walther@60358: section \Constants for evaluation by \ <^rule_eval>\ neuper@37906: consts neuper@37906: walther@60278: is_expanded :: "real => bool" ("_ is'_expanded") (*RL->Poly.thy*) walther@60278: is_ratpolyexp :: "real => bool" ("_ is'_ratpolyexp") jan@42300: get_denominator :: "real => real" walther@60017: get_numerator :: "real => real" neuper@37906: wneuper@59472: ML \ neuper@52105: (*.the expression contains + - * ^ / only ?.*) neuper@52105: fun is_ratpolyexp (Free _) = true wenzelm@60309: | is_ratpolyexp (Const (\<^const_name>\plus\,_) $ Free _ $ Free _) = true wenzelm@60309: | is_ratpolyexp (Const (\<^const_name>\minus\,_) $ Free _ $ Free _) = true wenzelm@60309: | is_ratpolyexp (Const (\<^const_name>\times\,_) $ Free _ $ Free _) = true wenzelm@60405: | is_ratpolyexp (Const (\<^const_name>\realpow\,_) $ Free _ $ Free _) = true wenzelm@60309: | is_ratpolyexp (Const (\<^const_name>\divide\,_) $ Free _ $ Free _) = true wenzelm@60309: | is_ratpolyexp (Const (\<^const_name>\plus\,_) $ t1 $ t2) = neuper@52105: ((is_ratpolyexp t1) andalso (is_ratpolyexp t2)) wenzelm@60309: | is_ratpolyexp (Const (\<^const_name>\minus\,_) $ t1 $ t2) = neuper@52105: ((is_ratpolyexp t1) andalso (is_ratpolyexp t2)) wenzelm@60309: | is_ratpolyexp (Const (\<^const_name>\times\,_) $ t1 $ t2) = neuper@52105: ((is_ratpolyexp t1) andalso (is_ratpolyexp t2)) wenzelm@60405: | is_ratpolyexp (Const (\<^const_name>\realpow\,_) $ t1 $ t2) = neuper@52105: ((is_ratpolyexp t1) andalso (is_ratpolyexp t2)) wenzelm@60309: | is_ratpolyexp (Const (\<^const_name>\divide\,_) $ t1 $ t2) = neuper@52105: ((is_ratpolyexp t1) andalso (is_ratpolyexp t2)) walther@60355: | is_ratpolyexp t = if TermC.is_num t then true else false; neuper@37950: walther@60278: (*("is_ratpolyexp", ("Rational.is_ratpolyexp", eval_is_ratpolyexp ""))*) neuper@52105: fun eval_is_ratpolyexp (thmid:string) _ Walther@60504: (t as (Const (\<^const_name>\Rational.is_ratpolyexp\, _) $ arg)) ctxt = neuper@52105: if is_ratpolyexp arg Walther@60504: then SOME (TermC.mk_thmid thmid (UnparseC.term_in_ctxt ctxt arg) "", wneuper@59390: HOLogic.Trueprop $ (TermC.mk_equality (t, @{term True}))) Walther@60504: else SOME (TermC.mk_thmid thmid (UnparseC.term_in_ctxt ctxt arg) "", wneuper@59390: HOLogic.Trueprop $ (TermC.mk_equality (t, @{term False}))) neuper@52105: | eval_is_ratpolyexp _ _ _ _ = NONE; neuper@52105: neuper@52105: (*("get_denominator", ("Rational.get_denominator", eval_get_denominator ""))*) neuper@52105: fun eval_get_denominator (thmid:string) _ walther@60335: (t as Const (\<^const_name>\Rational.get_denominator\, _) $ wenzelm@60309: (Const (\<^const_name>\divide\, _) $ _(*num*) $ Walther@60504: denom)) ctxt = Walther@60504: SOME (TermC.mk_thmid thmid (UnparseC.term_in_ctxt ctxt denom) "", wneuper@59390: HOLogic.Trueprop $ (TermC.mk_equality (t, denom))) neuper@52105: | eval_get_denominator _ _ _ _ = NONE; neuper@52105: neuper@52105: (*("get_numerator", ("Rational.get_numerator", eval_get_numerator ""))*) neuper@52105: fun eval_get_numerator (thmid:string) _ walther@60335: (t as Const (\<^const_name>\Rational.get_numerator\, _) $ wenzelm@60309: (Const (\<^const_name>\divide\, _) $num Walther@60504: $denom )) ctxt = Walther@60504: SOME (TermC.mk_thmid thmid (UnparseC.term_in_ctxt ctxt num) "", wneuper@59390: HOLogic.Trueprop $ (TermC.mk_equality (t, num))) neuper@52105: | eval_get_numerator _ _ _ _ = NONE; wneuper@59472: \ neuper@52105: wneuper@59472: section \Theorems for rewriting\ neuper@52105: neuper@52105: axiomatization (* naming due to Isabelle2002, but not contained in Isabelle2002; neuper@52105: many thms are due to RL and can be removed with updating the equation solver; neuper@52105: TODO: replace by equivalent thms in recent Isabelle201x *) neuper@52105: where neuper@52105: mult_cross: "[| b ~= 0; d ~= 0 |] ==> (a / b = c / d) = (a * d = b * c)" and neuper@52105: mult_cross1: " b ~= 0 ==> (a / b = c ) = (a = b * c)" and neuper@52105: mult_cross2: " d ~= 0 ==> (a = c / d) = (a * d = c)" and neuper@37950: neuper@52105: add_minus: "a + b - b = a"(*RL->Poly.thy*) and neuper@52105: add_minus1: "a - b + b = a"(*RL->Poly.thy*) and neuper@37950: neuper@52105: rat_mult: "a / b * (c / d) = a * c / (b * d)"(*?Isa02*) and neuper@52105: rat_mult2: "a / b * c = a * c / b "(*?Isa02*) and t@42211: neuper@52105: rat_mult_poly_l: "c is_polyexp ==> c * (a / b) = c * a / b" and neuper@52105: rat_mult_poly_r: "c is_polyexp ==> (a / b) * c = a * c / b" and neuper@37906: neuper@37906: (*real_times_divide1_eq .. Isa02*) neuper@52105: real_times_divide_1_eq: "-1 * (c / d) = -1 * c / d " and walther@60385: real_times_divide_num: "a is_num ==> a * (c / d) = a * c / d " and t@42211: neuper@52105: real_mult_div_cancel2: "k ~= 0 ==> m * k / (n * k) = m / n" and neuper@37978: (*real_mult_div_cancel1: "k ~= 0 ==> k * m / (k * n) = m / n"..Isa02*) neuper@37906: neuper@52105: real_divide_divide1: "y ~= 0 ==> (u / v) / (y / z) = (u / v) * (z / y)" and neuper@52105: real_divide_divide1_mg: "y ~= 0 ==> (u / v) / (y / z) = (u * z) / (y * v)" and neuper@37978: (*real_divide_divide2_eq: "x / y / z = x / (y * z)"..Isa02*) neuper@37906: walther@60242: rat_power: "(a / b) \ n = (a \ n) / (b \ n)" and neuper@37978: walther@60385: rat_add: "[| a is_num; b is_num; c is_num; d is_num |] ==> neuper@52105: a / c + b / d = (a * d + b * c) / (c * d)" and walther@60385: rat_add_assoc: "[| a is_num; b is_num; c is_num; d is_num |] ==> neuper@52105: a / c +(b / d + e) = (a * d + b * c)/(d * c) + e" and walther@60385: rat_add1: "[| a is_num; b is_num; c is_num |] ==> neuper@52105: a / c + b / c = (a + b) / c" and walther@60385: rat_add1_assoc: "[| a is_num; b is_num; c is_num |] ==> neuper@52105: a / c + (b / c + e) = (a + b) / c + e" and walther@60385: rat_add2: "[| a is_num; b is_num; c is_num |] ==> neuper@52105: a / c + b = (a + b * c) / c" and walther@60385: rat_add2_assoc: "[| a is_num; b is_num; c is_num |] ==> neuper@52105: a / c + (b + e) = (a + b * c) / c + e" and walther@60385: rat_add3: "[| a is_num; b is_num; c is_num |] ==> neuper@52105: a + b / c = (a * c + b) / c" and walther@60385: rat_add3_assoc: "[| a is_num; b is_num; c is_num |] ==> neuper@37950: a + (b / c + e) = (a * c + b) / c + e" neuper@37950: wneuper@59472: section \Cancellation and addition of fractions\ wneuper@59472: subsection \Conversion term <--> poly\ wneuper@59472: subsubsection \Convert a term to the internal representation of a multivariate polynomial\ wneuper@59472: ML \ walther@60347: fun monom_of_term vs (_, es) (t as Const (\<^const_name>\zero_class.zero\, _)) = walther@60347: (0, list_update es (find_index (curry op = t) vs) 1) walther@60347: | monom_of_term vs (c, es) (t as Const _) = wneuper@59532: (c, list_update es (find_index (curry op = t) vs) 1) walther@60335: | monom_of_term _ (c, es) (t as (Const (\<^const_name>\numeral\, _) $ _)) = walther@60319: (t |> HOLogic.dest_number |> snd |> curry op * c, es) (*several numerals in one monom*) walther@60335: | monom_of_term _ (c, es) (t as (Const (\<^const_name>\uminus\, _) $ _)) = walther@60319: (t |> HOLogic.dest_number |> snd |> curry op * c, es) (*several numerals in one monom*) walther@60318: | monom_of_term vs (c, es) (t as Free _) = walther@60318: (c, list_update es (find_index (curry op = t) vs) 1) wenzelm@60405: | monom_of_term vs (c, es) (Const (\<^const_name>\realpow\, _) $ (b as Free _) $ walther@60335: (e as Const (\<^const_name>\numeral\, _) $ _)) = walther@60319: (c, list_update es (find_index (curry op = b) vs) (e |> HOLogic.dest_number |> snd)) wenzelm@60405: | monom_of_term vs (c, es) (Const (\<^const_name>\realpow\, _) $ (b as Free _) $ walther@60335: (e as Const (\<^const_name>\uminus\, _) $ _)) = walther@60319: (c, list_update es (find_index (curry op = b) vs) (e |> HOLogic.dest_number |> snd)) walther@60331: wenzelm@60309: | monom_of_term vs (c, es) (Const (\<^const_name>\times\, _) $ m1 $ m2) = neuper@52087: let val (c', es') = monom_of_term vs (c, es) m1 neuper@52087: in monom_of_term vs (c', es') m2 end walther@59868: | monom_of_term _ _ t = raise ERROR ("poly malformed 1 with " ^ UnparseC.term t) neuper@52087: walther@60318: (*-------v------*) walther@60347: fun monoms_of_term vs (t as Const (\<^const_name>\zero_class.zero\, _)) = walther@60347: [monom_of_term vs (0, replicate (length vs) 0) t] walther@60347: | monoms_of_term vs (t as Const _) = wneuper@59531: [monom_of_term vs (1, replicate (length vs) 0) t] walther@60335: | monoms_of_term vs (t as Const (\<^const_name>\numeral\, _) $ _) = walther@60319: [monom_of_term vs (1, replicate (length vs) 0) t] walther@60335: | monoms_of_term vs (t as Const (\<^const_name>\uminus\, _) $ _) = walther@60319: [monom_of_term vs (1, replicate (length vs) 0) t] wneuper@59531: | monoms_of_term vs (t as Free _) = neuper@52087: [monom_of_term vs (1, replicate (length vs) 0) t] wenzelm@60405: | monoms_of_term vs (t as Const (\<^const_name>\realpow\, _) $ _ $ _) = neuper@52087: [monom_of_term vs (1, replicate (length vs) 0) t] wenzelm@60309: | monoms_of_term vs (t as Const (\<^const_name>\times\, _) $ _ $ _) = neuper@52087: [monom_of_term vs (1, replicate (length vs) 0) t] wenzelm@60309: | monoms_of_term vs (Const (\<^const_name>\plus\, _) $ ms1 $ ms2) = neuper@52087: (monoms_of_term vs ms1) @ (monoms_of_term vs ms2) walther@59868: | monoms_of_term _ t = raise ERROR ("poly malformed 2 with " ^ UnparseC.term t) neuper@52087: neuper@52087: (* convert a term to the internal representation of a multivariate polynomial; neuper@52087: the conversion is quite liberal, see test --- fun poly_of_term ---: neuper@52087: * the order of variables and the parentheses within a monomial are arbitrary neuper@52087: * the coefficient may be somewhere neuper@52087: * he order and the parentheses within monomials are arbitrary neuper@52087: But the term must be completely expand + over * (laws of distributivity are not applicable). neuper@52087: neuper@52087: The function requires the free variables as strings already given, neuper@52087: because the gcd involves 2 polynomials (with the same length for their list of exponents). neuper@52087: *) wenzelm@60309: fun poly_of_term vs (t as Const (\<^const_name>\plus\, _) $ _ $ _) = neuper@52101: (SOME (t |> monoms_of_term vs |> order) neuper@52087: handle ERROR _ => NONE) walther@60347: | poly_of_term vs t = (* 0 for zero polynomial *) neuper@52101: (SOME [monom_of_term vs (1, replicate (length vs) 0) t] neuper@52087: handle ERROR _ => NONE) neuper@52087: neuper@52087: fun is_poly t = wneuper@59532: let wneuper@59532: val vs = TermC.vars_of t neuper@52087: in neuper@52087: case poly_of_term vs t of SOME _ => true | NONE => false neuper@52087: end neuper@52105: val is_expanded = is_poly (* TODO: check names *) neuper@52105: val is_polynomial = is_poly (* TODO: check names *) wneuper@59472: \ neuper@52087: wneuper@59472: subsubsection \Convert internal representation of a multivariate polynomial to a term\ wneuper@59472: ML \ neuper@52087: fun term_of_es _ _ _ [] = [] (*assumes same length for vs and es*) wneuper@59532: | term_of_es baseT expT (_ :: vs) (0 :: es) = [] @ term_of_es baseT expT vs es wneuper@59532: | term_of_es baseT expT (v :: vs) (1 :: es) = v :: term_of_es baseT expT vs es neuper@52087: | term_of_es baseT expT (v :: vs) (e :: es) = wenzelm@60405: Const (\<^const_name>\realpow\, [baseT, expT] ---> baseT) $ v $ (HOLogic.mk_number expT e) wneuper@59532: :: term_of_es baseT expT vs es wneuper@59532: | term_of_es _ _ _ _ = raise ERROR "term_of_es: length vs <> length es" neuper@52087: neuper@52087: fun term_of_monom baseT expT vs ((c, es): monom) = neuper@52087: let val es' = term_of_es baseT expT vs es neuper@52087: in neuper@52087: if c = 1 neuper@52087: then neuper@52087: if es' = [] (*if es = [0,0,0,...]*) walther@60317: then HOLogic.mk_number baseT c neuper@52087: else foldl (HOLogic.mk_binop "Groups.times_class.times") (hd es', tl es') walther@60317: else foldl (HOLogic.mk_binop "Groups.times_class.times") walther@60317: (HOLogic.mk_number baseT c, es') neuper@52087: end neuper@52087: neuper@52087: fun term_of_poly baseT expT vs p = wneuper@59190: let val monos = map (term_of_monom baseT expT vs) p wenzelm@60309: in foldl (HOLogic.mk_binop \<^const_name>\plus\) (hd monos, tl monos) end wneuper@59472: \ neuper@52087: wneuper@59472: subsection \Apply gcd_poly for cancelling and adding fractions as terms\ wneuper@59472: ML \ neuper@52091: fun mk_noteq_0 baseT t = walther@60335: Const (\<^const_name>\Not\, HOLogic.boolT --> HOLogic.boolT) $ walther@60335: (Const (\<^const_name>\HOL.eq\, [baseT, baseT] ---> HOLogic.boolT) $ t $ HOLogic.mk_number HOLogic.realT 0) neuper@52091: neuper@52094: fun mk_asms baseT ts = wneuper@59389: let val as' = filter_out TermC.is_num ts (* asm like "2 ~= 0" is needless *) neuper@52094: in map (mk_noteq_0 baseT) as' end wneuper@59472: \ neuper@52094: wneuper@59472: subsubsection \Factor out gcd for cancellation\ wneuper@59472: ML \ neuper@52091: fun check_fraction t = walther@60269: case t of wenzelm@60309: Const (\<^const_name>\divide\, _) $ numerator $ denominator walther@60269: => SOME (numerator, denominator) walther@60269: | _ => NONE neuper@52091: neuper@52091: (* prepare a term for cancellation by factoring out the gcd neuper@52091: assumes: is a fraction with outmost "/"*) walther@60372: fun factout_p_ (_: theory) t = neuper@52091: let val opt = check_fraction t neuper@52091: in neuper@52091: case opt of neuper@52091: NONE => NONE neuper@52091: | SOME (numerator, denominator) => wneuper@59532: let wneuper@59532: val vs = TermC.vars_of t neuper@52091: val baseT = type_of numerator neuper@52091: val expT = HOLogic.realT neuper@52091: in neuper@52091: case (poly_of_term vs numerator, poly_of_term vs denominator) of neuper@52091: (SOME a, SOME b) => neuper@52091: let neuper@52091: val ((a', b'), c) = gcd_poly a b neuper@52096: val es = replicate (length vs) 0 neuper@52096: in neuper@52096: if c = [(1, es)] orelse c = [(~1, es)] neuper@52096: then NONE neuper@52096: else neuper@52096: let neuper@52096: val b't = term_of_poly baseT expT vs b' neuper@52096: val ct = term_of_poly baseT expT vs c neuper@52096: val t' = wenzelm@60309: HOLogic.mk_binop \<^const_name>\divide\ wenzelm@60309: (HOLogic.mk_binop \<^const_name>\times\ wneuper@59190: (term_of_poly baseT expT vs a', ct), wenzelm@60309: HOLogic.mk_binop \<^const_name>\times\ (b't, ct)) neuper@52105: in SOME (t', mk_asms baseT [b't, ct]) end neuper@52096: end neuper@52091: | _ => NONE : (term * term list) option neuper@52091: end neuper@52091: end wneuper@59472: \ neuper@52091: wneuper@59472: subsubsection \Cancel a fraction\ wneuper@59472: ML \ neuper@52096: (* cancel a term by the gcd ("" denote terms with internal algebraic structure) walther@60347: cancel_p_ : theory \ term \ (term \ term list) option neuper@52096: cancel_p_ thy "a / b" = SOME ("a' / b'", ["b' \ 0"]) neuper@52096: assumes: a is_polynomial \ b is_polynomial \ b \ 0 neuper@52096: yields neuper@52096: SOME ("a' / b'", ["b' \ 0"]). gcd_poly a b \ 1 \ gcd_poly a b \ -1 \ neuper@52096: a' * gcd_poly a b = a \ b' * gcd_poly a b = b neuper@52096: \ NONE *) neuper@52101: fun cancel_p_ (_: theory) t = neuper@52091: let val opt = check_fraction t neuper@52091: in neuper@52091: case opt of neuper@52091: NONE => NONE neuper@52091: | SOME (numerator, denominator) => wneuper@59532: let wneuper@59532: val vs = TermC.vars_of t neuper@52091: val baseT = type_of numerator neuper@52091: val expT = HOLogic.realT neuper@52091: in neuper@52091: case (poly_of_term vs numerator, poly_of_term vs denominator) of neuper@52091: (SOME a, SOME b) => neuper@52091: let neuper@52091: val ((a', b'), c) = gcd_poly a b neuper@52096: val es = replicate (length vs) 0 neuper@52096: in neuper@52096: if c = [(1, es)] orelse c = [(~1, es)] neuper@52096: then NONE neuper@52096: else neuper@52096: let neuper@52096: val bt' = term_of_poly baseT expT vs b' neuper@52096: val ct = term_of_poly baseT expT vs c neuper@52096: val t' = wenzelm@60309: HOLogic.mk_binop \<^const_name>\divide\ wneuper@59190: (term_of_poly baseT expT vs a', bt') neuper@52096: val asm = mk_asms baseT [bt'] neuper@52096: in SOME (t', asm) end neuper@52096: end neuper@52091: | _ => NONE : (term * term list) option neuper@52091: end neuper@52091: end wneuper@59472: \ neuper@52091: wneuper@59472: subsubsection \Factor out to a common denominator for addition\ wneuper@59472: ML \ neuper@52101: (* addition of fractions allows (at most) one non-fraction (a monomial) *) neuper@52101: fun check_frac_sum wenzelm@60309: (Const (\<^const_name>\plus\, _) $ wenzelm@60309: (Const (\<^const_name>\divide\, _) $ n1 $ d1) $ wenzelm@60309: (Const (\<^const_name>\divide\, _) $ n2 $ d2)) neuper@52091: = SOME ((n1, d1), (n2, d2)) neuper@52101: | check_frac_sum wenzelm@60309: (Const (\<^const_name>\plus\, _) $ neuper@52091: nofrac $ wenzelm@60309: (Const (\<^const_name>\divide\, _) $ n2 $ d2)) walther@60347: = SOME ((nofrac, HOLogic.mk_number HOLogic.realT 1), (n2, d2)) neuper@52101: | check_frac_sum wenzelm@60309: (Const (\<^const_name>\plus\, _) $ wenzelm@60309: (Const (\<^const_name>\divide\, _) $ n1 $ d1) $ neuper@52091: nofrac) walther@60317: = SOME ((n1, d1), (nofrac, HOLogic.mk_number HOLogic.realT 1)) neuper@52101: | check_frac_sum _ = NONE neuper@52091: neuper@52091: (* prepare a term for addition by providing the least common denominator as a product neuper@52091: assumes: is a term with outmost "+" and at least one outmost "/" in respective summands*) neuper@52101: fun common_nominator_p_ (_: theory) t = neuper@52101: let val opt = check_frac_sum t neuper@52091: in neuper@52091: case opt of neuper@52091: NONE => NONE neuper@52091: | SOME ((n1, d1), (n2, d2)) => wneuper@59532: let wneuper@59532: val vs = TermC.vars_of t neuper@52091: in neuper@52091: case (poly_of_term vs d1, poly_of_term vs d2) of neuper@52091: (SOME a, SOME b) => neuper@52091: let neuper@52091: val ((a', b'), c) = gcd_poly a b neuper@52101: val (baseT, expT) = (type_of n1, HOLogic.realT) wneuper@59190: val [d1', d2', c'] = map (term_of_poly baseT expT vs) [a', b', c] neuper@52091: (*----- minimum of parentheses & nice result, but breaks tests: ------------- wenzelm@60309: val denom = HOLogic.mk_binop \<^const_name>\times\ wenzelm@60309: (HOLogic.mk_binop \<^const_name>\times\ (d1', d2'), c') -------------*) neuper@52101: val denom = neuper@52101: if c = [(1, replicate (length vs) 0)] wenzelm@60309: then HOLogic.mk_binop \<^const_name>\times\ (d1', d2') neuper@52101: else wenzelm@60309: HOLogic.mk_binop \<^const_name>\times\ (c', wenzelm@60309: HOLogic.mk_binop \<^const_name>\times\ (d1', d2')) (*--------------*) neuper@52091: val t' = wenzelm@60309: HOLogic.mk_binop \<^const_name>\plus\ wenzelm@60309: (HOLogic.mk_binop \<^const_name>\divide\ wenzelm@60309: (HOLogic.mk_binop \<^const_name>\times\ (n1, d2'), denom), wenzelm@60309: HOLogic.mk_binop \<^const_name>\divide\ wenzelm@60309: (HOLogic.mk_binop \<^const_name>\times\ (n2, d1'), denom)) neuper@52094: val asm = mk_asms baseT [d1', d2', c'] neuper@52091: in SOME (t', asm) end neuper@52091: | _ => NONE : (term * term list) option neuper@52091: end neuper@52091: end wneuper@59472: \ neuper@52105: wneuper@59472: subsubsection \Addition of at least one fraction within a sum\ wneuper@59472: ML \ neuper@52091: (* add fractions neuper@52100: assumes: is a term with outmost "+" and at least one outmost "/" in respective summands walther@60347: \ NONE of the summands is zero. walther@60347: NOTE: the case "(_ + _) + _" need not be considered due to iterated addition *) neuper@52105: fun add_fraction_p_ (_: theory) t = neuper@52101: case check_frac_sum t of neuper@52101: NONE => NONE neuper@52101: | SOME ((n1, d1), (n2, d2)) => wneuper@59532: let wneuper@59532: val vs = TermC.vars_of t neuper@52101: in neuper@52101: case (poly_of_term vs n1, poly_of_term vs d1, poly_of_term vs n2, poly_of_term vs d2) of neuper@52101: (SOME _, SOME a, SOME _, SOME b) => neuper@52101: let neuper@52101: val ((a', b'), c) = gcd_poly a b neuper@52101: val (baseT, expT) = (type_of n1, HOLogic.realT) neuper@52101: val nomin = term_of_poly baseT expT vs neuper@52101: (((the (poly_of_term vs n1)) %%*%% b') %%+%% ((the (poly_of_term vs n2)) %%*%% a')) neuper@52101: val denom = term_of_poly baseT expT vs ((c %%*%% a') %%*%% b') wenzelm@60309: val t' = HOLogic.mk_binop \<^const_name>\divide\ (nomin, denom) neuper@52101: in SOME (t', mk_asms baseT [denom]) end neuper@52101: | _ => NONE : (term * term list) option neuper@52101: end wneuper@59472: \ neuper@52091: wneuper@59472: section \Embed cancellation and addition into rewriting\ wenzelm@60291: wneuper@59472: subsection \Rulesets and predicate for embedding\ wneuper@59472: ML \ neuper@52105: (* evaluates conditions in calculate_Rational *) neuper@52105: val calc_rat_erls = s1210629013@55444: prep_rls' Walther@60509: (Rule_Def.Repeat {id = "calc_rat_erls", preconds = [], rew_ord = ("dummy_ord", Rewrite_Ord.function_empty), walther@60389: erls = Rule_Set.Empty, srls = Rule_Set.Empty, calc = [], errpatts = [], walther@60358: rules = [ walther@60358: \<^rule_eval>\matches\ (Prog_Expr.eval_matches "#matches_"), walther@60358: \<^rule_eval>\HOL.eq\ (Prog_Expr.eval_equal "#equal_"), walther@60385: \<^rule_eval>\is_num\ (Prog_Expr.eval_is_num "#is_num_"), walther@60358: \<^rule_thm>\not_true\, walther@60358: \<^rule_thm>\not_false\], walther@59878: scr = Rule.Empty_Prog}); neuper@37950: neuper@52105: (* simplifies expressions with numerals; neuper@52105: does NOT rearrange the term by AC-rewriting; thus terms with variables neuper@52105: need to have constants to be commuted together respectively *) neuper@52105: val calculate_Rational = walther@59852: prep_rls' (Rule_Set.merge "calculate_Rational" Walther@60509: (Rule_Def.Repeat {id = "divide", preconds = [], rew_ord = ("dummy_ord", Rewrite_Ord.function_empty), walther@59851: erls = calc_rat_erls, srls = Rule_Set.Empty, neuper@52105: calc = [], errpatts = [], walther@60358: rules = [ walther@60358: \<^rule_eval>\divide\ (Prog_Expr.eval_cancel "#divide_e"), neuper@37950: walther@60358: \<^rule_thm_sym>\minus_divide_left\, (*SYM - ?x / ?y = - (?x / ?y) may come from subst*) wenzelm@60297: \<^rule_thm>\rat_add\, walther@60385: (*"[| a is_num; b is_num; c is_num; d is_num |] ==> a / c + b / d = (a * d) / (c * d) + (b * c ) / (d * c)"*) walther@60385: \<^rule_thm>\rat_add1\, (*"[| a is_num; b is_num; c is_num |] ==> a / c + b / c = (a + b) / c"*) walther@60385: \<^rule_thm>\rat_add2\, (*"[| ?a is_num; ?b is_num; ?c is_num |] ==> ?a / ?c + ?b = (?a + ?b * ?c) / ?c"*) walther@60385: \<^rule_thm>\rat_add3\, (*"[| a is_num; b is_num; c is_num |] ==> a + b / c = (a * c) / c + b / c" *) neuper@52105: walther@60358: \<^rule_thm>\rat_mult\, (*a / b * (c / d) = a * c / (b * d)*) walther@60358: \<^rule_thm>\times_divide_eq_right\, (*?x * (?y / ?z) = ?x * ?y / ?z*) walther@60358: \<^rule_thm>\times_divide_eq_left\, (*?y / ?z * ?x = ?y * ?x / ?z*) neuper@52105: walther@60358: \<^rule_thm>\real_divide_divide1\, (*"?y ~= 0 ==> ?u / ?v / (?y / ?z) = ?u / ?v * (?z / ?y)"*) walther@60358: \<^rule_thm>\divide_divide_eq_left\, (*"?x / ?y / ?z = ?x / (?y * ?z)"*) neuper@52105: walther@60358: \<^rule_thm>\rat_power\, (*"(?a / ?b) \ ?n = ?a \ ?n / ?b \ ?n"*) neuper@52105: walther@60358: \<^rule_thm>\mult_cross\, (*"[| b ~= 0; d ~= 0 |] ==> (a / b = c / d) = (a * d = b * c)*) walther@60358: \<^rule_thm>\mult_cross1\, (*" b ~= 0 ==> (a / b = c ) = (a = b * c)*) walther@60358: \<^rule_thm>\mult_cross2\ (*" d ~= 0 ==> (a = c / d) = (a * d = c)*)], walther@59878: scr = Rule.Empty_Prog}) neuper@52105: calculate_Poly); neuper@37950: walther@60278: (*("is_expanded", ("Rational.is_expanded", eval_is_expanded ""))*) neuper@37950: fun eval_is_expanded (thmid:string) _ Walther@60504: (t as (Const (\<^const_name>\Rational.is_expanded\, _) $ arg)) ctxt = neuper@37950: if is_expanded arg Walther@60504: then SOME (TermC.mk_thmid thmid (UnparseC.term_in_ctxt ctxt arg) "", wneuper@59390: HOLogic.Trueprop $ (TermC.mk_equality (t, @{term True}))) Walther@60504: else SOME (TermC.mk_thmid thmid (UnparseC.term_in_ctxt ctxt arg) "", wneuper@59390: HOLogic.Trueprop $ (TermC.mk_equality (t, @{term False}))) s1210629013@52159: | eval_is_expanded _ _ _ _ = NONE; wneuper@59472: \ wenzelm@60313: calculation is_expanded = \eval_is_expanded ""\ wneuper@59472: ML \ neuper@37950: val rational_erls = walther@59852: Rule_Set.merge "rational_erls" calculate_Rational walther@60358: (Rule_Set.append_rules "is_expanded" Atools_erls [ walther@60358: \<^rule_eval>\is_expanded\ (eval_is_expanded "")]); wneuper@59472: \ neuper@37950: wneuper@59472: subsection \Embed cancellation into rewriting\ wneuper@59472: ML \ walther@59603: (**)local (* cancel_p *) neuper@37950: walther@59852: val {rules = rules, rew_ord = (_, ro), ...} = Rule_Set.rep (assoc_rls' @{theory} "rev_rew_p"); neuper@37950: neuper@52105: fun init_state thy eval_rls ro t = neuper@52105: let neuper@52105: val SOME (t', _) = factout_p_ thy t; neuper@52105: val SOME (t'', asm) = cancel_p_ thy t; Walther@60500: val der = Derive.steps_reverse (Proof_Context.init_global thy) eval_rls rules ro NONE t'; neuper@52105: val der = der @ wenzelm@60297: [(\<^rule_thm>\real_mult_div_cancel2\, (t'', asm))] walther@60017: val rs = (Rule.distinct' o (map #1)) der walther@60017: val rs = filter_out (ThmC.member' neuper@52105: ["sym_real_add_zero_left", "sym_real_mult_0", "sym_real_mult_1"]) rs neuper@52105: in (t, t'', [rs(*one in order to ease locate_rule*)], der) end; neuper@37950: neuper@52105: fun locate_rule thy eval_rls ro [rs] t r = walther@59876: if member op = ((map (Rule.thm_id)) rs) (Rule.thm_id r) neuper@52105: then Walther@60500: let val ropt = Rewrite.rewrite_ (Proof_Context.init_global thy) ro eval_rls true (Rule.thm r) t; neuper@52105: in neuper@52105: case ropt of SOME ta => [(r, ta)] walther@59733: | NONE => ((*tracing walther@59876: ("### locate_rule: rewrite " ^ Rule.thm_id r ^ " " ^ UnparseC.term t ^ " = NONE");*) []) neuper@52105: end walther@59876: else ((*tracing ("### locate_rule: " ^ Rule.thm_id r ^ " not mem rrls");*) []) walther@59962: | locate_rule _ _ _ _ _ _ = raise ERROR "locate_rule: doesnt match rev-sets in istate"; neuper@37950: neuper@52105: fun next_rule thy eval_rls ro [rs] t = neuper@52105: let Walther@60500: val der = Derive.do_one (Proof_Context.init_global thy) eval_rls rs ro NONE t; neuper@52105: in case der of (_, r, _) :: _ => SOME r | _ => NONE end walther@59962: | next_rule _ _ _ _ _ = raise ERROR ("next_rule: doesnt match rev-sets in istate"); neuper@37950: wneuper@59416: fun attach_form (_: Rule.rule list list) (_: term) (_: term) = wneuper@59416: [(*TODO*)]: ( Rule.rule * (term * term list)) list; neuper@37950: walther@59861: (**)in(**) neuper@37950: neuper@52105: val cancel_p = walther@59850: Rule_Set.Rrls {id = "cancel_p", prepat = [], Walther@60506: rew_ord = ("ord_make_polynomial", ord_make_polynomial false \<^theory>), neuper@52105: erls = rational_erls, neuper@52105: calc = wenzelm@60309: [("PLUS", (\<^const_name>\plus\, (**)eval_binop "#add_")), wenzelm@60309: ("TIMES" , (\<^const_name>\times\, (**)eval_binop "#mult_")), wenzelm@60309: ("DIVIDE", (\<^const_name>\divide\, Prog_Expr.eval_cancel "#divide_e")), wenzelm@60405: ("POWER", (\<^const_name>\realpow\, (**)eval_binop "#power_"))], neuper@52105: errpatts = [], neuper@52105: scr = wenzelm@60291: Rule.Rfuns {init_state = init_state \<^theory> Atools_erls ro, wenzelm@60291: normal_form = cancel_p_ \<^theory>, wenzelm@60291: locate_rule = locate_rule \<^theory> Atools_erls ro, wenzelm@60291: next_rule = next_rule \<^theory> Atools_erls ro, neuper@52105: attach_form = attach_form}} walther@59861: (**)end(* local cancel_p *) wneuper@59472: \ neuper@37950: wneuper@59472: subsection \Embed addition into rewriting\ wneuper@59472: ML \ walther@59861: (**)local (* add_fractions_p *) neuper@37950: walther@59852: (*val {rules = rules, rew_ord = (_, ro), ...} = Rule_Set.rep (assoc_rls "make_polynomial");*) walther@59852: val {rules, rew_ord=(_,ro),...} = Rule_Set.rep (assoc_rls' @{theory} "rev_rew_p"); neuper@37950: neuper@52105: fun init_state thy eval_rls ro t = neuper@52105: let walther@60358: val SOME (t', _) = common_nominator_p_ thy t; neuper@52105: val SOME (t'', asm) = add_fraction_p_ thy t; Walther@60500: val der = Derive.steps_reverse (Proof_Context.init_global thy) eval_rls rules ro NONE t'; neuper@52105: val der = der @ wenzelm@60297: [(\<^rule_thm>\real_mult_div_cancel2\, (t'',asm))] walther@60017: val rs = (Rule.distinct' o (map #1)) der; walther@60017: val rs = filter_out (ThmC.member' neuper@52105: ["sym_real_add_zero_left", "sym_real_mult_0", "sym_real_mult_1"]) rs; neuper@52105: in (t, t'', [rs(*here only _ONE_*)], der) end; neuper@37950: neuper@52105: fun locate_rule thy eval_rls ro [rs] t r = walther@59876: if member op = ((map (Rule.thm_id)) rs) (Rule.thm_id r) neuper@52105: then Walther@60500: let val ropt = Rewrite.rewrite_ (Proof_Context.init_global thy) ro eval_rls true (Rule.thm r) t; neuper@52105: in neuper@52105: case ropt of neuper@52105: SOME ta => [(r, ta)] neuper@52105: | NONE => walther@59876: ((*tracing ("### locate_rule: rewrite " ^ Rule.thm_id r ^ " " ^ UnparseC.term t ^ " = NONE");*) neuper@52105: []) end walther@59876: else ((*tracing ("### locate_rule: " ^ Rule.thm_id r ^ " not mem rrls");*) []) walther@59962: | locate_rule _ _ _ _ _ _ = raise ERROR "locate_rule: doesnt match rev-sets in istate"; neuper@37950: neuper@37950: fun next_rule thy eval_rls ro [rs] t = Walther@60500: let val der = Derive.do_one (Proof_Context.init_global thy) eval_rls rs ro NONE t; neuper@52105: in neuper@52105: case der of neuper@52105: (_,r,_)::_ => SOME r neuper@52105: | _ => NONE neuper@37950: end walther@59962: | next_rule _ _ _ _ _ = raise ERROR ("next_rule: doesnt match rev-sets in istate"); neuper@37950: wenzelm@60291: val pat0 = TermC.parse_patt \<^theory> "?r/?s+?u/?v :: real"; wenzelm@60291: val pat1 = TermC.parse_patt \<^theory> "?r/?s+?u :: real"; wenzelm@60291: val pat2 = TermC.parse_patt \<^theory> "?r +?u/?v :: real"; neuper@48760: val prepat = [([@{term True}], pat0), neuper@48760: ([@{term True}], pat1), neuper@48760: ([@{term True}], pat2)]; walther@59861: (**)in(**) neuper@37950: neuper@52105: val add_fractions_p = walther@59850: Rule_Set.Rrls {id = "add_fractions_p", prepat=prepat, wenzelm@60291: rew_ord = ("ord_make_polynomial", ord_make_polynomial false \<^theory>), neuper@52105: erls = rational_erls, wenzelm@60309: calc = [("PLUS", (\<^const_name>\plus\, (**)eval_binop "#add_")), wenzelm@60309: ("TIMES", (\<^const_name>\times\, (**)eval_binop "#mult_")), wenzelm@60309: ("DIVIDE", (\<^const_name>\divide\, Prog_Expr.eval_cancel "#divide_e")), wenzelm@60405: ("POWER", (\<^const_name>\realpow\, (**)eval_binop "#power_"))], neuper@52105: errpatts = [], wenzelm@60291: scr = Rule.Rfuns {init_state = init_state \<^theory> Atools_erls ro, wenzelm@60291: normal_form = add_fraction_p_ \<^theory>, wenzelm@60291: locate_rule = locate_rule \<^theory> Atools_erls ro, wenzelm@60291: next_rule = next_rule \<^theory> Atools_erls ro, neuper@52105: attach_form = attach_form}} walther@59861: (**)end(*local add_fractions_p *) wneuper@59472: \ neuper@37950: wneuper@59472: subsection \Cancelling and adding all occurrences in a term /////////////////////////////\ wneuper@59472: ML \ neuper@52105: (*copying cancel_p_rls + add her caused error in interface.sml*) wneuper@59472: \ neuper@42451: wneuper@59472: section \Rulesets for general simplification\ wneuper@59472: ML \ neuper@37950: (*.all powers over + distributed; atoms over * collected, other distributed neuper@37950: contains absolute minimum of thms for context in norm_Rational .*) s1210629013@55444: val powers = prep_rls'( Walther@60509: Rule_Def.Repeat {id = "powers", preconds = [], rew_ord = ("dummy_ord",Rewrite_Ord.function_empty), walther@59851: erls = powers_erls, srls = Rule_Set.Empty, calc = [], errpatts = [], walther@60358: rules = [ walther@60358: \<^rule_thm>\realpow_multI\, (*"(r * s) \ n = r \ n * s \ n"*) walther@60358: \<^rule_thm>\realpow_pow\, (*"(a \ b) \ c = a \ (b * c)"*) walther@60358: \<^rule_thm>\realpow_oneI\, (*"r \ 1 = r"*) walther@60358: \<^rule_thm>\realpow_minus_even\, (*"n is_even ==> (- r) \ n = r \ n" ?-->discard_minus?*) walther@60358: \<^rule_thm>\realpow_minus_odd\, (*"Not (n is_even) ==> (- r) \ n = -1 * r \ n"*) neuper@37950: walther@60358: (*----- collect atoms over * -----*) walther@60358: \<^rule_thm>\realpow_two_atom\, (*"r is_atom ==> r * r = r \ 2"*) walther@60358: \<^rule_thm>\realpow_plus_1\, (*"r is_atom ==> r * r \ n = r \ (n + 1)"*) walther@60358: \<^rule_thm>\realpow_addI_atom\, (*"r is_atom ==> r \ n * r \ m = r \ (n + m)"*) walther@60358: walther@60358: (*----- distribute none-atoms -----*) walther@60358: \<^rule_thm>\realpow_def_atom\, (*"[| 1 < n; ~ (r is_atom) |]==>r \ n = r * r \ (n + -1)"*) walther@60358: \<^rule_thm>\realpow_eq_oneI\, (*"1 \ n = 1"*) walther@60358: \<^rule_eval>\plus\ (**)(eval_binop "#add_")], walther@60358: scr = Rule.Empty_Prog}); walther@60358: walther@60385: \ ML \ neuper@37950: (*.contains absolute minimum of thms for context in norm_Rational.*) s1210629013@55444: val rat_mult_divide = prep_rls'( walther@59851: Rule_Def.Repeat {id = "rat_mult_divide", preconds = [], Walther@60509: rew_ord = ("dummy_ord", Rewrite_Ord.function_empty), walther@59852: erls = Rule_Set.empty, srls = Rule_Set.Empty, calc = [], errpatts = [], walther@60358: rules = [ walther@60358: \<^rule_thm>\rat_mult\, (*(1)"?a / ?b * (?c / ?d) = ?a * ?c / (?b * ?d)"*) walther@60358: \<^rule_thm>\times_divide_eq_right\, (*(2)"?a * (?c / ?d) = ?a * ?c / ?d" must be [2], walther@60358: otherwise inv.to a / b / c = ...*) walther@60358: \<^rule_thm>\times_divide_eq_left\, (*"?a / ?b * ?c = ?a * ?c / ?b" order weights x \ n too much walther@60358: and does not commute a / b * c \ 2 !*) neuper@37950: walther@60358: \<^rule_thm>\divide_divide_eq_right\, (*"?x / (?y / ?z) = ?x * ?z / ?y"*) walther@60358: \<^rule_thm>\divide_divide_eq_left\, (*"?x / ?y / ?z = ?x / (?y * ?z)"*) walther@60358: \<^rule_eval>\divide\ (Prog_Expr.eval_cancel "#divide_e")], walther@60358: scr = Rule.Empty_Prog}); neuper@37979: walther@60385: \ ML \ neuper@37950: (*.contains absolute minimum of thms for context in norm_Rational.*) s1210629013@55444: val reduce_0_1_2 = prep_rls'( Walther@60509: Rule_Def.Repeat{id = "reduce_0_1_2", preconds = [], rew_ord = ("dummy_ord", Rewrite_Ord.function_empty), walther@60358: erls = Rule_Set.empty, srls = Rule_Set.Empty, calc = [], errpatts = [], walther@60358: rules = [ walther@60393: \<^rule_thm>\div_by_1\, (*"?x / 1 = ?x"*) walther@60358: \<^rule_thm>\mult_1_left\, (*"1 * z = z"*) walther@60389: \<^rule_thm>\minus_zero\, (*"- 0 = 0"*) walther@60358: (*\<^rule_thm>\real_mult_minus1\, "-1 * z = - z"*) walther@60358: (*\<^rule_thm>\real_minus_mult_cancel\, "- ?x * - ?y = ?x * ?y"*) walther@60358: walther@60358: walther@60358: \<^rule_thm>\mult_zero_left\, (*"0 * z = 0"*) walther@60358: \<^rule_thm>\add_0_left\, (*"0 + z = z"*) walther@60358: (*\<^rule_thm>\right_minus\, "?z + - ?z = 0"*) walther@60358: walther@60358: \<^rule_thm_sym>\real_mult_2\, (*"z1 + z1 = 2 * z1"*) walther@60358: \<^rule_thm>\real_mult_2_assoc\, (*"z1 + (z1 + k) = 2 * z1 + k"*) walther@60358: walther@60358: \<^rule_thm>\division_ring_divide_zero\ (*"0 / ?x = 0"*)], walther@60358: scr = Rule.Empty_Prog}); neuper@37950: neuper@37950: (*erls for calculate_Rational; neuper@37950: make local with FIXX@ME result:term *term list WN0609???SKMG*) s1210629013@55444: val norm_rat_erls = prep_rls'( Walther@60509: Rule_Def.Repeat {id = "norm_rat_erls", preconds = [], rew_ord = ("dummy_ord",Rewrite_Ord.function_empty), walther@60358: erls = Rule_Set.empty, srls = Rule_Set.Empty, calc = [], errpatts = [], walther@60358: rules = [ walther@60385: \<^rule_eval>\Prog_Expr.is_num\ (Prog_Expr.eval_is_num "#is_num_") walther@60385: ], walther@60358: scr = Rule.Empty_Prog}); neuper@37979: walther@60385: \ ML \ neuper@52105: (* consists of rls containing the absolute minimum of thms *) walther@60358: (* walther@60358: which is now replaced by MGs version "norm_Rational" below walther@60358: *) s1210629013@55444: val norm_Rational_min = prep_rls'( Walther@60509: Rule_Def.Repeat {id = "norm_Rational_min", preconds = [], rew_ord = ("dummy_ord",Rewrite_Ord.function_empty), walther@60358: erls = norm_rat_erls, srls = Rule_Set.Empty, calc = [], errpatts = [], walther@60358: rules = [(*sequence given by operator precedence*) walther@60358: Rule.Rls_ discard_minus, walther@60358: Rule.Rls_ powers, walther@60358: Rule.Rls_ rat_mult_divide, walther@60358: Rule.Rls_ expand, walther@60358: Rule.Rls_ reduce_0_1_2, walther@60358: Rule.Rls_ order_add_mult, walther@60358: Rule.Rls_ collect_numerals, walther@60358: Rule.Rls_ add_fractions_p, walther@60358: Rule.Rls_ cancel_p walther@60358: ], walther@60358: scr = Rule.Empty_Prog}); neuper@37979: walther@60385: \ ML \ s1210629013@55444: val norm_Rational_parenthesized = prep_rls'( walther@59878: Rule_Set.Sequence {id = "norm_Rational_parenthesized", preconds = []:term list, Walther@60509: rew_ord = ("dummy_ord", Rewrite_Ord.function_empty), walther@60358: erls = Atools_erls, srls = Rule_Set.Empty, walther@60358: calc = [], errpatts = [], walther@60358: rules = [ walther@60393: Rule.Rls_ norm_Rational_min, walther@60358: Rule.Rls_ discard_parentheses], walther@60358: scr = Rule.Empty_Prog}); neuper@37950: neuper@37950: (*WN030318???SK: simplifies all but cancel and common_nominator*) neuper@37950: val simplify_rational = walther@60358: Rule_Set.merge "simplify_rational" expand_binoms walther@60358: (Rule_Set.append_rules "divide" calculate_Rational [ walther@60358: \<^rule_thm>\div_by_1\, (*"?x / 1 = ?x"*) walther@60358: \<^rule_thm>\rat_mult\, (*(1)"?a / ?b * (?c / ?d) = ?a * ?c / (?b * ?d)"*) walther@60358: \<^rule_thm>\times_divide_eq_right\, (*(2)"?a * (?c / ?d) = ?a * ?c / ?d" must be [2], walther@60358: otherwise inv.to a / b / c = ...*) walther@60358: \<^rule_thm>\times_divide_eq_left\, (*"?a / ?b * ?c = ?a * ?c / ?b"*) walther@60358: \<^rule_thm>\add_minus\, (*"?a + ?b - ?b = ?a"*) walther@60358: \<^rule_thm>\add_minus1\, (*"?a - ?b + ?b = ?a"*) walther@60358: \<^rule_thm>\divide_minus1\ (*"?x / -1 = - ?x"*)]); walther@60358: s1210629013@55444: val add_fractions_p_rls = prep_rls'( Walther@60509: Rule_Def.Repeat {id = "add_fractions_p_rls", preconds = [], rew_ord = ("dummy_ord", Rewrite_Ord.function_empty), walther@59852: erls = Rule_Set.empty, srls = Rule_Set.Empty, calc = [], errpatts = [], wneuper@59416: rules = [Rule.Rls_ add_fractions_p], walther@59878: scr = Rule.Empty_Prog}); neuper@37950: walther@59851: (* "Rule_Def.Repeat" causes repeated application of cancel_p to one and the same term *) s1210629013@55444: val cancel_p_rls = prep_rls'( walther@59851: Rule_Def.Repeat Walther@60509: {id = "cancel_p_rls", preconds = [], rew_ord = ("dummy_ord", Rewrite_Ord.function_empty), walther@59852: erls = Rule_Set.empty, srls = Rule_Set.Empty, calc = [], errpatts = [], wneuper@59416: rules = [Rule.Rls_ cancel_p], walther@59878: scr = Rule.Empty_Prog}); neuper@52105: neuper@37950: (*. makes 'normal' fractions; 'is_polyexp' inhibits double fractions; neuper@37950: used in initial part norm_Rational_mg, see example DA-M02-main.p.60.*) s1210629013@55444: val rat_mult_poly = prep_rls'( Walther@60509: Rule_Def.Repeat {id = "rat_mult_poly", preconds = [], rew_ord = ("dummy_ord", Rewrite_Ord.function_empty), walther@60358: erls = Rule_Set.append_rules "Rule_Set.empty-is_polyexp" Rule_Set.empty [ walther@60358: \<^rule_eval>\is_polyexp\ (eval_is_polyexp "")], walther@59851: srls = Rule_Set.Empty, calc = [], errpatts = [], walther@60358: rules = [ walther@60358: \<^rule_thm>\rat_mult_poly_l\, (*"?c is_polyexp ==> ?c * (?a / ?b) = ?c * ?a / ?b"*) walther@60358: \<^rule_thm>\rat_mult_poly_r\ (*"?c is_polyexp ==> ?a / ?b * ?c = ?a * ?c / ?b"*)], walther@59878: scr = Rule.Empty_Prog}); neuper@37979: neuper@37950: (*. makes 'normal' fractions; 'is_polyexp' inhibits double fractions; neuper@37950: used in looping part norm_Rational_rls, see example DA-M02-main.p.60 walther@59852: .. WHERE THE LATTER DOES ALWAYS WORK, BECAUSE erls = Rule_Set.empty, wneuper@59416: I.E. THE RESPECTIVE ASSUMPTION IS STORED AND Rule.Thm APPLIED; WN051028 neuper@37950: ... WN0609???MG.*) s1210629013@55444: val rat_mult_div_pow = prep_rls'( Walther@60509: Rule_Def.Repeat {id = "rat_mult_div_pow", preconds = [], rew_ord = ("dummy_ord",Rewrite_Ord.function_empty), walther@59852: erls = Rule_Set.empty, srls = Rule_Set.Empty, calc = [], errpatts = [], walther@60358: rules = [ walther@60358: \<^rule_thm>\rat_mult\, (*"?a / ?b * (?c / ?d) = ?a * ?c / (?b * ?d)"*) walther@60358: \<^rule_thm>\rat_mult_poly_l\, (*"?c is_polyexp ==> ?c * (?a / ?b) = ?c * ?a / ?b"*) walther@60358: \<^rule_thm>\rat_mult_poly_r\, (*"?c is_polyexp ==> ?a / ?b * ?c = ?a * ?c / ?b"*) neuper@52105: walther@60358: \<^rule_thm>\real_divide_divide1_mg\, (*"y ~= 0 ==> (u / v) / (y / z) = (u * z) / (y * v)"*) walther@60358: \<^rule_thm>\divide_divide_eq_right\, (*"?x / (?y / ?z) = ?x * ?z / ?y"*) walther@60358: \<^rule_thm>\divide_divide_eq_left\, (*"?x / ?y / ?z = ?x / (?y * ?z)"*) wenzelm@60294: \<^rule_eval>\divide\ (Prog_Expr.eval_cancel "#divide_e"), neuper@52105: walther@60358: \<^rule_thm>\rat_power\ (*"(?a / ?b) \ ?n = ?a \ ?n / ?b \ ?n"*)], walther@59878: scr = Rule.Empty_Prog}); neuper@37950: s1210629013@55444: val rat_reduce_1 = prep_rls'( Walther@60509: Rule_Def.Repeat {id = "rat_reduce_1", preconds = [], rew_ord = ("dummy_ord", Rewrite_Ord.function_empty), walther@59852: erls = Rule_Set.empty, srls = Rule_Set.Empty, calc = [], errpatts = [], walther@60358: rules = [ walther@60358: \<^rule_thm>\div_by_1\, (*"?x / 1 = ?x"*) walther@60358: \<^rule_thm>\mult_1_left\ (*"1 * z = z"*)], walther@59878: scr = Rule.Empty_Prog}); neuper@52105: neuper@52105: (* looping part of norm_Rational *) s1210629013@55444: val norm_Rational_rls = prep_rls' ( Walther@60509: Rule_Def.Repeat {id = "norm_Rational_rls", preconds = [], rew_ord = ("dummy_ord",Rewrite_Ord.function_empty), walther@59851: erls = norm_rat_erls, srls = Rule_Set.Empty, calc = [], errpatts = [], walther@60358: rules = [ walther@60358: Rule.Rls_ add_fractions_p_rls, wneuper@59416: Rule.Rls_ rat_mult_div_pow, wneuper@59416: Rule.Rls_ make_rat_poly_with_parentheses, wneuper@59416: Rule.Rls_ cancel_p_rls, walther@60358: Rule.Rls_ rat_reduce_1], walther@59878: scr = Rule.Empty_Prog}); neuper@52105: s1210629013@55444: val norm_Rational = prep_rls' ( walther@59878: Rule_Set.Sequence Walther@60509: {id = "norm_Rational", preconds = [], rew_ord = ("dummy_ord", Rewrite_Ord.function_empty), walther@59851: erls = norm_rat_erls, srls = Rule_Set.Empty, calc = [], errpatts = [], walther@60358: rules = [ walther@60358: Rule.Rls_ discard_minus, wneuper@59416: Rule.Rls_ rat_mult_poly, (* removes double fractions like a/b/c *) wneuper@59416: Rule.Rls_ make_rat_poly_with_parentheses, wneuper@59416: Rule.Rls_ cancel_p_rls, wneuper@59416: Rule.Rls_ norm_Rational_rls, (* the main rls, looping (#) *) walther@60358: Rule.Rls_ discard_parentheses1], (* mult only *) walther@59878: scr = Rule.Empty_Prog}); wneuper@59472: \ neuper@52125: wenzelm@60289: rule_set_knowledge wenzelm@60286: calculate_Rational = calculate_Rational and wenzelm@60286: calc_rat_erls = calc_rat_erls and wenzelm@60286: rational_erls = rational_erls and wenzelm@60286: cancel_p = cancel_p and wenzelm@60286: add_fractions_p = add_fractions_p and wenzelm@60286: wenzelm@60286: add_fractions_p_rls = add_fractions_p_rls and wenzelm@60286: powers_erls = powers_erls and wenzelm@60286: powers = powers and wenzelm@60286: rat_mult_divide = rat_mult_divide and wenzelm@60286: reduce_0_1_2 = reduce_0_1_2 and wenzelm@60286: wenzelm@60286: rat_reduce_1 = rat_reduce_1 and wenzelm@60286: norm_rat_erls = norm_rat_erls and wenzelm@60286: norm_Rational = norm_Rational and wenzelm@60286: norm_Rational_rls = norm_Rational_rls and wenzelm@60286: norm_Rational_min = norm_Rational_min and wenzelm@60286: norm_Rational_parenthesized = norm_Rational_parenthesized and wenzelm@60286: wenzelm@60286: rat_mult_poly = rat_mult_poly and wenzelm@60286: rat_mult_div_pow = rat_mult_div_pow and wenzelm@60286: cancel_p_rls = cancel_p_rls neuper@37950: wneuper@59472: section \A problem for simplification of rationals\ wenzelm@60306: wenzelm@60306: problem pbl_simp_rat : "rational/simplification" = wenzelm@60306: \Rule_Set.append_rules "empty" Rule_Set.empty [(*for preds in where_*)]\ Walther@60449: Method_Ref: "simplification/of_rationals" wenzelm@60306: CAS: "Simplify t_t" wenzelm@60306: Given: "Term t_t" wenzelm@60306: Where: "t_t is_ratpolyexp" wenzelm@60306: Find: "normalform n_n" neuper@37950: wneuper@59472: section \A methods for simplification of rationals\ s1210629013@55373: (*WN061025 this methods script is copied from (auto-generated) script s1210629013@55373: of norm_Rational in order to ease repair on inform*) wneuper@59545: wneuper@59504: partial_function (tailrec) simplify :: "real \ real" wneuper@59504: where walther@59716: "simplify term = ( walther@59637: (Try (Rewrite_Set ''discard_minus'') #> walther@59637: Try (Rewrite_Set ''rat_mult_poly'') #> walther@59637: Try (Rewrite_Set ''make_rat_poly_with_parentheses'') #> walther@59637: Try (Rewrite_Set ''cancel_p_rls'') #> walther@59635: (Repeat ( walther@59637: Try (Rewrite_Set ''add_fractions_p_rls'') #> walther@59637: Try (Rewrite_Set ''rat_mult_div_pow'') #> walther@59637: Try (Rewrite_Set ''make_rat_poly_with_parentheses'') #> walther@59637: Try (Rewrite_Set ''cancel_p_rls'') #> walther@59637: Try (Rewrite_Set ''rat_reduce_1''))) #> walther@59635: Try (Rewrite_Set ''discard_parentheses1'')) walther@59716: term)" wenzelm@60303: wenzelm@60303: wenzelm@60303: method met_simp_rat : "simplification/of_rationals" = wenzelm@60303: \{rew_ord'="tless_true", rls' = Rule_Set.empty, calc = [], srls = Rule_Set.empty, wenzelm@60303: prls = Rule_Set.append_rules "simplification_of_rationals_prls" Rule_Set.empty wenzelm@60303: [(*for preds in where_*) \<^rule_eval>\is_ratpolyexp\ (eval_is_ratpolyexp "")], wenzelm@60303: crls = Rule_Set.empty, errpats = [], nrls = norm_Rational_rls}\ wenzelm@60303: Program: simplify.simps wenzelm@60303: Given: "Term t_t" wenzelm@60303: Where: "t_t is_ratpolyexp" wenzelm@60303: Find: "normalform n_n" wenzelm@60303: ML \ walther@60278: \ ML \ walther@60384: \ ML \ wneuper@59472: \ neuper@52105: end