diff options
Diffstat (limited to 'plugins/groebner/ideal.ml')
| -rw-r--r-- | plugins/groebner/ideal.ml | 1356 |
1 files changed, 0 insertions, 1356 deletions
diff --git a/plugins/groebner/ideal.ml b/plugins/groebner/ideal.ml deleted file mode 100644 index b41d6d8e3a..0000000000 --- a/plugins/groebner/ideal.ml +++ /dev/null @@ -1,1356 +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 *) -(************************************************************************) - -(* - Nullstellensatz par calcul de base de Grobner - - On utilise une representation creuse des polynomes: - un monome est un tableau d'exposants (un par variable), - avec son degre en tete. - un polynome est une liste de (coefficient,monome). - - L'algorithme de Buchberger a proprement parler est tire du code caml - extrait du code Coq ecrit par L.Thery. - - *) - -open Utile - -(* NB: Loic is using a coding-style "let x::q = ... in ..." that - produces lots of warnings about non-exhaustive pattern matchs. - Even worse, it is not clear whether a [Match_failure] could - happen (and be catched by a "with _ ->") or not. Loic told me - it shouldn't happen. - - In a first time, I used a camlp4 extension (search history - for lib/refutpat.ml4) for introducing an ad-hoc syntax - "let* x::q = ...". This is now removed (too complex during - porting to camlp4). - - Now, we simply use the following function that turns x::q - into (x,q) and hence an irrefutable pattern. Yes, this adds - a (small) cost since the intermediate pair is allocated - (in opt, the cost might even be 0 due to inlining). - If somebody want someday to remove this extra cost, - (x::q) could also be turned brutally into (x,q) by Obj.magic - (beware: be sure no floats are around in this case). -*) - -let of_cons = function - | [] -> assert false - | x::q -> x,q - -exception NotInIdeal - -module type S = sig - -(* Monomials *) -type mon = int array - -val mult_mon : int -> mon -> mon -> mon -val deg : mon -> int -val compare_mon : int -> mon -> mon -> int -val div_mon : int -> mon -> mon -> mon -val div_mon_test : int -> mon -> mon -> bool -val ppcm_mon : int -> mon -> mon -> mon - -(* Polynomials *) - -type deg = int -type coef -type poly -val repr : poly -> (coef * mon) list -val polconst : deg -> coef -> poly -val zeroP : poly -val gen : deg -> int -> poly - -val equal : poly -> poly -> bool -val name_var : string list ref -val getvar : string list -> int -> string -val lstringP : poly list -> string -val printP : poly -> unit -val lprintP : poly list -> unit - -val div_pol_coef : poly -> coef -> poly -val plusP : deg -> poly -> poly -> poly -val mult_t_pol : deg -> coef -> mon -> poly -> poly -val selectdiv : deg -> mon -> poly list -> poly -val oppP : poly -> poly -val emultP : coef -> poly -> poly -val multP : deg -> poly -> poly -> poly -val puisP : deg -> poly -> int -> poly -val contentP : poly -> coef -val contentPlist : poly list -> coef -val pgcdpos : coef -> coef -> coef -val div_pol : deg -> poly -> poly -> coef -> coef -> mon -> poly -val reduce2 : deg -> poly -> poly list -> coef * poly - -val poldepcontent : coef list ref -val coefpoldep_find : poly -> poly -> poly -val coefpoldep_set : poly -> poly -> poly -> unit -val initcoefpoldep : deg -> poly list -> unit -val reduce2_trace : deg -> poly -> poly list -> poly list -> poly list * poly -val spol : deg -> poly -> poly -> poly -val etrangers : deg -> poly -> poly -> bool -val div_ppcm : deg -> poly -> poly -> poly -> bool - -val genPcPf : deg -> poly -> poly list -> poly list -> poly list -val genOCPf : deg -> poly list -> poly list - -val is_homogeneous : poly -> bool - -type certificate = - { coef : coef; power : int; - gb_comb : poly list list; last_comb : poly list } -val test_dans_ideal : deg -> poly -> poly list -> poly list -> - poly list * poly * certificate -val in_ideal : deg -> poly list -> poly -> poly list * poly * certificate - -end - -(*********************************************************************** - Global options -*) -let lexico = ref false -let use_hmon = ref false - -(*********************************************************************** - Functor -*) - -module Make (P:Polynom.S) = struct - - type coef = P.t - let coef0 = P.of_num (Num.Int 0) - let coef1 = P.of_num (Num.Int 1) - let coefm1 = P.of_num (Num.Int (-1)) - let string_of_coef c = "["^(P.to_string c)^"]" - -(*********************************************************************** - Monomes - tableau d'entiers - le premier coefficient est le degre - *) - -type mon = int array -type deg = int -type poly = (coef * mon) list - -(* d représente le nb de variables du monome *) - -(* Multiplication de monomes ayant le meme nb de variables = d *) -let mult_mon d m m' = - let m'' = Array.create (d+1) 0 in - for i=0 to d do - m''.(i)<- (m.(i)+m'.(i)); - done; - m'' - -(* Degré d'un monome *) -let deg m = m.(0) - - -let compare_mon d m m' = - if !lexico - then ( - (* Comparaison de monomes avec ordre du degre lexicographique - = on commence par regarder la 1ere variable*) - let res=ref 0 in - let i=ref 1 in (* 1 si lexico pur 0 si degre*) - while (!res=0) && (!i<=d) do - res:= (compare m.(!i) m'.(!i)); - i:=!i+1; - done; - !res) - else ( - (* degre lexicographique inverse *) - match compare m.(0) m'.(0) with - | 0 -> (* meme degre total *) - let res=ref 0 in - let i=ref d in - while (!res=0) && (!i>=1) do - res:= - (compare m.(!i) m'.(!i)); - i:=!i-1; - done; - !res - | x -> x) - -(* Division de monome ayant le meme nb de variables *) -let div_mon d m m' = - let m'' = Array.create (d+1) 0 in - for i=0 to d do - m''.(i)<- (m.(i)-m'.(i)); - done; - m'' - -let div_pol_coef p c = - List.map (fun (a,m) -> (P.divP a c,m)) p - -(* m' divise m *) -let div_mon_test d m m' = - let res=ref true in - let i=ref 1 in - while (!res) && (!i<=d) do - res:= (m.(!i) >= m'.(!i)); - i:=succ !i; - done; - !res - - -(* Mise en place du degré total du monome *) -let set_deg d m = - m.(0)<-0; - for i=1 to d do - m.(0)<- m.(i)+m.(0); - done; - m - - -(* ppcm de monomes *) -let ppcm_mon d m m' = - let m'' = Array.create (d+1) 0 in - for i=1 to d do - m''.(i)<- (max m.(i) m'.(i)); - done; - set_deg d m'' - - - -(********************************************************************** - - Polynomes - liste de couples (coefficient,monome) ordonnee en decroissant - - *) - - -let repr p = p - -let equal = - Util.list_for_all2eq - (fun (c1,m1) (c2,m2) -> P.equal c1 c2 && m1=m2) - -let hash p = - let c = List.map fst p in - let m = List.map snd p in - List.fold_left (fun h p -> h * 17 + P.hash p) (Hashtbl.hash m) c - -module Hashpol = Hashtbl.Make( - struct - type t = poly - let equal = equal - let hash = hash - end) - - -(* - A pretty printer for polynomials, with Maple-like syntax. - *) - -open Format - -let getvar lv i = - try (List.nth lv i) - with _ -> (List.fold_left (fun r x -> r^" "^x) "lv= " lv) - ^" i="^(string_of_int i) - -let string_of_pol zeroP hdP tlP coefterm monterm string_of_coef - dimmon string_of_exp lvar p = - - let rec string_of_mon m coefone = - let s=ref [] in - for i=1 to (dimmon m) do - (match (string_of_exp m i) with - "0" -> () - | "1" -> s:= (!s) @ [(getvar !lvar (i-1))] - | e -> s:= (!s) @ [((getvar !lvar (i-1)) ^ "^" ^ e)]); - done; - (match !s with - [] -> if coefone - then "1" - else "" - | l -> if coefone - then (String.concat "*" l) - else ( "*" ^ - (String.concat "*" l))) - and string_of_term t start = let a = coefterm t and m = monterm t in - match (string_of_coef a) with - "0" -> "" - | "1" ->(match start with - true -> string_of_mon m true - |false -> ( "+ "^ - (string_of_mon m true))) - | "-1" ->( "-" ^" "^(string_of_mon m true)) - | c -> if (String.get c 0)='-' - then ( "- "^ - (String.sub c 1 - ((String.length c)-1))^ - (string_of_mon m false)) - else (match start with - true -> ( c^(string_of_mon m false)) - |false -> ( "+ "^ - c^(string_of_mon m false))) - and stringP p start = - if (zeroP p) - then (if start - then ("0") - else "") - else ((string_of_term (hdP p) start)^ - " "^ - (stringP (tlP p) false)) - in - (stringP p true) - - - -let print_pol zeroP hdP tlP coefterm monterm string_of_coef - dimmon string_of_exp lvar p = - - let rec print_mon m coefone = - let s=ref [] in - for i=1 to (dimmon m) do - (match (string_of_exp m i) with - "0" -> () - | "1" -> s:= (!s) @ [(getvar !lvar (i-1))] - | e -> s:= (!s) @ [((getvar !lvar (i-1)) ^ "^" ^ e)]); - done; - (match !s with - [] -> if coefone - then print_string "1" - else () - | l -> if coefone - then print_string (String.concat "*" l) - else (print_string "*"; - print_string (String.concat "*" l))) - and print_term t start = let a = coefterm t and m = monterm t in - match (string_of_coef a) with - "0" -> () - | "1" ->(match start with - true -> print_mon m true - |false -> (print_string "+ "; - print_mon m true)) - | "-1" ->(print_string "-";print_space();print_mon m true) - | c -> if (String.get c 0)='-' - then (print_string "- "; - print_string (String.sub c 1 - ((String.length c)-1)); - print_mon m false) - else (match start with - true -> (print_string c;print_mon m false) - |false -> (print_string "+ "; - print_string c;print_mon m false)) - and printP p start = - if (zeroP p) - then (if start - then print_string("0") - else ()) - else (print_term (hdP p) start; - if start then open_hovbox 0; - print_space(); - print_cut(); - printP (tlP p) false) - in open_hovbox 3; - printP p true; - print_flush() - - -let name_var= ref [] - -let stringP = string_of_pol - (fun p -> match p with [] -> true | _ -> false) - (fun p -> match p with (t::p) -> t |_ -> failwith "print_pol dans dansideal") - (fun p -> match p with (t::p) -> p |_ -> failwith "print_pol dans dansideal") - (fun (a,m) -> a) - (fun (a,m) -> m) - string_of_coef - (fun m -> (Array.length m)-1) - (fun m i -> (string_of_int (m.(i)))) - name_var - - -let stringPcut p = - if (List.length p)>20 - then (stringP [List.hd p])^" + "^(string_of_int (List.length p))^" termes" - else stringP p - -let rec lstringP l = - match l with - [] -> "" - |p::l -> (stringP p)^("\n")^(lstringP l) - -let printP = print_pol - (fun p -> match p with [] -> true | _ -> false) - (fun p -> match p with (t::p) -> t |_ -> failwith "print_pol dans dansideal") - (fun p -> match p with (t::p) -> p |_ -> failwith "print_pol dans dansideal") - (fun (a,m) -> a) - (fun (a,m) -> m) - string_of_coef - (fun m -> (Array.length m)-1) - (fun m i -> (string_of_int (m.(i)))) - name_var - - -let rec lprintP l = - match l with - [] -> () - |p::l -> printP p;print_string "\n"; lprintP l - - -(* Operations - *) - -let zeroP = [] - -(* Retourne un polynome constant à d variables *) -let polconst d c = - let m = Array.create (d+1) 0 in - let m = set_deg d m in - [(c,m)] - - - -(* somme de polynomes= liste de couples (int,monomes) *) -let plusP d p q = - let rec plusP p q = - match p with - [] -> q - |t::p' -> - match q with - [] -> p - |t'::q' -> - match compare_mon d (snd t) (snd t') with - 1 -> t::(plusP p' q) - |(-1) -> t'::(plusP p q') - |_ -> let c=P.plusP (fst t) (fst t') in - match P.equal c coef0 with - true -> (plusP p' q') - |false -> (c,(snd t))::(plusP p' q') - in plusP p q - - -(* multiplication d'un polynome par (a,monome) *) -let mult_t_pol d a m p = - let rec mult_t_pol p = - match p with - [] -> [] - |(b,m')::p -> ((P.multP a b),(mult_mon d m m'))::(mult_t_pol p) - in mult_t_pol p - - -(* Retourne un polynome de l dont le monome de tete divise m, [] si rien *) -let rec selectdiv d m l = - match l with - [] -> [] - | q::r -> - let m'= snd (List.hd q) in - if div_mon_test d m m' then q else selectdiv d m r - - -(* Retourne un polynome générateur 'i' à d variables *) -let gen d i = - let m = Array.create (d+1) 0 in - m.(i) <- 1; - let m = set_deg d m in - [(coef1,m)] - - - -(* oppose d'un polynome *) -let oppP p = - let rec oppP p = - match p with - [] -> [] - |(b,m')::p -> ((P.oppP b),m')::(oppP p) - in oppP p - - -(* multiplication d'un polynome par un coefficient par 'a' *) -let emultP a p = - let rec emultP p = - match p with - [] -> [] - |(b,m')::p -> ((P.multP a b),m')::(emultP p) - in emultP p - - -let multP d p q = - let rec aux p = - match p with - [] -> [] - |(a,m)::p' -> plusP d (mult_t_pol d a m q) (aux p') - in aux p - - -let puisP d p n= - let rec puisP n = - match n with - 0 -> [coef1, Array.create (d+1) 0] - | 1 -> p - |_ -> multP d p (puisP (n-1)) - in puisP n - -let pgcdpos a b = P.pgcdP a b -let pgcd1 p q = - if P.equal p coef1 || P.equal p coefm1 then p else P.pgcdP p q - -let rec contentP p = - match p with - |[] -> coef1 - |[a,m] -> a - |(a,m)::p1 -> pgcd1 a (contentP p1) - -let contentPlist lp = - match lp with - |[] -> coef1 - |p::l1 -> List.fold_left (fun r q -> pgcd1 r (contentP q)) (contentP p) l1 - -(*********************************************************************** - Division de polynomes - *) - -let hmon = (Hashtbl.create 1000 : (mon,poly) Hashtbl.t) - -let find_hmon m = - if !use_hmon - then Hashtbl.find hmon m - else raise Not_found - -let add_hmon m q = - if !use_hmon then Hashtbl.add hmon m q - -let selectdiv_cache d m l = - try find_hmon m - with Not_found -> - match selectdiv d m l with - [] -> [] - | q -> add_hmon m q; q - -let div_pol d p q a b m = -(* info ".";*) - plusP d (emultP a p) (mult_t_pol d b m q) - -(* si false on ne divise que le monome de tete *) -let reduire_les_queues = false - -(* reste de la division de p par les polynomes de l - rend le reste et le coefficient multiplicateur *) - -let reduce2 d p l = - let rec reduce p = - match p with - [] -> (coef1,[]) - | (a,m)::p' -> - let q = selectdiv_cache d m l in - (match q with - [] -> - if reduire_les_queues - then - let (c,r)=(reduce p') in - (c,((P.multP a c,m)::r)) - else (coef1,p) - |(b,m')::q' -> - let c=(pgcdpos a b) in - let a'= (P.divP b c) in - let b'=(P.oppP (P.divP a c)) in - let (e,r)=reduce (div_pol d p' q' a' b' - (div_mon d m m')) in - (P.multP a' e,r)) in - reduce p - -(* trace des divisions *) - -(* liste des polynomes de depart *) -let poldep = ref [] -let poldepcontent = ref [] - - -module HashPolPair = Hashtbl.Make - (struct - type t = poly * poly - let equal (p,q) (p',q') = equal p p' && equal q q' - let hash (p,q) = - let c = List.map fst p @ List.map fst q in - let m = List.map snd p @ List.map snd q in - List.fold_left (fun h p -> h * 17 + P.hash p) (Hashtbl.hash m) c - end) - -(* table des coefficients des polynomes en fonction des polynomes de depart *) -let coefpoldep = HashPolPair.create 51 - -(* coefficient de q dans l expression de p = sum_i c_i*q_i *) -let coefpoldep_find p q = - try (HashPolPair.find coefpoldep (p,q)) - with _ -> [] - -let coefpoldep_set p q c = - HashPolPair.add coefpoldep (p,q) c - -let initcoefpoldep d lp = - poldep:=lp; - poldepcontent:= List.map contentP (!poldep); - List.iter - (fun p -> coefpoldep_set p p (polconst d coef1)) - lp - -(* garde la trace dans coefpoldep - divise sans pseudodivisions *) - -let reduce2_trace d p l lcp = - (* rend (lq,r), ou r = p + sum(lq) *) - let rec reduce p = - match p with - [] -> ([],[]) - |t::p' -> let (a,m)=t in - let q = - (try Hashtbl.find hmon m - with Not_found -> - let q = selectdiv d m l in - match q with - t'::q' -> (Hashtbl.add hmon m q;q) - |[] -> q) in - match q with - [] -> - if reduire_les_queues - then - let (lq,r)=(reduce p') in - (lq,((a,m)::r)) - else ([],p) - |(b,m')::q' -> - let b' = P.oppP (P.divP a b) in - let m''= div_mon d m m' in - let p1=plusP d p' (mult_t_pol d b' m'' q') in - let (lq,r)=reduce p1 in - ((b',m'',q)::lq, r) - in let (lq,r) = reduce p in - (*info "reduce2_trace:\n"; - List.iter - (fun (a,m,s) -> - let x = mult_t_pol d a m s in - info ((stringP x)^"\n")) - lq; - info "ok\n";*) - (List.map2 - (fun c0 q -> - let c = - List.fold_left - (fun x (a,m,s) -> - if equal s q - then - plusP d x (mult_t_pol d a m (polconst d coef1)) - else x) - c0 - lq in - c) - lcp - !poldep, - r) - -(*********************************************************************** - Algorithme de Janet (V.P.Gerdt Involutive algorithms...) -*) - -(*********************************** - deuxieme version, qui elimine des poly inutiles -*) -let homogeneous = ref false -let pol_courant = ref [] - - -type pol3 = - {pol : poly; - anc : poly; - nmp : mon} - -let fst_mon q = snd (List.hd q.pol) -let lm_anc q = snd (List.hd q.anc) - -let pol_to_pol3 d p = - {pol = p; anc = p; nmp = Array.create (d+1) 0} - -let is_multiplicative u s i = - if i=1 - then List.for_all (fun q -> (fst_mon q).(1) <= u.(1)) s - else - List.for_all - (fun q -> - let v = fst_mon q in - let res = ref true in - let j = ref 1 in - while !j < i && !res do - res:= v.(!j) = u.(!j); - j:= !j + 1; - done; - if !res - then v.(i) <= u.(i) - else true) - s - -let is_multiplicative_rev d u s i = - if i=1 - then - List.for_all - (fun q -> (fst_mon q).(d+1-1) <= u.(d+1-1)) - s - else - List.for_all - (fun q -> - let v = fst_mon q in - let res = ref true in - let j = ref 1 in - while !j < i && !res do - res:= v.(d+1- !j) = u.(d+1- !j); - j:= !j + 1; - done; - if !res - then v.(d+1-i) <= u.(d+1-i) - else true) - s - -let monom_multiplicative d u s = - let m = Array.create (d+1) 0 in - for i=1 to d do - if is_multiplicative u s i - then m.(i)<- 1; - done; - m - -(* mu monome des variables multiplicative de u *) -let janet_div_mon d u mu v = - let res = ref true in - let i = ref 1 in - while !i <= d && !res do - if mu.(!i) = 0 - then res := u.(!i) = v.(!i) - else res := u.(!i) <= v.(!i); - i:= !i + 1; - done; - !res - -let find_multiplicative p mg = - try Hashpol.find mg p.pol - with Not_found -> (info "\nPROBLEME DANS LA TABLE DES VAR MULT"; - info (stringPcut p.pol); - failwith "aie") - -(* mg hashtable de p -> monome_multiplicatif de g *) - -let hashtbl_reductor = ref (Hashtbl.create 51 : (mon,pol3) Hashtbl.t) - -(* suppose que la table a été initialisée *) -let find_reductor d v lt mt = - try Hashtbl.find !hashtbl_reductor v - with Not_found -> - let r = - List.find - (fun q -> - let u = fst_mon q in - let mu = find_multiplicative q mt in - janet_div_mon d u mu v - ) - lt in - Hashtbl.add !hashtbl_reductor v r; - r - -let normal_form d p g mg onlyhead = - let rec aux = function - [] -> (coef1,p) - | (a,v)::p' -> - (try - let q = find_reductor d v g mg in - let (b,u),q' = of_cons q.pol in - let c = P.pgcdP a b in - let a' = P.divP b c in - let b' = P.oppP (P.divP a c) in - let m = div_mon d v u in - (* info ".";*) - let (c,r) = aux (plusP d (emultP a' p') (mult_t_pol d b' m q')) in - (P.multP c a', r) - with _ -> (* TODO: catch only relevant exn *) - if onlyhead - then (coef1,p) - else - let (c,r)= (aux p') in - (c, plusP d [(P.multP a c,v)] r)) in - aux p - -let janet_normal_form d p g mg = - let (_,r) = normal_form d p g mg false in r - -let head_janet_normal_form d p g mg = - let (_,r) = normal_form d p g mg true in r - -let reduce_rem d r lt lq = - Hashtbl.clear hmon; - let (_,r) = reduce2 d r (List.map (fun p -> p.pol) (lt @ lq)) in - Hashtbl.clear hmon; - r - -let tail_normal_form d p g mg = - let (a,v),p' = of_cons p in - let (c,r)= (normal_form d p' g mg false) in - plusP d [(P.multP a c,v)] r - -let div_strict d m1 m2 = - m1 <> m2 && div_mon_test d m2 m1 - -let criteria d p g lt = - mult_mon d (lm_anc p) (lm_anc g) = fst_mon p -|| - (let c = ppcm_mon d (lm_anc p) (lm_anc g) in - div_strict d c (fst_mon p)) -|| - (List.exists - (fun t -> - let cp = ppcm_mon d (lm_anc p) (fst_mon t) in - let cg = ppcm_mon d (lm_anc g) (fst_mon t) in - let c = ppcm_mon d (lm_anc p) (lm_anc g) in - div_strict d cp c && div_strict d cg c) - lt) - -let head_normal_form d p lt mt = - let h = ref (p.pol) in - let res = - try ( - let v = snd(List.hd !h) in - let g = ref (find_reductor d v lt mt) in - if snd(List.hd !h) <> lm_anc p && criteria d p !g lt - then ((* info "=";*) []) - else ( - while !h <> [] && (!g).pol <> [] do - let (a,v),p' = of_cons !h in - let (b,u),q' = of_cons (!g).pol in - let c = P.pgcdP a b in - let a' = P.divP b c in - let b' = P.oppP (P.divP a c) in - let m = (div_mon d v u) in - h := plusP d (emultP a' p') (mult_t_pol d b' m q'); - let v = snd(List.hd !h) in - g := ( - try find_reductor d v lt mt - with _ -> pol_to_pol3 d []); - done; - !h) - ) - with _ -> ((* info ".";*) !h) - in - (*info ("temps de head_normal_form: " - ^(Format.sprintf "@[%10.3f@]s\n" ((Unix.gettimeofday ())-.t1)));*) - res - -let deg_hom p = - match p with - | [] -> -1 - | (_,m)::_ -> m.(0) - -let head_reduce d lq lt mt = - let ls = ref lq in - let lq = ref [] in - while !ls <> [] do - let p,ls1 = of_cons !ls in - ls := ls1; - if !homogeneous && p.pol<>[] && deg_hom p.pol > deg_hom !pol_courant - then info "h" - else - match head_normal_form d p lt mt with - (_,v)::_ as h -> - if fst_mon p <> v - then lq := (!lq) @ [{pol = h; anc = h; nmp = Array.create (d+1) 0}] - else lq := (!lq) @ [p] - | [] -> - (* info "*";*) - if fst_mon p = lm_anc p - then ls := List.filter (fun q -> not (equal q.anc p.anc)) !ls - done; - (*info ("temps de head_reduce: " - ^(Format.sprintf "@[%10.3f@]s\n" ((Unix.gettimeofday ())-.t1)));*) - !lq - -let choose_irreductible d lf = - List.hd lf -(* bien plus lent - (List.sort (fun p q -> compare_mon d (fst_mon p.pol) (fst_mon q.pol)) lf) -*) - - -let hashtbl_multiplicative d lf = - let mg = Hashpol.create 51 in - hashtbl_reductor := Hashtbl.create 51; - List.iter - (fun g -> - let (_,u) = List.hd g.pol in - Hashpol.add mg g.pol (monom_multiplicative d u lf)) - lf; - (*info ("temps de hashtbl_multiplicative: " - ^(Format.sprintf "@[%10.3f@]s\n" ((Unix.gettimeofday ())-.t1)));*) - mg - -let list_diff l x = - List.filter (fun y -> y <> x) l - -let janet2 d lf p0 = - hashtbl_reductor := Hashtbl.create 51; - let t1 = Unix.gettimeofday() in - info ("------------- Janet2 ------------------\n"); - pol_courant := p0; - let r = ref p0 in - let lf = List.map (pol_to_pol3 d) lf in - let f = choose_irreductible d lf in - let lt = ref [f] in - let mt = ref (hashtbl_multiplicative d !lt) in - let lq = ref (list_diff lf f) in - lq := head_reduce d !lq !lt !mt; - r := (* lent head_janet_normal_form d !r !lt !mt ; *) - reduce_rem d !r !lt !lq ; - info ("reste: "^(stringPcut !r)^"\n"); - while !lq <> [] && !r <> [] do - let p = choose_irreductible d !lq in - lq := list_diff !lq p; - if p.pol = p.anc - then ( (* on enleve de lt les pol divisibles par p et on les met dans lq *) - let m = fst_mon p in - let lt1 = !lt in - List.iter - (fun q -> - let m'= fst_mon q in - if div_strict d m m' - then ( - lq := (!lq) @ [q]; - lt := list_diff !lt q)) - lt1; - mt := hashtbl_multiplicative d !lt; - ); - let h = tail_normal_form d p.pol !lt !mt in - if h = [] - then info "************ reduction a zero, ne devrait pas arriver *\n" - else ( - lt := (!lt) @ [{pol = h; anc = p.anc; nmp = Array.copy p.nmp}]; - info ("nouveau polynome: "^(stringPcut h)^"\n"); - mt := hashtbl_multiplicative d !lt; - r := (* lent head_janet_normal_form d !r !lt !mt ; *) - reduce_rem d !r !lt !lq ; - info ("reste: "^(stringPcut !r)^"\n"); - if !r <> [] - then ( - List.iter - (fun q -> - let mq = find_multiplicative q !mt in - for i=1 to d do - if mq.(i) = 1 - then q.nmp.(i)<- 0 - else - if q.nmp.(i) = 0 - then ( - (* info "+";*) - lq := (!lq) @ - [{pol = multP d (gen d i) q.pol; - anc = q.anc; - nmp = Array.create (d+1) 0}]; - q.nmp.(i)<-1; - ); - done; - ) - !lt; - lq := head_reduce d !lq !lt !mt; - info ("["^(string_of_int (List.length !lt))^";" - ^(string_of_int (List.length !lq))^"]"); - )); - done; - info ("--- Janet2 donne:\n"); - (* List.iter (fun p -> info ("polynome: "^(stringPcut p.pol)^"\n")) !lt; *) - info ("reste: "^(stringPcut !r)^"\n"); - info ("--- fin Janet2\n"); - info ("temps: "^(Format.sprintf "@[%10.3f@]s\n" ((Unix.gettimeofday ())-.t1))); - List. map (fun q -> q.pol) !lt - -(********************************************************************** - version 3 *) - -let head_normal_form3 d p lt mt = - let h = ref (p.pol) in - let res = - try ( - let v = snd(List.hd !h) in - let g = ref (find_reductor d v lt mt) in - if snd(List.hd !h) <> lm_anc p && criteria d p !g lt - then ((* info "=";*) []) - else ( - while !h <> [] && (!g).pol <> [] do - let (a,v),p' = of_cons !h in - let (b,u),q' = of_cons (!g).pol in - let c = P.pgcdP a b in - let a' = P.divP b c in - let b' = P.oppP (P.divP a c) in - let m = div_mon d v u in - h := plusP d (emultP a' p') (mult_t_pol d b' m q'); - let v = snd(List.hd !h) in - g := ( - try find_reductor d v lt mt - with _ -> pol_to_pol3 d []); - done; - !h) - ) - with _ -> ((* info ".";*) !h) - in - (*info ("temps de head_normal_form: " - ^(Format.sprintf "@[%10.3f@]s\n" ((Unix.gettimeofday ())-.t1)));*) - res - - -let janet3 d lf p0 = - hashtbl_reductor := Hashtbl.create 51; - let t1 = Unix.gettimeofday() in - info ("------------- Janet2 ------------------\n"); - let r = ref p0 in - let lf = List.map (pol_to_pol3 d) lf in - - let f,lf1 = of_cons lf in - let lt = ref [f] in - let mt = ref (hashtbl_multiplicative d !lt) in - let lq = ref lf1 in - r := reduce_rem d !r !lt !lq ; (* janet_normal_form d !r !lt !mt ;*) - info ("reste: "^(stringPcut !r)^"\n"); - while !lq <> [] && !r <> [] do - let p,lq1 = of_cons !lq in - lq := lq1; -(* - if p.pol = p.anc - then ( (* on enleve de lt les pol divisibles par p et on les met dans lq *) - let m = fst_mon (p.pol) in - let lt1 = !lt in - List.iter - (fun q -> - let m'= fst_mon (q.pol) in - if div_strict d m m' - then ( - lq := (!lq) @ [q]; - lt := list_diff !lt q)) - lt1; - mt := hashtbl_multiplicative d !lt; - ); -*) - let h = head_normal_form3 d p !lt !mt in - if h = [] - then ( - info "*"; - if fst_mon p = lm_anc p - then - lq := List.filter (fun q -> not (equal q.anc p.anc)) !lq; - ) - else ( - let q = - if fst_mon p <> snd(List.hd h) - then {pol = h; anc = h; nmp = Array.create (d+1) 0} - else {pol = h; anc = p.anc; nmp = Array.copy p.nmp} - in - lt:= (!lt) @ [q]; - info ("nouveau polynome: "^(stringPcut q.pol)^"\n"); - mt := hashtbl_multiplicative d !lt; - r := reduce_rem d !r !lt !lq ; (* janet_normal_form d !r !lt !mt ;*) - info ("reste: "^(stringPcut !r)^"\n"); - if !r <> [] - then ( - List.iter - (fun q -> - let mq = find_multiplicative q !mt in - for i=1 to d do - if mq.(i) = 1 - then q.nmp.(i)<- 0 - else - if q.nmp.(i) = 0 - then ( - (* info "+";*) - lq := (!lq) @ - [{pol = multP d (gen d i) q.pol; - anc = q.anc; - nmp = Array.create (d+1) 0}]; - q.nmp.(i)<-1; - ); - done; - ) - !lt; - info ("["^(string_of_int (List.length !lt))^";" - ^(string_of_int (List.length !lq))^"]"); - )); - done; - info ("--- Janet3 donne:\n"); - (* List.iter (fun p -> info ("polynome: "^(stringPcut p.pol)^"\n")) !lt; *) - info ("reste: "^(stringPcut !r)^"\n"); - info ("--- fin Janet3\n"); - info ("temps: "^(Format.sprintf "@[%10.3f@]s\n" ((Unix.gettimeofday ())-.t1))); - List. map (fun q -> q.pol) !lt - - -(*********************************************************************** - Completion - *) - -let sugar_flag = ref true - -let sugartbl = (Hashpol.create 1000 : int Hashpol.t) - -let compute_sugar p = - List.fold_left (fun s (a,m) -> max s m.(0)) 0 p - -let sugar p = - try Hashpol.find sugartbl p - with Not_found -> - let s = compute_sugar p in - Hashpol.add sugartbl p s; - s - -let spol d p q= - let m = snd (List.hd p) in - let m'= snd (List.hd q) in - let a = fst (List.hd p) in - let b = fst (List.hd q) in - let p'= List.tl p in - let q'= List.tl q in - let c=(pgcdpos a b) in - let m''=(ppcm_mon d m m') in - let m1 = div_mon d m'' m in - let m2 = div_mon d m'' m' in - let fsp p' q' = - plusP d - (mult_t_pol d (P.divP b c) m1 p') - (mult_t_pol d (P.oppP (P.divP a c)) m2 q') in - let sp = fsp p' q' in - coefpoldep_set sp p (fsp (polconst d coef1) []); - coefpoldep_set sp q (fsp [] (polconst d coef1)); - Hashpol.add sugartbl sp - (max (m1.(0) + (sugar p)) (m2.(0) + (sugar q))); - sp - -let etrangers d p p'= - let m = snd (List.hd p) in - let m'= snd (List.hd p') in - let res=ref true in - let i=ref 1 in - while (!res) && (!i<=d) do - res:= (m.(!i) = 0) || (m'.(!i)=0); - i:=!i+1; - done; - !res - - -(* teste si le monome dominant de p'' - divise le ppcm des monomes dominants de p et p' *) - -let div_ppcm d p p' p'' = - let m = snd (List.hd p) in - let m'= snd (List.hd p') in - let m''= snd (List.hd p'') in - let res=ref true in - let i=ref 1 in - while (!res) && (!i<=d) do - res:= ((max m.(!i) m'.(!i)) >= m''.(!i)); - i:=!i+1; - done; - !res - -(*********************************************************************** - Code extrait de la preuve de L.Thery en Coq - *) -type 'poly cpRes = - Keep of ('poly list) - | DontKeep of ('poly list) - -let addRes i = function - Keep h'0 -> Keep (i::h'0) - | DontKeep h'0 -> DontKeep (i::h'0) - -let rec slice d i a = function - [] -> if etrangers d i a then DontKeep [] else Keep [] - | b::q1 -> - if div_ppcm d i a b then DontKeep (b::q1) - else if div_ppcm d i b a then slice d i a q1 - else addRes b (slice d i a q1) - -let rec addS x l = l @[x] - -let addSugar x l = - if !sugar_flag - then - let sx = sugar x in - let rec insere l = - match l with - | [] -> [x] - | y::l1 -> - if sx <= (sugar y) - then x::l - else y::(insere l1) - in insere l - else addS x l - -(* ajoute les spolynomes de i avec la liste de polynomes aP, - a la liste q *) - -let rec genPcPf d i aP q = - match aP with - [] -> q - | a::l1 -> - (match slice d i a l1 with - Keep l2 -> addSugar (spol d i a) (genPcPf d i l2 q) - | DontKeep l2 -> genPcPf d i l2 q) - -let rec genOCPf d = function - [] -> [] - | a::l -> genPcPf d a l (genOCPf d l) - -let step = ref 0 - -let infobuch p q = - if !step = 0 - then (info ("[" ^ (string_of_int (List.length p)) - ^ "," ^ (string_of_int (List.length q)) - ^ "]")) - -(***********************************************************************) -(* dans lp les nouveaux sont en queue *) - -let coef_courant = ref coef1 - - -type certificate = - { coef : coef; power : int; - gb_comb : poly list list; last_comb : poly list } - -let test_dans_ideal d p lp lp0 = - let (c,r) = reduce2 d !pol_courant lp in - info ("reste: "^(stringPcut r)^"\n"); - coef_courant:= P.multP !coef_courant c; - pol_courant:= r; - if r=[] - then (info "polynome reduit a 0\n"; - let lcp = List.map (fun q -> []) !poldep in - let c = !coef_courant in - let (lcq,r) = reduce2_trace d (emultP c p) lp lcp in - info ("r: "^(stringP r)^"\n"); - let res=ref (emultP c p) in - List.iter2 - (fun cq q -> res:=plusP d (!res) (multP d cq q); - ) - lcq !poldep; - info ("verif somme: "^(stringP (!res))^"\n"); - info ("coefficient: "^(stringP (polconst d c))^"\n"); - let rec aux lp = - match lp with - |[] -> [] - |p::lp -> - (List.map - (fun q -> coefpoldep_find p q) - lp)::(aux lp) - in - let liste_polynomes_de_depart = List.rev lp0 in - let polynome_a_tester = p in - let liste_des_coefficients_intermediaires = - (let lci = List.rev (aux (List.rev lp)) in - let lci = ref lci (* (List.map List.rev lci) *) in - List.iter (fun x -> lci := List.tl (!lci)) lp0; - !lci) in - let liste_des_coefficients = - List.map - (fun cq -> emultP coefm1 cq) - (List.rev lcq) in - (liste_polynomes_de_depart, - polynome_a_tester, - {coef=c; - power=1; - gb_comb = liste_des_coefficients_intermediaires; - last_comb = liste_des_coefficients})) - else ((*info "polynome non reduit a 0\n"; - info ("\nreste: "^(stringPcut r)^"\n");*) - raise NotInIdeal) - -let divide_rem_with_critical_pair = ref false - -let choix_spol d p l = - if !divide_rem_with_critical_pair - then ( - let (_,m) = List.hd p in - try ( - let q = - List.find - (fun q -> - let (_,m') = List.hd q in - div_mon_test d m m') - l in - q::(list_diff l q)) - with _ -> l) - else l - -let pbuchf d pq p lp0= - info "calcul de la base de Groebner\n"; - step:=0; - Hashtbl.clear hmon; - let rec pbuchf lp lpc = - infobuch lp lpc; -(* step:=(!step+1)mod 10;*) - match lpc with - [] -> test_dans_ideal d p lp lp0 - | _ -> - let a,lpc2 = of_cons (choix_spol d !pol_courant lpc) in - if !homogeneous && a<>[] && deg_hom a > deg_hom !pol_courant - then (info "h";pbuchf lp lpc2) - else - let sa = sugar a in - let (ca,a0)= reduce2 d a lp in - match a0 with - [] -> info "0";pbuchf lp lpc2 - | _ -> - let a1 = emultP ca a in - List.iter - (fun q -> - coefpoldep_set a1 q (emultP ca (coefpoldep_find a q))) - !poldep; - let (lca,a0) = reduce2_trace d a1 lp - (List.map (fun q -> coefpoldep_find a1 q) !poldep) in - List.iter2 (fun c q -> coefpoldep_set a0 q c) lca !poldep; - info ("\nnouveau polynome: "^(stringPcut a0)^"\n"); - let ct = coef1 (* contentP a0 *) in - (*info ("contenu: "^(string_of_coef ct)^"\n");*) - Hashpol.add sugartbl a0 sa; - poldep:=addS a0 lp; - poldepcontent:=addS ct (!poldepcontent); - try test_dans_ideal d p (addS a0 lp) lp0 - with NotInIdeal -> pbuchf (addS a0 lp) (genPcPf d a0 lp lpc2) - in pbuchf (fst pq) (snd pq) - -let is_homogeneous p = - match p with - | [] -> true - | (a,m)::p1 -> let d = m.(0) in - List.for_all (fun (b,m') -> m'.(0)=d) p1 - -(* rend - c - lp = [pn;...;p1] - p - lci = [[a(n+1,n);...;a(n+1,1)]; - [a(n+2,n+1);...;a(n+2,1)]; - ... - [a(n+m,n+m-1);...;a(n+m,1)]] - lc = [qn+m; ... q1] - - tels que - c*p = sum qi*pi - ou pn+k = a(n+k,n+k-1)*pn+k-1 + ... + a(n+k,1)* p1 - *) - -let in_ideal d lp p = - homogeneous := List.for_all is_homogeneous (p::lp); - if !homogeneous then info "polynomes homogenes\n"; - (* janet2 d lp p;*) - info ("p: "^stringPcut p^"\n"); - info ("lp:\n"^List.fold_left (fun r p -> r^stringPcut p^"\n") "" lp); - initcoefpoldep d lp; - coef_courant:=coef1; - pol_courant:=p; - try test_dans_ideal d p lp lp - with NotInIdeal -> pbuchf d (lp, genOCPf d lp) p lp - -end |
