glexconv.red 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362
  1. module glexconv;% Newbase - algorithm :
  2. % Faugere,Gianni,Lazard,Mora .
  3. flag('(gvarslast),'share);
  4. switch groebfac,trgroeb;
  5. % Variables for counting and numbering .
  6. fluid '(pcount!*);
  7. fluid '(glexmat!*);% Matrix for the indirect lex ordering .
  8. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  9. %
  10. % Interface functions .
  11. % Parameters;
  12. % glexconvert(basis,[vars],[maxdeg=n],[newvars={x,y,..}]) .
  13. symbolic procedure glexconverteval u;
  14. begin scalar !*groebfac,!*groebrm,!*factor,!*gsugar,
  15. v,bas,vars,maxdeg,newvars,!*exp;!*exp:=t;
  16. u:=for each p in u collect reval p;
  17. bas:=car u;u:=cdr u;
  18. while u do
  19. << v:=car u;u:=cdr u;
  20. if eqcar(v,'list)and null vars then vars:=v
  21. else if eqcar(v,'equal)then
  22. if(v:=cdr v)and eqcar(v,'maxdeg)then maxdeg:=cadr v
  23. else if eqcar(v,'newvars)then newvars:=cadr v
  24. else << prin2(car v);
  25. rerror(groebnr2,4,"glexconvert, keyword unknown")>>
  26. else rerror(groebnr2,5,
  27. "Glexconvert, too many positional parameters")>>;
  28. return glexbase1(bas,vars,maxdeg,newvars)end;
  29. put( 'glexconvert,'psopfn,'glexconverteval);
  30. symbolic procedure glexbase1(u,v,maxdeg,nv);
  31. begin scalar vars,w,nd,oldorder,!*gcd,!*ezgcd,!*gsugar;
  32. integer pcount!*;!*gcd:=t;
  33. w:=for each j in groerevlist u
  34. collect if eqexpr j then !*eqn2a j else j;
  35. if null w then rerror(groebnr2,6,"Empty list in Groebner");
  36. vars:=groebnervars(w,v);
  37. !*vdpinteger:=!*vdpmodular:=nil;
  38. if not flagp(dmode!*,'field)then !*vdpinteger:=t
  39. else if !*modular then !*vdpmodular:=t;
  40. if null vars then vdperr 'groebner;
  41. oldorder:=vdpinit vars;
  42. % Cancel common denominators .
  43. w:=for each j in w collect reorder numr simp j;
  44. % Optimize varable sequence if desired .
  45. w:=for each j in w collect f2vdp j;
  46. for each p in w do nd:=nd or not vdpcoeffcientsfromdomain!? p;
  47. if nd then
  48. << !*vdpmodular:= nil;!*vdpinteger:=t;glexdomain!*:=2 >>
  49. else glexdomain!*:=1;
  50. if glexdomain!*=1 and not !*vdpmodular then !*ezgcd:=t;
  51. if null maxdeg then maxdeg:=200;
  52. if nv then nv:=groerevlist nv;
  53. if null nv then nv:=vars else
  54. for each x in nv do if not member(x,vars) then
  55. << rerror(groebnr2,7,{ "new variable ",x,
  56. " is not a basis variable" })>>;
  57. u:=for each v in nv collect a2vdp v;
  58. gbtest w;
  59. w:=glexbase2(w,u,maxdeg);
  60. w:='list.for each j in w collect prepf j;
  61. setkorder oldorder;
  62. gvarslast:='list.vars;return w end;
  63. fluid '(glexeqsys!* glexvars!* glexcount!* glexsub!*);
  64. symbolic procedure glexbase2(oldbase,vars,maxdeg);
  65. % In contrast to documented algorithm monbase ist a list of
  66. % triplets(mon . cof . vect)
  67. % such that cof * mon== vect modulo oldbase
  68. %(cof is needed because of the integer algoritm).
  69. begin scalar lexbase,staircase,monbase;
  70. scalar monom,listofnexts,vect,q,glexeqsys!*,glexvars!*,glexsub!*;
  71. integer n;
  72. if not groezerodim!?(oldbase,length vars)then
  73. prin2t "####### warning: ideal is not zerodimensional ######";
  74. % Prepare matrix for the indirect lex ordering .
  75. glexmat!*:=for each u in vars collect vdpevlmon u;
  76. monbase:=staircase:=lexbase:=nil;
  77. monom:=a2vdp 1;listofnexts:=nil;
  78. while not(monom=nil)do
  79. << if not glexmultipletest(monom,staircase)then
  80. << vect:=glexnormalform(monom,oldbase);
  81. q:=glexlinrel(monom,vect,monbase);
  82. if q then
  83. << lexbase:=q . lexbase;maxdeg:=nil;
  84. staircase:=monom . staircase >>
  85. else
  86. << monbase:=glexaddtomonbase(monom,vect,monbase);
  87. n:=n #+1;
  88. if maxdeg and n#> maxdeg then
  89. rerror(groebnr2,8,"No univar. polynomial within degree bound");
  90. listofnexts:=glexinsernexts(monom,listofnexts,vars)>> >>;
  91. if null listofnexts then monom:=nil
  92. else << monom:=car listofnexts;listofnexts:=cdr listofnexts >>
  93. >>;return lexbase end;
  94. symbolic procedure glexinsernexts(monom,l,vars);
  95. begin scalar x;
  96. for each v in vars do
  97. << x:=vdpprod(monom,v);
  98. if not vdpmember(x,l)then
  99. << vdpputprop(x,'factor,monom);
  100. vdpputprop(x,'monfac,v);
  101. l:=glexinsernexts1(x,l)>> >>;return l end;
  102. symbolic procedure glexmultipletest(monom,staircase);
  103. if null staircase then nil
  104. else if vevmtest!?(vdpevlmon monom,vdpevlmon car staircase)
  105. then t
  106. else glexmultipletest(monom,cdr staircase);
  107. symbolic procedure glexinsernexts1(m,l);
  108. if null l then list m
  109. else if glexcomp(vdpevlmon m,vdpevlmon car l)then m . l
  110. else car l . glexinsernexts1(m,cdr l);
  111. symbolic procedure glexcomp(ev1,ev2);
  112. % True if ev1 is greater than ev2;
  113. % we use an indirect ordering here(mapping via newbase variables) .
  114. glexcomp0(glexcompmap(ev1,glexmat!*), glexcompmap(ev2,glexmat!*));
  115. symbolic procedure glexcomp0(ev1,ev2);
  116. if null ev1 then nil
  117. else if null ev2 then glexcomp0(ev1,'(0))
  118. else if(car ev1 #- car ev2)=0
  119. then glexcomp0( cdr ev1,cdr ev2)
  120. else if car ev1 #< car ev2 then t else nil;
  121. symbolic procedure glexcompmap(ev,ma);
  122. if null ma then nil
  123. else glexcompmap1(ev,car ma). glexcompmap(ev,cdr ma);
  124. symbolic procedure glexcompmap1(ev1,ev2);
  125. % The dot product of two vectors .
  126. if null ev1 or null ev2 then 0
  127. else(car ev1 #* car ev2)#+ glexcompmap1(cdr ev1,cdr ev2);
  128. symbolic procedure glexaddtomonbase(monom,vect,monbase);
  129. % Primary effect:(monom . vect) . monbase;
  130. % Secondary effect: builds the equation system .
  131. begin scalar x;
  132. if null glexeqsys!* then
  133. << glexeqsys!*:=a2vdp 0;glexcount!*:=-1 >>;
  134. x:=mkid('gunivar,glexcount!*:=glexcount!*+1);
  135. glexeqsys!*:=vdpsum(glexeqsys!*,vdpprod(a2vdp x,cdr vect));
  136. glexsub!*:=(x .(monom . vect)) . glexsub!*;
  137. glexvars!*:=x . glexvars!*;
  138. return(monom . vect). monbase end;
  139. symbolic procedure glexlinrelold(monom,vect,monbase);
  140. if monbase then
  141. begin scalar sys,sub,auxvars,r,v,x;
  142. integer n;
  143. v:=cdr vect;
  144. for each b in reverse monbase do
  145. << x:=mkid('gunivar,n);n:=n + 1;
  146. v:=vdpsum(v,vdpprod(a2vdp x,cddr b));
  147. sub:=( x . b). sub;
  148. auxvars:=x . auxvars >>;
  149. while not vdpzero!? v do
  150. << sys:=vdp2f vdpfmon(vdplbc v,nil). sys;v:=vdpred v >>;
  151. x:=sys;sys:=groelinsolve(sys,auxvars);
  152. if null sys then return nil;
  153. % Construct the lex polynomial .
  154. if !*trgroeb then prin2t "======= constructing new basis polynomial";
  155. r:=vdp2f vdpprod(monom,car vect)./ 1;
  156. for each s in sub do
  157. r:= addsq(r,multsq(vdp2f vdpprod(cadr s,caddr s)./ 1,
  158. cdr assoc(car s,sys)));
  159. r:=vdp2f vdpsimpcont f2vdp numr r;return r end;
  160. symbolic procedure glexlinrel(monom,vect,monbase);
  161. if monbase then
  162. begin scalar sys,r,v,x;
  163. v:=vdpsum(cdr vect,glexeqsys!*);
  164. while not vdpzero!? v do
  165. << sys:=vdp2f vdpfmon(vdplbc v,nil). sys;v:=vdpred v >>;
  166. x:=sys;sys:=groelinsolve(sys,glexvars!*);
  167. if null sys then return nil;
  168. r:=vdp2f vdpprod(monom,car vect)./ 1; % Construct the lex polynomial.
  169. for each s in glexsub!* do
  170. r:= addsq(r,multsq(vdp2f vdpprod(cadr s,caddr s)./ 1,
  171. cdr assoc(car s,sys)));
  172. r:=vdp2f vdpsimpcont f2vdp numr r;
  173. return r end;
  174. symbolic procedure glexnormalform(m,g);
  175. % Reduce 'm' wrt basis 'g';
  176. % the reduction product is preserved in m for later usage .
  177. begin scalar cof,vect,r,f,fac1;
  178. if !*trgroeb then prin2t "======= reducing ";
  179. fac1:=vdpgetprop(m,'factor);
  180. if fac1 then vect:=vdpgetprop(fac1,'vector);
  181. if vect then
  182. <<f:=vdpprod(cdr vect,vdpgetprop(m,'monfac));cof:=car vect>>
  183. else
  184. <<f:=m;cof:= a2vdp 1 >>;
  185. r:=glexnormalform1(f,g,cof);
  186. vdpputprop(m,'vector,r);
  187. if !*trgroeb then
  188. <<vdpprint vdpprod(car r,m);prin2t "=====> ";vdpprint cdr r>>;return r end;
  189. symbolic procedure glexnormalform1(f,g,cof);
  190. begin scalar f1,c,vev,divisor,done,fold,a,b;
  191. fold:=f;f1:=vdpzero();a:= a2vdp 1;
  192. while not vdpzero!? f do
  193. begin vev:=vdpevlmon f;c:=vdplbc f;
  194. divisor:=groebsearchinlist(vev,g); if divisor then done:=t;
  195. if divisor then
  196. if !*vdpinteger then
  197. <<f:=groebreduceonestepint(f,a,c,vev,divisor); b:=secondvalue!*;
  198. cof:=vdpprod(b,cof); if not vdpzero!? f1 then f1:=vdpprod(b,f1)>>
  199. else f:=groebreduceonesteprat(f,nil,c,vev,divisor)
  200. else
  201. <<f1:=vdpappendmon(f1,vdplbc f,vdpevlmon f);f:=vdpred f>>end;
  202. if not done then return cof.fold;
  203. f:=groebsimpcont2(f1,cof);cof:=secondvalue!*; return cof.f end;
  204. symbolic procedure groelinsolve(equations,xvars);
  205. (begin scalar r,q,test,oldmod,oldmodulus;
  206. if !*trgroeb then prin2t "======= testing linear dependency ";
  207. r:=t;
  208. if not !*modular and glexdomain!*=1 then
  209. <<oldmod:=dmode!*;
  210. if oldmod then setdmode(get(oldmod,'dname), nil);
  211. oldmodulus:=current!-modulus;
  212. setmod list 16381;%=2**14-3
  213. setdmode('modular,t);
  214. r:=groelinsolve1(for each u in equations collect numr simp prepf u,xvars);
  215. setdmode('modular,nil);
  216. setmod{oldmodulus};
  217. if oldmod then setdmode(get(oldmod,'dname),t);
  218. >> where !*ezgcd=nil;
  219. if null r then return nil;
  220. r:=groelinsolve1(equations,xvars);
  221. if null r then return nil;
  222. % Divide out the common content .
  223. for each s in r do if not(denr cdr s=1)then test:=t;
  224. if test then return r;
  225. q:=numr cdr car r;
  226. % for each s in cdr r do
  227. % if q neq 1 then
  228. % q:=gcdf!*(q,numr cdr s);
  229. % if q=1 then return r;
  230. % r:=for each s in r collect
  231. % car s .(quotf(numr cdr s,q)./ 1);
  232. return r end)where !*ezgcd=!*ezgcd;% Stack old value.
  233. symbolic procedure groelinsolve1(equations,xvars);
  234. % Gaussian elimination in integer mode;
  235. % free of unexact divisions(see Davenport et al,CA,pp 86 - 87
  236. % special cases: trivial equations are ruled out early.
  237. % INPUT:
  238. % equations: List of standard forms.
  239. % xvars:
  240. % OUTPUT:
  241. % list of pairs(var.solu) where solu is a standard quotient.
  242. % Internal data structure: standard forms as polynomials invars.
  243. begin scalar oldorder,x,p,solutions,val,later,break,gc,field;
  244. oldorder:=setkorder xvars;
  245. field:=dmode!* and flagp(dmode!*,'field);
  246. equations:=for each eqa in equations collect reorder eqa;
  247. for each eqa in equations do
  248. if eqa and domainp eqa then break:= t;
  249. if break then goto empty;
  250. equations:=sort(equations,function grloelinord);
  251. again: break:=nil;
  252. for each eqa in equations do if not break then
  253. % First step: eliminate equations of type 23=0 and 17 * u=0
  254. % and 17 * u + 22=0.
  255. <<if null eqa then equations:=delete(eqa,equations)
  256. else if domainp eqa then break:=t % Inconsistent system .
  257. else if not member(mvar eqa,xvars)then break:=t
  258. else if domainp red eqa or not member(mvar red eqa,xvars)then
  259. <<equations:=delete(eqa,equations);x:=mvar eqa;
  260. val:=if lc eqa=1 then negf red eqa ./ 1
  261. else multsq(negf red eqa ./ 1,1 ./lc eqa);
  262. solutions:=(x.val).solutions;
  263. equations:=for each q in equations collect
  264. groelinsub(q,list(x . val));
  265. later:= for each q in later collect groelinsub(q,list(x.val));
  266. break:=0>> >>;
  267. if break=0 then goto again else if break then goto empty;
  268. % Perform an elimination loop.
  269. if null equations then goto ready;
  270. equations:=sort(equations,function grloelinord);
  271. p:=car equations;x:=mvar p;
  272. equations:=for each eqa in cdr equations collect
  273. if mvar eqa=x then
  274. <<if field then
  275. eqa:=addf(eqa,negf multf(quotf(lc eqa,lc p),p)) else
  276. <<gc:=gcdf(lc p,lc eqa);
  277. eqa:=addf(multf(quotf(lc p,gc),eqa),
  278. negf multf(quotf(lc eqa,gc),p)) >>;
  279. if not domainp eqa then eqa:=numr multsq(eqa ./ 1,1 ./ lc eqa);
  280. %%%%%%eqa:=groelinscont(eqa,xvars);
  281. eqa>>
  282. else eqa;
  283. later:=p.later;goto again;
  284. ready: % Do backsubstitutions .
  285. while later do
  286. <<p:=car later;later:=cdr later;
  287. p:=groelinsub(p,solutions);
  288. if domainp p or not member(mvar p,xvars)or
  289. (not domainp red p and member(mvar red p,xvars)) then
  290. <<break:=t;later:=nil>>;
  291. x:=mvar p;
  292. val:=if lc p=1 then negf red p ./ 1
  293. else quotsq(negf red p ./ 1,lc p ./ 1);
  294. solutions:=(x.val).solutions>>;
  295. if break then goto empty else goto finis;
  296. empty: solutions:=nil;
  297. finis: setkorder oldorder;
  298. solutions:=for each s in solutions collect
  299. car s.(reorder numr cdr s ./ reorder denr cdr s);
  300. return solutions end;
  301. symbolic procedure grloelinord(u,v);
  302. % Apply ordop to the mainvars of 'u' and 'v'.
  303. ordop(mvar u,mvar v);
  304. %symbolic procedure groelinscont(f,vars);
  305. %% Reduce content from standard form f.
  306. % if domainp f then f else
  307. % begin scalar c;
  308. % c:=groelinscont1(lc f,red f,vars);
  309. % if c=1 then return f;
  310. % prin2 "*************content: ";print c;
  311. % return quotf(f,c)end;
  312. %symbolic procedure groelinscont1(q,f,vars);
  313. %% Calculate the contents of standard form 'f'.
  314. % if null f or q=1 then q
  315. % else if domainp f or not member(mvar f,vars)then gcdf!*(q,f)
  316. % else groelinscont1(gcdf!*(q,lc f),red f,vars);
  317. symbolic procedure groelinsub(s,a);
  318. % 's' is a standard form linear in the top level variables,
  319. % a is an assiciation list(variable.sq). ...
  320. % The value is the standard form,where all substitutions
  321. % from a are done in 's'(common denominator ignored).
  322. numr groelinsub1(s,a);
  323. symbolic procedure groelinsub1(s,a);
  324. if domainp s then s ./ 1
  325. else(if x then addsq(multsq(cdr x,lc s ./ 1), y)
  326. else addsq(lt s.+nil ./ 1,y))
  327. where x=assoc(mvar s,a), y=groelinsub1(red s,a);
  328. endmodule;;end;