kuechl.red 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  1. module kuechl;% Walking faster,B . Amrhrein,O . Gloor,W . Kuechlin
  2. % in: Calmet,Limongelli(Eds .)Design and
  3. % Implementation of Symbolic Computation Systems,Sept.1996
  4. % Version 3 with a rational local solution(after letters from H.M.Moeller).
  5. % Version 4 with keeping the polynomials as DIPs converting only
  6. % their order mode.
  7. switch trgroeb;
  8. put('groebner_walk,' psopfn,' groeb!-walk);
  9. symbolic procedure groeb!-walk u;
  10. begin if !*groebopt then
  11. rerror(groebner,31,"don't call 'groebner_walk' with 'on groebopt'");
  12. if null dipvars!* then rerror(groebner,30,"'torder' must be called before");
  13. groetime!*:=time();
  14. !*gsugar:=t;!*groebrm:=nil;u:=car groeparams(u,1,1);
  15. groebnervars(u,nil);u:=groeb!-list(u,'simp);
  16. groedomainmode();u:=groeb!-w2 u;
  17. return'list.groeb!-collect(u,'mk!*sq)end;
  18. symbolic procedure groeb!-list(u,fcn);
  19. % Execute the function ' fcn ' for the elements of the algebriac
  20. % list 'u'.
  21. <<if atom u or not(eqcar(u,'list))then
  22. rerror('groebner,29,"groebner: list as argument required");
  23. groeb!-collect(cdr u, fcn)>>;
  24. symbolic procedure groeb!-collect(l,f);
  25. % Collect the elements of function 'f' applied to the elements of
  26. % the symbolic list 'l'. If 'f' is a number,map 'l' only.
  27. for each x in l collect if numberp f then f else apply1(f,x);
  28. symbolic procedure groeb!-w2 g;
  29. % This is(essentially)the routine Groebner_Walk.
  30. % G is a list of standard quotients,
  31. % a Groebner basis gradlex or based on a vector like [1 1 1 ...].
  32. % The result is the Groebner basis(standard quotients)with the
  33. % final term order(lex)as its main order.
  34. begin scalar iwv,owv,omega,gomega,gomegaplus,tt,tto,pc;
  35. scalar first,mx,imx,mmx,immx,nn,ll,prim;
  36. scalar !*vdpinteger,!*groebdivide;
  37. !*vdpinteger: nil; % switch on division mode
  38. !*groebdivide:=t;
  39. first:=t;pcount!*:=0;mmx:=!*i2rn 1;immx:=mmx;
  40. iwv:=groeb!-collect(dipvars!*,1);
  41. omega:=iwv; % Input order vector.
  42. owv:=1 .groeb!-collect(cdr dipvars!*,0);
  43. tto:=owv; % Output order vector .
  44. groeb!-w9('weighted,omega);% Install omega as weighted order.
  45. g:=groeb!-collect(g,'sq2vdp);
  46. pc:=pcount!*;
  47. gbtest g; % Test the Groebner property.
  48. nn:=length dipvars!*;
  49. ll:=rninv!: !*i2rn nn; % Inverse of the length.
  50. prim:=t; % Preset.
  51. loop:groeb!-w9(' weighted,omega);
  52. mx:=groeb!-w6!-4 groeb!-collect(omega,1);
  53. % Compute the maximum of \omega.
  54. if !*trgroeb then groebmess34 cadr mx;
  55. imx:=rninv!: mx;
  56. g:=if first then groeb!-collect(g,'vdpsimpcont) else groeb!-w10 g;
  57. if !*trgroeb then groebmess29 omega;
  58. gomega:=if first or not prim then g
  59. else groeb!-w3(g,omega); % G_\omega = initials(G_\omega);
  60. pcount!*:=pc;
  61. if !*trgroeb and not first then groebmess32 gomega;
  62. gomegaplus:=if first then{gomega}else gtraverso(gomega,nil,nil);
  63. if cdr gomegaplus then rerror(groebner,31,
  64. "groebner_walk,cdr of 'groebner' must be nil")
  65. else gomegaplus:=car gomegaplus;
  66. if !*trgroeb and not first then groebmess30 gomegaplus;
  67. if not first and prim
  68. then g:=groeb!-w4(gomegaplus,gomega,g)
  69. else if not prim then g:=gomega;
  70. % G=lift(G_{%omega}{plus},<{plus},G_{%omega),G,<)
  71. if not first then g:=for each x in g collect gsetsugar(x,nil);
  72. if !*trgroeb and not first then groebmess31 g;
  73. if groeb!-w5(omega,imx,tto,immx)then go to ret;
  74. % Stop if tt has been 1 once.
  75. if not first and rnonep!: tt then go to ret;% Secodary abort crit.
  76. tt:=groeb!-w6!-6(g,tto,immx,omega,imx,ll);% Determine_border .
  77. if !*trgroeb then groebmess36 tt;
  78. if null tt then go to ret;
  79. % criterion: take primary only if tt neq 1
  80. prim:=not rnonep!: tt;
  81. if !*trgroeb then groebmess37 prim;
  82. %\omega =(1-t)*\omega+t*tau
  83. omega:=groeb!-w7(tt,omega,imx,tto,immx);
  84. if !*trgroeb then groebmess35 omega;
  85. first:=nil;go to loop;
  86. ret:
  87. if !*trgroeb then groebmess33 g;
  88. g:=groeb!-collect(g,'vdpsimpcont);
  89. g:=groeb!-collect(g,'vdp2sq);
  90. return g end;
  91. symbolic procedure groeb!-w3(g,omega);
  92. % Extract head terms of g corresponding to omega.
  93. begin scalar x,y,gg,ff;
  94. gg:=for each f in g collect<<ff:=vdpfmon(vdplbc f,vdpevlmon f);
  95. gsetsugar(ff,nil);
  96. x:=evweightedcomp2(0,vdpevlmon ff,omega);
  97. y:=x;
  98. f:=vdpred f;
  99. while not vdpzero!? f and y=x do
  100. <<y:=evweightedcomp2(0,vdpevlmon f,omega);
  101. if y=x then
  102. ff:=vdpsum(ff,vdpfmon(vdplbc f,vdpevlmon f));f:=vdpred f>>;
  103. ff>>;return gg end;
  104. symbolic procedure groeb!-w4(gb,gomega,g);
  105. % gb Groebner basis of gomega,
  106. % gomega head term system g_\omega of g,
  107. % g full(original)system of polynomials.
  108. begin scalar x;
  109. for each y in gb do gsetsugar(y,nil);
  110. x:=for each y in gomega collect groeb!-w8(y,gb);
  111. x:=for each z in x collect groeb!-w4!-1(z,g);return x end;
  112. symbolic procedure groeb!-w4!-1(pl,fs);
  113. % pl is a list of polynomials corresponding to the full system fs.
  114. % Compute the sum of pl*fs. Result is the sum.
  115. begin scalar z;z:=vdpzero();
  116. gsetsugar(z,0);
  117. for each p in pair(pl,fs)do
  118. if car p then z:=vdpsum(z,vdpprod(car p,cdr p));
  119. z:=vdpsimpcont z;return z end;
  120. symbolic procedure groeb!-w5(ev1,x1,ev2,x2);
  121. % ev1=ev2 equality test.
  122. groeb!-w5!-1(x1,ev1,x2,ev2);
  123. symbolic procedure groeb!-w5!-1(x1,ev1,x2,ev2);
  124. ( null ev1 and null ev2)or
  125. (rntimes!:(!*i2rn car ev1,x1)=rntimes!:(!*i2rn car ev2,x2)
  126. and groeb!-w5!-1(x1,cdr ev1,x2,cdr ev2));
  127. symbolic procedure groeb!-w6!-4 omega;
  128. % Compute the weighted length of \omega.
  129. groeb!-w6!-5(omega,vdpsortextension!*,0);
  130. symbolic procedure groeb!-w6!-5(omega,v,m);
  131. if null omega then !*i2rn m
  132. else if 0=car omega then groeb!-w6!-5(cdr omega,cdr v,m)
  133. else if 1 = car omega
  134. then groeb!-w6!-5(cdr omega,cdr v,m #+ car v)
  135. else groeb!-w6!-5(cdr omega,cdr v,m #+ car omega #* car v);
  136. symbolic procedure groeb!-w6!-6(gb,tt,ifactt,tp,ifactp,ll);
  137. % Compute the weight border(minimum over all polynomials of gb).
  138. begin scalar mn,x,zero,one;
  139. zero:=!*i2rn 0;one:=!*i2rn 1;
  140. while not null gb do
  141. <<x:=groeb!-w6!-7(car gb,tt,ifactt,tp,ifactp,zero,one,ll);
  142. if null mn or(x and rnminusp!: rndifference!:(x,mn))
  143. then mn:=x;gb:=cdr gb>>;return mn end;
  144. symbolic procedure groeb!-w6!-7(pol,tt,ifactt,tp,ifactp,zero,one,ll);
  145. % Compute the minimal weight for one polynomial;the idea is,
  146. % that the polynomial has a degree greater than 0.
  147. begin scalar a,b,ev1,ev2,x,y,z,mn;
  148. ev1:=vdpevlmon pol;
  149. a:=evweightedcomp2(0,ev1,vdpsortextension!*);
  150. y:=groeb!-w6!-8(ev1,tt,ifactt,tp,ifactp,zero,zero,one,ll);
  151. y:=(rnminus!: car y).(rnminus!: cdr y);
  152. pol:=vdpred pol;
  153. while not(vdpzero!? pol)do
  154. <<ev2:=vdpevlmon pol;
  155. pol:=vdpred pol;
  156. b:=evweightedcomp2(0,ev2,vdpsortextension!*);
  157. if not(a=b)then
  158. <<x:=groeb!-w6!-9(ev2,tt,ifactt,tp,ifactp,car y,cdr y,one,ll,nil);
  159. if x then
  160. <<z:=rndifference!:(x,one);
  161. if rnminusp!: rndifference!:(zero,x)and
  162. (rnminusp!: z or rnzerop!: z)and
  163. (null mn or rnminusp!: rndifference!:(x,mn))
  164. then mn:=x>>>>>>;return mn end;
  165. symbolic procedure groeb!-w6!-8(ev,tt,ifactt,tp,ifactp,sum1,sum2,m,dm);
  166. begin scalar x,y,z;
  167. if ev then<<x:=rntimes!:(!*i2rn car ev,m);
  168. y:=rntimes!:(!*i2rn car tp,ifactp);
  169. z:=rntimes!:(!*i2rn car tt,ifactt)>>;
  170. return
  171. if null ev then sum1.sum2 else
  172. groeb!-w6!-8(cdr ev,cdr tt,ifactt,cdr tp,ifactp,
  173. rnplus!:(sum1,rntimes!:(y,x)),
  174. rnplus!:(sum2,rntimes!:(rndifference!:(z,y),x)),
  175. rndifference!:(m,dm),
  176. dm)end;
  177. symbolic procedure groeb!-w6!-9(ev,tt,ifactt,tp,ifactp,y1,y2,m,dm,done);
  178. % Compute the rational solution s:
  179. %(tp+s*(tt-tp))*ev1=(tp+s*(tt-tp))*evn.
  180. % The sum with ev1 is collected already in y1 and y2(with negative sign).
  181. % This routine collects the sum with evn and computes the solution.
  182. begin scalar x,y,z;
  183. if ev then<<x:=rntimes!:(!*i2rn car ev,m);
  184. y:=rntimes!:(!*i2rn car tp,ifactp),
  185. z:=rntimes!:(!*i2rn car tt,ifactt)>>;
  186. return if null ev then
  187. if null done then nil
  188. else rnquotient!:(rnminus!: y1,y2)
  189. else
  190. groeb!-w6!-9(cdr ev,cdr tt,ifactt,cdr tp,ifactp,
  191. rnplus!:(y1,rntimes!:(y,x)),
  192. rnplus!:(y2,rntimes!:(rndifference!:(z,y),x)),
  193. rndifference!:(m,dm),
  194. dm,
  195. done or not(car ev = 0)) end;
  196. symbolic procedure groeb!-w7(tt,omega,x,tto,y);
  197. % Compute omega*x*(1-tt)+tto*y*tt.
  198. % tt is a rational number.
  199. % x and y are rational numbers(inverses of the legths of omega/tt).
  200. begin scalar n,z;n:=!*i2rn 1;
  201. omega:=for each g in omega collect
  202. <<z:=rnplus!:(rntimes!:(rntimes!:(!*i2rn g,x),
  203. rndifference!:(!*i2rn 1,tt)),
  204. rntimes!:(rntimes!:(!*i2rn car tto,y),tt));
  205. tto:=cdr tto;
  206. n:=groeb!-w7!-1(n,rninv!: z);z>>;
  207. omega:=for each a in omega collect rnequiv rntimes!:(a,!*i2rn n);
  208. return omega end;
  209. symbolic procedure groeb!-w7!-1(n,m);
  210. % Compute lcm of n and m. N and m are rational numbers.
  211. % Return the lcm.
  212. % Ignore the denominators of n and m.
  213. begin scalar x,y,z;
  214. if atom n then x:=n else
  215. <<x:=rnprep!: n;
  216. if not atom x then x:=cadr x>>;
  217. if atom m then y:=m else
  218. <<y:=rnprep!: m;if not atom y then y:=cadr y>>;
  219. z:=lcm(x,y);return z end;
  220. symbolic procedure groeb!-w8(p,gb);
  221. % Computes the cofactor of p wrt gb.
  222. % Result is a list of cofactors corresponding to g.
  223. % The cofactor 0 is represented as nil.
  224. begin scalar x,y;
  225. x:=groeb!-w8!-1(p,gb);p:=secondvalue!*;
  226. while not vdpzero!? p do
  227. <<y:=groeb!-w8!-1(p,gb);p:=secondvalue!*;
  228. x:=for each pp in pair(x,y)do
  229. if null car pp then cdr pp
  230. else if null cdr pp then car pp
  231. else vdpsum(car pp,cdr pp)>>;return x end;
  232. symbolic procedure groeb!-w8!-1(p,gb);
  233. % Search in groebner basis gb the polynomial which divides the
  234. % head monomial of the polynomial p. The walk version of
  235. % groebsearchinlist.
  236. % Result: the sequence corresponding to g with the monomial
  237. % factor inserted.
  238. begin scalar e,cc,r,done,pp;
  239. pp:=vdpevlmon p;cc:=vdplbc p;
  240. r:=for each poly in gb collect
  241. if done then nil else
  242. if vevdivides!?(vdpevlmon poly,pp)then
  243. <<done:=t;e:=poly;
  244. cc:=vbcquot(cc,vdplbc poly);
  245. pp:=vevdif(pp,vdpevlmon poly);
  246. secondvalue!*:=
  247. vdpsum(vdpprod(gsetsugar(vdpfmon(vbcneg cc,pp),nil),poly), p);
  248. vdpfmon(cc,pp)>>
  249. else nil;
  250. if null e then
  251. <<print p;print "-----------------";print gb;
  252. rerror(groebner,28,"groeb-w8-1 illegal structure")>>;
  253. return r end;
  254. symbolic procedure groeb!-w9(mode,ext);
  255. % Switch on vdp order mode 'mode' with extension 'ext'.
  256. % Result is the previous extension.
  257. begin scalar x;
  258. x:=vdpsortextension!*;vdpsortextension!*:=ext;
  259. torder2 mode;return x end;
  260. symbolic procedure groeb!-w10 s;
  261. % Convert the dips in s corresponding to the actual order.
  262. groeb!-collect(s,'groeb!-w10!-1);
  263. symbolic procedure groeb!-w10!-1 p;
  264. % Convert the dip p corresponding to the actal order.
  265. begin scalar x;
  266. x:=vdpfmon(vdplbc p,vdpevlmon p);
  267. x:=gsetsugar(vdpenumerate x,nil);
  268. p:=vdpred p;
  269. while not vdpzero!? p do
  270. <<x:=vdpsum(vdpfmon(vdplbc p,vdpevlmon p),x);p:=vdpred p>>;
  271. return x end;
  272. symbolic procedure rninv!: x;
  273. % Return inverse of a(rational)number x: 1/x.
  274. <<if atom x then x:=!*i2rn x;
  275. x:=cdr x;
  276. if car x < 0 then mkrn(- cdr x,- car x)else mkrn(cdr x,car x)>>;
  277. symbolic procedure sq2vdp s;
  278. % Standard quotient to vdp.
  279. begin scalar x,y;x:=f2vdp numr s;
  280. gsetsugar(x,nil);y:=f2vdp denr s;
  281. gsetsugar(y,0);s:=vdpdivmon(x,vdplbc y,vdpevlmon y);
  282. return s end;
  283. symbolic procedure vdp2sq v;
  284. % Conversion vdp to standard quotient.
  285. begin scalar x,y,z,one;one := 1 ./ 1;x := nil ./ 1;
  286. while not vdpzero!? v do
  287. <<y:=vdp2f vdpfmon(one,vdpevlmon v)./ 1;
  288. z:=vdplbc v;
  289. x:=addsq(x,multsq(z,y));
  290. v:=vdpred v>>;return x end;
  291. endmodule;;end;