123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654 |
- module groebf;
- Comment
- ##############################
- ### ###
- ### GROEBNER FACTORIZER ###
- ### ###
- ##############################
- The Groebner algorithm with factorization and constraint lists.
- New in version 2.2 :
- syntax for groebfactor
- listgroebfactor!*
- extendedgroebfactor!*
- There are two versions of the extended groebner factorizer.
- One needs the lex. term order, the other supports arbitrary ones (the
- default). Switch between both versions via switch lexefgb.
- Internal data structure
- result::={dpmat, constraint list }
- extendedresult::=
- {dpmat, constraint list, (dimension | indepvarset) }
- problem::={dpmat, constraint list, pair list, easydim}
- aggregate::=
- { (list of problems) , (list of results) }
- For a system with constraints m=(b,c) V(m)=V(b,c) denotes the zero set
- V(b)\setminus D(c).
- The Groebner algorithm supports only the classical reduction
- principle.
- end Comment;
- % --- The side effect switching lexefgb on or off :
- put('lexefgb,'simpfg,'((t (put 'cali 'efgb 'lex))
- (nil (remprop 'cali 'efgb))));
- symbolic procedure groebf!=problemsort(a,b);
- % Sorted by ascending easydim to force depth first search.
- (nth(a,4)<nth(b,4))
- or (nth(a,4)=nth(b,4)) and (length second a<= length second b);
- symbolic procedure groebf!=resultsort(a,b);
- % Sort extendedresults by descending true dimension, assuming the
- % third part being the dimension.
- third a > third b;
- put('groebfactor,'psopfn,'intf!=groebfactor);
- symbolic procedure intf!=groebfactor m;
- begin scalar bas,con;
- bas:=dpmat_from_a reval first m;
- if length m=1 then con:=nil
- else if length m=2 then
- con:=for each x in cdr reval second m collect dp_from_a x
- else rederr("Syntax : GROEBFACTOR(base list [,constraint list])");
- return makelist
- for each x in groebfactor!*(bas,con) collect dpmat_2a first x;
- end;
- symbolic operator listgroebfactor;
- symbolic procedure listgroebfactor l;
- % l is a list of polynomial systems. We look for the union of the
- % solution sets.
- if !*mode='algebraic then
- makelist for each x in listgroebfactor!*
- for each y in cdr reval l collect dpmat_from_a y
- collect dpmat_2a x
- else listgroebfactor!* l;
- symbolic procedure listgroebfactor!* l;
- % Proceed a whole list of dpmats at once.
- begin scalar gbs;
- gbs:=for each x in
- groebf!=preprocess(nil,for each x in l collect {x,nil})
- collect groebf!=initproblem x;
- gbs:=sort(gbs,function groebf!=problemsort);
- return for each x in groebf!=masterprocess(gbs,nil) collect first x;
- end;
- symbolic procedure groebfactor!*(bas,poly);
- % Returns a list l of results (b,c) such that
- % V(bas,poly) = \union { V(b,c) : (b,c) \in l }
- if dpmat_cols bas > 0 then
- rederr "GROEBFACTOR only for ideal bases"
- else if null !*noetherian then
- rederr "GROEBFACTOR only for noetherian term orders"
- else if dpmat_zero!? bas then list({bas,poly})
- else begin scalar gbs;
- if cali_trace() > 5 then
- << write"GROEBFACTOR the system "; dpmat_print bas >>;
- gbs:=for each x in groebf!=preprocess(nil,list {bas,poly}) collect
- groebf!=initproblem x;
- gbs:=sort(gbs,function groebf!=problemsort);
- return groebf!=masterprocess(gbs,nil);
- end;
- put('extendedgroebfactor,'psopfn,'intf!=extendedgroebfactor);
- symbolic procedure intf!=extendedgroebfactor m;
- begin scalar bas,con;
- bas:=dpmat_from_a reval first m;
- if length m=1 then con:=nil
- else if length m=2 then
- con:=for each x in cdr reval second m collect dp_from_a x
- else rederr
- "Syntax : EXTENDEDGROEBFACTOR(base list [,constraint list])";
- return makelist
- for each x in extendedgroebfactor!*(bas,con) collect
- makelist {first x,makelist second x,makelist third x};
- end;
- symbolic procedure extendedgroebfactor!*(bas,poly);
- % Returns a list l of extendedresults (b,c,vars) in prefix form such
- % that V(bas,poly) = \union { V(b,c) : (b,c) \in l }
- % and b:<\prod c> is puredimensional with independent variable set vars.
- if dpmat_cols bas > 0 then
- rederr "EXTENDEDGROEBFACTOR only for ideal bases"
- else if null !*noetherian then
- rederr "EXTENDEDGROEBFACTOR only for noetherian term orders"
- else if dpmat_zero!? bas then
- list({dpmat_2a bas,nil,ring_names cali!=basering})
- else begin scalar gbs;
- if cali_trace() > 5 then
- << write"EXTENDEDGROEBFACTOR the system "; dpmat_print bas >>;
- gbs:=for each x in groebf!=preprocess(nil,list {bas,poly}) collect
- groebf!=initproblem x;
- return groebf!=extendedmasterprocess gbs;
- end;
- symbolic procedure groebf!=extendedmasterprocess gbs;
- % gbs is a list of problems to process. Returns a list of
- % extendedresults in prefix form.
- % If {m,con,vars} is such an extendedresult then m:<\prod con> is the
- % (puredimensional) recontraction of m\tensor k(vars).
- begin scalar res,res1,u;
- while gbs or res do
- if gbs then
- % The hard postprocessing is done only at the end.
- << gbs:=sort(gbs,function groebf!=problemsort);
- % Convert results to extendedresults and sort them :
- res:=for each x in groebf!=masterprocess(gbs,res) collect
- if (length x=3) then x
- else {first x,second x,dim!* first x};
- res:=sort(res,function groebf!=resultsort);
- gbs:=nil
- >>
- else % Do the first (hard) postprocessing
- << % process result by result :
- u:=groebf!=postprocess2 car res; res:=cdr res;
- % Extract and preprocess new problems from u.
- % This needs descent by dimension of the results proceeded.
- gbs:=for each x in groebf!=preprocess(res,second u)
- collect groebf!=initproblem x;
- % Extract extendedresults from u.
- % They may be non-GB wrt t h i s term order, see above.
- res1:=nconc(first u,res1);
- >>;
- return res1;
- end;
- % --------- Another version of the extended Groebner factorizer -------
- put('extendedgroebfactor1,'psopfn,'intf!=extendedgroebfactor1);
- symbolic procedure intf!=extendedgroebfactor1 m;
- begin scalar bas,con;
- bas:=dpmat_from_a reval first m;
- if length m=1 then con:=nil
- else if length m=2 then
- con:=for each x in cdr reval second m collect dp_from_a x
- else rederr
- "Syntax : EXTENDEDGROEBFACTOR1(base list [,constraint list])";
- return makelist
- for each x in extendedgroebfactor1!*(bas,con) collect
- makelist {first x,makelist second x,makelist third x};
- end;
- symbolic procedure extendedgroebfactor1!*(bas,poly);
- % Returns a list l of extendedresults (b,c,vars) in prefix form such
- % that V(bas,poly) = \union { V(b,c) : (b,c) \in l }
- % and b:<\prod c> is puredimensional with independent variable set vars.
- if dpmat_cols bas > 0 then
- rederr "EXTENDEDGROEBFACTOR1 only for ideal bases"
- else if null !*noetherian then
- rederr "EXTENDEDGROEBFACTOR1 only for noetherian term orders"
- else if dpmat_zero!? bas then
- list({dpmat_2a bas,nil,ring_names cali!=basering})
- else begin scalar gbs;
- if cali_trace() > 5 then
- << write"EXTENDEDGROEBFACTOR1 the system "; dpmat_print bas >>;
- gbs:=for each x in groebf!=preprocess(nil,list {bas,poly}) collect
- groebf!=initproblem x;
- return for each x in groebf!=extendedmasterprocess1 gbs collect
- nth(x,4);
- end;
- symbolic procedure groebf!=extendedmasterprocess1 gbs;
- % Version that computes the retraction of each intermediate result
- % to apply FGB shortcuts. gbs is a list of problems to process.
- % Returns a list of extendedresults in prefix form.
- % If {m,con,vars} is such an extendedresult then m:<\prod con> is the
- % (puredimensional) recontraction of m\tensor k(vars).
- % internally they are incorporated into res as
- % {dpmat, nil (since no constraints), dim, prefix form}.
- begin scalar res,u,v,p;
- while gbs or
- (p:=listtest(res,nil,function (lambda(x,y); length x<4))) do
- if gbs then
- % The hard postprocessing is done only at the end.
- << gbs:=sort(gbs,function groebf!=problemsort);
- % Convert results to extendedresults and sort them :
- res:=for each x in groebf!=masterprocess(gbs,res) collect
- if (length x>2) then x
- else {first x,second x,dim!* first x};
- res:=sort(res,function groebf!=resultsort);
- gbs:=nil
- >>
- else % Do the first (hard) postprocessing
- << % process result by result :
- u:=groebf!=postprocess2 p; res:=delete(p,res);
- % Extract extendedresults from u and convert them
- % with postprocess3 to quotient ideals.
- v:=for each x in first u collect
- {groebf!=postprocess3 x, nil, length third x,x};
- for each y in v do
- if not groebf!=redtest(res,y) then
- res:=merge({y},groebf!=sieve(res,y),
- function groebf!=resultsort);
- % Extract and preprocess new problems from u.
- gbs:=for each x in groebf!=preprocess(res,second u) collect
- groebf!=initproblem x;
- >>;
- return res;
- end;
- % ------- end of the second version ------------------------
- symbolic procedure groebf!=masterprocess(gbs,res);
- % gbs = list of problems, res = list of results (since several times
- % involved in the extendedmasterprocess).
- % Returns a list of results already postprocessed with (the easy)
- % groebf!=postpocess1 where the elements surviving from res may
- % change only in the constraints part.
- begin scalar u,v;
- while gbs do
- << if cali_trace()>10 then
- print for each x in gbs collect nth(x,4);
- u:=groebf!=slave car gbs; gbs:=cdr gbs;
- if u then % u is an aggregate.
- << % postprocess the result part returning a list of aggregates.
- v:=for each x in second u collect groebf!=postprocess1(res,x);
- % split up into the problems u and results v
- u:=nconc(car u,for each x in v join car x);
- v:=for each x in v join second x;
- for each y in v do
- if cali_trace() > 5 then
- << write"partial result :"; terpri();
- dpmat_print car y ;
- prin2"constraints : ";
- for each x in second y do dp_print2 x;
- >>;
- for each y in v do
- if not groebf!=redtest(res,y) then
- res:=y . groebf!=sieve(res,y);
- for each x in u do
- if not groebf!=redtest(res,x) then
- gbs:=merge({x},groebf!=sieve(gbs,x),
- function groebf!=problemsort);
- if cali_trace()>20 then
- << terpri(); write length gbs," remaining branches. ",
- length res," partial results"; terpri()
- >>;
- >>
- else % branch discarded
- if cali_trace()>20 then print"Branch discarded";
- >>;
- return res;
- end;
- symbolic procedure groebf!=initproblem x;
- % Converts a result into a problem.
- list(car x,second x, groeb_makepairlist(dpmat_list car x,t),
- easydim!* car x);
- % The following two procedures make destructive changes
- % on the cdr of some of the list elements.
- symbolic procedure groebf!=redtest(a,c);
- % Ex. u \in a : car u \submodule car c ?
- % If so, update the constraints of u.
- begin scalar u;
- u:=listtest(a,c,function(lambda(x,y); submodulep!*(car x,car y)));
- if u then cdr u:=intersection(second u,second c).cddr u;
- return u;
- end;
- symbolic procedure groebf!=sieve(a,c);
- % Remove u \in a with car c \submodule car u
- % and update the constraints of c.
- for each x in a join if not submodulep!*(car c,car x) then {x}
- else << cdr c:=intersection(second x,second c).cddr c; >>;
- symbolic procedure groebf!=test(con,m);
- % nil <=> ex. f \in con : f mod m = 0. m is a baslist.
- if null m then t
- else if dp_unit!? bas_dpoly first m then nil
- else if null con then t
- else begin scalar p; p:=t;
- while p and con do
- << p:=p and bas_dpoly car red_redpol(m,bas_make(0,car con));
- con:=cdr con
- >>;
- return p;
- end;
- symbolic procedure groebf!=newcon(r,d);
- % r=(m,c) is a result, d a list of polynomials. Returns the
- % (slightly optimized) result list ( (m+(p),c+(q|q<p)) | p \in d ).
- begin scalar m,c,u;
- m:=first r; c:=second r;
- return for each p in d join
- if not member(p,c) then
- << u:={matsum!* {m, dpmat_from_dpoly(p)}, c}; c:=p.c; {u} >>;
- end;
- symbolic procedure groebf!=preprocess(a1,b);
- % Try to split (factor) each polynomial in each problem of the list b.
- % Returns a list of results.
- % a1 is a list of results already computed.
- begin scalar a,c,d,back,u;
- if cali_trace()>20 then prin2"preprocessing started";
- while b do
- << if cali_trace()>20 then
- << terpri(); write length a," ready. ";
- write length b," left."; terpri()
- >>;
- c:=car b; b:=cdr b;
- if not (null groebf!=test(second c,dpmat_list car c)
- or groebf!=redtest(a1,c)
- or groebf!=redtest(a,c)) then
- << d:=dpmat_list car c; back:=nil;
- while d and not back do
- << u:=((fctrf numr simp dp_2a bas_dpoly car d)
- where !*factor=t);
- if (length u>2) or (cdadr u>1) then
- << back:=t;
- b:=append(groebf!=newcon(c,
- for each y in cdr u collect
- dp_from_a prepf car y),b);
- >>
- else d:=cdr d
- >>;
- if not back then
- << if cali_trace()>20 then
- << terpri(); write"Subproblem :"; dpmat_print car c >>;
- if not groebf!=redtest(a,c) then a:=c . groebf!=sieve(a,c);
- >>
- >>
- >>;
- if cali_trace()>20 then prin2"preprocessing finished...";
- return a;
- end;
- symbolic procedure groebf!=slave c;
- % Proceed upto the first splitting. Returns an aggregate.
- begin scalar be,back,p,u,v,a,b,gb,pl,nr,pol,con;
- back:=nil;
- gb:=bas_sort dpmat_list first c;
- con:=second c; pl:=third c; nr:=length gb;
- while pl and not back do
- << p:=car pl; pl:=cdr pl;
- if cali_trace() > 10 then groeb_printpair(p,pl);
- pol:=groeb_spol p;
- if cali_trace() > 70 then
- << terpri(); write"S.-pol : "; dp_print2 bas_dpoly pol >>;
- pol:=bas_dpoly car red_redpol(gb,pol);
- if cali_trace() > 70 then
- << terpri(); write"Reduced S.-pol. : "; dp_print2 pol >>;
- if pol then
- << if !*bcsimp then pol:=car dp_simp pol;
- if dp_unit!? pol then
- << if cali_trace()>20 then print "unit ideal";
- back:=t
- >>
- else
- << % -- factorize pol
- u:=((fctrf numr simp dp_2a pol) where !*factor=t);
- nr:=nr+1;
- if length cdr u=1 then % only one factor
- << pol:=dp_from_a prepf caadr u;
- be:=bas_make(nr,pol);
- u:=be.gb;
- if null groebf!=test(con,u) then
- << back:=t;
- if cali_trace()>20 then print" zero constraint";
- >>
- else
- << if cali_trace()>20 then
- << terpri(); write nr,". "; dp_print2 pol >>;
- pl:=groeb_updatePL(pl,gb,be,t);
- if cali_trace() > 30 then
- << terpri(); groeb_printpairlist pl >>;
- gb:=merge(list be,gb,function red_better);
- >>
- >>
- else % more than one factor
- << for each x in cdr u do
- << pol:=dp_from_a prepf car x;
- be:=bas_make(nr,pol);
- a:=be.gb;
- if groebf!=test(con,a) then
- << if cali_trace()>20 then
- << terpri(); write nr; write". "; dp_print2 pol >>;
- p:=groeb_updatePL(append(pl,nil),gb,be,t);
- if cali_trace() > 30 then
- << terpri(); groeb_printpairlist p >>;
- b:=merge(list be,append(gb,nil),
- function red_better);
- b:=dpmat_make(length b,0,b,nil,nil);
- v:={b,con,p}.v;
- >>
- else if cali_trace()>20 then print" zero constraint";
- if not member(pol,con) then con:=pol . con;
- >>;
- if null v then
- << if cali_trace()>20 then print "Branch canceled";
- back:=t
- >>
- else if length v=1 then
- << c:=car v; gb:=dpmat_list first c; con:=second c;
- pl:=third c; v:=nil;
- >>
- else
- << back:=t;
- if cali_trace()>20 then
- << write" Branching into ",length v," parts ";
- terpri();
- >>;
- >>;
- >>;
- >>;
- >>;
- >>;
- if not back then % pl exhausted => new partial result.
- return
- {nil,list {groeb_mingb dpmat_make(length gb,0,gb,nil,t),con}}
- else if v then return
- {for each x in v collect
- {first x,second x,third x,easydim!* first x},
- nil}
- else return nil;
- end;
- symbolic procedure groebf!=postprocess1(res,x);
- % Easy postprocessing a result. Returns an aggregate.
- % res is a list of results, already obtained.
- begin scalar p,r,v;
- % ---- interreduce and try factorization once more.
- if !*red_total then
- << v:=groebf!=preprocess(res,
- list {dpmat_make(dpmat_rows car x,0,
- red_straight dpmat_list car x,nil,
- dpmat_gbtag car x),
- second x});
- if (length v=1) and dpmat_gbtag caar v then r:=v
- else p:=for each x in v collect groebf!=initproblem x;
- >>
- else r:={x};
- return {p,r};
- end;
- symbolic procedure groebf!=postprocess2 m;
- (begin scalar d,vars,u,v,c1,m1,m1a,m2,p,con;
- con:=second m; d:=third m; m:=first m;
- v:=moid_goodindepvarset m;
- if neq(length v,d) then
- rederr"In POSTPROCESS2 the dimension is wrong";
- if null v then return
- {for each x in groebf!=zerosolve(m,con)
- collect {x,nil,nil},nil};
- % -- Prepare data for change to dimension zero :
- % Recompute gbases wrt. the elimination order for u and
- % take only those components for which v remains independent.
- vars:=ring_names(c1:=cali!=basering);
- u:=setdiff(vars,v);
- if get('cali,'efgb)='lex then setring!* ring_lp(c1,u)
- else setring!* ring_rlp(c1,u);
- m1:=for each u in groebfactor!*(dpmat_neworder(m,nil),
- for each x in con collect dp_neworder x) collect
- {first u,second u,dim!* first u};
- for each x in m1 do
- if (third x = d) and member(v,indepvarsets!* car x)
- then m1a := x . m1a
- else m2:=x.m2;
- % m1a : components with indepvarset v
- % m2 : components with v being dependent variables.
- % -- Change to dimension zero.
- m1:=for each x in m1a collect
- {dpmat_2a first x,for each p in second x collect dp_2a p};
- if get('cali,'efgb)='lex then
- setring!* ring_define(u,nil,'lex,for each x in u collect 1)
- else setring!* ring_define(u,degreeorder!* u,'revlex,
- for each x in u collect 1);
- m1:=for each x in m1 collect
- {groeb_mingb dpmat_from_a first x,
- for each p in second x collect dp_from_a p};
- % Extract the lc's of the lifted Groebner bases and save them
- % for NewCon on the list m1a, since in the zerodimensional part
- % lc's are assumed to be invertible.
- m1a:=pair(m1a,for each x in m1 collect groebf!=elcbe first x);
- % Compute the zerodimensional TriangSets from m1 and their lists
- % of lc's and prepare them for lifting.
- m1:=for each x in m1 join groebf!=zerosolve(first x,second x);
- m1:=for each x in m1 collect {x,groebf!=elcbe dpmat_from_a x};
- % -- Lift all stuff back to c1.
- setring!* c1;
- % Extract the TriangSets as extendedresults in prefix form (!).
- m1:=for each x in m1 collect {first x,second x,v};
- % List of new problems found during recomputation of GB :
- m2:=for each x in m2 collect
- {dpmat_neworder(first x,nil),
- for each y in second x collect dp_neworder y};
- % List of new problems, derived from nonzero conditions for
- % lc's in dimension zero.
- m1a:=for each x in m1a join
- groebf!=newcon({dpmat_neworder(first car x,nil),
- for each p in second car x collect dp_neworder p},
- for each p in cdr x collect dp_from_a p);
- Comment The list of results :
- m1 : The list of TriangSets wrt. v produced in this run. They are in
- alg. prefix form to remember that they are Groebner bases only
- wrt. the pure lex. term order.
- m2 : Results (in prefix form), for which v is dependent.
- m1a : Branches, where some of the critical lc's of the TriangSets
- vanish.
- Both m2 and m1a should be returned in the pool of problems.
- end comment;
- return {m1,nconc(m1a,m2)};
- end)
- where cali!=degrees:=cali!=degrees,
- cali!=basering:=cali!=basering;
- symbolic procedure groebf!=elcbe(m);
- % Extract list of leading coefficients in algebraic prefix form
- % from base elements of the dpmat m.
- for each x in dpmat_list m join
- if domainp dp_lc bas_dpoly x then {}
- else {bc_2a dp_lc bas_dpoly x};
- symbolic procedure groebf!=postprocess3 u;
- % Compute for the extendedresult u={m,con,vars} in prefix form
- % m:<\prod con>.
- matqquot!*(dpmat_from_a first u,
- groebf!=prod for each x in second u collect dp_from_a x);
- symbolic procedure groebf!=prod l;
- begin scalar p; p:=dp_fi 1;
- l:=listminimize(for each x in l join dp_factor x,function equal);
- for each x in l do p:=dp_prod(x,p);
- return p;
- end;
- symbolic procedure groebf!=zerosolve(m,con);
- % Hook for the zerodimensional solver.
- % Input : m = zerodimensional dpmat (not to be checked),
- % con = list of dpoly constraints.
- % Output : a list of dpmats in prefix form.
- begin scalar u;
- % Look up the constraints, since during the change to dimension zero
- % some of them may trivialize :
- con:=for each x in con join if not dp_unit!? x then {x};
- % Factorized radical computation.
- u:=groebf_zeroprimes1(m,con);
- % Apply the zerosolver to each of these results.
- return for each x in u join
- if get('cali,'efgb)='lex then zerosolve!* x else zerosolve1!* x;
- end;
- symbolic procedure groebf_zeroprimes1(m,con);
- % Returns a list of gbases for the zerodimensional ideal m,
- % incorporating as in the Groebner factorizer the factors of the
- % univariate polynomials in m according to such variables, that don't
- % appear as leading terms in m.
- begin scalar m1,m2,p,u,l;
- l:=list {m,con};
- for each x in ring_names cali!=basering do
- << m1:=m2:=nil;
- for each y in l do
- % The following checks, whether x is a leading term of first
- % y. Such x may be skipped, since embedding dimension may be
- % reduced. On the other hand, computing univariate polynomials
- % for them is often quite nasty.
- if not member(x,for each v in dpmat_list first y join
- {mo_linear dp_lmon bas_dpoly v}) then
- << p:=odim_up(x,first y); u:=dp_factor p;
- if (length u>1) or not equal(first u,p) then
- m1:=nconc(groebf!=newcon(y,u),m1)
- else m2:=y.m2;
- >>
- else m2:=y.m2;
- l:=groebf!=masterprocess(
- sort(for each x in m1 collect groebf!=initproblem x,
- function groebf!=problemsort),
- m2);
- >>;
- return for each x in l join
- if second x then {matqquot!*(first x,groebf!=prod second x)}
- % Here one can use the linear algebra quotient algorithm, since
- % first x is known to be zerodimensional radical.
- else {first x};
- end;
- endmodule; % groebf
- end;
|