1 (* rationals, i.e. fractions of multivariate polynomials over the real field
3 Copyright (c) isac team 2002
4 Use is subject to license terms.
6 depends on Poly (and not on Atools), because
7 fractions with _normalized_ polynomials are canceled, added, etc.
10 theory Rational imports Poly begin
14 is'_expanded :: "real => bool" ("_ is'_expanded") (*RL->Poly.thy*)
15 is'_ratpolyexp :: "real => bool" ("_ is'_ratpolyexp")
17 axioms (*.not contained in Isabelle2002,
18 stated as axioms, TODO?: prove as theorems*)
20 mult_cross "[| b ~= 0; d ~= 0 |] ==> (a / b = c / d) = (a * d = b * c)"
21 mult_cross1 " b ~= 0 ==> (a / b = c ) = (a = b * c)"
22 mult_cross2 " d ~= 0 ==> (a = c / d) = (a * d = c)"
24 add_minus "a + b - b = a"(*RL->Poly.thy*)
25 add_minus1 "a - b + b = a"(*RL->Poly.thy*)
27 rat_mult "a / b * (c / d) = a * c / (b * d)"(*?Isa02*)
28 rat_mult2 "a / b * c = a * c / b "(*?Isa02*)
30 rat_mult_poly_l "c is_polyexp ==> c * (a / b) = c * a / b"
31 rat_mult_poly_r "c is_polyexp ==> (a / b) * c = a * c / b"
33 (*real_times_divide1_eq .. Isa02*)
34 real_times_divide_1_eq "-1 * (c / d) =-1 * c / d "
35 real_times_divide_num "a is_const ==>
36 a * (c / d) = a * c / d "
38 real_mult_div_cancel2 "k ~= 0 ==> m * k / (n * k) = m / n"
39 (*real_mult_div_cancel1 "k ~= 0 ==> k * m / (k * n) = m / n"..Isa02*)
41 real_divide_divide1 "y ~= 0 ==> (u / v) / (y / z) = (u / v) * (z / y)"
42 real_divide_divide1_mg "y ~= 0 ==> (u / v) / (y / z) = (u * z) / (y * v)"
43 (*real_divide_divide2_eq "x / y / z = x / (y * z)"..Isa02*)
45 rat_power "(a / b)^^^n = (a^^^n) / (b^^^n)"
48 rat_add "[| a is_const; b is_const; c is_const; d is_const |] ==>
49 a / c + b / d = (a * d + b * c) / (c * d)"
50 rat_add_assoc "[| a is_const; b is_const; c is_const; d is_const |] ==>
51 a / c +(b / d + e) = (a * d + b * c)/(d * c) + e"
52 rat_add1 "[| a is_const; b is_const; c is_const |] ==>
53 a / c + b / c = (a + b) / c"
54 rat_add1_assoc "[| a is_const; b is_const; c is_const |] ==>
55 a / c + (b / c + e) = (a + b) / c + e"
56 rat_add2 "[| a is_const; b is_const; c is_const |] ==>
57 a / c + b = (a + b * c) / c"
58 rat_add2_assoc "[| a is_const; b is_const; c is_const |] ==>
59 a / c + (b + e) = (a + b * c) / c + e"
60 rat_add3 "[| a is_const; b is_const; c is_const |] ==>
61 a + b / c = (a * c + b) / c"
62 rat_add3_assoc "[| a is_const; b is_const; c is_const |] ==>
63 a + (b / c + e) = (a * c + b) / c + e"
65 text {*calculate in rationals: gcd, lcm, etc.
66 (c) Stefan Karnel 2002
67 Institute for Mathematics D and Institute for Software Technology,
70 text {* Remark on notions in the documentation below:
71 referring to the remark on 'polynomials' in Poly.sml we use
72 [2] 'polynomial' normalform (Polynom)
73 [3] 'expanded_term' normalform (Ausmultiplizierter Term),
74 where normalform [2] is a special case of [3], i.e. [3] implies [2].
76 'fraction with numerator and nominator both in normalform [2]'
77 'fraction with numerator and nominator both in normalform [3]'
79 'fraction in normalform [2]'
80 'fraction in normalform [3]'
84 a 'simple fraction' is a term with '/' as outmost operator and
85 numerator and nominator in normalform [2] or [3].
93 val add_fraction_ : theory -> term -> (term * term list) option
94 val add_fraction_p_ : theory -> term -> (term * term list) option
95 val calculate_Rational : rls
98 val cancel_ : theory -> term -> (term * term list) option
100 val cancel_p_ : theory -> term -> (term * term list) option
101 val common_nominator : rls
102 val common_nominator_ : theory -> term -> (term * term list) option
103 val common_nominator_p : rls
104 val common_nominator_p_ : theory -> term -> (term * term list) option
105 val eval_is_expanded : string -> 'a -> term -> theory ->
106 (string * term) option
107 val expanded2polynomial : term -> term option
108 val factout_ : theory -> term -> (term * term list) option
109 val factout_p_ : theory -> term -> (term * term list) option
110 val is_expanded : term -> bool
111 val is_polynomial : term -> bool
113 val mv_gcd : (int * int list) list -> mv_poly -> mv_poly
114 val mv_lcm : mv_poly -> mv_poly -> mv_poly
116 val norm_expanded_rat_ : theory -> term -> (term * term list) option
117 (*WN0602.2.6.pull into struct !!!
118 val norm_Rational : rls(*.normalizes an arbitrary rational term without
119 roots into a simple and canceled fraction
120 with normalform [2].*)
122 (*val norm_rational_p : 19.10.02 missing FIXXXXXXXXXXXXME
123 rls (*.normalizes an rational term [2] without
124 roots into a simple and canceled fraction
125 with normalform [2].*)
127 val norm_rational_ : theory -> term -> (term * term list) option
128 val polynomial2expanded : term -> term option
130 rls (*.evaluates an arbitrary rational term with numerals.*)
132 (*WN0210???SK: fehlen Funktionen, die exportiert werden sollen ? *)
135 (*.**************************************************************************
136 survey on the functions
137 ~~~~~~~~~~~~~~~~~~~~~~~
138 [2] 'polynomial' :rls | [3]'expanded_term':rls
139 --------------------:------------------+-------------------:-----------------
140 factout_p_ : | factout_ :
141 cancel_p_ : | cancel_ :
143 --------------------:------------------+-------------------:-----------------
144 common_nominator_p_: | common_nominator_ :
145 :common_nominator_p| :common_nominator
146 add_fraction_p_ : | add_fraction_ :
147 --------------------:------------------+-------------------:-----------------
148 ???SK :norm_rational_p | :norm_rational
150 This survey shows only the principal functions for reuse, and the identifiers
151 of the rls exported. The list below shows some more useful functions.
154 conversion from Isabelle-term to internal representation
155 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
157 ... BITTE FORTSETZEN ...
159 polynomial2expanded = ...
160 expanded2polynomial = ...
162 remark: polynomial2expanded o expanded2polynomial = I,
163 where 'o' is function chaining, and 'I' is identity WN0210???SK
165 functions for greatest common divisor and canceling
166 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
173 functions for least common multiple and addition of fractions
174 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
178 add_fraction_ (*.add 2 or more fractions.*)
179 add_fraction_p_ (*.add 2 or more fractions.*)
181 functions for normalform of rationals
182 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
183 WN0210???SK interne Funktionen f"ur norm_rational:
184 schaffen diese SML-Funktionen wirklich ganz allgemeine Terme ?
189 **************************************************************************.*)
193 structure RationalI : RATIONALI =
197 infix mem ins union; (*WN100819 updating to Isabelle2009-2*)
199 | x mem (y :: ys) = x = y orelse x mem ys;
200 fun (x ins xs) = if x mem xs then xs else x :: xs;
203 | (x :: xs) union ys = xs union (x ins ys);
205 (*. gcd of integers .*)
206 (* die gcd Funktion von Isabelle funktioniert nicht richtig !!! *)
207 fun gcd_int a b = if b=0 then a
208 else gcd_int b (a mod b);
210 (*. univariate polynomials (uv) .*)
211 (*. univariate polynomials are represented as a list
212 of the coefficent in reverse maximum degree order .*)
213 (*. 5 * x^5 + 4 * x^3 + 2 * x^2 + x + 19 => [19,1,2,4,0,5] .*)
214 type uv_poly = int list;
216 (*. adds two uv polynomials .*)
217 fun uv_mod_add_poly ([]:uv_poly,p2:uv_poly) = p2:uv_poly
218 | uv_mod_add_poly (p1,[]) = p1
219 | uv_mod_add_poly (x::p1,y::p2) = (x+y)::(uv_mod_add_poly(p1,p2));
221 (*. multiplies a uv polynomial with a skalar s .*)
222 fun uv_mod_smul_poly ([]:uv_poly,s:int) = []:uv_poly
223 | uv_mod_smul_poly (x::p,s) = (x*s)::(uv_mod_smul_poly(p,s));
225 (*. calculates the remainder of a polynomial divided by a skalar s .*)
226 fun uv_mod_rem_poly ([]:uv_poly,s) = []:uv_poly
227 | uv_mod_rem_poly (x::p,s) = (x mod s)::(uv_mod_smul_poly(p,s));
229 (*. calculates the degree of a uv polynomial .*)
230 fun uv_mod_deg ([]:uv_poly) = 0
231 | uv_mod_deg p = length(p)-1;
233 (*. calculates the remainder of x/p and represents it as
234 value between -p/2 and p/2 .*)
235 fun uv_mod_mod2(x,p)=
239 if (y)>(p div 2) then (y)-p else
241 if (y)<(~p div 2) then p+(y) else (y)
245 (*.calculates the remainder for each element of a integer list divided by p.*)
246 fun uv_mod_list_modp [] p = []
247 | uv_mod_list_modp (x::xs) p = (uv_mod_mod2(x,p))::(uv_mod_list_modp xs p);
249 (*. appends an integer at the end of a integer list .*)
250 fun uv_mod_null (p1:int list,0) = p1
251 | uv_mod_null (p1:int list,n1:int) = uv_mod_null(p1,n1-1) @ [0];
253 (*. uv polynomial division, result is (quotient, remainder) .*)
254 (*. only for uv_mod_divides .*)
255 (* FIXME: Division von x^9+x^5+1 durch x-1000 funktioniert nicht,
257 fun uv_mod_pdiv (p1:uv_poly) ([]:uv_poly) =
258 raise error ("RATIONALS_UV_MOD_PDIV_EXCEPTION: division by zero")
259 | uv_mod_pdiv p1 [x] =
265 xs:=(uv_mod_rem_poly(p1,x));
266 while length(!xs)>0 andalso hd(!xs)=0 do xs:=tl(!xs)
268 else raise error ("RATIONALS_UV_MOD_PDIV_EXCEPTION: division by zero");
269 ([]:uv_poly,!xs:uv_poly)
271 | uv_mod_pdiv p1 p2 =
273 val n= uv_mod_deg(p2);
274 val m= ref (uv_mod_deg(p1));
275 val p1'=ref (rev(p1));
280 val output=ref ([],[]);
283 if (!m)=0 orelse p2=[0]
284 then raise error ("RATIONALS_UV_MOD_PDIV_EXCEPTION: Division by zero")
295 c:=hd(!p1') div hd(p2');
298 p1':=uv_mod_add_poly(!p1',uv_mod_null(uv_mod_smul_poly(p2',~(!c)),!m-n));
299 while length(!p1')>0 andalso hd(!p1')=0 do p1':= tl(!p1');
304 output:=(rev(!q),rev(!p1'))
311 (*. divides p1 by p2 in Zp .*)
312 fun uv_mod_pdivp (p1:uv_poly) (p2:uv_poly) p =
314 val n=uv_mod_deg(p2);
315 val m=ref (uv_mod_deg(uv_mod_list_modp p1 p));
316 val p1'=ref (rev(p1));
317 val p2'=(rev(uv_mod_list_modp p2 p));
321 val output=ref ([],[]);
324 if (!m)=0 orelse p2=[0] then raise error ("RATIONALS_UV_MOD_PDIVP_EXCEPTION: Division by zero")
335 c:=uv_mod_mod2(hd(!p1')*(power lc2 1), p);
337 p1':=uv_mod_list_modp(tl(uv_mod_add_poly(uv_mod_smul_poly(!p1',lc2),
338 uv_mod_smul_poly(uv_mod_smul_poly(p2',hd(!p1')),~1)))) p;
342 while !p1'<>[] andalso hd(!p1')=0 do
347 output:=(rev(uv_mod_list_modp (!q) (p)),rev(!p1'))
350 !output:uv_poly * uv_poly
354 (*. calculates the remainder of p1/p2 .*)
355 fun uv_mod_prest (p1:uv_poly) ([]:uv_poly) = raise error("UV_MOD_PREST_EXCEPTION: Division by zero")
356 | uv_mod_prest [] p2 = []:uv_poly
357 | uv_mod_prest p1 p2 = (#2(uv_mod_pdiv p1 p2));
359 (*. calculates the remainder of p1/p2 in Zp .*)
360 fun uv_mod_prestp (p1:uv_poly) ([]:uv_poly) p= raise error("UV_MOD_PRESTP_EXCEPTION: Division by zero")
361 | uv_mod_prestp [] p2 p= []:uv_poly
362 | uv_mod_prestp p1 p2 p = #2(uv_mod_pdivp p1 p2 p);
364 (*. calculates the content of a uv polynomial .*)
365 fun uv_mod_cont ([]:uv_poly) = 0
366 | uv_mod_cont (x::p)= gcd_int x (uv_mod_cont(p));
368 (*. divides each coefficient of a uv polynomial by y .*)
369 fun uv_mod_div_list (p:uv_poly,0) = raise error("UV_MOD_DIV_LIST_EXCEPTION: Division by zero")
370 | uv_mod_div_list ([],y) = []:uv_poly
371 | uv_mod_div_list (x::p,y) = (x div y)::uv_mod_div_list(p,y);
373 (*. calculates the primitiv part of a uv polynomial .*)
374 fun uv_mod_pp ([]:uv_poly) = []:uv_poly
382 if !c=0 then raise error ("RATIONALS_UV_MOD_PP_EXCEPTION: content is 0")
383 else uv_mod_div_list(p,!c)
387 (*. gets the leading coefficient of a uv polynomial .*)
388 fun uv_mod_lc ([]:uv_poly) = 0
389 | uv_mod_lc p = hd(rev(p));
391 (*. calculates the euklidean polynomial remainder sequence in Zp .*)
392 fun uv_mod_prs_euklid_p(p1:uv_poly,p2:uv_poly,p)=
400 while uv_mod_deg(!f')>0 do
402 f':=uv_mod_prestp (hd(tl(!f))) (hd(!f)) p;
415 (*. calculates the gcd of p1 and p2 in Zp .*)
416 fun uv_mod_gcd_modp ([]:uv_poly) (p2:uv_poly) p = p2:uv_poly
417 | uv_mod_gcd_modp p1 [] p= p1
418 | uv_mod_gcd_modp p1 p2 p=
428 if uv_mod_deg(p1)>=uv_mod_deg(p2) then
430 p1':=uv_mod_list_modp (uv_mod_pp(p1)) p;
431 p2':=uv_mod_list_modp (uv_mod_pp(p2)) p
435 p1':=uv_mod_list_modp (uv_mod_pp(p2)) p;
436 p2':=uv_mod_list_modp (uv_mod_pp(p1)) p
438 d:=uv_mod_mod2((gcd_int (uv_mod_cont(p1))) (uv_mod_cont(p2)), p) ;
439 if !d>(p div 2) then d:=(!d)-p else ();
441 prs:=uv_mod_prs_euklid_p(!p1',!p2',p);
443 if hd(!prs)=[] then pc:=hd(tl(!prs))
446 g:=uv_mod_smul_poly(uv_mod_pp(!pc),!d);
451 (*. calculates the minimum of two real values x and y .*)
452 fun uv_mod_r_min(x,y):BasisLibrary.Real.real = if x>y then y else x;
454 (*. calculates the minimum of two integer values x and y .*)
455 fun uv_mod_min(x,y) = if x>y then y else x;
457 (*. adds the squared values of a integer list .*)
458 fun uv_mod_add_qu [] = 0.0
459 | uv_mod_add_qu (x::p) = BasisLibrary.Real.fromInt(x)*BasisLibrary.Real.fromInt(x) + uv_mod_add_qu p;
461 (*. calculates the euklidean norm .*)
462 fun uv_mod_norm ([]:uv_poly) = 0.0
463 | uv_mod_norm p = Math.sqrt(uv_mod_add_qu(p));
465 (*. multipies two values a and b .*)
466 fun uv_mod_multi a b = a * b;
468 (*. decides if x is a prim, the list contains all primes which are lower then x .*)
469 fun uv_mod_prim(x,[])= false
470 | uv_mod_prim(x,[y])=if ((x mod y) <> 0) then true
472 | uv_mod_prim(x,y::ys) = if uv_mod_prim(x,[y])
474 if uv_mod_prim(x,ys) then true
478 (*. gets the first prime, which is greater than p and does not divide g .*)
479 fun uv_mod_nextprime(g,p)=
485 while (!i<p) do (* calculates the primes lower then p *)
487 if uv_mod_prim(!i,!list) then
492 list:= (!i)::(!list);
500 while (!exit=0) do (* calculate next prime which does not divide g *)
502 if uv_mod_prim(!i,!list) then
507 list:= (!i)::(!list);
517 (*. decides if p1 is a factor of p2 in Zp .*)
518 fun uv_mod_dividesp ([]:uv_poly) (p2:uv_poly) p= raise error("UV_MOD_DIVIDESP: Division by zero")
519 | uv_mod_dividesp p1 p2 p= if uv_mod_prestp p2 p1 p = [] then true else false;
521 (*. decides if p1 is a factor of p2 .*)
522 fun uv_mod_divides ([]:uv_poly) (p2:uv_poly) = raise error("UV_MOD_DIVIDES: Division by zero")
523 | uv_mod_divides p1 p2 = if uv_mod_prest p2 p1 = [] then true else false;
525 (*. chinese remainder algorithm .*)
526 fun uv_mod_cra2(r1,r2,m1,m2)=
534 while (uv_mod_mod2((!c)*m1,m2))<>1 do
538 r1':= uv_mod_mod2(r1,m1);
539 d:=uv_mod_mod2(((r2-(!r1'))*(!c)),m2);
544 (*. applies the chinese remainder algorithmen to the coefficients of x1 and x2 .*)
545 fun uv_mod_cra_2 ([],[],m1,m2) = []
546 | uv_mod_cra_2 ([],x2,m1,m2) = raise error("UV_MOD_CRA_2_EXCEPTION: invalid call x1")
547 | uv_mod_cra_2 (x1,[],m1,m2) = raise error("UV_MOD_CRA_2_EXCEPTION: invalid call x2")
548 | uv_mod_cra_2 (x1::x1s,x2::x2s,m1,m2) = (uv_mod_cra2(x1,x2,m1,m2))::(uv_mod_cra_2(x1s,x2s,m1,m2));
550 (*. calculates the gcd of two uv polynomials p1' and p2' with the modular algorithm .*)
551 fun uv_mod_gcd (p1':uv_poly) (p2':uv_poly) =
553 val p1=ref (uv_mod_pp(p1'));
554 val p2=ref (uv_mod_pp(p2'));
555 val c=gcd_int (uv_mod_cont(p1')) (uv_mod_cont(p2'));
568 if length(!p1)>length(!p2) then ()
577 d:=gcd_int (uv_mod_lc(!p1)) (uv_mod_lc(!p2));
578 g1:=uv_mod_lc(!p1)*uv_mod_lc(!p2);
581 m:=BasisLibrary.Real.ceil(2.0 *
582 BasisLibrary.Real.fromInt(!d) *
583 BasisLibrary.Real.fromInt(power 2 (uv_mod_min(uv_mod_deg(!p2),uv_mod_deg(!p1)))) *
584 BasisLibrary.Real.fromInt(!d) *
585 uv_mod_r_min(uv_mod_norm(!p1) / BasisLibrary.Real.fromInt(abs(uv_mod_lc(!p1))),
586 uv_mod_norm(!p2) / BasisLibrary.Real.fromInt(abs(uv_mod_lc(!p2)))));
590 p:=uv_mod_nextprime(!d,!p);
591 cp:=(uv_mod_gcd_modp (uv_mod_list_modp(!p1) (!p)) (uv_mod_list_modp(!p2) (!p)) (!p)) ;
592 if abs(uv_mod_lc(!cp))<>1 then (* leading coefficient = 1 ? *)
595 while (!i)<(!p) andalso (abs(uv_mod_mod2((uv_mod_lc(!cp)*(!i)),(!p)))<>1) do
599 cp:=uv_mod_list_modp (map (uv_mod_multi (!i)) (!cp)) (!p)
603 qp:= ((map (uv_mod_multi (uv_mod_mod2(!d,!p)))) (!cp));
605 if uv_mod_deg(!qp)=0 then (q:=[1]; exit:=1) else ();
610 while !pn<= !m andalso !m>(!p) andalso !exit=0 do
612 p:=uv_mod_nextprime(!d,!p);
613 cp:=(uv_mod_gcd_modp (uv_mod_list_modp(!p1) (!p)) (uv_mod_list_modp(!p2) (!p)) (!p));
614 if uv_mod_lc(!cp)<>1 then (* leading coefficient = 1 ? *)
617 while (!i)<(!p) andalso ((uv_mod_mod2((uv_mod_lc(!q)*(!i)),(!p)))<>1) do
621 cp:=uv_mod_list_modp (map (uv_mod_multi (!i)) (!cp)) (!p)
625 qp:=uv_mod_list_modp ((map (uv_mod_multi (uv_mod_mod2(!d,!p)))) (!cp) ) (!p);
626 if uv_mod_deg(!qp)>uv_mod_deg(!q) then
628 (*print("degree to high!!!\n")*)
632 if uv_mod_deg(!qp)=uv_mod_deg(!q) then
634 q:=uv_mod_cra_2(!q,!qp,!pn,!p);
636 q:=uv_mod_pp(uv_mod_list_modp (!q) (!pn)); (* found already gcd ? *)
637 if (uv_mod_divides (!q) (p1')) andalso (uv_mod_divides (!q) (p2')) then (exit:=1) else ()
641 if uv_mod_deg(!qp)<uv_mod_deg(!q) then
650 q:=uv_mod_pp(uv_mod_list_modp (!q) (!pn));
651 if (uv_mod_divides (!q) (p1')) andalso (uv_mod_divides (!q) (p2')) then exit:=1 else ()
653 uv_mod_smul_poly(!q,c):uv_poly
656 (*. multivariate polynomials .*)
657 (*. multivariate polynomials are represented as a list of the pairs,
658 first is the coefficent and the second is a list of the exponents .*)
659 (*. 5 * x^5 * y^3 + 4 * x^3 * z^2 + 2 * x^2 * y * z^3 - z - 19
660 => [(5,[5,3,0]),(4,[3,0,2]),(2,[2,1,3]),(~1,[0,0,1]),(~19,[0,0,0])] .*)
662 (*. global variables .*)
663 (*. order indicators .*)
664 val LEX_=0; (* lexicographical term order *)
665 val GGO_=1; (* greatest degree order *)
667 (*. datatypes for internal representation.*)
668 type mv_monom = (int * (*.coefficient or the monom.*)
669 int list); (*.list of exponents) .*)
670 fun mv_monom2str (i, is) = "("^ int2str i^"," ^ ints2str' is ^ ")";
672 type mv_poly = mv_monom list;
673 fun mv_poly2str p = (strs2str' o (map mv_monom2str)) p;
675 (*. help function for monom_greater and geq .*)
676 fun mv_mg_hlp([]) = EQUAL
677 | mv_mg_hlp(x::list)=if x<0 then LESS
678 else if x>0 then GREATER
679 else mv_mg_hlp(list);
681 (*. adds a list of values .*)
682 fun mv_addlist([]) = 0
683 | mv_addlist(p1) = hd(p1)+mv_addlist(tl(p1));
685 (*. tests if the monomial M1 is greater as the monomial M2 and returns a boolean value .*)
686 (*. 2 orders are implemented LEX_/GGO_ (lexigraphical/greatest degree order) .*)
687 fun mv_monom_greater((M1x,M1l):mv_monom,(M2x,M2l):mv_monom,order)=
690 if length(M1l)<>length(M2l) then raise error ("RATIONALS_MV_MONOM_GREATER_EXCEPTION: Order error")
691 else if (mv_mg_hlp((map op- (M1l~~M2l)))<>GREATER) then false else true
696 if length(M1l)<>length(M2l) then raise error ("RATIONALS_MV_MONOM_GREATER_EXCEPTION: Order error")
698 if mv_addlist(M1l)=mv_addlist(M2l) then if (mv_mg_hlp((map op- (M1l~~M2l)))<>GREATER) then false else true
699 else if mv_addlist(M1l)>mv_addlist(M2l) then true else false
701 else raise error ("RATIONALS_MV_MONOM_GREATER_EXCEPTION: Wrong Order");
703 (*. tests if the monomial X is greater as the monomial Y and returns a order value (GREATER,EQUAL,LESS) .*)
704 (*. 2 orders are implemented LEX_/GGO_ (lexigraphical/greatest degree order) .*)
705 fun mv_geq order ((x1,x):mv_monom,(x2,y):mv_monom) =
711 if length(x)<>length(y) then
712 raise error ("RATIONALS_MV_GEQ_EXCEPTION: Order error")
715 temp:=mv_mg_hlp((map op- (x~~y)));
717 ( if x1=x2 then EQUAL
718 else if x1>x2 then GREATER
727 if length(x)<>length(y) then
728 raise error ("RATIONALS_MV_GEQ_EXCEPTION: Order error")
730 if mv_addlist(x)=mv_addlist(y) then
731 (mv_mg_hlp((map op- (x~~y))))
732 else if mv_addlist(x)>mv_addlist(y) then GREATER else LESS
734 else raise error ("RATIONALS_MV_GEQ_EXCEPTION: Wrong Order")
737 (*. cuts the first variable from a polynomial .*)
738 fun mv_cut([]:mv_poly)=[]:mv_poly
739 | mv_cut((x,[])::list) = raise error ("RATIONALS_MV_CUT_EXCEPTION: Invalid list ")
740 | mv_cut((x,y::ys)::list)=(x,ys)::mv_cut(list);
742 (*. leading power product .*)
743 fun mv_lpp([]:mv_poly,order) = []
744 | mv_lpp([(x,y)],order) = y
745 | mv_lpp(p1,order) = #2(hd(rev(sort (mv_geq order) p1)));
747 (*. leading monomial .*)
748 fun mv_lm([]:mv_poly,order) = (0,[]):mv_monom
749 | mv_lm([x],order) = x
750 | mv_lm(p1,order) = hd(rev(sort (mv_geq order) p1));
752 (*. leading coefficient in term order .*)
753 fun mv_lc2([]:mv_poly,order) = 0
754 | mv_lc2([(x,y)],order) = x
755 | mv_lc2(p1,order) = #1(hd(rev(sort (mv_geq order) p1)));
758 (*. reverse the coefficients in mv polynomial .*)
759 fun mv_rev_to([]:mv_poly) = []:mv_poly
760 | mv_rev_to((c,e)::xs) = (c,rev(e))::mv_rev_to(xs);
762 (*. leading coefficient in reverse term order .*)
763 fun mv_lc([]:mv_poly,order) = []:mv_poly
764 | mv_lc([(x,y)],order) = mv_rev_to(mv_cut(mv_rev_to([(x,y)])))
767 val p1o=ref (rev(sort (mv_geq order) (mv_rev_to(p1))));
768 val lp=hd(#2(hd(!p1o)));
772 while (length(!p1o)>0 andalso hd(#2(hd(!p1o)))=lp) do
774 lc:=hd(mv_cut([hd(!p1o)]))::(!lc);
777 if !lc=[] then raise error ("RATIONALS_MV_LC_EXCEPTION: lc is empty") else ();
782 (*. compares two powerproducts .*)
783 fun mv_monom_equal((_,xlist):mv_monom,(_,ylist):mv_monom) = (foldr and_) (((map op=) (xlist~~ylist)),true);
785 (*. help function for mv_add .*)
786 fun mv_madd([]:mv_poly,[]:mv_poly,order) = []:mv_poly
787 | mv_madd([(0,_)],p2,order) = p2
788 | mv_madd(p1,[(0,_)],order) = p1
789 | mv_madd([],p2,order) = p2
790 | mv_madd(p1,[],order) = p1
791 | mv_madd(p1,p2,order) =
793 if mv_monom_greater(hd(p1),hd(p2),order)
794 then hd(p1)::mv_madd(tl(p1),p2,order)
795 else if mv_monom_equal(hd(p1),hd(p2))
796 then if mv_lc2(p1,order)+mv_lc2(p2,order)<>0
797 then (mv_lc2(p1,order)+mv_lc2(p2,order),mv_lpp(p1,order))::mv_madd(tl(p1),tl(p2),order)
798 else mv_madd(tl(p1),tl(p2),order)
799 else hd(p2)::mv_madd(p1,tl(p2),order)
802 (*. adds two multivariate polynomials .*)
803 fun mv_add([]:mv_poly,p2:mv_poly,order) = p2
804 | mv_add(p1,[],order) = p1
805 | mv_add(p1,p2,order) = mv_madd(rev(sort (mv_geq order) p1),rev(sort (mv_geq order) p2), order);
807 (*. monom multiplication .*)
808 fun mv_mmul((x1,y1):mv_monom,(x2,y2):mv_monom)=(x1*x2,(map op+) (y1~~y2)):mv_monom;
810 (*. deletes all monomials with coefficient 0 .*)
811 fun mv_shorten([]:mv_poly,order) = []:mv_poly
812 | mv_shorten(x::xs,order)=mv_madd([x],mv_shorten(xs,order),order);
816 | mv_null2(x::l)=0::mv_null2(l);
818 (*. multiplies two multivariate polynomials .*)
819 fun mv_mul([]:mv_poly,[]:mv_poly,_) = []:mv_poly
820 | mv_mul([],y::p2,_) = [(0,mv_null2(#2(y)))]
821 | mv_mul(x::p1,[],_) = [(0,mv_null2(#2(x)))]
822 | mv_mul(x::p1,y::p2,order) = mv_shorten(rev(sort (mv_geq order) (mv_mmul(x,y) :: (mv_mul(p1,y::p2,order) @
823 mv_mul([x],p2,order)))),order);
825 (*. gets the maximum value of a list .*)
827 | mv_getmax(x::p1)= let
833 (*. calculates the maximum degree of an multivariate polynomial .*)
834 fun mv_grad([]:mv_poly) = 0
835 | mv_grad(p1:mv_poly)= mv_getmax((map mv_addlist) ((map #2) p1));
837 (*. converts the sign of a value .*)
838 fun mv_minus(x)=(~1) * x;
840 (*. converts the sign of all coefficients of a polynomial .*)
841 fun mv_minus2([]:mv_poly)=[]:mv_poly
842 | mv_minus2(p1)=(mv_minus(#1(hd(p1))),#2(hd(p1)))::(mv_minus2(tl(p1)));
844 (*. searches for a negativ value in a list .*)
845 fun mv_is_negativ([])=false
846 | mv_is_negativ(x::xs)=if x<0 then true else mv_is_negativ(xs);
848 (*. division of monomials .*)
849 fun mv_mdiv((0,[]):mv_monom,_:mv_monom)=(0,[]):mv_monom
850 | mv_mdiv(_,(0,[]))= raise error ("RATIONALS_MV_MDIV_EXCEPTION Division by 0 ")
851 | mv_mdiv(p1:mv_monom,p2:mv_monom)=
857 if !c=0 then raise error("MV_MDIV_EXCEPTION Dividing by zero")
858 else c:=(#1(p1) div #1(p2));
861 pp:=(#2(mv_mmul((1,#2(p1)),(1,(map mv_minus) (#2(p2))))));
862 if mv_is_negativ(!pp) then (0,!pp)
865 else raise error("MV_MDIV_EXCEPTION Dividing by empty Polynom")
869 (*. prints a polynom for (internal use only) .*)
870 fun mv_print_poly([]:mv_poly)=print("[]\n")
871 | mv_print_poly((x,y)::[])= print("("^BasisLibrary.Int.toString(x)^","^ints2str(y)^")\n")
872 | mv_print_poly((x,y)::p1) = (print("("^BasisLibrary.Int.toString(x)^","^ints2str(y)^"),");mv_print_poly(p1));
875 (*. division of two multivariate polynomials .*)
876 fun mv_division([]:mv_poly,g:mv_poly,order)=([]:mv_poly,[]:mv_poly)
877 | mv_division(f,[],order)= raise error ("RATIONALS_MV_DIVISION_EXCEPTION Division by zero")
878 | mv_division(f,g,order)=
887 r := rev(sort (mv_geq order) (mv_shorten(f,order)));
888 g':= rev(sort (mv_geq order) (mv_shorten(g,order)));
889 if #1(hd(!g'))=0 then raise error("RATIONALS_MV_DIVISION_EXCEPTION: Dividing by zero") else ();
890 if (mv_monom_greater (hd(!g'),hd(!r),order)) then ([(0,mv_null2(#2(hd(f))))],(!r))
894 while (if (!exit)=0 then not(mv_monom_greater (hd(!g'),hd(!r),order)) else false) do
896 if (#1(mv_lm(!g',order)))<>0 then m:=mv_mdiv(mv_lm(!r,order),mv_lm(!g',order))
897 else raise error ("RATIONALS_MV_DIVISION_EXCEPTION: Dividing by zero");
901 r:=mv_add((!r),mv_minus2(mv_mul(!g',[!m],order)),order)
904 if (if length(!r)<>0 then length(!g')<>0 else false) then ()
911 (*. multiplies a polynomial with an integer .*)
912 fun mv_skalar_mul([]:mv_poly,c) = []:mv_poly
913 | mv_skalar_mul((x,y)::p1,c) = ((x * c),y)::mv_skalar_mul(p1,c);
915 (*. inserts the a first variable into an polynomial with exponent v .*)
916 fun mv_correct([]:mv_poly,v:int)=[]:mv_poly
917 | mv_correct((x,y)::list,v:int)=(x,v::y)::mv_correct(list,v);
919 (*. multivariate case .*)
921 (*. decides if x is a factor of y .*)
922 fun mv_divides([]:mv_poly,[]:mv_poly)= raise error("RATIONALS_MV_DIVIDES_EXCEPTION: division by zero")
923 | mv_divides(x,[]) = raise error("RATIONALS_MV_DIVIDES_EXCEPTION: division by zero")
924 | mv_divides(x:mv_poly,y:mv_poly) = #2(mv_division(y,x,LEX_))=[];
926 (*. gets the maximum of a and b .*)
927 fun mv_max(a,b) = if a>b then a else b;
929 (*. gets the maximum exponent of a mv polynomial in the lexicographic term order .*)
930 fun mv_deg([]:mv_poly) = 0
933 val p1'=mv_shorten(p1,LEX_);
935 if length(p1')=0 then 0
936 else mv_max(hd(#2(hd(p1'))),mv_deg(tl(p1')))
939 (*. gets the maximum exponent of a mv polynomial in the reverse lexicographic term order .*)
940 fun mv_deg2([]:mv_poly) = 0
943 val p1'=mv_shorten(p1,LEX_);
945 if length(p1')=0 then 0
946 else mv_max(hd(rev(#2(hd(p1')))),mv_deg2(tl(p1')))
949 (*. evaluates the mv polynomial at the value v of the main variable .*)
950 fun mv_subs([]:mv_poly,v) = []:mv_poly
951 | mv_subs((c,e)::p1:mv_poly,v) = mv_skalar_mul(mv_cut([(c,e)]),power v (hd(e))) @ mv_subs(p1,v);
953 (*. calculates the content of a uv-polynomial in mv-representation .*)
954 fun uv_content2([]:mv_poly) = 0
955 | uv_content2((c,e)::p1) = (gcd_int c (uv_content2(p1)));
957 (*. converts a uv-polynomial from mv-representation to uv-representation .*)
958 fun uv_to_list ([]:mv_poly)=[]:uv_poly
959 | uv_to_list ((c1,e1)::others) =
962 val max=mv_grad((c1,e1)::others);
963 val help=ref ((c1,e1)::others);
966 if length(e1)>1 then raise error ("RATIONALS_TO_LIST_EXCEPTION: not univariate")
967 else if length(e1)=0 then [c1]
971 while (!count)<=max do
973 if length(!help)>0 andalso hd(#2(hd(!help)))=max-(!count) then
975 list:=(#1(hd(!help)))::(!list);
982 count := (!count) + 1
988 (*. converts a uv-polynomial from uv-representation to mv-representation .*)
989 fun uv_to_poly ([]:uv_poly) = []:mv_poly
996 while length(!help)>0 do
998 if hd(!help)=0 then ()
999 else list:=(hd(!help),[!count])::(!list);
1006 (*. univariate gcd calculation from polynomials in multivariate representation .*)
1007 fun uv_gcd ([]:mv_poly) p2 = p2
1008 | uv_gcd p1 ([]:mv_poly) = p1
1009 | uv_gcd p1 [(c,[e])] =
1011 val list=ref (rev(sort (mv_geq LEX_) (mv_shorten(p1,LEX_))));
1012 val min=uv_mod_min(e,(hd(#2(hd(rev(!list))))));
1014 [(gcd_int (uv_content2(p1)) c,[min])]
1016 | uv_gcd [(c,[e])] p2 =
1018 val list=ref (rev(sort (mv_geq LEX_) (mv_shorten(p2,LEX_))));
1019 val min=uv_mod_min(e,(hd(#2(hd(rev(!list))))));
1021 [(gcd_int (uv_content2(p2)) c,[min])]
1023 | uv_gcd p11 p22 = uv_to_poly(uv_mod_gcd (uv_to_list(mv_shorten(p11,LEX_))) (uv_to_list(mv_shorten(p22,LEX_))));
1025 (*. help function for the newton interpolation .*)
1026 fun mv_newton_help ([]:mv_poly list,k:int) = []:mv_poly list
1027 | mv_newton_help (pl:mv_poly list,k) =
1029 val x=ref (rev(pl));
1036 while length(!x)>1 do
1038 if length(hd(!x))>0 then n1:=mv_null2(#2(hd(hd(!x))))
1039 else if length(hd(tl(!x)))>0 then n1:=mv_null2(#2(hd(hd(tl(!x)))))
1041 t:= #1(mv_division(mv_add(hd(!x),mv_skalar_mul(hd(tl(!x)),~1),LEX_),[(k,!n1)],LEX_));
1049 (*. help function for the newton interpolation .*)
1050 fun mv_newton_add ([]:mv_poly list) t = []:mv_poly
1051 | mv_newton_add [x:mv_poly] t = x
1052 | mv_newton_add (pl:mv_poly list) t =
1059 while length(!pll)>0 andalso hd(!pll)=[] do
1063 if length(!pll)>0 then expos:= #2(hd(hd(!pll))) else expos:=[];
1066 mv_add(mv_correct(mv_cut([(1,mv_null2(!expos))]),1),[(~t,mv_null2(!expos))],LEX_),
1067 mv_newton_add (tl(pl)) (t+1),
1074 (*. calculates the newton interpolation with polynomial coefficients .*)
1075 (*. step-depth is 1 and if the result is not an integerpolynomial .*)
1076 (*. this function returns [] .*)
1077 fun mv_newton ([]:(mv_poly) list) = []:mv_poly
1078 | mv_newton ([mp]:(mv_poly) list) = mp:mv_poly
1089 c:=mv_newton_help(!c,!k);
1090 c1:=(hd(!c))::(!c1);
1091 while(length(!c)>1 andalso !k<n) do
1094 while length(!c)>0 andalso hd(!c)=[] do c:=tl(!c);
1095 if !c=[] then () else c:=mv_newton_help(!c,!k);
1097 if !c=[] then () else c1:=(hd(!c))::(!c1)
1099 while hd(!c1)=[] do c1:=tl(!c1);
1102 mv_newton_add (!c1) 1
1105 (*. sets the exponents of the first variable to zero .*)
1106 fun mv_null3([]:mv_poly) = []:mv_poly
1107 | mv_null3((x,y)::xs) = (x,0::tl(y))::mv_null3(xs);
1109 (*. calculates the minimum exponents of a multivariate polynomial .*)
1110 fun mv_min_pp([]:mv_poly)=[]
1111 | mv_min_pp((c,e)::xs)=
1118 while length(!y)>0 do
1120 x:=(map uv_mod_min) ((!x) ~~ (#2(hd(!y))));
1127 (*. checks if all elements of the list have value zero .*)
1128 fun list_is_null [] = true
1129 | list_is_null (x::xs) = (x=0 andalso list_is_null(xs));
1131 (* check if main variable is zero*)
1132 fun main_zero (ms : mv_poly) = (list_is_null o (map (hd o #2))) ms;
1134 (*. calculates the content of an polynomial .*)
1135 fun mv_content([]:mv_poly) = []:mv_poly
1138 val list=ref (rev(sort (mv_geq LEX_) (mv_shorten(p1,LEX_))));
1139 val test=ref (hd(#2(hd(!list))));
1141 val min=(hd(#2(hd(rev(!list)))));
1144 if length(!list)>1 then
1146 while (if length(!list)>0 then (hd(#2(hd(!list)))=(!test)) else false) do
1148 result:=(#1(hd(!list)),tl(#2(hd(!list))))::(!result);
1150 if length(!list)<1 then list:=[]
1151 else list:=tl(!list)
1154 if length(!list)>0 then
1156 list:=mv_gcd (!result) (mv_cut(mv_content(!list)))
1158 else list:=(!result);
1159 list:=mv_correct(!list,0);
1169 (*. calculates the primitiv part of a polynomial .*)
1170 and mv_pp([]:mv_poly) = []:mv_poly
1175 cont:=mv_content(p1);
1176 pp:=(#1(mv_division(p1,!cont,LEX_)));
1178 then raise error("RATIONALS_MV_PP_EXCEPTION: Invalid Content ")
1182 (*. calculates the gcd of two multivariate polynomials with a modular approach .*)
1183 and mv_gcd ([]:mv_poly) ([]:mv_poly) :mv_poly= []:mv_poly
1184 | mv_gcd ([]:mv_poly) (p2) :mv_poly= p2:mv_poly
1185 | mv_gcd (p1:mv_poly) ([]) :mv_poly= p1:mv_poly
1186 | mv_gcd ([(x,xs)]:mv_poly) ([(y,ys)]):mv_poly =
1188 val xpoly:mv_poly = [(x,xs)];
1189 val ypoly:mv_poly = [(y,ys)];
1192 if xs=ys then [((gcd_int x y),xs)]
1193 else [((gcd_int x y),(map uv_mod_min)(xs~~ys))]:mv_poly
1196 | mv_gcd (p1:mv_poly) ([(y,ys)]) :mv_poly=
1198 [(gcd_int (uv_content2(p1)) (y),(map uv_mod_min)(mv_min_pp(p1)~~ys))]:mv_poly
1200 | mv_gcd ([(y,ys)]:mv_poly) (p2):mv_poly =
1202 [(gcd_int (uv_content2(p2)) (y),(map uv_mod_min)(mv_min_pp(p2)~~ys))]:mv_poly
1204 | mv_gcd (p1':mv_poly) (p2':mv_poly):mv_poly=
1206 val vc=length(#2(hd(p1')));
1209 if main_zero(mv_content(p1')) andalso
1210 (main_zero(mv_content(p2'))) then
1211 mv_correct((mv_gcd (mv_cut(mv_content(p1'))) (mv_cut(mv_content(p2')))),0)
1213 mv_gcd (mv_content(p1')) (mv_content(p2'))
1215 val p1= #1(mv_division(p1',mv_content(p1'),LEX_));
1216 val p2= #1(mv_division(p2',mv_content(p2'),LEX_));
1218 val candidate=ref [];
1219 val interpolation_list=ref [];
1230 val current_degree=ref 99999; (*. FIXME: unlimited ! .*)
1233 if vc<2 then (* areUnivariate(p1',p2') *)
1235 gcd:=uv_gcd (mv_shorten(p1',LEX_)) (mv_shorten(p2',LEX_))
1242 p1r := mv_lc(p1,LEX_);
1243 p2r := mv_lc(p2,LEX_);
1244 if main_zero(!p1r) andalso
1248 delta := mv_correct((mv_gcd (mv_cut (!p1r)) (mv_cut (!p2r))),0)
1252 delta := mv_gcd (!p1r) (!p2r)
1254 (*if mv_shorten(mv_subs(!p1r,!r),LEX_)=[] andalso
1255 mv_shorten(mv_subs(!p2r,!r),LEX_)=[] *)
1256 if mv_lc2(mv_shorten(mv_subs(!p1r,!r),LEX_),LEX_)=0 andalso
1257 mv_lc2(mv_shorten(mv_subs(!p2r,!r),LEX_),LEX_)=0
1263 gcd_r:=mv_shorten(mv_gcd (mv_shorten(mv_subs(p1,!r),LEX_))
1264 (mv_shorten(mv_subs(p2,!r),LEX_)) ,LEX_);
1265 gcd_r:= #1(mv_division(mv_mul(mv_correct(mv_subs(!delta,!r),0),!gcd_r,LEX_),
1266 mv_correct(mv_lc(!gcd_r,LEX_),0),LEX_));
1267 d:=mv_deg2(!gcd_r); (* deg(gcd_r,z) *)
1268 if (!d < !current_degree) then
1270 current_degree:= !d;
1271 interpolation_list:=mv_correct(!gcd_r,0)::(!interpolation_list)
1275 if (!d = !current_degree) then
1277 interpolation_list:=mv_correct(!gcd_r,0)::(!interpolation_list)
1282 if length(!interpolation_list)> uv_mod_min(mv_deg(p1),mv_deg(p2)) then
1284 candidate := mv_newton(rev(!interpolation_list));
1285 if !candidate=[] then ()
1288 candidate:=mv_pp(!candidate);
1289 if mv_divides(!candidate,p1) andalso mv_divides(!candidate,p2) then
1291 gcd:= mv_mul(!candidate,cont,LEX_);
1296 interpolation_list:=[mv_correct(!gcd_r,0)]
1306 (*. calculates the least common divisor of two polynomials .*)
1307 fun mv_lcm (p1:mv_poly) (p2:mv_poly) :mv_poly =
1309 #1(mv_division(mv_mul(p1,p2,LEX_),mv_gcd p1 p2,LEX_))
1312 (*. gets the variables (strings) of a term .*)
1313 fun get_vars(term1) = (map free2str) (vars term1); (*["a","b","c"]; *)
1315 (*. counts the negative coefficents in a polynomial .*)
1316 fun count_neg ([]:mv_poly) = 0
1317 | count_neg ((c,e)::xs) = if c<0 then 1+count_neg xs
1320 (*. help function for is_polynomial
1321 checks the order of the operators .*)
1322 fun test_polynomial (Const ("uminus",_) $ Free (str,_)) _ = true (*WN.13.3.03*)
1323 | test_polynomial (t as Free(str,_)) v = true
1324 | test_polynomial (t as Const ("op *",_) $ t1 $ t2) v = if v="^" then false
1325 else (test_polynomial t1 "*") andalso (test_polynomial t2 "*")
1326 | test_polynomial (t as Const ("op +",_) $ t1 $ t2) v = if v="*" orelse v="^" then false
1327 else (test_polynomial t1 " ") andalso (test_polynomial t2 " ")
1328 | test_polynomial (t as Const ("Atools.pow",_) $ t1 $ t2) v = (test_polynomial t1 "^") andalso (test_polynomial t2 "^")
1329 | test_polynomial _ v = false;
1331 (*. tests if a term is a polynomial .*)
1332 fun is_polynomial t = test_polynomial t " ";
1334 (*. help function for is_expanded
1335 checks the order of the operators .*)
1336 fun test_exp (t as Free(str,_)) v = true
1337 | test_exp (t as Const ("op *",_) $ t1 $ t2) v = if v="^" then false
1338 else (test_exp t1 "*") andalso (test_exp t2 "*")
1339 | test_exp (t as Const ("op +",_) $ t1 $ t2) v = if v="*" orelse v="^" then false
1340 else (test_exp t1 " ") andalso (test_exp t2 " ")
1341 | test_exp (t as Const ("op -",_) $ t1 $ t2) v = if v="*" orelse v="^" then false
1342 else (test_exp t1 " ") andalso (test_exp t2 " ")
1343 | test_exp (t as Const ("Atools.pow",_) $ t1 $ t2) v = (test_exp t1 "^") andalso (test_exp t2 "^")
1344 | test_exp _ v = false;
1347 (*. help function for check_coeff:
1348 converts the term to a list of coefficients .*)
1349 fun term2coef' (t as Free(str,_(*typ*))) v :mv_poly option =
1357 if is_numeral str then
1359 SOME [(((the o int_of_str) str),mv_null2(v))] handle _ => NONE
1365 while ((!len)>(!i)) do
1367 if str=hd((!vh)) then
1378 SOME [(1,rev(!vl))] handle _ => NONE
1381 | term2coef' (Const ("op *",_) $ t1 $ t2) v :mv_poly option=
1389 t1pp:=(#2(hd(the(term2coef' t1 v))));
1390 t2pp:=(#2(hd(the(term2coef' t2 v))));
1391 t1c:=(#1(hd(the(term2coef' t1 v))));
1392 t2c:=(#1(hd(the(term2coef' t2 v))));
1394 SOME [( (!t1c)*(!t2c) ,( (map op+) ((!t1pp)~~(!t2pp)) ) )] handle _ => NONE
1398 | term2coef' (Const ("Atools.pow",_) $ (t1 as Free (str1,_)) $ (t2 as Free (str2,_))) v :mv_poly option=
1408 if (not o is_numeral) str1 andalso is_numeral str2 then
1413 while ((!len)>(!i)) do
1415 if str1=hd((!vh)) then
1417 vl:=((the o int_of_str) str2)::(!vl)
1426 SOME [(1,rev(!vl))] handle _ => NONE
1428 else raise error ("RATIONALS_TERM2COEF_EXCEPTION 1: Invalid term")
1431 | term2coef' (Const ("op +",_) $ t1 $ t2) v :mv_poly option=
1433 SOME ((the(term2coef' t1 v)) @ (the(term2coef' t2 v))) handle _ => NONE
1435 | term2coef' (Const ("op -",_) $ t1 $ t2) v :mv_poly option=
1437 SOME ((the(term2coef' t1 v)) @ mv_skalar_mul((the(term2coef' t2 v)),1)) handle _ => NONE
1439 | term2coef' (term) v = raise error ("RATIONALS_TERM2COEF_EXCEPTION 2: Invalid term");
1441 (*. checks if all coefficients of a polynomial are positiv (except the first) .*)
1442 fun check_coeff t = (* erste Koeffizient kann <0 sein !!! *)
1443 if count_neg(tl(the(term2coef' t (get_vars(t)))))=0 then true
1446 (*. checks for expanded term [3] .*)
1447 fun is_expanded t = test_exp t " " andalso check_coeff(t);
1449 (*WN.7.3.03 Hilfsfunktion f"ur term2poly'*)
1450 fun mk_monom v' p vs =
1451 let fun conv p (v: string) = if v'= v then p else 0
1452 in map (conv p) vs end;
1453 (* mk_monom "y" 5 ["a","b","x","y","z"];
1454 val it = [0,0,0,5,0] : int list*)
1456 (*. this function converts the term representation into the internal representation mv_poly .*)
1457 fun term2poly' (Const ("uminus",_) $ Free (str,_)) v = (*WN.7.3.03*)
1459 then SOME [((the o int_of_str) ("-"^str), mk_monom "#" 0 v)]
1460 else SOME [(~1, mk_monom str 1 v)]
1462 | term2poly' (Free(str,_)) v :mv_poly option =
1470 if is_numeral str then
1472 SOME [(((the o int_of_str) str),mv_null2 v)] handle _ => NONE
1478 while ((!len)>(!i)) do
1480 if str=hd((!vh)) then
1491 SOME [(1,rev(!vl))] handle _ => NONE
1494 | term2poly' (Const ("op *",_) $ t1 $ t2) v :mv_poly option=
1502 t1pp:=(#2(hd(the(term2poly' t1 v))));
1503 t2pp:=(#2(hd(the(term2poly' t2 v))));
1504 t1c:=(#1(hd(the(term2poly' t1 v))));
1505 t2c:=(#1(hd(the(term2poly' t2 v))));
1507 SOME [( (!t1c)*(!t2c) ,( (map op+) ((!t1pp)~~(!t2pp)) ) )]
1512 | term2poly' (Const ("Atools.pow",_) $ (t1 as Free (str1,_)) $
1513 (t2 as Free (str2,_))) v :mv_poly option=
1523 if (not o is_numeral) str1 andalso is_numeral str2 then
1528 while ((!len)>(!i)) do
1530 if str1=hd((!vh)) then
1532 vl:=((the o int_of_str) str2)::(!vl)
1541 SOME [(1,rev(!vl))] handle _ => NONE
1543 else raise error ("RATIONALS_TERM2POLY_EXCEPTION 1: Invalid term")
1546 | term2poly' (Const ("op +",_) $ t1 $ t2) v :mv_poly option =
1548 SOME ((the(term2poly' t1 v)) @ (the(term2poly' t2 v))) handle _ => NONE
1550 | term2poly' (Const ("op -",_) $ t1 $ t2) v :mv_poly option =
1552 SOME ((the(term2poly' t1 v)) @ mv_skalar_mul((the(term2poly' t2 v)),~1)) handle _ => NONE
1554 | term2poly' (term) v = raise error ("RATIONALS_TERM2POLY_EXCEPTION 2: Invalid term");
1556 (*. translates an Isabelle term into internal representation.
1558 fn : term -> (*normalform [2] *)
1559 string list -> (*for ...!!! BITTE DIE ERKLÄRUNG,
1560 DIE DU MIR LETZTES MAL GEGEBEN HAST*)
1561 mv_monom list (*internal representation *)
1562 option (*the translation may fail with NONE*)
1564 fun term2poly (t:term) v =
1565 if is_polynomial t then term2poly' t v
1566 else raise error ("term2poly: invalid = "^(term2str t));
1568 (*. same as term2poly with automatic detection of the variables .*)
1569 fun term2polyx t = term2poly t (((map free2str) o vars) t);
1571 (*. checks if the term is in expanded polynomial form and converts it into the internal representation .*)
1572 fun expanded2poly (t:term) v =
1573 (*if is_expanded t then*) term2poly' t v
1574 (*else raise error ("RATIONALS_EXPANDED2POLY_EXCEPTION: Invalid Polynomial")*);
1576 (*. same as expanded2poly with automatic detection of the variables .*)
1577 fun expanded2polyx t = expanded2poly t (((map free2str) o vars) t);
1579 (*. converts a powerproduct into term representation .*)
1580 fun powerproduct2term(xs,v) =
1592 if list_is_null(tl(!xss)) then
1594 if hd(!xss)=1 then Free(hd(!vv), HOLogic.realT)
1597 Const("Atools.pow",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT) $
1598 Free(hd(!vv), HOLogic.realT) $ Free(str_of_int (hd(!xss)),HOLogic.realT)
1605 Const("op *",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT) $
1606 Free(hd(!vv), HOLogic.realT) $
1607 powerproduct2term(tl(!xss),tl(!vv))
1611 Const("op *",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT) $
1613 Const("Atools.pow",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT) $
1614 Free(hd(!vv), HOLogic.realT) $ Free(str_of_int (hd(!xss)),HOLogic.realT)
1616 powerproduct2term(tl(!xss),tl(!vv))
1622 (*. converts a monom into term representation .*)
1623 (*fun monom2term ((c,e):mv_monom, v:string list) =
1624 if c=0 then Free(str_of_int 0,HOLogic.realT)
1627 if list_is_null(e) then
1629 Free(str_of_int c,HOLogic.realT)
1635 powerproduct2term(e,v)
1639 Const("op *",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT) $
1640 Free(str_of_int c,HOLogic.realT) $
1641 powerproduct2term(e,v)
1647 (*fun monom2term ((i, is):mv_monom, v) =
1651 then Free (str_of_int i, HOLogic.realT)
1652 else Const ("uminus", HOLogic.realT --> HOLogic.realT) $
1653 Free ((str_of_int o abs) i, HOLogic.realT)
1656 then Const ("op *", [HOLogic.realT,HOLogic.realT]---> HOLogic.realT) $
1657 (Free (str_of_int i, HOLogic.realT)) $
1658 powerproduct2term(is, v)
1659 else Const ("op *", [HOLogic.realT,HOLogic.realT]---> HOLogic.realT) $
1660 (Const ("uminus", HOLogic.realT --> HOLogic.realT) $
1661 Free ((str_of_int o abs) i, HOLogic.realT)) $
1662 powerproduct2term(is, vs);---------------------------*)
1663 fun monom2term ((i, is) : mv_monom, vs) =
1665 then Free (str_of_int i, HOLogic.realT)
1667 then powerproduct2term (is, vs)
1668 else Const ("op *", [HOLogic.realT, HOLogic.realT] ---> HOLogic.realT) $
1669 (Free (str_of_int i, HOLogic.realT)) $
1670 powerproduct2term (is, vs);
1672 (*. converts the internal polynomial representation into an Isabelle term.*)
1673 fun poly2term' ([] : mv_poly, vs) = Free(str_of_int 0, HOLogic.realT)
1674 | poly2term' ([(c, e) : mv_monom], vs) = monom2term ((c, e), vs)
1675 | poly2term' ((c, e) :: ces, vs) =
1676 Const("op +", [HOLogic.realT, HOLogic.realT] ---> HOLogic.realT) $
1677 poly2term (ces, vs) $ monom2term ((c, e), vs)
1678 and poly2term (xs, vs) = poly2term' (rev (sort (mv_geq LEX_) (xs)), vs);
1681 (*. converts a monom into term representation .*)
1682 (*. ignores the sign of the coefficients => use only for exp-poly functions .*)
1683 fun monom2term2((c,e):mv_monom, v:string list) =
1684 if c=0 then Free(str_of_int 0,HOLogic.realT)
1687 if list_is_null(e) then
1689 Free(str_of_int (abs(c)),HOLogic.realT)
1695 powerproduct2term(e,v)
1699 Const("op *",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT) $
1700 Free(str_of_int (abs(c)),HOLogic.realT) $
1701 powerproduct2term(e,v)
1706 (*. converts the expanded polynomial representation into the term representation .*)
1707 fun exp2term' ([]:mv_poly,vars) = Free(str_of_int 0,HOLogic.realT)
1708 | exp2term' ([(c,e)],vars) = monom2term((c,e),vars)
1709 | exp2term' ((c1,e1)::others,vars) =
1711 Const("op -",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT) $
1712 exp2term'(others,vars) $
1714 monom2term2((c1,e1),vars)
1717 Const("op +",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT) $
1718 exp2term'(others,vars) $
1720 monom2term2((c1,e1),vars)
1723 (*. sorts the powerproduct by lexicographic termorder and converts them into
1724 a term in polynomial representation .*)
1725 fun poly2expanded (xs,vars) = exp2term'(rev(sort (mv_geq LEX_) (xs)),vars);
1727 (*. converts a polynomial into expanded form .*)
1728 fun polynomial2expanded t =
1730 val vars=(((map free2str) o vars) t);
1732 SOME (poly2expanded (the (term2poly t vars), vars))
1733 end) handle _ => NONE;
1735 (*. converts a polynomial into polynomial form .*)
1736 fun expanded2polynomial t =
1738 val vars=(((map free2str) o vars) t);
1740 SOME (poly2term (the (expanded2poly t vars), vars))
1741 end) handle _ => NONE;
1744 (*. calculates the greatest common divisor of numerator and denominator and seperates it from each .*)
1745 fun step_cancel (t as Const ("HOL.divide",_) $ p1 $ p2) =
1750 val vars = rev(get_vars(p1) union get_vars(p2));
1753 p1':= sort (mv_geq LEX_) (the (term2poly p1 vars ));
1754 p2':= sort (mv_geq LEX_) (the (term2poly p2 vars ));
1755 p3:= sort (mv_geq LEX_) (mv_gcd (!p1') (!p2'));
1756 if (!p3)=[(1,mv_null2(vars))] then
1758 Const ("HOL.divide",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT) $ p1 $ p2
1763 p1':=sort (mv_geq LEX_) (#1(mv_division((!p1'),(!p3),LEX_)));
1764 p2':=sort (mv_geq LEX_) (#1(mv_division((!p2'),(!p3),LEX_)));
1766 if #1(hd(sort (mv_geq LEX_) (!p2'))) (*mv_lc2(!p2',LEX_)*)>0 then
1768 Const ("HOL.divide",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT)
1771 Const ("op *",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT) $
1772 poly2term(!p1',vars) $
1777 Const ("op *",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT) $
1778 poly2term(!p2',vars) $
1784 p1':=mv_skalar_mul(!p1',~1);
1785 p2':=mv_skalar_mul(!p2',~1);
1786 p3:=mv_skalar_mul(!p3,~1);
1788 Const ("HOL.divide",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT)
1791 Const ("op *",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT) $
1792 poly2term(!p1',vars) $
1797 Const ("op *",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT) $
1798 poly2term(!p2',vars) $
1806 | step_cancel _ = raise error ("RATIONALS_STEP_CANCEL_EXCEPTION: Invalid fraction");
1809 (*. same as step_cancel, this time for expanded forms (input+output) .*)
1810 fun step_cancel_expanded (t as Const ("HOL.divide",_) $ p1 $ p2) =
1815 val vars = rev(get_vars(p1) union get_vars(p2));
1818 p1':= sort (mv_geq LEX_) (the (expanded2poly p1 vars ));
1819 p2':= sort (mv_geq LEX_) (the (expanded2poly p2 vars ));
1820 p3:= sort (mv_geq LEX_) (mv_gcd (!p1') (!p2'));
1821 if (!p3)=[(1,mv_null2(vars))] then
1823 Const ("HOL.divide",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT) $ p1 $ p2
1828 p1':=sort (mv_geq LEX_) (#1(mv_division((!p1'),(!p3),LEX_)));
1829 p2':=sort (mv_geq LEX_) (#1(mv_division((!p2'),(!p3),LEX_)));
1831 if #1(hd(sort (mv_geq LEX_) (!p2')))(* mv_lc2(!p2',LEX_)*)>0 then
1833 Const ("HOL.divide",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT)
1836 Const ("op *",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT) $
1837 poly2expanded(!p1',vars) $
1838 poly2expanded(!p3,vars)
1842 Const ("op *",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT) $
1843 poly2expanded(!p2',vars) $
1844 poly2expanded(!p3,vars)
1849 p1':=mv_skalar_mul(!p1',~1);
1850 p2':=mv_skalar_mul(!p2',~1);
1851 p3:=mv_skalar_mul(!p3,~1);
1853 Const ("HOL.divide",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT)
1856 Const ("op *",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT) $
1857 poly2expanded(!p1',vars) $
1858 poly2expanded(!p3,vars)
1862 Const ("op *",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT) $
1863 poly2expanded(!p2',vars) $
1864 poly2expanded(!p3,vars)
1871 | step_cancel_expanded _ = raise error ("RATIONALS_STEP_CANCEL_EXCEPTION: Invalid fraction");
1873 (*. calculates the greatest common divisor of numerator and denominator and divides each through it .*)
1874 fun direct_cancel (t as Const ("HOL.divide",_) $ p1 $ p2) =
1879 val vars = rev(get_vars(p1) union get_vars(p2));
1882 p1':=sort (mv_geq LEX_) (mv_shorten((the (term2poly p1 vars )),LEX_));
1883 p2':=sort (mv_geq LEX_) (mv_shorten((the (term2poly p2 vars )),LEX_));
1884 p3 :=sort (mv_geq LEX_) (mv_gcd (!p1') (!p2'));
1886 if (!p3)=[(1,mv_null2(vars))] then
1888 (Const ("HOL.divide",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT) $ p1 $ p2,[])
1892 p1':=sort (mv_geq LEX_) (#1(mv_division((!p1'),(!p3),LEX_)));
1893 p2':=sort (mv_geq LEX_) (#1(mv_division((!p2'),(!p3),LEX_)));
1894 if #1(hd(sort (mv_geq LEX_) (!p2'))) (*mv_lc2(!p2',LEX_)*)>0 then
1897 Const ("HOL.divide",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT)
1900 poly2term((!p1'),vars)
1904 poly2term((!p2'),vars)
1908 if mv_grad(!p3)>0 then
1911 Const ("Not",[bool]--->bool) $
1913 Const("op =",[HOLogic.realT,HOLogic.realT]--->bool) $
1914 poly2term((!p3),vars) $
1915 Free("0",HOLogic.realT)
1924 p1':=mv_skalar_mul(!p1',~1);
1925 p2':=mv_skalar_mul(!p2',~1);
1926 if length(!p3)> 2*(count_neg(!p3)) then () else p3 :=mv_skalar_mul(!p3,~1);
1928 Const ("HOL.divide",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT)
1931 poly2term((!p1'),vars)
1935 poly2term((!p2'),vars)
1938 if mv_grad(!p3)>0 then
1941 Const ("Not",[bool]--->bool) $
1943 Const("op =",[HOLogic.realT,HOLogic.realT]--->bool) $
1944 poly2term((!p3),vars) $
1945 Free("0",HOLogic.realT)
1956 | direct_cancel _ = raise error ("RATIONALS_DIRECT_CANCEL_EXCEPTION: Invalid fraction");
1958 (*. same es direct_cancel, this time for expanded forms (input+output).*)
1959 fun direct_cancel_expanded (t as Const ("HOL.divide",_) $ p1 $ p2) =
1964 val vars = rev(get_vars(p1) union get_vars(p2));
1967 p1':=sort (mv_geq LEX_) (mv_shorten((the (expanded2poly p1 vars )),LEX_));
1968 p2':=sort (mv_geq LEX_) (mv_shorten((the (expanded2poly p2 vars )),LEX_));
1969 p3 :=sort (mv_geq LEX_) (mv_gcd (!p1') (!p2'));
1971 if (!p3)=[(1,mv_null2(vars))] then
1973 (Const ("HOL.divide",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT) $ p1 $ p2,[])
1977 p1':=sort (mv_geq LEX_) (#1(mv_division((!p1'),(!p3),LEX_)));
1978 p2':=sort (mv_geq LEX_) (#1(mv_division((!p2'),(!p3),LEX_)));
1979 if #1(hd(sort (mv_geq LEX_) (!p2'))) (*mv_lc2(!p2',LEX_)*)>0 then
1982 Const ("HOL.divide",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT)
1985 poly2expanded((!p1'),vars)
1989 poly2expanded((!p2'),vars)
1993 if mv_grad(!p3)>0 then
1996 Const ("Not",[bool]--->bool) $
1998 Const("op =",[HOLogic.realT,HOLogic.realT]--->bool) $
1999 poly2expanded((!p3),vars) $
2000 Free("0",HOLogic.realT)
2009 p1':=mv_skalar_mul(!p1',~1);
2010 p2':=mv_skalar_mul(!p2',~1);
2011 if length(!p3)> 2*(count_neg(!p3)) then () else p3 :=mv_skalar_mul(!p3,~1);
2013 Const ("HOL.divide",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT)
2016 poly2expanded((!p1'),vars)
2020 poly2expanded((!p2'),vars)
2023 if mv_grad(!p3)>0 then
2026 Const ("Not",[bool]--->bool) $
2028 Const("op =",[HOLogic.realT,HOLogic.realT]--->bool) $
2029 poly2expanded((!p3),vars) $
2030 Free("0",HOLogic.realT)
2041 | direct_cancel_expanded _ = raise error ("RATIONALS_DIRECT_CANCEL_EXCEPTION: Invalid fraction");
2044 (*. adds two fractions .*)
2045 fun add_fract ((Const("HOL.divide",_) $ t11 $ t12),(Const("HOL.divide",_) $ t21 $ t22)) =
2047 val vars=get_vars(t11) union get_vars(t12) union get_vars(t21) union get_vars(t22);
2048 val t11'=ref (the(term2poly t11 vars));
2049 val _= writeln"### add_fract: done t11"
2050 val t12'=ref (the(term2poly t12 vars));
2051 val _= writeln"### add_fract: done t12"
2052 val t21'=ref (the(term2poly t21 vars));
2053 val _= writeln"### add_fract: done t21"
2054 val t22'=ref (the(term2poly t22 vars));
2055 val _= writeln"### add_fract: done t22"
2063 den :=sort (mv_geq LEX_) (mv_lcm (!t12') (!t22'));
2064 writeln"### add_fract: done sort mv_lcm";
2065 m1 :=sort (mv_geq LEX_) (#1(mv_division(!den,!t12',LEX_)));
2066 writeln"### add_fract: done sort mv_division t12";
2067 m2 :=sort (mv_geq LEX_) (#1(mv_division(!den,!t22',LEX_)));
2068 writeln"### add_fract: done sort mv_division t22";
2069 nom :=sort (mv_geq LEX_)
2070 (mv_shorten(mv_add(mv_mul(!t11',!m1,LEX_),
2071 mv_mul(!t21',!m2,LEX_),
2074 writeln"### add_fract: done sort mv_add";
2076 Const ("HOL.divide",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT)
2079 poly2term((!nom),vars)
2083 poly2term((!den),vars)
2088 | add_fract (_,_) = raise error ("RATIONALS_ADD_FRACTION_EXCEPTION: Invalid add_fraction call");
2090 (*. adds two expanded fractions .*)
2091 fun add_fract_exp ((Const("HOL.divide",_) $ t11 $ t12),(Const("HOL.divide",_) $ t21 $ t22)) =
2093 val vars=get_vars(t11) union get_vars(t12) union get_vars(t21) union get_vars(t22);
2094 val t11'=ref (the(expanded2poly t11 vars));
2095 val t12'=ref (the(expanded2poly t12 vars));
2096 val t21'=ref (the(expanded2poly t21 vars));
2097 val t22'=ref (the(expanded2poly t22 vars));
2105 den :=sort (mv_geq LEX_) (mv_lcm (!t12') (!t22'));
2106 m1 :=sort (mv_geq LEX_) (#1(mv_division(!den,!t12',LEX_)));
2107 m2 :=sort (mv_geq LEX_) (#1(mv_division(!den,!t22',LEX_)));
2108 nom :=sort (mv_geq LEX_) (mv_shorten(mv_add(mv_mul(!t11',!m1,LEX_),mv_mul(!t21',!m2,LEX_),LEX_),LEX_));
2110 Const ("HOL.divide",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT)
2113 poly2expanded((!nom),vars)
2117 poly2expanded((!den),vars)
2122 | add_fract_exp (_,_) = raise error ("RATIONALS_ADD_FRACTION_EXP_EXCEPTION: Invalid add_fraction call");
2124 (*. adds a list of terms .*)
2125 fun add_list_of_fractions []= (Free("0",HOLogic.realT),[])
2126 | add_list_of_fractions [x]= direct_cancel x
2127 | add_list_of_fractions (x::y::xs) =
2129 val (t1a,rest1)=direct_cancel(x);
2130 val _= writeln"### add_list_of_fractions xs: has done direct_cancel(x)";
2131 val (t2a,rest2)=direct_cancel(y);
2132 val _= writeln"### add_list_of_fractions xs: has done direct_cancel(y)";
2133 val (t3a,rest3)=(add_list_of_fractions (add_fract(t1a,t2a)::xs));
2134 val _= writeln"### add_list_of_fractions xs: has done add_list_of_fraction xs";
2135 val (t4a,rest4)=direct_cancel(t3a);
2136 val _= writeln"### add_list_of_fractions xs: has done direct_cancel(t3a)";
2137 val rest=rest1 union rest2 union rest3 union rest4;
2139 (writeln"### add_list_of_fractions in";
2146 (*. adds a list of expanded terms .*)
2147 fun add_list_of_fractions_exp []= (Free("0",HOLogic.realT),[])
2148 | add_list_of_fractions_exp [x]= direct_cancel_expanded x
2149 | add_list_of_fractions_exp (x::y::xs) =
2151 val (t1a,rest1)=direct_cancel_expanded(x);
2152 val (t2a,rest2)=direct_cancel_expanded(y);
2153 val (t3a,rest3)=(add_list_of_fractions_exp (add_fract_exp(t1a,t2a)::xs));
2154 val (t4a,rest4)=direct_cancel_expanded(t3a);
2155 val rest=rest1 union rest2 union rest3 union rest4;
2162 (*. calculates the lcm of a list of mv_poly .*)
2163 fun calc_lcm ([x],var)= (x,var)
2164 | calc_lcm ((x::xs),var) = (mv_lcm x (#1(calc_lcm (xs,var))),var);
2166 (*. converts a list of terms to a list of mv_poly .*)
2168 | t2d((t as (Const("HOL.divide",_) $ p1 $ p2))::xs,vars)= (the(term2poly p2 vars)) :: t2d(xs,vars);
2170 (*. same as t2d, this time for expanded forms .*)
2171 fun t2d_exp([],_)=[]
2172 | t2d_exp((t as (Const("HOL.divide",_) $ p1 $ p2))::xs,vars)= (the(expanded2poly p2 vars)) :: t2d_exp(xs,vars);
2174 (*. converts a list of fract terms to a list of their denominators .*)
2175 fun termlist2denominators [] = ([],[])
2176 | termlist2denominators xs =
2182 while length(!xxs)>0 do
2185 val (t as Const ("HOL.divide",_) $ p1x $ p2x)=hd(!xxs);
2189 var:=((get_vars(p2x)) union (get_vars(p1x)) union (!var))
2196 (*. calculates the lcm of a list of mv_poly .*)
2197 fun calc_lcm ([x],var)= (x,var)
2198 | calc_lcm ((x::xs),var) = (mv_lcm x (#1(calc_lcm (xs,var))),var);
2200 (*. converts a list of terms to a list of mv_poly .*)
2202 | t2d((t as (Const("HOL.divide",_) $ p1 $ p2))::xs,vars)= (the(term2poly p2 vars)) :: t2d(xs,vars);
2204 (*. same as t2d, this time for expanded forms .*)
2205 fun t2d_exp([],_)=[]
2206 | t2d_exp((t as (Const("HOL.divide",_) $ p1 $ p2))::xs,vars)= (the(expanded2poly p2 vars)) :: t2d_exp(xs,vars);
2208 (*. converts a list of fract terms to a list of their denominators .*)
2209 fun termlist2denominators [] = ([],[])
2210 | termlist2denominators xs =
2216 while length(!xxs)>0 do
2219 val (t as Const ("HOL.divide",_) $ p1x $ p2x)=hd(!xxs);
2223 var:=((get_vars(p2x)) union (get_vars(p1x)) union (!var))
2230 (*. same as termlist2denminators, this time for expanded forms .*)
2231 fun termlist2denominators_exp [] = ([],[])
2232 | termlist2denominators_exp xs =
2238 while length(!xxs)>0 do
2241 val (t as Const ("HOL.divide",_) $ p1x $ p2x)=hd(!xxs);
2245 var:=((get_vars(p2x)) union (get_vars(p1x)) union (!var))
2249 (t2d_exp(xs,!var),!var)
2252 (*. reduces all fractions to the least common denominator .*)
2253 fun com_den(x::xs,denom,den,var)=
2255 val (t as Const ("HOL.divide",_) $ p1' $ p2')=x;
2256 val p2= sort (mv_geq LEX_) (the(term2poly p2' var));
2257 val p3= #1(mv_division(denom,p2,LEX_));
2258 val p1var=get_vars(p1');
2260 if length(xs)>0 then
2261 if p3=[(1,mv_null2(var))] then
2263 Const ("op +",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT)
2266 Const ("HOL.divide",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT)
2268 poly2term(the (term2poly p1' p1var),p1var)
2273 #1(com_den(xs,denom,den,var))
2279 Const ("op +",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT)
2282 Const ("HOL.divide",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT)
2285 Const ("op *",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT) $
2286 poly2term(the (term2poly p1' p1var),p1var) $
2295 #1(com_den(xs,denom,den,var))
2300 if p3=[(1,mv_null2(var))] then
2303 Const ("HOL.divide",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT)
2305 poly2term(the (term2poly p1' p1var),p1var)
2314 Const ("HOL.divide",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT)
2317 Const ("op *",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT) $
2318 poly2term(the (term2poly p1' p1var),p1var) $
2328 (*. same as com_den, this time for expanded forms .*)
2329 fun com_den_exp(x::xs,denom,den,var)=
2331 val (t as Const ("HOL.divide",_) $ p1' $ p2')=x;
2332 val p2= sort (mv_geq LEX_) (the(expanded2poly p2' var));
2333 val p3= #1(mv_division(denom,p2,LEX_));
2334 val p1var=get_vars(p1');
2336 if length(xs)>0 then
2337 if p3=[(1,mv_null2(var))] then
2339 Const ("op +",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT)
2342 Const ("HOL.divide",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT)
2344 poly2expanded(the(expanded2poly p1' p1var),p1var)
2349 #1(com_den_exp(xs,denom,den,var))
2355 Const ("op +",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT)
2358 Const ("HOL.divide",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT)
2361 Const ("op *",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT) $
2362 poly2expanded(the(expanded2poly p1' p1var),p1var) $
2363 poly2expanded(p3,var)
2371 #1(com_den_exp(xs,denom,den,var))
2376 if p3=[(1,mv_null2(var))] then
2379 Const ("HOL.divide",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT)
2381 poly2expanded(the(expanded2poly p1' p1var),p1var)
2390 Const ("HOL.divide",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT)
2393 Const ("op *",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT) $
2394 poly2expanded(the(expanded2poly p1' p1var),p1var) $
2395 poly2expanded(p3,var)
2404 (* wird aktuell nicht mehr gebraucht, bei rückänderung schon
2405 -------------------------------------------------------------
2406 (* WN0210???SK brauch ma des überhaupt *)
2407 fun com_den2(x::xs,denom,den,var)=
2409 val (t as Const ("HOL.divide",_) $ p1' $ p2')=x;
2410 val p2= sort (mv_geq LEX_) (the(term2poly p2' var));
2411 val p3= #1(mv_division(denom,p2,LEX_));
2412 val p1var=get_vars(p1');
2414 if length(xs)>0 then
2415 if p3=[(1,mv_null2(var))] then
2417 Const ("op +",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT) $
2418 poly2term(the(term2poly p1' p1var),p1var) $
2419 com_den2(xs,denom,den,var)
2423 Const ("op +",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT) $
2426 val p3'=poly2term(p3,var);
2427 val vars= (((map free2str) o vars) p1') union (((map free2str) o vars) p3');
2429 poly2term(sort (mv_geq LEX_) (mv_mul(the(term2poly p1' vars) ,the(term2poly p3' vars),LEX_)),vars)
2432 com_den2(xs,denom,den,var)
2435 if p3=[(1,mv_null2(var))] then
2437 poly2term(the(term2poly p1' p1var),p1var)
2442 val p3'=poly2term(p3,var);
2443 val vars= (((map free2str) o vars) p1') union (((map free2str) o vars) p3');
2445 poly2term(sort (mv_geq LEX_) (mv_mul(the(term2poly p1' vars) ,the(term2poly p3' vars),LEX_)),vars)
2450 (* WN0210???SK brauch ma des überhaupt *)
2451 fun com_den_exp2(x::xs,denom,den,var)=
2453 val (t as Const ("HOL.divide",_) $ p1' $ p2')=x;
2454 val p2= sort (mv_geq LEX_) (the(expanded2poly p2' var));
2455 val p3= #1(mv_division(denom,p2,LEX_));
2456 val p1var=get_vars p1';
2458 if length(xs)>0 then
2459 if p3=[(1,mv_null2(var))] then
2461 Const ("op +",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT) $
2462 poly2expanded(the (expanded2poly p1' p1var),p1var) $
2463 com_den_exp2(xs,denom,den,var)
2467 Const ("op +",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT) $
2470 val p3'=poly2expanded(p3,var);
2471 val vars= (((map free2str) o vars) p1') union (((map free2str) o vars) p3');
2473 poly2expanded(sort (mv_geq LEX_) (mv_mul(the(expanded2poly p1' vars) ,the(expanded2poly p3' vars),LEX_)),vars)
2476 com_den_exp2(xs,denom,den,var)
2479 if p3=[(1,mv_null2(var))] then
2481 poly2expanded(the (expanded2poly p1' p1var),p1var)
2486 val p3'=poly2expanded(p3,var);
2487 val vars= (((map free2str) o vars) p1') union (((map free2str) o vars) p3');
2489 poly2expanded(sort (mv_geq LEX_) (mv_mul(the(expanded2poly p1' vars) ,the(expanded2poly p3' vars),LEX_)),vars)
2493 ---------------------------------------------------------*)
2496 (*. searches for an element y of a list ys, which has an gcd not 1 with x .*)
2497 fun exists_gcd (x,[]) = false
2498 | exists_gcd (x,y::ys) = if mv_gcd x y = [(1,mv_null2(#2(hd(x))))] then exists_gcd (x,ys)
2501 (*. divides each element of the list xs with y .*)
2502 fun list_div ([],y) = []
2503 | list_div (x::xs,y) =
2505 val (d,r)=mv_division(x,y,LEX_);
2509 else x::list_div(xs,y)
2512 (*. checks if x is in the list ys .*)
2513 fun in_list (x,[]) = false
2514 | in_list (x,y::ys) = if x=y then true
2517 (*. deletes all equal elements of the list xs .*)
2518 fun kill_equal [] = []
2519 | kill_equal (x::xs) = if in_list(x,xs) orelse x=[(1,mv_null2(#2(hd(x))))] then kill_equal(xs)
2520 else x::kill_equal(xs);
2522 (*. searches for new factors .*)
2523 fun new_factors [] = []
2524 | new_factors (list:mv_poly list):mv_poly list =
2526 val l = kill_equal list;
2527 val len = length(l);
2535 if gcd=[(1,mv_null2(#2(hd(x))))] then
2537 if exists_gcd(x,xs) then new_factors (y::xs @ [x])
2538 else x::new_factors(y::xs)
2540 else gcd::new_factors(kill_equal(list_div(x::y::xs,gcd)))
2544 if len=1 then [hd(l)]
2548 (*. gets the factors of a list .*)
2549 fun get_factors x = new_factors x;
2551 (*. multiplies the elements of the list .*)
2552 fun multi_list [] = []
2553 | multi_list (x::xs) = if xs=[] then x
2554 else mv_mul(x,multi_list xs,LEX_);
2556 (*. makes a term out of the elements of the list (polynomial representation) .*)
2557 fun make_term ([],vars) = Free(str_of_int 0,HOLogic.realT)
2558 | make_term ((x::xs),vars) = if length(xs)=0 then poly2term(sort (mv_geq LEX_) (x),vars)
2561 Const ("op *",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT) $
2562 poly2term(sort (mv_geq LEX_) (x),vars) $
2566 (*. factorizes the denominator (polynomial representation) .*)
2567 fun factorize_den (l,den,vars) =
2569 val factor_list=kill_equal( (get_factors l));
2570 val mlist=multi_list(factor_list);
2571 val (last,rest)=mv_division(den,multi_list(factor_list),LEX_);
2575 if last=[(1,mv_null2(vars))] then make_term(factor_list,vars)
2576 else make_term(last::factor_list,vars)
2578 else raise error ("RATIONALS_FACTORIZE_DEN_EXCEPTION: Invalid factor by division")
2581 (*. makes a term out of the elements of the list (expanded polynomial representation) .*)
2582 fun make_exp ([],vars) = Free(str_of_int 0,HOLogic.realT)
2583 | make_exp ((x::xs),vars) = if length(xs)=0 then poly2expanded(sort (mv_geq LEX_) (x),vars)
2586 Const ("op *",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT) $
2587 poly2expanded(sort (mv_geq LEX_) (x),vars) $
2591 (*. factorizes the denominator (expanded polynomial representation) .*)
2592 fun factorize_den_exp (l,den,vars) =
2594 val factor_list=kill_equal( (get_factors l));
2595 val mlist=multi_list(factor_list);
2596 val (last,rest)=mv_division(den,multi_list(factor_list),LEX_);
2600 if last=[(1,mv_null2(vars))] then make_exp(factor_list,vars)
2601 else make_exp(last::factor_list,vars)
2603 else raise error ("RATIONALS_FACTORIZE_DEN_EXP_EXCEPTION: Invalid factor by division")
2606 (*. calculates the common denominator of all elements of the list and multiplies .*)
2607 (*. the nominators and denominators with the correct factor .*)
2608 (*. (polynomial representation) .*)
2609 fun step_add_list_of_fractions []=(Free("0",HOLogic.realT),[]:term list)
2610 | step_add_list_of_fractions [x]= raise error ("RATIONALS_STEP_ADD_LIST_OF_FRACTIONS_EXCEPTION: Nothing to add")
2611 | step_add_list_of_fractions (xs) =
2613 val den_list=termlist2denominators (xs); (* list of denominators *)
2614 val (denom,var)=calc_lcm(den_list); (* common denominator *)
2615 val den=factorize_den(#1(den_list),denom,var); (* faktorisierter Nenner !!! *)
2617 com_den(xs,denom,den,var)
2620 (*. calculates the common denominator of all elements of the list and multiplies .*)
2621 (*. the nominators and denominators with the correct factor .*)
2622 (*. (expanded polynomial representation) .*)
2623 fun step_add_list_of_fractions_exp [] = (Free("0",HOLogic.realT),[]:term list)
2624 | step_add_list_of_fractions_exp [x] = raise error ("RATIONALS_STEP_ADD_LIST_OF_FRACTIONS_EXP_EXCEPTION: Nothing to add")
2625 | step_add_list_of_fractions_exp (xs)=
2627 val den_list=termlist2denominators_exp (xs); (* list of denominators *)
2628 val (denom,var)=calc_lcm(den_list); (* common denominator *)
2629 val den=factorize_den_exp(#1(den_list),denom,var); (* faktorisierter Nenner !!! *)
2631 com_den_exp(xs,denom,den,var)
2634 (* wird aktuell nicht mehr gebraucht, bei rückänderung schon
2635 -------------------------------------------------------------
2636 (* WN0210???SK brauch ma des überhaupt *)
2637 fun step_add_list_of_fractions2 []=(Free("0",HOLogic.realT),[]:term list)
2638 | step_add_list_of_fractions2 [x]=(x,[])
2639 | step_add_list_of_fractions2 (xs) =
2641 val den_list=termlist2denominators (xs); (* list of denominators *)
2642 val (denom,var)=calc_lcm(den_list); (* common denominator *)
2643 val den=factorize_den(#1(den_list),denom,var); (* faktorisierter Nenner !!! *)
2646 Const ("HOL.divide",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT) $
2647 com_den2(xs,denom, poly2term(denom,var)(*den*),var) $
2648 poly2term(denom,var)
2654 (* WN0210???SK brauch ma des überhaupt *)
2655 fun step_add_list_of_fractions2_exp []=(Free("0",HOLogic.realT),[]:term list)
2656 | step_add_list_of_fractions2_exp [x]=(x,[])
2657 | step_add_list_of_fractions2_exp (xs) =
2659 val den_list=termlist2denominators_exp (xs); (* list of denominators *)
2660 val (denom,var)=calc_lcm(den_list); (* common denominator *)
2661 val den=factorize_den_exp(#1(den_list),denom,var); (* faktorisierter Nenner !!! *)
2664 Const ("HOL.divide",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT) $
2665 com_den_exp2(xs,denom, poly2term(denom,var)(*den*),var) $
2666 poly2expanded(denom,var)
2671 ---------------------------------------------- *)
2674 (*. converts a term, which contains severel terms seperated by +, into a list of these terms .*)
2675 fun term2list (t as (Const("HOL.divide",_) $ _ $ _)) = [t]
2676 | term2list (t as (Const("Atools.pow",_) $ _ $ _)) =
2677 [Const("HOL.divide",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT) $
2678 t $ Free("1",HOLogic.realT)
2680 | term2list (t as (Free(_,_))) =
2681 [Const("HOL.divide",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT) $
2682 t $ Free("1",HOLogic.realT)
2684 | term2list (t as (Const("op *",_) $ _ $ _)) =
2685 [Const("HOL.divide",[HOLogic.realT,HOLogic.realT]--->HOLogic.realT) $
2686 t $ Free("1",HOLogic.realT)
2688 | term2list (Const("op +",_) $ t1 $ t2) = term2list(t1) @ term2list(t2)
2689 | term2list (Const("op -",_) $ t1 $ t2) =
2690 raise error ("RATIONALS_TERM2LIST_EXCEPTION: - not implemented yet")
2691 | term2list _ = raise error ("RATIONALS_TERM2LIST_EXCEPTION: invalid term");
2693 (*.factors out the gcd of nominator and denominator:
2694 a/b = (a' * gcd)/(b' * gcd), a,b,gcd are poly[2].*)
2695 fun factout_p_ (thy:theory) t = SOME (step_cancel t,[]:term list);
2696 fun factout_ (thy:theory) t = SOME (step_cancel_expanded t,[]:term list);
2698 (*.cancels a single fraction with normalform [2]
2699 resulting in a canceled fraction [2], see factout_ .*)
2700 fun cancel_p_ (thy:theory) t = (*WN.2.6.03 no rewrite -> NONE !*)
2701 (let val (t',asm) = direct_cancel(*_expanded ... corrected MG.21.8.03*) t
2702 in if t = t' then NONE else SOME (t',asm)
2703 end) handle _ => NONE;
2704 (*.the same as above with normalform [3]
2706 theory -> (*10.02 unused *)
2707 term -> (*fraction in normalform [3] *)
2708 (term * (*fraction in normalform [3] *)
2709 term list) (*casual asumptions in normalform [3] *)
2710 option (*NONE: the function is not applicable *).*)
2711 fun cancel_ (thy:theory) t = SOME (direct_cancel_expanded t) handle _ => NONE;
2713 (*.transforms sums of at least 2 fractions [3] to
2714 sums with the least common multiple as nominator.*)
2715 fun common_nominator_p_ (thy:theory) t =
2716 ((*writeln("### common_nominator_p_ called");*)
2717 SOME (step_add_list_of_fractions(term2list(t))) handle _ => NONE
2719 fun common_nominator_ (thy:theory) t =
2720 SOME (step_add_list_of_fractions_exp(term2list(t))) handle _ => NONE;
2722 (*.add 2 or more fractions
2723 val add_fraction_p_ :
2724 theory -> (*10.02 unused *)
2725 term -> (*2 or more fractions with normalform [2] *)
2726 (term * (*one fraction with normalform [2] *)
2727 term list) (*casual assumptions in normalform [2] WN0210???SK *)
2728 option (*NONE: the function is not applicable *).*)
2729 fun add_fraction_p_ (thy:theory) t =
2730 (writeln("### add_fraction_p_ called");
2731 (let val ts = term2list t
2733 then SOME (add_list_of_fractions ts)
2734 else NONE (*raise error ("RATIONALS_ADD_EXCEPTION: nothing to add")*)
2735 end) handle _ => NONE
2737 (*.same as add_fraction_p_ but with normalform [3].*)
2738 (*SOME (step_add_list_of_fractions2(term2list(t))); *)
2739 fun add_fraction_ (thy:theory) t =
2740 if length(term2list(t))>1
2741 then SOME (add_list_of_fractions_exp(term2list(t))) handle _ => NONE
2742 else (*raise error ("RATIONALS_ADD_FRACTION_EXCEPTION: nothing to add")*)
2744 fun add_fraction_ (thy:theory) t =
2745 (if 1 < length (term2list t)
2746 then SOME (add_list_of_fractions_exp (term2list t))
2747 else (*raise error ("RATIONALS_ADD_FRACTION_EXCEPTION: nothing to add")*)
2748 NONE) handle _ => NONE;
2750 (*SOME (step_add_list_of_fractions2_exp(term2list(t))); *)
2752 (*. brings the term into a normal form .*)
2753 fun norm_rational_ (thy:theory) t =
2754 SOME (add_list_of_fractions(term2list(t))) handle _ => NONE;
2755 fun norm_expanded_rat_ (thy:theory) t =
2756 SOME (add_list_of_fractions_exp(term2list(t))) handle _ => NONE;
2759 (*.evaluates conditions in calculate_Rational.*)
2760 (*make local with FIXX@ME result:term *term list*)
2761 val calc_rat_erls = prep_rls(
2762 Rls {id = "calc_rat_erls", preconds = [], rew_ord = ("dummy_ord",dummy_ord),
2763 erls = e_rls, srls = Erls, calc = [], (*asm_thm = [], *)
2765 [Calc ("op =",eval_equal "#equal_"),
2766 Calc ("Atools.is'_const",eval_const "#is_const_"),
2767 Thm ("not_true",num_str not_true),
2768 Thm ("not_false",num_str not_false)
2773 (*.simplifies expressions with numerals;
2774 does NOT rearrange the term by AC-rewriting; thus terms with variables
2775 need to have constants to be commuted together respectively.*)
2776 val calculate_Rational = prep_rls(
2777 merge_rls "calculate_Rational"
2778 (Rls {id = "divide", preconds = [], rew_ord = ("dummy_ord",dummy_ord),
2779 erls = calc_rat_erls, srls = Erls, (*asm_thm = [],*)
2782 [Calc ("HOL.divide" ,eval_cancel "#divide_"),
2784 Thm ("sym_real_minus_divide_eq",
2785 num_str (real_minus_divide_eq RS sym)),
2786 (*SYM - ?x / ?y = - (?x / ?y) may come from subst*)
2788 Thm ("rat_add",num_str rat_add),
2789 (*"[| a is_const; b is_const; c is_const; d is_const |] ==> \
2790 \"a / c + b / d = (a * d) / (c * d) + (b * c ) / (d * c)"*)
2791 Thm ("rat_add1",num_str rat_add1),
2792 (*"[| a is_const; b is_const; c is_const |] ==> \
2793 \"a / c + b / c = (a + b) / c"*)
2794 Thm ("rat_add2",num_str rat_add2),
2795 (*"[| ?a is_const; ?b is_const; ?c is_const |] ==> \
2796 \?a / ?c + ?b = (?a + ?b * ?c) / ?c"*)
2797 Thm ("rat_add3",num_str rat_add3),
2798 (*"[| a is_const; b is_const; c is_const |] ==> \
2799 \"a + b / c = (a * c) / c + b / c"\
2800 \.... is_const to be omitted here FIXME*)
2802 Thm ("rat_mult",num_str rat_mult),
2803 (*a / b * (c / d) = a * c / (b * d)*)
2804 Thm ("real_times_divide1_eq",num_str real_times_divide1_eq),
2805 (*?x * (?y / ?z) = ?x * ?y / ?z*)
2806 Thm ("real_times_divide2_eq",num_str real_times_divide2_eq),
2807 (*?y / ?z * ?x = ?y * ?x / ?z*)
2809 Thm ("real_divide_divide1",num_str real_divide_divide1),
2810 (*"?y ~= 0 ==> ?u / ?v / (?y / ?z) = ?u / ?v * (?z / ?y)"*)
2811 Thm ("real_divide_divide2_eq",num_str real_divide_divide2_eq),
2812 (*"?x / ?y / ?z = ?x / (?y * ?z)"*)
2814 Thm ("rat_power", num_str rat_power),
2815 (*"(?a / ?b) ^^^ ?n = ?a ^^^ ?n / ?b ^^^ ?n"*)
2817 Thm ("mult_cross",num_str mult_cross),
2818 (*"[| b ~= 0; d ~= 0 |] ==> (a / b = c / d) = (a * d = b * c)*)
2819 Thm ("mult_cross1",num_str mult_cross1),
2820 (*" b ~= 0 ==> (a / b = c ) = (a = b * c)*)
2821 Thm ("mult_cross2",num_str mult_cross2)
2822 (*" d ~= 0 ==> (a = c / d) = (a * d = c)*)
2827 (*("is_expanded", ("Rational.is'_expanded", eval_is_expanded ""))*)
2828 fun eval_is_expanded (thmid:string) _
2829 (t as (Const("Rational.is'_expanded", _) $ arg)) thy =
2831 then SOME (mk_thmid thmid ""
2832 ((Syntax.string_of_term (thy2ctxt thy)) arg) "",
2833 Trueprop $ (mk_equality (t, HOLogic.true_const)))
2834 else SOME (mk_thmid thmid ""
2835 ((Syntax.string_of_term (thy2ctxt thy)) arg) "",
2836 Trueprop $ (mk_equality (t, HOLogic.false_const)))
2837 | eval_is_expanded _ _ _ _ = NONE;
2840 merge_rls "rational_erls" calculate_Rational
2841 (append_rls "is_expanded" Atools_erls
2842 [Calc ("Rational.is'_expanded", eval_is_expanded "")
2847 (*.3 'reverse-rewrite-sets' for symbolic computation on rationals:
2848 =================================================================
2851 B[2] 'common_nominator_p': transforms summands in a term [2]
2852 to fractions with the (least) common multiple as nominator.
2853 B[3] 'norm_rational': normalizes arbitrary algebraic terms (without
2854 radicals and transzendental functions) to one canceled fraction,
2855 nominator and denominator in polynomial form.
2857 In order to meet isac's requirements for interactive and stepwise calculation,
2858 each 'reverse-rewerite-set' consists of an initialization for the interpreter
2859 state and of 4 functions, each of which employs rewriting as much as possible.
2860 The signature of these functions are the same in each 'reverse-rewrite-set'
2863 (* ************************************************************************* *)
2867 ------------------------
2868 cancels a single fraction consisting of two (uni- or multivariate)
2869 polynomials WN0609???SK[2] into another such a fraction; examples:
2872 -------------------- = ---------
2873 a^2 + -2*a*b + b^2 a + -1*b
2879 Remark: the reverse ruleset does _NOT_ work properly with other input !.*)
2880 (*WN020824 wir werden "uberlegen, wie wir ungeeignete inputs zur"uckweisen*)
2882 val {rules, rew_ord=(_,ro),...} =
2883 rep_rls (assoc_rls "make_polynomial");
2884 (*WN060829 ... make_deriv does not terminate with 1st expl above,
2885 see rational.sml --- investigate rulesets for cancel_p ---*)
2886 val {rules, rew_ord=(_,ro),...} =
2887 rep_rls (assoc_rls "rev_rew_p");
2889 val thy = Rational.thy;
2891 (*.init_state = fn : term -> istate
2892 initialzies the state of the script interpreter. The state is:
2894 type rrlsstate = (*state for reverse rewriting*)
2895 (term * (*the current formula*)
2896 term * (*the final term*)
2897 rule list (*'reverse rule list' (#)*)
2898 list * (*may be serveral, eg. in norm_rational*)
2899 (rule * (*Thm (+ Thm generated from Calc) resulting in ...*)
2900 (term * (*... rewrite with ...*)
2901 term list)) (*... assumptions*)
2902 list); (*derivation from given term to normalform
2903 in reverse order with sym_thm;
2904 (#) could be extracted from here by (map #1)*).*)
2905 (* val {rules, rew_ord=(_,ro),...} =
2906 rep_rls (assoc_rls "rev_rew_p") (*USE ALWAYS, SEE val cancel_p*);
2907 val (thy, eval_rls, ro) =(Rational.thy, Atools_erls, ro) (*..val cancel_p*);
2910 fun init_state thy eval_rls ro t =
2911 let val SOME (t',_) = factout_p_ thy t
2912 val SOME (t'',asm) = cancel_p_ thy t
2913 val der = reverse_deriv thy eval_rls rules ro NONE t'
2914 val der = der @ [(Thm ("real_mult_div_cancel2",
2915 num_str real_mult_div_cancel2),
2917 val rs = (distinct_Thm o (map #1)) der
2918 val rs = filter_out (eq_Thms ["sym_real_add_zero_left",
2921 (*..insufficient,eg.make_Polynomial*)])rs
2922 in (t,t'',[rs(*here only _ONE_ to ease locate_rule*)],der) end;
2924 (*.locate_rule = fn : rule list -> term -> rule
2925 -> (rule * (term * term list) option) list.
2926 checks a rule R for being a cancel-rule, and if it is,
2927 then return the list of rules (+ the terms they are rewriting to)
2928 which need to be applied before R should be applied.
2929 precondition: the rule is applicable to the argument-term.
2931 rule list: the reverse rule list
2932 -> term : ... to which the rule shall be applied
2933 -> rule : ... to be applied to term
2935 -> (rule : a rule rewriting to ...
2936 * (term : ... the resulting term ...
2937 * term list): ... with the assumptions ( //#0).
2938 ) list : there may be several such rules;
2939 the list is empty, if the rule has nothing to do
2943 fun locate_rule thy eval_rls ro [rs] t r =
2944 if (id_of_thm r) mem (map (id_of_thm)) rs
2946 rewrite_ thy ro eval_rls true (thm_of_thm r) t;
2948 SOME ta => [(r, ta)]
2949 | NONE => (writeln("### locate_rule: rewrite "^
2950 (id_of_thm r)^" "^(term2str t)^" = NONE");
2952 else (writeln("### locate_rule: "^(id_of_thm r)^" not mem rrls");[])
2953 | locate_rule _ _ _ _ _ _ =
2954 raise error ("locate_rule: doesnt match rev-sets in istate");
2956 (*.next_rule = fn : rule list -> term -> rule option
2957 for a given term return the next rules to be done for cancelling.
2959 rule list : the reverse rule list
2960 term : the term for which ...
2962 -> rule option: ... this rule is appropriate for cancellation;
2963 there may be no such rule (if the term is canceled already.*)
2964 (* val thy = Rational.thy;
2965 val Rrls {rew_ord=(_,ro),...} = cancel;
2966 val ([rs],t) = (rss,f);
2967 next_rule thy eval_rls ro [rs] t;(*eval fun next_rule ... before!*)
2969 val (thy, [rs]) = (Rational.thy, revsets);
2970 val Rrls {rew_ord=(_,ro),...} = cancel;
2973 fun next_rule thy eval_rls ro [rs] t =
2974 let val der = make_deriv thy eval_rls rs ro NONE t;
2976 (* val (_,r,_)::_ = der;
2978 (_,r,_)::_ => SOME r
2981 | next_rule _ _ _ _ _ =
2982 raise error ("next_rule: doesnt match rev-sets in istate");
2984 (*.val attach_form = f : rule list -> term -> term
2985 -> (rule * (term * term list)) list
2986 checks an input term TI, if it may belong to a current cancellation, by
2987 trying to derive it from the given term TG.
2989 term : TG, the last one in the cancellation agreed upon by user + math-eng
2990 -> term: TI, the next one input by the user
2992 -> (rule : the rule to be applied in order to reach TI
2993 * (term : ... obtained by applying the rule ...
2994 * term list): ... and the respective assumptions.
2995 ) list : there may be several such rules;
2996 the list is empty, if the users term does not belong
2997 to a cancellation of the term last agreed upon.*)
2998 fun attach_form (_:rule list list) (_:term) (_:term) = (*still missing*)
2999 []:(rule * (term * term list)) list;
3004 Rrls {id = "cancel_p", prepat=[],
3005 rew_ord=("ord_make_polynomial",
3006 ord_make_polynomial false Rational.thy),
3007 erls = rational_erls,
3008 calc = [("PLUS" ,("op +" ,eval_binop "#add_")),
3009 ("TIMES" ,("op *" ,eval_binop "#mult_")),
3010 ("DIVIDE" ,("HOL.divide" ,eval_cancel "#divide_")),
3011 ("POWER" ,("Atools.pow" ,eval_binop "#power_"))],
3012 (*asm_thm=[("real_mult_div_cancel2","")],*)
3013 scr=Rfuns {init_state = init_state thy Atools_erls ro,
3014 normal_form = cancel_p_ thy,
3015 locate_rule = locate_rule thy Atools_erls ro,
3016 next_rule = next_rule thy Atools_erls ro,
3017 attach_form = attach_form}}
3021 local(*.ad (1) 'cancel'
3022 ------------------------------
3023 cancels a single fraction consisting of two (uni- or multivariate)
3024 polynomials WN0609???SK[3] into another such a fraction; examples:
3027 -------------------- = ---------
3028 a^2 - 2*a*b + b^2 a - *b
3030 Remark: the reverse ruleset does _NOT_ work properly with other input !.*)
3031 (*WN 24.8.02: wir werden "uberlegen, wie wir ungeeignete inputs zur"uckweisen*)
3034 val SOME (Rls {rules=rules,rew_ord=(_,ro),...}) =
3035 assoc'(!ruleset',"expand_binoms");
3037 val {rules=rules,rew_ord=(_,ro),...} =
3038 rep_rls (assoc_rls "expand_binoms");
3039 val thy = Rational.thy;
3041 fun init_state thy eval_rls ro t =
3042 let val SOME (t',_) = factout_ thy t;
3043 val SOME (t'',asm) = cancel_ thy t;
3044 val der = reverse_deriv thy eval_rls rules ro NONE t';
3045 val der = der @ [(Thm ("real_mult_div_cancel2",
3046 num_str real_mult_div_cancel2),
3048 val rs = map #1 der;
3049 in (t,t'',[rs],der) end;
3051 fun locate_rule thy eval_rls ro [rs] t r =
3052 if (id_of_thm r) mem (map (id_of_thm)) rs
3054 rewrite_ thy ro eval_rls true (thm_of_thm r) t;
3056 SOME ta => [(r, ta)]
3057 | NONE => (writeln("### locate_rule: rewrite "^
3058 (id_of_thm r)^" "^(term2str t)^" = NONE");
3060 else (writeln("### locate_rule: "^(id_of_thm r)^" not mem rrls");[])
3061 | locate_rule _ _ _ _ _ _ =
3062 raise error ("locate_rule: doesnt match rev-sets in istate");
3064 fun next_rule thy eval_rls ro [rs] t =
3065 let val der = make_deriv thy eval_rls rs ro NONE t;
3067 (* val (_,r,_)::_ = der;
3069 (_,r,_)::_ => SOME r
3072 | next_rule _ _ _ _ _ =
3073 raise error ("next_rule: doesnt match rev-sets in istate");
3075 fun attach_form (_:rule list list) (_:term) (_:term) = (*still missing*)
3076 []:(rule * (term * term list)) list;
3078 val pat = (term_of o the o (parse thy)) "?r/?s";
3079 val pre1 = (term_of o the o (parse thy)) "?r is_expanded";
3080 val pre2 = (term_of o the o (parse thy)) "?s is_expanded";
3081 val prepat = [([pre1, pre2], pat)];
3087 Rrls {id = "cancel", prepat=prepat,
3088 rew_ord=("ord_make_polynomial",
3089 ord_make_polynomial false Rational.thy),
3090 erls = rational_erls,
3091 calc = [("PLUS" ,("op +" ,eval_binop "#add_")),
3092 ("TIMES" ,("op *" ,eval_binop "#mult_")),
3093 ("DIVIDE" ,("HOL.divide" ,eval_cancel "#divide_")),
3094 ("POWER" ,("Atools.pow" ,eval_binop "#power_"))],
3095 scr=Rfuns {init_state = init_state thy Atools_erls ro,
3096 normal_form = cancel_ thy,
3097 locate_rule = locate_rule thy Atools_erls ro,
3098 next_rule = next_rule thy Atools_erls ro,
3099 attach_form = attach_form}}
3104 local(*.ad [2] 'common_nominator_p'
3105 ---------------------------------
3106 FIXME Beschreibung .*)
3109 val {rules=rules,rew_ord=(_,ro),...} =
3110 rep_rls (assoc_rls "make_polynomial");
3111 (*WN060829 ... make_deriv does not terminate with 1st expl above,
3112 see rational.sml --- investigate rulesets for cancel_p ---*)
3113 val {rules, rew_ord=(_,ro),...} =
3114 rep_rls (assoc_rls "rev_rew_p");
3115 val thy = Rational.thy;
3118 (*.common_nominator_p_ = fn : theory -> term -> (term * term list) option
3121 (*.init_state = fn : term -> istate
3122 initialzies the state of the interactive interpreter. The state is:
3124 type rrlsstate = (*state for reverse rewriting*)
3125 (term * (*the current formula*)
3126 term * (*the final term*)
3127 rule list (*'reverse rule list' (#)*)
3128 list * (*may be serveral, eg. in norm_rational*)
3129 (rule * (*Thm (+ Thm generated from Calc) resulting in ...*)
3130 (term * (*... rewrite with ...*)
3131 term list)) (*... assumptions*)
3132 list); (*derivation from given term to normalform
3133 in reverse order with sym_thm;
3134 (#) could be extracted from here by (map #1)*).*)
3135 fun init_state thy eval_rls ro t =
3136 let val SOME (t',_) = common_nominator_p_ thy t;
3137 val SOME (t'',asm) = add_fraction_p_ thy t;
3138 val der = reverse_deriv thy eval_rls rules ro NONE t';
3139 val der = der @ [(Thm ("real_mult_div_cancel2",
3140 num_str real_mult_div_cancel2),
3142 val rs = (distinct_Thm o (map #1)) der;
3143 val rs = filter_out (eq_Thms ["sym_real_add_zero_left",
3145 "sym_real_mult_1"]) rs;
3146 in (t,t'',[rs(*here only _ONE_*)],der) end;
3148 (* use"knowledge/Rational.ML";
3151 (*.locate_rule = fn : rule list -> term -> rule
3152 -> (rule * (term * term list) option) list.
3153 checks a rule R for being a cancel-rule, and if it is,
3154 then return the list of rules (+ the terms they are rewriting to)
3155 which need to be applied before R should be applied.
3156 precondition: the rule is applicable to the argument-term.
3158 rule list: the reverse rule list
3159 -> term : ... to which the rule shall be applied
3160 -> rule : ... to be applied to term
3162 -> (rule : a rule rewriting to ...
3163 * (term : ... the resulting term ...
3164 * term list): ... with the assumptions ( //#0).
3165 ) list : there may be several such rules;
3166 the list is empty, if the rule has nothing to do
3170 fun locate_rule thy eval_rls ro [rs] t r =
3171 if (id_of_thm r) mem (map (id_of_thm)) rs
3173 rewrite_ thy ro eval_rls true (thm_of_thm r) t;
3175 SOME ta => [(r, ta)]
3176 | NONE => (writeln("### locate_rule: rewrite "^
3177 (id_of_thm r)^" "^(term2str t)^" = NONE");
3179 else (writeln("### locate_rule: "^(id_of_thm r)^" not mem rrls");[])
3180 | locate_rule _ _ _ _ _ _ =
3181 raise error ("locate_rule: doesnt match rev-sets in istate");
3183 (*.next_rule = fn : rule list -> term -> rule option
3184 for a given term return the next rules to be done for cancelling.
3186 rule list : the reverse rule list
3187 term : the term for which ...
3189 -> rule option: ... this rule is appropriate for cancellation;
3190 there may be no such rule (if the term is canceled already.*)
3191 (* val thy = Rational.thy;
3192 val Rrls {rew_ord=(_,ro),...} = cancel;
3193 val ([rs],t) = (rss,f);
3194 next_rule thy eval_rls ro [rs] t;(*eval fun next_rule ... before!*)
3196 val (thy, [rs]) = (Rational.thy, revsets);
3197 val Rrls {rew_ord=(_,ro),...} = cancel;
3200 fun next_rule thy eval_rls ro [rs] t =
3201 let val der = make_deriv thy eval_rls rs ro NONE t;
3203 (* val (_,r,_)::_ = der;
3205 (_,r,_)::_ => SOME r
3208 | next_rule _ _ _ _ _ =
3209 raise error ("next_rule: doesnt match rev-sets in istate");
3211 (*.val attach_form = f : rule list -> term -> term
3212 -> (rule * (term * term list)) list
3213 checks an input term TI, if it may belong to a current cancellation, by
3214 trying to derive it from the given term TG.
3216 term : TG, the last one in the cancellation agreed upon by user + math-eng
3217 -> term: TI, the next one input by the user
3219 -> (rule : the rule to be applied in order to reach TI
3220 * (term : ... obtained by applying the rule ...
3221 * term list): ... and the respective assumptions.
3222 ) list : there may be several such rules;
3223 the list is empty, if the users term does not belong
3224 to a cancellation of the term last agreed upon.*)
3225 fun attach_form (_:rule list list) (_:term) (_:term) = (*still missing*)
3226 []:(rule * (term * term list)) list;
3228 val pat0 = (term_of o the o (parse thy)) "?r/?s+?u/?v";
3229 val pat1 = (term_of o the o (parse thy)) "?r/?s+?u ";
3230 val pat2 = (term_of o the o (parse thy)) "?r +?u/?v";
3231 val prepat = [([HOLogic.true_const], pat0),
3232 ([HOLogic.true_const], pat1),
3233 ([HOLogic.true_const], pat2)];
3237 (*11.02 schnelle L"osung f"ur RL: Bruch auch gek"urzt;
3238 besser w"are: auf 1 gemeinsamen Bruchstrich, Nenner und Z"ahler unvereinfacht
3239 dh. wie common_nominator_p_, aber auf 1 Bruchstrich*)
3240 val common_nominator_p =
3241 Rrls {id = "common_nominator_p", prepat=prepat,
3242 rew_ord=("ord_make_polynomial",
3243 ord_make_polynomial false Rational.thy),
3244 erls = rational_erls,
3245 calc = [("PLUS" ,("op +" ,eval_binop "#add_")),
3246 ("TIMES" ,("op *" ,eval_binop "#mult_")),
3247 ("DIVIDE" ,("HOL.divide" ,eval_cancel "#divide_")),
3248 ("POWER" ,("Atools.pow" ,eval_binop "#power_"))],
3249 scr=Rfuns {init_state = init_state thy Atools_erls ro,
3250 normal_form = add_fraction_p_ thy,(*FIXME.WN0211*)
3251 locate_rule = locate_rule thy Atools_erls ro,
3252 next_rule = next_rule thy Atools_erls ro,
3253 attach_form = attach_form}}
3257 local(*.ad [2] 'common_nominator'
3258 ---------------------------------
3259 FIXME Beschreibung .*)
3262 val {rules=rules,rew_ord=(_,ro),...} =
3263 rep_rls (assoc_rls "make_polynomial");
3264 val thy = Rational.thy;
3267 (*.common_nominator_ = fn : theory -> term -> (term * term list) option
3270 (*.init_state = fn : term -> istate
3271 initialzies the state of the interactive interpreter. The state is:
3273 type rrlsstate = (*state for reverse rewriting*)
3274 (term * (*the current formula*)
3275 term * (*the final term*)
3276 rule list (*'reverse rule list' (#)*)
3277 list * (*may be serveral, eg. in norm_rational*)
3278 (rule * (*Thm (+ Thm generated from Calc) resulting in ...*)
3279 (term * (*... rewrite with ...*)
3280 term list)) (*... assumptions*)
3281 list); (*derivation from given term to normalform
3282 in reverse order with sym_thm;
3283 (#) could be extracted from here by (map #1)*).*)
3284 fun init_state thy eval_rls ro t =
3285 let val SOME (t',_) = common_nominator_ thy t;
3286 val SOME (t'',asm) = add_fraction_ thy t;
3287 val der = reverse_deriv thy eval_rls rules ro NONE t';
3288 val der = der @ [(Thm ("real_mult_div_cancel2",
3289 num_str real_mult_div_cancel2),
3291 val rs = (distinct_Thm o (map #1)) der;
3292 val rs = filter_out (eq_Thms ["sym_real_add_zero_left",
3294 "sym_real_mult_1"]) rs;
3295 in (t,t'',[rs(*here only _ONE_*)],der) end;
3297 (* use"knowledge/Rational.ML";
3300 (*.locate_rule = fn : rule list -> term -> rule
3301 -> (rule * (term * term list) option) list.
3302 checks a rule R for being a cancel-rule, and if it is,
3303 then return the list of rules (+ the terms they are rewriting to)
3304 which need to be applied before R should be applied.
3305 precondition: the rule is applicable to the argument-term.
3307 rule list: the reverse rule list
3308 -> term : ... to which the rule shall be applied
3309 -> rule : ... to be applied to term
3311 -> (rule : a rule rewriting to ...
3312 * (term : ... the resulting term ...
3313 * term list): ... with the assumptions ( //#0).
3314 ) list : there may be several such rules;
3315 the list is empty, if the rule has nothing to do
3319 fun locate_rule thy eval_rls ro [rs] t r =
3320 if (id_of_thm r) mem (map (id_of_thm)) rs
3322 rewrite_ thy ro eval_rls true (thm_of_thm r) t;
3324 SOME ta => [(r, ta)]
3325 | NONE => (writeln("### locate_rule: rewrite "^
3326 (id_of_thm r)^" "^(term2str t)^" = NONE");
3328 else (writeln("### locate_rule: "^(id_of_thm r)^" not mem rrls");[])
3329 | locate_rule _ _ _ _ _ _ =
3330 raise error ("locate_rule: doesnt match rev-sets in istate");
3332 (*.next_rule = fn : rule list -> term -> rule option
3333 for a given term return the next rules to be done for cancelling.
3335 rule list : the reverse rule list
3336 term : the term for which ...
3338 -> rule option: ... this rule is appropriate for cancellation;
3339 there may be no such rule (if the term is canceled already.*)
3340 (* val thy = Rational.thy;
3341 val Rrls {rew_ord=(_,ro),...} = cancel;
3342 val ([rs],t) = (rss,f);
3343 next_rule thy eval_rls ro [rs] t;(*eval fun next_rule ... before!*)
3345 val (thy, [rs]) = (Rational.thy, revsets);
3346 val Rrls {rew_ord=(_,ro),...} = cancel_p;
3349 fun next_rule thy eval_rls ro [rs] t =
3350 let val der = make_deriv thy eval_rls rs ro NONE t;
3352 (* val (_,r,_)::_ = der;
3354 (_,r,_)::_ => SOME r
3357 | next_rule _ _ _ _ _ =
3358 raise error ("next_rule: doesnt match rev-sets in istate");
3360 (*.val attach_form = f : rule list -> term -> term
3361 -> (rule * (term * term list)) list
3362 checks an input term TI, if it may belong to a current cancellation, by
3363 trying to derive it from the given term TG.
3365 term : TG, the last one in the cancellation agreed upon by user + math-eng
3366 -> term: TI, the next one input by the user
3368 -> (rule : the rule to be applied in order to reach TI
3369 * (term : ... obtained by applying the rule ...
3370 * term list): ... and the respective assumptions.
3371 ) list : there may be several such rules;
3372 the list is empty, if the users term does not belong
3373 to a cancellation of the term last agreed upon.*)
3374 fun attach_form (_:rule list list) (_:term) (_:term) = (*still missing*)
3375 []:(rule * (term * term list)) list;
3377 val pat0 = (term_of o the o (parse thy)) "?r/?s+?u/?v";
3378 val pat01 = (term_of o the o (parse thy)) "?r/?s-?u/?v";
3379 val pat1 = (term_of o the o (parse thy)) "?r/?s+?u ";
3380 val pat11 = (term_of o the o (parse thy)) "?r/?s-?u ";
3381 val pat2 = (term_of o the o (parse thy)) "?r +?u/?v";
3382 val pat21 = (term_of o the o (parse thy)) "?r -?u/?v";
3383 val prepat = [([HOLogic.true_const], pat0),
3384 ([HOLogic.true_const], pat01),
3385 ([HOLogic.true_const], pat1),
3386 ([HOLogic.true_const], pat11),
3387 ([HOLogic.true_const], pat2),
3388 ([HOLogic.true_const], pat21)];
3393 val common_nominator =
3394 Rrls {id = "common_nominator", prepat=prepat,
3395 rew_ord=("ord_make_polynomial",
3396 ord_make_polynomial false Rational.thy),
3397 erls = rational_erls,
3398 calc = [("PLUS" ,("op +" ,eval_binop "#add_")),
3399 ("TIMES" ,("op *" ,eval_binop "#mult_")),
3400 ("DIVIDE" ,("HOL.divide" ,eval_cancel "#divide_")),
3401 ("POWER" ,("Atools.pow" ,eval_binop "#power_"))],
3402 (*asm_thm=[("real_mult_div_cancel2","")],*)
3403 scr=Rfuns {init_state = init_state thy Atools_erls ro,
3404 normal_form = add_fraction_ (*NOT common_nominator_*) thy,
3405 locate_rule = locate_rule thy Atools_erls ro,
3406 next_rule = next_rule thy Atools_erls ro,
3407 attach_form = attach_form}}
3418 (*.the expression contains + - * ^ / only ?.*)
3419 fun is_ratpolyexp (Free _) = true
3420 | is_ratpolyexp (Const ("op +",_) $ Free _ $ Free _) = true
3421 | is_ratpolyexp (Const ("op -",_) $ Free _ $ Free _) = true
3422 | is_ratpolyexp (Const ("op *",_) $ Free _ $ Free _) = true
3423 | is_ratpolyexp (Const ("Atools.pow",_) $ Free _ $ Free _) = true
3424 | is_ratpolyexp (Const ("HOL.divide",_) $ Free _ $ Free _) = true
3425 | is_ratpolyexp (Const ("op +",_) $ t1 $ t2) =
3426 ((is_ratpolyexp t1) andalso (is_ratpolyexp t2))
3427 | is_ratpolyexp (Const ("op -",_) $ t1 $ t2) =
3428 ((is_ratpolyexp t1) andalso (is_ratpolyexp t2))
3429 | is_ratpolyexp (Const ("op *",_) $ t1 $ t2) =
3430 ((is_ratpolyexp t1) andalso (is_ratpolyexp t2))
3431 | is_ratpolyexp (Const ("Atools.pow",_) $ t1 $ t2) =
3432 ((is_ratpolyexp t1) andalso (is_ratpolyexp t2))
3433 | is_ratpolyexp (Const ("HOL.divide",_) $ t1 $ t2) =
3434 ((is_ratpolyexp t1) andalso (is_ratpolyexp t2))
3435 | is_ratpolyexp _ = false;
3437 (*("is_ratpolyexp", ("Rational.is'_ratpolyexp", eval_is_ratpolyexp ""))*)
3438 fun eval_is_ratpolyexp (thmid:string) _
3439 (t as (Const("Rational.is'_ratpolyexp", _) $ arg)) thy =
3440 if is_ratpolyexp arg
3441 then SOME (mk_thmid thmid ""
3442 ((Syntax.string_of_term (thy2ctxt thy)) arg) "",
3443 Trueprop $ (mk_equality (t, HOLogic.true_const)))
3444 else SOME (mk_thmid thmid ""
3445 ((Syntax.string_of_term (thy2ctxt thy)) arg) "",
3446 Trueprop $ (mk_equality (t, HOLogic.false_const)))
3447 | eval_is_ratpolyexp _ _ _ _ = NONE;
3451 (*-------------------18.3.03 --> struct <-----------vvv--*)
3452 val add_fractions_p = common_nominator_p; (*FIXXXME:eilig f"ur norm_Rational*)
3454 (*.discard binary minus, shift unary minus into -1*;
3455 unary minus before numerals are put into the numeral by parsing;
3456 contains absolute minimum of thms for context in norm_Rational .*)
3457 val discard_minus = prep_rls(
3458 Rls {id = "discard_minus", preconds = [], rew_ord = ("dummy_ord",dummy_ord),
3459 erls = e_rls, srls = Erls, calc = [], (*asm_thm = [],*)
3460 rules = [Thm ("real_diff_minus", num_str real_diff_minus),
3461 (*"a - b = a + -1 * b"*)
3462 Thm ("sym_real_mult_minus1",num_str (real_mult_minus1 RS sym))
3463 (*- ?z = "-1 * ?z"*)
3465 scr = Script ((term_of o the o (parse thy))
3468 (*erls for calculate_Rational; make local with FIXX@ME result:term *term list*)
3469 val powers_erls = prep_rls(
3470 Rls {id = "powers_erls", preconds = [], rew_ord = ("dummy_ord",dummy_ord),
3471 erls = e_rls, srls = Erls, calc = [], (*asm_thm = [],*)
3472 rules = [Calc ("Atools.is'_atom",eval_is_atom "#is_atom_"),
3473 Calc ("Atools.is'_even",eval_is_even "#is_even_"),
3474 Calc ("op <",eval_equ "#less_"),
3475 Thm ("not_false", not_false),
3476 Thm ("not_true", not_true),
3477 Calc ("op +",eval_binop "#add_")
3479 scr = Script ((term_of o the o (parse thy))
3482 (*.all powers over + distributed; atoms over * collected, other distributed
3483 contains absolute minimum of thms for context in norm_Rational .*)
3484 val powers = prep_rls(
3485 Rls {id = "powers", preconds = [], rew_ord = ("dummy_ord",dummy_ord),
3486 erls = powers_erls, srls = Erls, calc = [], (*asm_thm = [],*)
3487 rules = [Thm ("realpow_multI", num_str realpow_multI),
3488 (*"(r * s) ^^^ n = r ^^^ n * s ^^^ n"*)
3489 Thm ("realpow_pow",num_str realpow_pow),
3490 (*"(a ^^^ b) ^^^ c = a ^^^ (b * c)"*)
3491 Thm ("realpow_oneI",num_str realpow_oneI),
3493 Thm ("realpow_minus_even",num_str realpow_minus_even),
3494 (*"n is_even ==> (- r) ^^^ n = r ^^^ n" ?-->discard_minus?*)
3495 Thm ("realpow_minus_odd",num_str realpow_minus_odd),
3496 (*"Not (n is_even) ==> (- r) ^^^ n = -1 * r ^^^ n"*)
3498 (*----- collect atoms over * -----*)
3499 Thm ("realpow_two_atom",num_str realpow_two_atom),
3500 (*"r is_atom ==> r * r = r ^^^ 2"*)
3501 Thm ("realpow_plus_1",num_str realpow_plus_1),
3502 (*"r is_atom ==> r * r ^^^ n = r ^^^ (n + 1)"*)
3503 Thm ("realpow_addI_atom",num_str realpow_addI_atom),
3504 (*"r is_atom ==> r ^^^ n * r ^^^ m = r ^^^ (n + m)"*)
3506 (*----- distribute none-atoms -----*)
3507 Thm ("realpow_def_atom",num_str realpow_def_atom),
3508 (*"[| 1 < n; not(r is_atom) |]==>r ^^^ n = r * r ^^^ (n + -1)"*)
3509 Thm ("realpow_eq_oneI",num_str realpow_eq_oneI),
3511 Calc ("op +",eval_binop "#add_")
3513 scr = Script ((term_of o the o (parse thy))
3516 (*.contains absolute minimum of thms for context in norm_Rational.*)
3517 val rat_mult_divide = prep_rls(
3518 Rls {id = "rat_mult_divide", preconds = [],
3519 rew_ord = ("dummy_ord",dummy_ord),
3520 erls = e_rls, srls = Erls, calc = [], (*asm_thm = [],*)
3521 rules = [Thm ("rat_mult",num_str rat_mult),
3522 (*(1)"?a / ?b * (?c / ?d) = ?a * ?c / (?b * ?d)"*)
3523 Thm ("real_times_divide1_eq",num_str real_times_divide1_eq),
3524 (*(2)"?a * (?c / ?d) = ?a * ?c / ?d" must be [2],
3525 otherwise inv.to a / b / c = ...*)
3526 Thm ("real_times_divide2_eq",num_str real_times_divide2_eq),
3527 (*"?a / ?b * ?c = ?a * ?c / ?b" order weights x^^^n too much
3528 and does not commute a / b * c ^^^ 2 !*)
3530 Thm ("real_divide_divide1_eq", real_divide_divide1_eq),
3531 (*"?x / (?y / ?z) = ?x * ?z / ?y"*)
3532 Thm ("real_divide_divide2_eq", real_divide_divide2_eq),
3533 (*"?x / ?y / ?z = ?x / (?y * ?z)"*)
3534 Calc ("HOL.divide" ,eval_cancel "#divide_")
3536 scr = Script ((term_of o the o (parse thy)) "empty_script")
3538 (*.contains absolute minimum of thms for context in norm_Rational.*)
3539 val reduce_0_1_2 = prep_rls(
3540 Rls{id = "reduce_0_1_2", preconds = [], rew_ord = ("dummy_ord", dummy_ord),
3541 erls = e_rls,srls = Erls,calc = [],(*asm_thm = [],*)
3542 rules = [(*Thm ("real_divide_1",num_str real_divide_1),
3543 "?x / 1 = ?x" unnecess.for normalform*)
3544 Thm ("real_mult_1",num_str real_mult_1),
3546 (*Thm ("real_mult_minus1",num_str real_mult_minus1),
3548 (*Thm ("real_minus_mult_cancel",num_str real_minus_mult_cancel),
3549 "- ?x * - ?y = ?x * ?y"*)
3551 Thm ("real_mult_0",num_str real_mult_0),
3553 Thm ("real_add_zero_left",num_str real_add_zero_left),
3555 (*Thm ("real_add_minus",num_str real_add_minus),
3558 Thm ("sym_real_mult_2",num_str (real_mult_2 RS sym)),
3559 (*"z1 + z1 = 2 * z1"*)
3560 Thm ("real_mult_2_assoc",num_str real_mult_2_assoc),
3561 (*"z1 + (z1 + k) = 2 * z1 + k"*)
3563 Thm ("real_0_divide",num_str real_0_divide)
3565 ], scr = EmptyScr}:rls);
3567 (*erls for calculate_Rational;
3568 make local with FIXX@ME result:term *term list WN0609???SKMG*)
3569 val norm_rat_erls = prep_rls(
3570 Rls {id = "norm_rat_erls", preconds = [], rew_ord = ("dummy_ord",dummy_ord),
3571 erls = e_rls, srls = Erls, calc = [], (*asm_thm = [],*)
3572 rules = [Calc ("Atools.is'_const",eval_const "#is_const_")
3574 scr = Script ((term_of o the o (parse thy))
3577 (*.consists of rls containing the absolute minimum of thms.*)
3578 (*040209: this version has been used by RL for his equations,
3579 which is now replaced by MGs version below
3580 vvv OLD VERSION !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*)
3581 val norm_Rational = prep_rls(
3582 Rls {id = "norm_Rational", preconds = [], rew_ord = ("dummy_ord",dummy_ord),
3583 erls = norm_rat_erls, srls = Erls, calc = [], (*asm_thm = [],*)
3584 rules = [(*sequence given by operator precedence*)
3587 Rls_ rat_mult_divide,
3590 (*^^^^^^^^^ from RL -- not the latest one vvvvvvvvv*)
3591 Rls_ order_add_mult,
3592 Rls_ collect_numerals,
3593 Rls_ add_fractions_p,
3596 scr = Script ((term_of o the o (parse thy))
3599 val norm_Rational_parenthesized = prep_rls(
3600 Seq {id = "norm_Rational_parenthesized", preconds = []:term list,
3601 rew_ord = ("dummy_ord", dummy_ord),
3602 erls = Atools_erls, srls = Erls,
3603 calc = [], (*asm_thm = [],*)
3604 rules = [Rls_ norm_Rational, (*from RL -- not the latest one*)
3605 Rls_ discard_parentheses
3611 (*-------------------18.3.03 --> struct <-----------^^^--*)
3615 theory' := overwritel (!theory', [("Rational.thy",Rational.thy)]);
3618 (*WN030318???SK: simplifies all but cancel and common_nominator*)
3619 val simplify_rational =
3620 merge_rls "simplify_rational" expand_binoms
3621 (append_rls "divide" calculate_Rational
3622 [Thm ("real_divide_1",num_str real_divide_1),
3624 Thm ("rat_mult",num_str rat_mult),
3625 (*(1)"?a / ?b * (?c / ?d) = ?a * ?c / (?b * ?d)"*)
3626 Thm ("real_times_divide1_eq",num_str real_times_divide1_eq),
3627 (*(2)"?a * (?c / ?d) = ?a * ?c / ?d" must be [2],
3628 otherwise inv.to a / b / c = ...*)
3629 Thm ("real_times_divide2_eq",num_str real_times_divide2_eq),
3630 (*"?a / ?b * ?c = ?a * ?c / ?b"*)
3631 Thm ("add_minus",num_str add_minus),
3632 (*"?a + ?b - ?b = ?a"*)
3633 Thm ("add_minus1",num_str add_minus1),
3634 (*"?a - ?b + ?b = ?a"*)
3635 Thm ("real_divide_minus1",num_str real_divide_minus1)
3636 (*"?x / -1 = - ?x"*)
3643 (*---------vvv-------------MG ab 1.07.2003--------------vvv-----------*)
3645 (* ------------------------------------------------------------------ *)
3646 (* Simplifier für beliebige Buchterme *)
3647 (* ------------------------------------------------------------------ *)
3648 (*----------------------- norm_Rational_mg ---------------------------*)
3649 (*. description of the simplifier see MG-DA.p.56ff .*)
3650 (* ------------------------------------------------------------------- *)
3651 val common_nominator_p_rls = prep_rls(
3652 Rls {id = "common_nominator_p_rls", preconds = [],
3653 rew_ord = ("dummy_ord",dummy_ord),
3654 erls = e_rls, srls = Erls, calc = [],
3656 [Rls_ common_nominator_p
3657 (*FIXME.WN0401 ? redesign Rrls - use exhaustively on a term ?
3658 FIXME.WN0510 unnecessary nesting: introduce RRls_ : rls -> rule*)
3661 (* ------------------------------------------------------------------- *)
3662 val cancel_p_rls = prep_rls(
3663 Rls {id = "cancel_p_rls", preconds = [],
3664 rew_ord = ("dummy_ord",dummy_ord),
3665 erls = e_rls, srls = Erls, calc = [],
3668 (*FIXME.WN.0401 ? redesign Rrls - use exhaustively on a term ?*)
3671 (* -------------------------------------------------------------------- *)
3672 (*. makes 'normal' fractions; 'is_polyexp' inhibits double fractions;
3673 used in initial part norm_Rational_mg, see example DA-M02-main.p.60.*)
3674 val rat_mult_poly = prep_rls(
3675 Rls {id = "rat_mult_poly", preconds = [],
3676 rew_ord = ("dummy_ord",dummy_ord),
3677 erls = append_rls "e_rls-is_polyexp" e_rls
3678 [Calc ("Poly.is'_polyexp", eval_is_polyexp "")],
3679 srls = Erls, calc = [],
3681 [Thm ("rat_mult_poly_l",num_str rat_mult_poly_l),
3682 (*"?c is_polyexp ==> ?c * (?a / ?b) = ?c * ?a / ?b"*)
3683 Thm ("rat_mult_poly_r",num_str rat_mult_poly_r)
3684 (*"?c is_polyexp ==> ?a / ?b * ?c = ?a * ?c / ?b"*)
3687 (* ------------------------------------------------------------------ *)
3688 (*. makes 'normal' fractions; 'is_polyexp' inhibits double fractions;
3689 used in looping part norm_Rational_rls, see example DA-M02-main.p.60
3690 .. WHERE THE LATTER DOES ALWAYS WORK, BECAUSE erls = e_rls,
3691 I.E. THE RESPECTIVE ASSUMPTION IS STORED AND Thm APPLIED; WN051028
3693 val rat_mult_div_pow = prep_rls(
3694 Rls {id = "rat_mult_div_pow", preconds = [],
3695 rew_ord = ("dummy_ord",dummy_ord),
3697 (*FIXME.WN051028 append_rls "e_rls-is_polyexp" e_rls
3698 [Calc ("Poly.is'_polyexp", eval_is_polyexp "")],
3699 with this correction ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ we get
3700 error "rational.sml.sml: diff.behav. in norm_Rational_mg 29" etc.
3701 thus we decided to go on with this flaw*)
3702 srls = Erls, calc = [],
3703 rules = [Thm ("rat_mult",num_str rat_mult),
3704 (*"?a / ?b * (?c / ?d) = ?a * ?c / (?b * ?d)"*)
3705 Thm ("rat_mult_poly_l",num_str rat_mult_poly_l),
3706 (*"?c is_polyexp ==> ?c * (?a / ?b) = ?c * ?a / ?b"*)
3707 Thm ("rat_mult_poly_r",num_str rat_mult_poly_r),
3708 (*"?c is_polyexp ==> ?a / ?b * ?c = ?a * ?c / ?b"*)
3710 Thm ("real_divide_divide1_mg", real_divide_divide1_mg),
3711 (*"y ~= 0 ==> (u / v) / (y / z) = (u * z) / (y * v)"*)
3712 Thm ("real_divide_divide1_eq", real_divide_divide1_eq),
3713 (*"?x / (?y / ?z) = ?x * ?z / ?y"*)
3714 Thm ("real_divide_divide2_eq", real_divide_divide2_eq),
3715 (*"?x / ?y / ?z = ?x / (?y * ?z)"*)
3716 Calc ("HOL.divide" ,eval_cancel "#divide_"),
3718 Thm ("rat_power", num_str rat_power)
3719 (*"(?a / ?b) ^^^ ?n = ?a ^^^ ?n / ?b ^^^ ?n"*)
3721 scr = Script ((term_of o the o (parse thy)) "empty_script")
3723 (* ------------------------------------------------------------------ *)
3724 val rat_reduce_1 = prep_rls(
3725 Rls {id = "rat_reduce_1", preconds = [],
3726 rew_ord = ("dummy_ord",dummy_ord),
3727 erls = e_rls, srls = Erls, calc = [],
3728 rules = [Thm ("real_divide_1",num_str real_divide_1),
3730 Thm ("real_mult_1",num_str real_mult_1)
3733 scr = Script ((term_of o the o (parse thy)) "empty_script")
3735 (* ------------------------------------------------------------------ *)
3736 (*. looping part of norm_Rational(*_mg*) .*)
3737 val norm_Rational_rls = prep_rls(
3738 Rls {id = "norm_Rational_rls", preconds = [],
3739 rew_ord = ("dummy_ord",dummy_ord),
3740 erls = norm_rat_erls, srls = Erls, calc = [],
3741 rules = [Rls_ common_nominator_p_rls,
3742 Rls_ rat_mult_div_pow,
3743 Rls_ make_rat_poly_with_parentheses,
3744 Rls_ cancel_p_rls,(*FIXME:cancel_p does NOT order sometimes*)
3747 scr = Script ((term_of o the o (parse thy)) "empty_script")
3749 (* ------------------------------------------------------------------ *)
3750 (*040109 'norm_Rational'(by RL) replaced by 'norm_Rational_mg'(MG)
3752 val norm_Rational(*_mg*) = prep_rls(
3753 Seq {id = "norm_Rational"(*_mg*), preconds = [],
3754 rew_ord = ("dummy_ord",dummy_ord),
3755 erls = norm_rat_erls, srls = Erls, calc = [],
3756 rules = [Rls_ discard_minus_,
3757 Rls_ rat_mult_poly,(* removes double fractions like a/b/c *)
3758 Rls_ make_rat_poly_with_parentheses, (*WN0510 also in(#)below*)
3759 Rls_ cancel_p_rls, (*FIXME.MG:cancel_p does NOT order sometim*)
3760 Rls_ norm_Rational_rls, (* the main rls, looping (#) *)
3761 Rls_ discard_parentheses_ (* mult only *)
3763 scr = Script ((term_of o the o (parse thy)) "empty_script")
3765 (* ------------------------------------------------------------------ *)
3768 ruleset' := overwritelthy thy (!ruleset',
3769 [("calculate_Rational", calculate_Rational),
3770 ("calc_rat_erls",calc_rat_erls),
3771 ("rational_erls", rational_erls),
3772 ("cancel_p", cancel_p),
3774 ("common_nominator_p", common_nominator_p),
3775 ("common_nominator_p_rls", common_nominator_p_rls),
3776 ("common_nominator" , common_nominator),
3777 ("discard_minus", discard_minus),
3778 ("powers_erls", powers_erls),
3780 ("rat_mult_divide", rat_mult_divide),
3781 ("reduce_0_1_2", reduce_0_1_2),
3782 ("rat_reduce_1", rat_reduce_1),
3783 ("norm_rat_erls", norm_rat_erls),
3784 ("norm_Rational", norm_Rational),
3785 ("norm_Rational_rls", norm_Rational_rls),
3786 ("norm_Rational_parenthesized", norm_Rational_parenthesized),
3787 ("rat_mult_poly", rat_mult_poly),
3788 ("rat_mult_div_pow", rat_mult_div_pow),
3789 ("cancel_p_rls", cancel_p_rls)
3792 calclist':= overwritel (!calclist',
3793 [("is_expanded", ("Rational.is'_expanded", eval_is_expanded ""))
3799 (prep_pbt Rational.thy "pbl_simp_rat" [] e_pblID
3800 (["rational","simplification"],
3801 [("#Given" ,["term t_"]),
3802 ("#Where" ,["t_ is_ratpolyexp"]),
3803 ("#Find" ,["normalform n_"])
3805 append_rls "e_rls" e_rls [(*for preds in where_*)],
3807 [["simplification","of_rationals"]]));
3811 (*WN061025 this methods script is copied from (auto-generated) script
3812 of norm_Rational in order to ease repair on inform*)
3814 (prep_met Rational.thy "met_simp_rat" [] e_metID
3815 (["simplification","of_rationals"],
3816 [("#Given" ,["term t_"]),
3817 ("#Where" ,["t_ is_ratpolyexp"]),
3818 ("#Find" ,["normalform n_"])
3820 {rew_ord'="tless_true",
3822 calc = [], srls = e_rls,
3823 prls = append_rls "simplification_of_rationals_prls" e_rls
3824 [(*for preds in where_*)
3825 Calc ("Rational.is'_ratpolyexp",
3826 eval_is_ratpolyexp "")],
3827 crls = e_rls, nrls = norm_Rational_rls},
3828 "Script SimplifyScript (t_::real) = " ^
3829 " ((Try (Rewrite_Set discard_minus_ False) @@ " ^
3830 " Try (Rewrite_Set rat_mult_poly False) @@ " ^
3831 " Try (Rewrite_Set make_rat_poly_with_parentheses False) @@ " ^
3832 " Try (Rewrite_Set cancel_p_rls False) @@ " ^
3834 " ((Try (Rewrite_Set common_nominator_p_rls False) @@ " ^
3835 " Try (Rewrite_Set rat_mult_div_pow False) @@ " ^
3836 " Try (Rewrite_Set make_rat_poly_with_parentheses False) @@" ^
3837 " Try (Rewrite_Set cancel_p_rls False) @@ " ^
3838 " Try (Rewrite_Set rat_reduce_1 False)))) @@ " ^
3839 " Try (Rewrite_Set discard_parentheses_ False)) " ^