diff options
| author | pottier | 2010-06-03 09:27:00 +0000 |
|---|---|---|
| committer | pottier | 2010-06-03 09:27:00 +0000 |
| commit | cc197b0decd566a3ec28ac1ab58de4dcbfa0ea77 (patch) | |
| tree | 61c773dc218e467bdf96b4db267b171078ec1203 /plugins/groebner/polynom.ml | |
| parent | 2349d832f3141ef33c1097e7ad6255ba5be9461e (diff) | |
plugin groebner updated and renamed as nsatz; first version of the doc of nsatz in the refman
git-svn-id: svn+ssh://scm.gforge.inria.fr/svn/coq/trunk@13056 85f007b7-540e-0410-9357-904b9bb8a0f7
Diffstat (limited to 'plugins/groebner/polynom.ml')
| -rw-r--r-- | plugins/groebner/polynom.ml | 1051 |
1 files changed, 0 insertions, 1051 deletions
diff --git a/plugins/groebner/polynom.ml b/plugins/groebner/polynom.ml deleted file mode 100644 index 0a9c3e270e..0000000000 --- a/plugins/groebner/polynom.ml +++ /dev/null @@ -1,1051 +0,0 @@ -(************************************************************************) -(* v * The Coq Proof Assistant / The Coq Development Team *) -(* <O___,, * CNRS-Ecole Polytechnique-INRIA Futurs-Universite Paris Sud *) -(* \VV/ **************************************************************) -(* // * This file is distributed under the terms of the *) -(* * GNU Lesser General Public License Version 2.1 *) -(************************************************************************) - -(* - Polynomes récursifs: Z[x1]...[xn]. -*) -open Utile -open Util - -module type Coef = sig - type t - val equal : t -> t -> bool - val lt : t -> t -> bool - val le : t -> t -> bool - val abs : t -> t - val plus : t -> t -> t - val mult : t -> t -> t - val sub : t -> t -> t - val opp : t -> t - val div : t -> t -> t - val modulo : t -> t -> t - val puis : t -> int -> t - val pgcd : t -> t -> t - - val hash : t -> int - val of_num : Num.num -> t - val to_string : t -> string -end - -module type S = sig - type coef - type variable = int - type t = Pint of coef | Prec of variable * t array - - val of_num : Num.num -> t - val x : variable -> t - val monome : variable -> int -> t - val is_constantP : t -> bool - val is_zero : t -> bool - - val max_var_pol : t -> variable - val max_var_pol2 : t -> variable - val max_var : t array -> variable - val equal : t -> t -> bool - val norm : t -> t - val deg : variable -> t -> int - val deg_total : t -> int - val copyP : t -> t - val coef : variable -> int -> t -> t - - val plusP : t -> t -> t - val content : t -> coef - val div_int : t -> coef -> t - val vire_contenu : t -> t - val vars : t -> variable list - val int_of_Pint : t -> coef - val multx : int -> variable -> t -> t - val multP : t -> t -> t - val deriv : variable -> t -> t - val oppP : t -> t - val moinsP : t -> t -> t - val puisP : t -> int -> t - val ( @@ ) : t -> t -> t - val ( -- ) : t -> t -> t - val ( ^^ ) : t -> int -> t - val coefDom : variable -> t -> t - val coefConst : variable -> t -> t - val remP : variable -> t -> t - val coef_int_tete : t -> coef - val normc : t -> t - val coef_constant : t -> coef - val univ : bool ref - val string_of_var : int -> string - val nsP : int ref - val to_string : t -> string - val printP : t -> unit - val print_tpoly : t array -> unit - val print_lpoly : t list -> unit - val quo_rem_pol : t -> t -> variable -> t * t - val div_pol : t -> t -> variable -> t - val divP : t -> t -> t - val div_pol_rat : t -> t -> bool - val pseudo_div : t -> t -> variable -> t * t * int * t - val pgcdP : t -> t -> t - val pgcd_pol : t -> t -> variable -> t - val content_pol : t -> variable -> t - val pgcd_coef_pol : t -> t -> variable -> t - val pgcd_pol_rec : t -> t -> variable -> t - val gcd_sub_res : t -> t -> variable -> t - val gcd_sub_res_rec : t -> t -> t -> t -> int -> variable -> t - val lazard_power : t -> t -> int -> variable -> t - val sans_carre : t -> variable -> t - val facteurs : t -> variable -> t list - val facteurs_impairs : t -> variable -> t list - val hcontentP : (string, t) Hashtbl.t - val prcontentP : unit -> unit - val contentP : t * variable -> t - val hash : t -> int - module Hashpol : Hashtbl.S with type key=t - val memoP : string -> 'a Hashpol.t -> (t -> 'a) -> t -> 'a - val hfactorise : t list list Hashpol.t - val prfactorise : unit -> unit - val factorise : t -> t list list - val facteurs2 : t -> t list - val pol_de_factorisation : t list list -> t - val set_of_array_facteurs : t list array -> t list - val factorise_tableauP2 : - t array -> t list array -> t array * (t * int list) array - val factorise_tableauP : t array -> t array * (t * int list) array - val is_positif : t -> bool - val is_negatif : t -> bool - val pseudo_euclide : - t list -> t -> t -> variable -> - t * t * int * t * t * (t * int) list * (t * int) list - val implique_non_nul : t list -> t -> bool - val ajoute_non_nul : t -> t list -> t list -end - -(*********************************************************************** - 2. Le type des polynômes, operations. -*) -module Make (C:Coef) = struct - -type coef = C.t -let coef_of_int i = C.of_num (Num.Int i) -let coef0 = coef_of_int 0 -let coef1 = coef_of_int 1 - -type variable = int - -type t = - Pint of coef (* polynome constant *) - | Prec of variable * (t array) (* coefficients par degre croissant *) - -(* sauf mention du contraire, les opérations ne concernent que des - polynomes normalisés: - - les variables sont des entiers strictement positifs. - - les coefficients d'un polynome en x ne font intervenir que des variables < x. - - pas de coefficient nul en tête. - - pas de Prec(x,a) ou a n'a qu'un element (constant en x). -*) - -(* Polynômes constant *) -let of_num x = Pint (C.of_num x) -let cf0 = of_num (Num.Int 0) -let cf1 = of_num (Num.Int 1) - -(* la n-ième variable *) -let x n = Prec (n,[|cf0;cf1|]) - -(* crée rapidement v^n *) -let monome v n = - match n with - 0->Pint coef1; - |_->let tmp = Array.create (n+1) (Pint coef0) in - tmp.(n)<-(Pint coef1); - Prec (v, tmp) - - -(* teste si un polynome est constant *) -let is_constantP = function - Pint _ -> true - | Prec _ -> false - - -(* conversion d'un poly cst en entier*) -let int_of_Pint = function - Pint x -> x - | _ -> failwith "non" - - -(* teste si un poly est identiquement nul *) -let is_zero p = - match p with Pint n -> if C.equal n coef0 then true else false |_-> false - -(* variable max *) -let max_var_pol p = - match p with - Pint _ -> 0 - |Prec(x,_) -> x - - -(* p n'est pas forcément normalisé *) -let rec max_var_pol2 p = - match p with - Pint _ -> 0 - |Prec(v,c)-> Array.fold_right (fun q m -> max (max_var_pol2 q) m) c v - - -(* variable max d'une liste de polynômes *) -let rec max_var l = Array.fold_right (fun p m -> max (max_var_pol2 p) m) l 0 - - -(* Egalité de deux polynômes - On ne peut pas utiliser = car elle ne marche pas sur les Big_int. -*) -let rec equal p q = - match (p,q) with - (Pint a,Pint b) -> C.equal a b - |(Prec(x,p1),Prec(y,q1)) -> - if x<>y then false - else if (Array.length p1)<>(Array.length q1) then false - else (try (Array.iteri (fun i a -> if not (equal a q1.(i)) - then failwith "raté") - p1; - true) - with _ -> false) - | (_,_) -> false - -(* vire les zéros de tête d'un polynôme non normalisé, dont les coefficients - sont supposés normalisés. - si constant, rend le coef constant. -*) - -let rec norm p = match p with - Pint _ -> p - |Prec (x,a)-> - let d = (Array.length a -1) in - let n = ref d in - while !n>0 && (equal a.(!n) (Pint coef0)) do - n:=!n-1; - done; - if !n<0 then Pint coef0 - else if !n=0 then a.(0) - else if !n=d then p - else (let b=Array.create (!n+1) (Pint coef0) in - for i=0 to !n do b.(i)<-a.(i);done; - Prec(x,b)) - - -(* degré en la variable v du polynome p, v >= max var de p *) -let rec deg v p = - match p with - Prec(x,p1) when x=v -> Array.length p1 -1 - |_ -> 0 - - -(* degré total *) -let rec deg_total p = - match p with - Prec (x,p1) -> let d = ref 0 in - Array.iteri (fun i q -> d:= (max !d (i+(deg_total q)))) p1; - !d - |_ -> 0 - - -(* copie le polynome *) -let rec copyP p = - match p with - Pint i -> Pint i - |Prec(x,q) -> Prec(x,Array.map copyP q) - - -(* coefficient de degre i en v, v >= max var de p *) -let coef v i p = - match p with - Prec (x,p1) when x=v -> if i<(Array.length p1) then p1.(i) else Pint coef0 - |_ -> if i=0 then p else Pint coef0 - - -let rec plusP p q = - let res = - (match (p,q) with - (Pint a,Pint b) -> Pint (C.plus a b) - |(Pint a, Prec (y,q1)) -> let q2=Array.map copyP q1 in - q2.(0)<- plusP p q1.(0); - Prec (y,q2) - |(Prec (x,p1),Pint b) -> let p2=Array.map copyP p1 in - p2.(0)<- plusP p1.(0) q; - Prec (x,p2) - |(Prec (x,p1),Prec (y,q1)) -> - if x<y then (let q2=Array.map copyP q1 in - q2.(0)<- plusP p q1.(0); - Prec (y,q2)) - else if x>y then (let p2=Array.map copyP p1 in - p2.(0)<- plusP p1.(0) q; - Prec (x,p2)) - else - (let n=max (deg x p) (deg x q) in - let r=Array.create (n+1) (Pint coef0) in - for i=0 to n do - r.(i)<- plusP (coef x i p) (coef x i q); - done; - Prec(x,r))) - in norm res - - -(* contenu entier positif *) -let rec content p = - match p with - Pint a -> C.abs a - | Prec (x ,p1) -> - Array.fold_left C.pgcd coef0 (Array.map content p1) - - -(* divise tous les coefficients de p par l'entier a*) -let rec div_int p a= - match p with - Pint b -> Pint (C.div b a) - | Prec(x,p1) -> Prec(x,Array.map (fun x -> div_int x a) p1) - -(* divise p par son contenu entier positif. *) -let vire_contenu p = - let c = content p in - if C.equal c coef0 then p else div_int p c - - -(* liste triee des variables impliquees dans un poly *) -let rec vars=function - Pint _->[] - | Prec (x,l)->(List.flatten ([x]::(List.map vars (Array.to_list l)))) - - -(* multiplie p par v^n, v >= max_var p *) -let rec multx n v p = - match p with - Prec (x,p1) when x=v -> let p2= Array.create ((Array.length p1)+n) (Pint coef0) in - for i=0 to (Array.length p1)-1 do - p2.(i+n)<-p1.(i); - done; - Prec (x,p2) - |_ -> if p = (Pint coef0) then (Pint coef0) - else (let p2=Array.create (n+1) (Pint coef0) in - p2.(n)<-p; - Prec (v,p2)) - - -(* produit de 2 polynomes *) -let rec multP p q = - match (p,q) with - (Pint a,Pint b) -> Pint (C.mult a b) - |(Pint a, Prec (y,q1)) -> - if C.equal a coef0 then Pint coef0 - else let q2 = Array.map (fun z-> multP p z) q1 in - Prec (y,q2) - - |(Prec (x,p1), Pint b) -> - if C.equal b coef0 then Pint coef0 - else let p2 = Array.map (fun z-> multP z q) p1 in - Prec (x,p2) - |(Prec (x,p1), Prec(y,q1)) -> - if x<y - then (let q2 = Array.map (fun z-> multP p z) q1 in - Prec (y,q2)) - else if x>y - then (let p2 = Array.map (fun z-> multP z q) p1 in - Prec (x,p2)) - else Array.fold_left plusP (Pint coef0) - (Array.mapi (fun i z-> (multx i x (multP z q))) p1) - - - -(* derive p par rapport a la variable v, v >= max_var p *) -let rec deriv v p = - match p with - Pint a -> Pint coef0 - | Prec(x,p1) when x=v -> - let d = Array.length p1 -1 in - if d=1 then p1.(1) - else - (let p2 = Array.create d (Pint coef0) in - for i=0 to d-1 do - p2.(i)<- multP (Pint (coef_of_int (i+1))) p1.(i+1); - done; - Prec (x,p2)) - | Prec(x,p1)-> Pint coef0 - - -(* opposé de p *) -let rec oppP p = - match p with - Pint a -> Pint (C.opp a) - |Prec(x,p1) -> Prec(x,Array.map oppP p1) - - -(* différence de deux polynômes. *) -let moinsP p q=plusP p (oppP q) - -let rec puisP p n = match n with - 0 -> cf1 - |_ -> (multP p (puisP p (n-1))) - - -(* notations infixes...*) -(*let (++) a b = plusP a b -*) -let (@@) a b = multP a b - -let (--) a b = moinsP a b - -let (^^) a b = puisP a b - - -(* coefficient dominant de p, v>= max_var p *) - -let coefDom v p= coef v (deg v p) p - - -let coefConst v p = coef v 0 p - -(* queue d'un polynôme *) -let remP v p = - moinsP p (multP (coefDom v p) (puisP (x v) (deg v p))) - - -(* premier coef entier de p *) -let rec coef_int_tete p = - let v = max_var_pol p in - if v>0 - then coef_int_tete (coefDom v p) - else (match p with | Pint a -> a |_ -> assert false) - - -(* divise par le contenu, et rend positif le premier coefficient entier *) -let normc p = - let p = vire_contenu p in - let a = coef_int_tete p in - if C.le coef0 a then p else oppP p - - -(*coef constant d'un polynome normalise*) -let rec coef_constant p = - match p with - Pint a->a - |Prec(_,q)->coef_constant q.(0) - - -(*********************************************************************** - 3. Affichage des polynômes. -*) - -(* si univ=false, on utilise x,y,z,a,b,c,d... comme noms de variables, - sinon, x1,x2,... -*) -let univ=ref true - -(* joli jusqu'a trois variables -- sinon changer le 'w' *) -let string_of_var x= - if !univ then - "u"^(string_of_int x) - else - if x<=3 then String.make 1 (Char.chr(x+(Char.code 'w'))) - else String.make 1 (Char.chr(x-4+(Char.code 'a'))) - -let nsP = ref 0 - -let rec string_of_Pcut p = - if (!nsP)<=0 - then "..." - else - match p with - |Pint a-> nsP:=(!nsP)-1; - if C.le coef0 a - then C.to_string a - else "("^(C.to_string a)^")" - |Prec (x,t)-> - let v=string_of_var x - and s=ref "" - and sp=ref "" in - let st0 = string_of_Pcut t.(0) in - if st0<>"0" - then s:=st0; - let fin = ref false in - for i=(Array.length t)-1 downto 1 do - if (!nsP)<0 - then (sp:="..."; - if not (!fin) then s:=(!s)^"+"^(!sp); - fin:=true) - else ( - let si=string_of_Pcut t.(i) in - sp:=""; - if i=1 - then ( - if si<>"0" - then (nsP:=(!nsP)-1; - if si="1" - then sp:=v - else - (if (String.contains si '+') - then sp:="("^si^")*"^v - else sp:=si^"*"^v))) - else ( - if si<>"0" - then (nsP:=(!nsP)-1; - if si="1" - then sp:=v^"^"^(string_of_int i) - else (if (String.contains si '+') - then sp:="("^si^")*"^v^"^"^(string_of_int i) - else sp:=si^"*"^v^"^"^(string_of_int i)))); - if !sp<>"" && not (!fin) - then (nsP:=(!nsP)-1; - if !s="" - then s:=!sp - else s:=(!s)^"+"^(!sp))); - done; - if !s="" then (nsP:=(!nsP)-1; - (s:="0")); - !s - -let to_string p = - nsP:=20; - string_of_Pcut p - -let printP p = Format.printf "@[%s@]" (to_string p) - - -let print_tpoly lp = - let s = ref "\n{ " in - Array.iter (fun p -> s:=(!s)^(to_string p)^"\n") lp; - prt0 ((!s)^"}") - - -let print_lpoly lp = print_tpoly (Array.of_list lp) - -(* #install_printer printP *) - -(*********************************************************************** - 4. Division exacte de polynômes. -*) - -(* rend (s,r) tel que p = s*q+r *) -let rec quo_rem_pol p q x = - if x=0 - then (match (p,q) with - |(Pint a, Pint b) -> - if C.equal (C.modulo a b) coef0 - then (Pint (C.div a b), cf0) - else failwith "div_pol1" - |_ -> assert false) - else - let m = deg x q in - let b = coefDom x q in - let q1 = remP x q in (* q = b*x^m+q1 *) - let r = ref p in - let s = ref cf0 in - let continue =ref true in - while (!continue) && (not (equal !r cf0)) do - let n = deg x !r in - if n<m - then continue:=false - else ( - let a = coefDom x !r in - let p1 = remP x !r in (* r = a*x^n+p1 *) - let c = div_pol a b (x-1) in (* a = c*b *) - let s1 = c @@ ((monome x (n-m))) in - s:= plusP (!s) s1; - r:= p1 -- (s1 @@ q1); - ) - done; - (!s,!r) - -(* echoue si q ne divise pas p, rend le quotient sinon *) -and div_pol p q x = - let (s,r) = quo_rem_pol p q x in - if equal r cf0 - then s - else failwith ("div_pol:\n" - ^"p:"^(to_string p)^"\n" - ^"q:"^(to_string q)^"\n" - ^"r:"^(to_string r)^"\n" - ^"x:"^(string_of_int x)^"\n" - ) - - -(* test de division exacte de p par q mais constantes rationnels - à vérifier *) -let divP p q= - let x = max (max_var_pol p) (max_var_pol q) in - div_pol p q x - -(* test de division exacte de p par q mais constantes rationnels - à vérifier *) -let div_pol_rat p q= - let x = max (max_var_pol p) (max_var_pol q) in - try (let s = div_pol (multP p (puisP (Pint(coef_int_tete q)) - (1+(deg x p) - (deg x q)))) - q x in - (*degueulasse, mais c 'est pour enlever un warning *) - if s==s then true else true) - with _ -> false - - - - -(*********************************************************************** - 5. Pseudo-division et pgcd par les sous-résultants. -*) - -(* pseudo division : - q = c*x^m+q1 - rend (r,c,d,s) tels que c^d*p = s*q + r. -*) - -let pseudo_div p q x = - match q with - Pint _ -> (cf0, q,1, p) - | Prec (v,q1) when x<>v -> (cf0, q,1, p) - | Prec (v,q1) -> - ( - (* pr "pseudo_division: c^d*p = s*q + r";*) - let delta = ref 0 in - let r = ref p in - let c = coefDom x q in - let q1 = remP x q in - let d' = deg x q in - let s = ref cf0 in - while (deg x !r)>=(deg x q) do - let d = deg x !r in - let a = coefDom x !r in - let r1=remP x !r in - let u = a @@ ((monome x (d-d'))) in - r:=(c @@ r1) -- (u @@ q1); - s:=plusP (c @@ (!s)) u; - delta := (!delta) + 1; - done; - (* - pr ("deg d: "^(string_of_int (!delta))^", deg c: "^(string_of_int (deg_total c))); - pr ("deg r:"^(string_of_int (deg_total !r))); - *) - (!r,c,!delta, !s) - ) - - -(* pgcd de polynômes par les sous-résultants *) - - -let rec pgcdP p q = - let x = max (max_var_pol p) (max_var_pol q) in - pgcd_pol p q x - -and pgcd_pol p q x = - pgcd_pol_rec p q x - -and content_pol p x = - match p with - Prec(v,p1) when v=x -> - Array.fold_left (fun a b -> pgcd_pol_rec a b (x-1)) cf0 p1 - | _ -> p - -and pgcd_coef_pol c p x = - match p with - Prec(v,p1) when x=v -> - Array.fold_left (fun a b -> pgcd_pol_rec a b (x-1)) c p1 - |_ -> pgcd_pol_rec c p (x-1) - - -and pgcd_pol_rec p q x = - match (p,q) with - (Pint a,Pint b) -> Pint (C.pgcd (C.abs a) (C.abs b)) - |_ -> - if equal p cf0 - then q - else if equal q cf0 - then p - else if (deg x q) = 0 - then pgcd_coef_pol q p x - else if (deg x p) = 0 - then pgcd_coef_pol p q x - else ( - let a = content_pol p x in - let b = content_pol q x in - let c = pgcd_pol_rec a b (x-1) in - pr (string_of_int x); - let p1 = div_pol p c x in - let q1 = div_pol q c x in - let r = gcd_sub_res p1 q1 x in - let cr = content_pol r x in - let res = c @@ (div_pol r cr x) in - res - ) - -(* Sous-résultants: - - ai*Ai = Qi*Ai+1 + bi*Ai+2 - - deg Ai+2 < deg Ai+1 - - Ai = ci*X^ni + ... - di = ni - ni+1 - - ai = (- ci+1)^(di + 1) - b1 = 1 - bi = ci*si^di si i>1 - - s1 = 1 - si+1 = ((ci+1)^di*si)/si^di - -*) -and gcd_sub_res p q x = - if equal q cf0 - then p - else - let d = deg x p in - let d' = deg x q in - if d<d' - then gcd_sub_res q p x - else - let delta = d-d' in - let c' = coefDom x q in - let r = snd (quo_rem_pol (((oppP c')^^(delta+1))@@p) (oppP q) x) in - gcd_sub_res_rec q r (c'^^delta) c' d' x - -and gcd_sub_res_rec p q s c d x = - if equal q cf0 - then p - else ( - let d' = deg x q in - let c' = coefDom x q in - let delta = d-d' in - let r = snd (quo_rem_pol (((oppP c')^^(delta+1))@@p) (oppP q) x) in - let s'= lazard_power c' s delta x in - gcd_sub_res_rec q (div_pol r (c @@ (s^^delta)) x) s' c' d' x - ) - -and lazard_power c s d x = - let res = ref c in - for i=1 to d-1 do - res:= div_pol ((!res)@@c) s x; - done; - !res - - - -(*********************************************************************** - 6. Décomposition sans carré, factorisation. -*) - -(* - p = f1 f2^2 ... fn^r - p/\p'= f2 f3^2...fn^(r-1) - sans_carré(p)= p/p/\p '= f1 f2 ... fn -*) - -let sans_carre p x = - if (deg x p) <= 1 then p - else - let p' = deriv x p in - div_pol p (pgcd_pol p p' x) x - - -(* liste [f1;...;fn] *) -let facteurs p x = - let rec facteurs_rec p q = - if (deg x p)=0 then [] - else - let p2 = div_pol p q x in - let q2 = sans_carre p2 x in - (div_pol q q2 x)::(facteurs_rec p2 q2) - in facteurs_rec p (sans_carre p x) - - -(* liste [f1;f3;...] *) -let facteurs_impairs p x = - let lf = Array.of_list (facteurs p x) in - let r = ref [] in - Array.iteri (fun i f -> - if ((i+1) mod 2)=1 - then r:=(!r)@[f]) - lf; - !r - - -(* décomposition sans carrés en toutes les variables *) - - -let hcontentP = (Hashtbl.create 51 : (string,t) Hashtbl.t) - -let prcontentP () = - Hashtbl.iter (fun s c -> - prn (s^" -> "^(to_string c))) - hcontentP - - -let contentP = - memos "c" hcontentP (fun (p,x) -> ((to_string p)^":"^(string_of_int x))) - (fun (p,x) -> content_pol p x) - - -(* Tables de hash et polynômes, mémo *) - -(* fonction de hachage des polynômes *) -let rec hash = function - Pint a -> (C.hash a) - | Prec (v,p) -> - Array.fold_right (fun q h -> h + hash q) p 0 - - -module Hashpol = Hashtbl.Make( - struct - type poly = t - type t = poly - let equal = equal - let hash = hash - end) - - -let memoP s memoire fonction x = - try (let v = Hashpol.find memoire x in pr s;v) - with _ -> (pr "#"; - let v = fonction x in - Hashpol.add memoire x v; - v) - - -let hfactorise = Hashpol.create 51 - -let prfactorise () = - Hashpol.iter (fun p c -> - prn ((to_string p)^" -> "); - print_lpoly (List.flatten c)) - hfactorise - -let factorise = - memoP "f" hfactorise - (fun p -> - let rec fact p x = - if x=0 - then [] - else - let c = contentP (p,x) in - let q = div_pol p c x in - (facteurs q x)::(fact c (x-1)) - in fact p (max_var_pol p)) - - -(* liste des facteurs sans carré non constants, - avec coef entier de tête positif *) -let facteurs2 p = - List.map normc - (List.filter (fun q -> deg_total q >0) - (List.flatten (factorise (normc p)))) - - -(* produit des facteurs non constants d'une décomposition sans carré *) -let pol_de_factorisation lf = - let p = ref cf1 in - List.iter (fun lq -> - Array.iteri (fun i q -> if (deg_total q)>0 then p:=(!p)@@(q^^(i+1))) - (Array.of_list lq)) - lf; - !p - - -let set_of_array_facteurs tf = - let h = Hashpol.create 51 in - Array.iter (fun lf -> - List.iter (fun p -> if not (Hashpol.mem h p) - then Hashpol.add h p true) - lf) - tf; - let res = ref [] in - Hashpol.iter (fun p _ -> res:=p::(!res)) h; - !res - - -(* Factorise un tableau de polynômes f, et rend: - - un tableau p de facteurs (degré>0, contenu entier 1, - coefficient de tête >0) obtenu par décomposition sans carrés - puis par division mutuelle - - un tableau l de couples (constante, listes d'indices l) - tels que f.(i) = l.(i)_1*Produit(p.(j), j dans l.(i)_2) -*) - -(* on donne le tableau des facteurs de chaque poly de f *) -let factorise_tableauP2 f l1 = - let x = max_var f in - (* liste des facteurs sans carré des polynômes de f *) - pr"<"; - let l1 = set_of_array_facteurs l1 in - (* on les divise entre eux pour éventuellement trouver - de nouveaux facteurs *) - pr "~"; - let l1 = Sort.list (fun p q -> (deg_total p)<(deg_total q)) l1 in - let l1 = Array.of_list (facteurs_liste (fun a b -> div_pol a b x) - (fun p -> (deg_total p)<1) - l1) in - (* puis on décompose les polynômes de f avec ces facteurs *) - pr "-"; - let res = factorise_tableau (fun a b -> div_pol a b x) - (fun p -> equal p cf0) - cf0 - f l1 in - pr ">"; - res - -let factorise_tableauP f = - factorise_tableauP2 f (Array.map facteurs2 f) - - -(*********************************************************************** - 7. Pseudo-division avec reste de même signe, - en utilisant des polynômes non nuls pour diviser le reste. -*) - -(* polynôme pair et coefficients positifs *) -let rec is_positif p = - - let res = - match p with - Pint a -> C.le coef0 a - |Prec(x,p1) -> - (array_for_all is_positif p1) - && (try (Array.iteri (fun i c -> if (i mod 2)<>0 && not (equal c cf0) - then failwith "pas pair") - p1; - true) - with Failure _ -> false) - in - res - - - -let is_negatif p = is_positif (oppP p) - - -(* rend r tel que deg r < deg q et r a le signe de p en les racines de q. - le coefficient dominant de q est non nul - quand les polynômes de coef_non_nuls le sont. - (rs,cs,ds,ss,crs,lpos,lpol)= pseudo_euclide coef_non_nuls vect.(s-1) res.(s-1) v -*) -let pseudo_euclide coef_non_nuls p q x = - let (r,c,d,s) = pseudo_div p q x in - (* - c^d * p = s*q + r, c = coef dominant de q - *) - (* vérification de la pseudo-division: - let verif = ((c^^d)@@p)--(plusP (s@@q) r) in - if not (equal verif cf0) - then (prn ("p:"^(to_string p)); - prn ("q:"^(to_string q)); - prn ("c:"^(to_string c)); - prn ("r:"^(to_string r)); - prn ("d:"^(string_of_int d)); - failwith "erreur dans la pseudo-division"); - *) - - (* pour autoriser des c pas positifs, il faut modifier algo14 et preuve3*) - let r = if d mod 2 = 1 then c@@r else r in - let s = if d mod 2 = 1 then c@@s else s in - let d = if d mod 2 = 1 then d+1 else d in - - (* on encore c^d * p = s*q + r, mais d pair *) - if equal r cf0 - then ((*pr "reste nul"; *) (r,c,d,s,cf1,[],[])) - else ( - let r1 = vire_contenu r in - let cr = div_pol r r1 x in - let r = ref r1 in - (* r a maintenant le même signe que p en les racines de q.*) - (* on tente de diviser r par les polynômes de coef_non_nuls *) - let lf = ref [] in (* liste de (facteur, puissance) *) - List.iter (fun f -> - if (deg_total f)>0 && (max_var_pol f) < x - then ( - let k = ref 0 in - (try (while true do - let rd = div_pol !r f x in - (* verification de la division - if not (equal cf0 ((!r)--(f@@rd))) - then failwith "erreur dans la division"; - *) - k:=(!k)+1; - r:=rd; - (*pr "+";*) - done) - with _ -> ()); - lf:=(f,!k)::(!lf))) - coef_non_nuls; - (* il faut éventuellement remultiplier pour garder le signe de r *) - let lpos = ref [] in - let lpol = ref [] in - List.iter (fun (f,k) -> - if k>0 - then ( - if (is_positif f) - (* f est positif, tout va bien *) - then lpos:=(f,k)::(!lpos) - else if (is_negatif f) - (* f est négatif *) - then (if k mod 2 = 1 - (* k est impair *) - then (lpos:=(oppP f,k)::(!lpos); - r:=oppP (!r)) - else lpos:=(f,k)::(!lpos)) - (* on ne connaît pas le signe de f *) - else if k mod 2 = 0 - (* k est pair, tout va bien *) - then lpol:=(f,k)::(!lpol) - (* k est impair *) - else (lpol:=(f,k-1)::(!lpol); - r:=multP (!r) f))) - !lf; - (* - pr ((* "------reste de même signe: " - ^(to_string c) - ^" variable: "^(string_of_int x) - ^" c:"^(string_of_int (deg_total c)) - ^" d:"^(string_of_int d) - ^" deg(r)-deg(r0):" - ^*)(string_of_int ((deg_total !r)-(deg_total r0)))); - *) - (* lpos = liste de (f,k) ou f est non nul positif, et f^k divise r0 - lpol = liste de (f,k) ou f non nul, k est pair et f^k divise r0 - on c^d * p = s*q + r0 - avec d pair - r0 = cr * r * PI_lpos f^k * PI_lpol g^k - cr non nul positif - *) - (!r,c,d,s,cr,!lpos,!lpol)) - - - -(* teste si la non-nullité des polynômes de lp entraîne celle de p: - chacun des facteurs de la décomposition sans carrés de p - divise un des polynômes de lp (dans Q[x1...xn]) *) - -let implique_non_nul lp p = - if equal p cf0 then false - else( - pr "["; - let lf = facteurs2 p in - let r =( - try (List.iter (fun f -> - if (try (List.iter (fun q -> - if div_pol_rat q f - then failwith "divise") - lp; - true) - with _ -> false) - then failwith "raté") - lf; - true) - with _ -> false) - in pr "]";r) - - -let ajoute_non_nul p lp = - if (deg_total p) >0 - then( - let p = normc p in - let lf = facteurs2 p in - let r = set_of_list_eq equal (lp@lf@[p]) in - r) - else lp - -end |
