glexconv.red 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472
  1. module glexconv; % Newbase-Algorithm:
  2. % Faugere, Gianni, Lazard, Mora
  3. fluid '(!*factor !*complex !*exp !*gcd !*ezgcd); % REDUCE switch
  4. fluid '( % switches from the user interface
  5. !*groebopt !*groebfac !*groebres !*trgroeb !*trgroebs !*groebrm
  6. !*trgroeb1 !*trgroebr !*groebprereduce groebrestriction!*
  7. !*fullreduction !*groebstat !*groebprot !*gltbasis
  8. !*groebsubs
  9. !*vdpinteger !*vdpmodular % indicating type of algorithm
  10. !*gsugar % sugar mode
  11. vdpsortmode!* % term ordering mode
  12. secondvalue!* thirdvalue!* % auxiliary: multiple return values
  13. fourthvalue!*
  14. factortime!* % computing time spent in factoring
  15. factorlvevel!* % bookkeeping of factor tree
  16. pairsdone!* % list of pairs already calculated
  17. probcount!* % counting subproblems
  18. vbccurrentmode!* % current domain for base coeffs.
  19. vbcmodule!* % for modular calculation: current prime
  20. glexdomain!* % information wrt current domain
  21. !*gsugar
  22. );
  23. global '(groebrestriction % interface: name of function
  24. groebresmax % maximum number of internal results
  25. gvarslast % output: variable list
  26. groebprotfile
  27. gltb
  28. );
  29. flag ('(groebrestriction groebresmax gvarslast groebprotfile
  30. gltb),'share);
  31. switch groebopt,groebfac,groebres,trgroeb,trgroebs,trgroeb1,
  32. trgroebr,groebstat,gltbasis;
  33. % variables for counting and numbering
  34. fluid '(hcount!* pcount!* mcount!* fcount!* bcount!* b4count!*
  35. basecount!* hzerocount!*);
  36. % control of the polynomial arithmetic actually loaded
  37. fluid '(currentvdpmodule!*);
  38. fluid '(glexmat!*); % matrix for the indirect lex ordering
  39. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  40. %
  41. % interface functions
  42. % parameters;
  43. % glexconvert(basis,[vars],[maxdeg=n],[newvars={x,y,..}])
  44. symbolic procedure glexconverteval u;
  45. begin integer n; scalar !*groebfac,!*groebrm,!*factor,!*gsugar,
  46. v, bas,vars,maxdeg,newvars,!*exp; !*exp := t;
  47. u := for each p in u collect reval p;
  48. bas := car u ; u := cdr u;
  49. while u do
  50. << v := car u; u := cdr u;
  51. if eqcar(v,'list) and null vars then vars := v
  52. else if eqcar(v,'equal) then
  53. if(v := cdr v)and eqcar(v,'maxdeg) then maxdeg := cadr v
  54. else if eqcar(v,'newvars) then newvars := cadr v
  55. else <<prin2 (car v);
  56. rerror(groebnr2,4,"Glexconvert, keyword unknown")>>
  57. else rerror(groebnr2,5,
  58. "Glexconvert, too many positional parameters")>>;
  59. return glexbase1(bas,vars,maxdeg,newvars);
  60. end;
  61. put('glexconvert,'psopfn,'glexconverteval);
  62. symbolic procedure glexbase1(u,v,maxdeg,nv);
  63. begin scalar vars,w,nd,oldorder,!*gcd,!*ezgcd,!*gsugar;
  64. integer pcount!*;
  65. !*gcd := t;
  66. w := for each j in groerevlist u
  67. collect if eqexpr j then !*eqn2a j else j;
  68. if null w then rerror(groebnr2,6,"Empty list in Groebner");
  69. vars := groebnervars(w,v);
  70. !*vdpinteger := !*vdpmodular := nil;
  71. if not flagp(dmode!*,'field) then !*vdpinteger := t
  72. else
  73. if !*modular then !*vdpmodular := t;
  74. if null vars then vdperr 'groebner;
  75. oldorder := vdpinit vars;
  76. % cancel common denominators
  77. w := for each j in w collect reorder numr simp j;
  78. % optimize varable sequence if desired
  79. w := for each j in w collect f2vdp j;
  80. for each p in w do
  81. nd := nd or not vdpcoeffcientsfromdomain!? p;
  82. if nd then <<!*vdpmodular:= nil;
  83. !*vdpinteger := t;
  84. glexdomain!* := 2>>
  85. else glexdomain!* := 1;
  86. if glexdomain!*=1 and not !*vdpmodular then !*ezgcd:=t;
  87. if null maxdeg then maxdeg := 200;
  88. if nv then nv := groerevlist nv;
  89. if null nv then nv := vars else
  90. for each x in nv do if not member(x,vars) then
  91. <<rerror(groebnr2,7,list("new variable ",x,
  92. " is not a basis variable"))>>;
  93. u := for each v in nv collect a2vdp v;
  94. gbtest w;
  95. w := glexbase2(w,u,maxdeg);
  96. w := 'list . for each j in w collect prepf j;
  97. setkorder oldorder;
  98. gvarslast := 'list . vars;
  99. return w;
  100. end;
  101. fluid '(glexeqsys!* glexvars!* glexcount!* glexsub!*);
  102. symbolic procedure glexbase2(oldbase,vars,maxdeg);
  103. % in contrast to documented algorithm monbase ist a list of
  104. % triplets (mon.cof.vect)
  105. % such that cof * mon == vect modulo oldbase
  106. % (cof is needed because of the integer algoritm)
  107. begin scalar lexbase, staircase, monbase;
  108. scalar monom, listofnexts, vect,q,glexeqsys!*,glexvars!*,
  109. glexsub!*;
  110. integer n;
  111. if not groezerodim!?(oldbase,length vars) then
  112. prin2t "####### warning: ideal is not zerodimensional ######";
  113. % prepare matrix for the indirect lex ordering
  114. glexmat!* := for each u in vars collect vdpevlmon u;
  115. monbase := staircase := lexbase := nil;
  116. monom := a2vdp 1;
  117. listofnexts := nil;
  118. while not(monom = nil) do
  119. <<
  120. if not glexmultipletest(monom,staircase) then
  121. << vect := glexnormalform(monom,oldbase);
  122. q := glexlinrel(monom,vect,monbase);
  123. if q then
  124. <<lexbase := q . lexbase; maxdeg := nil;
  125. staircase := monom . staircase;
  126. >>
  127. else
  128. <<monbase := glexaddtomonbase(monom,vect,monbase);
  129. n := n #+1;
  130. if maxdeg and n#> maxdeg then
  131. rerror(groebnr2,8,
  132. "No univar. polynomial within degree bound");
  133. listofnexts :=
  134. glexinsernexts(monom,listofnexts,vars)>>;
  135. >>;
  136. if null listofnexts then monom := nil
  137. else << monom := car listofnexts ;
  138. listofnexts := cdr listofnexts >>;
  139. >>;
  140. return lexbase;
  141. end;
  142. symbolic procedure glexinsernexts(monom,l,vars);
  143. begin scalar x;
  144. for each v in vars do
  145. << x := vdpprod(monom,v);
  146. if not vdpmember(x,l) then
  147. <<vdpputprop(x,'factor,monom); vdpputprop(x,'monfac,v);
  148. l := glexinsernexts1(x,l);
  149. >>;
  150. >>;
  151. return l;
  152. end;
  153. symbolic procedure glexmultipletest(monom,staircase);
  154. if null staircase then nil
  155. else if vevmtest!?(vdpevlmon monom, vdpevlmon car staircase)
  156. then t
  157. else glexmultipletest(monom, cdr staircase);
  158. symbolic procedure glexinsernexts1(m,l);
  159. if null l then list m
  160. else if glexcomp(vdpevlmon m,vdpevlmon car l) then m.l
  161. else car l . glexinsernexts1(m,cdr l);
  162. symbolic procedure glexcomp(ev1,ev2);
  163. % true if ev1 is greater than ev2
  164. % we use an indirect ordering here (mapping via newbase variables)
  165. glexcomp0(glexcompmap(ev1,glexmat!*),
  166. glexcompmap(ev2,glexmat!*));
  167. symbolic procedure glexcomp0(ev1,ev2);
  168. if null ev1 then nil
  169. else if null ev2 then glexcomp0(ev1,'(0))
  170. else if (car ev1 #- car ev2) = 0
  171. then glexcomp0(cdr ev1,cdr ev2)
  172. else if car ev1 #< car ev2 then t
  173. else nil;
  174. symbolic procedure glexcompmap (ev,ma);
  175. if null ma then nil
  176. else glexcompmap1(ev,car ma) . glexcompmap(ev,cdr ma);
  177. symbolic procedure glexcompmap1(ev1,ev2);
  178. % the dot product of two vectors
  179. if null ev1 or null ev2 then 0
  180. else (car ev1 #* car ev2) #+ glexcompmap1(cdr ev1,cdr ev2);
  181. symbolic procedure glexaddtomonbase(monom,vect,monbase);
  182. % primary effect: (monom . vect) . monbase
  183. % secondary effect: builds the equation system
  184. begin scalar x;
  185. if null glexeqsys!* then
  186. <<glexeqsys!* := a2vdp 0; glexcount!*:=-1>>;
  187. x := mkid('gunivar,glexcount!*:=glexcount!*+1);
  188. glexeqsys!* := vdpsum(glexeqsys!*,vdpprod(a2vdp x,cdr vect));
  189. glexsub!* := (x .(monom . vect)) . glexsub!*;
  190. glexvars!* := x . glexvars!*;
  191. return (monom . vect) . monbase;
  192. end;
  193. symbolic procedure glexlinrelold(monom,vect,monbase);
  194. if monbase then
  195. begin scalar sys,sub,auxvars,r,v,x;
  196. integer n;
  197. v := cdr vect;
  198. for each b in reverse monbase do
  199. <<x := mkid('gunivar,n); n := n+1;
  200. v := vdpsum(v,vdpprod(a2vdp x,cddr b));
  201. sub := (x . b) . sub;
  202. auxvars := x . auxvars>>;
  203. while not vdpzero!? v do
  204. <<sys := vdp2f vdpfmon(vdplbc v,nil) . sys; v := vdpred v>>;
  205. x := sys;
  206. sys := groelinsolve(sys,auxvars);
  207. if null sys then return nil;
  208. % construct the lex polynomial
  209. if !*trgroeb
  210. then prin2t " ======= constructing new basis polynomial";
  211. r := vdp2f vdpprod(monom,car vect) ./ 1;
  212. for each s in sub do
  213. r:= addsq(r,multsq(vdp2f vdpprod(cadr s,caddr s) ./ 1,
  214. cdr assoc(car s,sys)));
  215. r := vdp2f vdpsimpcont f2vdp numr r;
  216. return r;
  217. end;
  218. symbolic procedure glexlinrel(monom,vect,monbase);
  219. if monbase then
  220. begin scalar sys,r,v,x;
  221. v := vdpsum(cdr vect,glexeqsys!*);
  222. while not vdpzero!? v do
  223. <<sys := vdp2f vdpfmon(vdplbc v,nil) . sys; v := vdpred v>>;
  224. x := sys;
  225. sys := groelinsolve(sys,glexvars!*);
  226. if null sys then return nil;
  227. % construct the lex polynomial
  228. r := vdp2f vdpprod(monom,car vect) ./ 1;
  229. for each s in glexsub!* do
  230. r:= addsq(r,multsq(vdp2f vdpprod(cadr s,caddr s) ./ 1,
  231. cdr assoc(car s,sys)));
  232. r := vdp2f vdpsimpcont f2vdp numr r;
  233. return r;
  234. end;
  235. symbolic procedure glexnormalform(m,g);
  236. % reduce m wrt basis G;
  237. % the reduction product is preserved in m for later usage
  238. begin scalar cof,vect,r,f,fac1;
  239. if !*trgroeb then prin2t " ======= reducing ";
  240. fac1 := vdpgetprop(m,'factor);
  241. if fac1 then vect := vdpgetprop(fac1,'vector);
  242. if vect then
  243. << f := vdpprod(cdr vect,vdpgetprop(m,'monfac));
  244. cof := car vect>>
  245. else
  246. << f := m; cof := a2vdp 1>>;
  247. r := glexnormalform1(f,g,cof);
  248. vdpputprop(m,'vector,r);
  249. if !*trgroeb then
  250. <<vdpprint vdpprod(car r,m); prin2t " =====> ";
  251. vdpprint cdr r>>;
  252. return r;
  253. end;
  254. symbolic procedure glexnormalform1(f,g,cof);
  255. begin scalar f1,c,vev,divisor,done,fold,a,b;
  256. fold := f; f1 := vdpzero(); a:= a2vdp 1;
  257. while not vdpzero!? f do
  258. begin
  259. vev:=vdpevlmon f; c:=vdplbc f;
  260. divisor := groebsearchinlist (vev,g);
  261. if divisor then done := t;
  262. if divisor then
  263. if !*vdpinteger then
  264. << f:=groebreduceonestepint(f,a,c,vev,divisor);
  265. b := secondvalue!*;
  266. cof := vdpprod(b,cof);
  267. if not vdpzero!? f1 then
  268. f1 := vdpprod(b,f1);
  269. >>
  270. else
  271. f := groebreduceonesteprat(f,nil,c,vev,divisor)
  272. else
  273. <<f1 := vdpappendmon (f1,vdplbc f,vdpevlmon f);
  274. f := vdpred f;
  275. >>;
  276. end;
  277. if not done then return cof . fold;
  278. f := groebsimpcont2(f1,cof); cof := secondvalue!*;
  279. return cof . f;
  280. end;
  281. symbolic procedure groelinsolve(equations,xvars);
  282. (begin scalar r,q,test,oldmod,oldmodulus;
  283. if !*trgroeb then prin2t " ======= testing linear dependency ";
  284. r := t;
  285. if not !*modular and glexdomain!*=1 then
  286. <<oldmod := dmode!*;
  287. if oldmod then setdmode(get(oldmod,'dname),nil);
  288. oldmodulus := current!-modulus;
  289. setmod list 16381; % = 2**14-3
  290. setdmode('modular,t);
  291. r := groelinsolve1(for each u in equations collect
  292. numr simp prepf u, xvars);
  293. setdmode('modular,nil);
  294. setmod list oldmodulus;
  295. if oldmod then setdmode(get(oldmod,'dname),t);
  296. >> where !*ezgcd=nil;
  297. if null r then return nil;
  298. r := groelinsolve1(equations,xvars);
  299. if null r then return nil;
  300. % divide out the common content
  301. for each s in r do
  302. if not(denr cdr s = 1) then test := t;
  303. if test then return r;
  304. q := numr cdr car r;
  305. % for each s in cdr r do
  306. % if q neq 1 then
  307. % q := gcdf!*(q,numr cdr s);
  308. % if q=1 then return r;
  309. % r := for each s in r collect
  310. % car s . (quotf(numr cdr s, q) ./ 1);
  311. return r;
  312. end) where !*ezgcd=!*ezgcd; % stack old value
  313. symbolic procedure groelinsolve1(equations,xvars);
  314. % Gaussian elimination in integer mode
  315. % free of unexact divisions (see Davenport et al,CA, pp86-87
  316. % special cases: trivial equations are ruled out early
  317. % INPUT:
  318. % equations: list of standard forms
  319. % xvars: variables for the solution
  320. % OUTPUT:
  321. % list of pairs (var . solu) where solu is a standard quotient
  322. %
  323. % internal data structure: standard forms as polynomials in xvars
  324. begin scalar oldorder,x,p,solutions,val,later,break,gc,field;
  325. oldorder := setkorder xvars;
  326. field := dmode!* and flagp(dmode!*,'field);
  327. equations := for each eqa in equations collect reorder eqa;
  328. for each eqa in equations do
  329. if eqa and domainp eqa then break:= t;
  330. if break then goto empty;
  331. equations := sort(equations,function grloelinord);
  332. again:
  333. break := nil;
  334. for each eqa in equations do if not break then
  335. % car step: eliminate equations of type 23 = 0
  336. % and 17 * u = 0
  337. % and 17 * u + 22 = 0;
  338. << if null eqa then equations := delete(eqa,equations)
  339. else if domainp eqa then break := t % inconsistent system
  340. else if not member(mvar eqa,xvars) then break := t
  341. else if domainp red eqa or not member(mvar red eqa,xvars) then
  342. <<equations := delete (eqa,equations);
  343. x := mvar eqa;
  344. val := if lc eqa = 1 then negf red eqa ./ 1
  345. else multsq(negf red eqa ./ 1, 1 ./lc eqa);
  346. solutions := (x . val) . solutions;
  347. equations := for each q in equations collect
  348. groelinsub(q,list(x.val));
  349. later :=
  350. for each q in later collect groelinsub(q,list(x.val));
  351. break := 0;
  352. >>;
  353. >>;
  354. if break = 0 then goto again else if break then goto empty;
  355. % perform an elimination loop
  356. if null equations then goto ready;
  357. equations := sort(equations,function grloelinord);
  358. p := car equations; x := mvar p;
  359. equations := for each eqa in cdr equations collect
  360. if mvar eqa = x then
  361. << if field then
  362. eqa := addf(eqa, negf multf(quotf(lc eqa,lc p),p))
  363. else
  364. <<gc := gcdf(lc p,lc eqa);
  365. eqa := addf(multf(quotf(lc p,gc),eqa),
  366. negf multf(quotf(lc eqa,gc),p))>>;
  367. if not domainp eqa then
  368. eqa := numr multsq(eqa ./ 1, 1 ./ lc eqa);
  369. %%%%%%eqa := groelinscont(eqa,xvars);
  370. eqa>>
  371. else eqa;
  372. later := p . later;
  373. goto again;
  374. ready: % do backsubstitutions
  375. while later do
  376. <<p := car later; later := cdr later;
  377. p := groelinsub(p,solutions);
  378. if domainp p or not member(mvar p,xvars) or
  379. (not domainp red p and member(mvar red p,xvars)) then
  380. <<break := t; later := nil>>;
  381. x := mvar p;
  382. val := if lc p = 1 then negf red p ./ 1
  383. else quotsq(negf red p ./ 1 , lc p ./ 1);
  384. solutions := (x . val) . solutions;
  385. >>;
  386. if break then goto empty else goto finis;
  387. empty: solutions := nil;
  388. finis: setkorder oldorder;
  389. solutions := for each s in solutions collect
  390. car s . (reorder numr cdr s ./ reorder denr cdr s);
  391. return solutions;
  392. end;
  393. symbolic procedure grloelinord(u,v);
  394. % apply ordop to the mainvars of u and v
  395. ordop(mvar u, mvar v);
  396. symbolic procedure groelinscont(f,vars);
  397. % reduce content from standard form f
  398. if domainp f then f else
  399. begin scalar c;
  400. c := groelinscont1(lc f,red f,vars);
  401. if c=1 then return f;
  402. prin2 "*************content: ";print c;
  403. return quotf(f,c);
  404. end;
  405. symbolic procedure groelinscont1(q,f,vars);
  406. % calculate the contents of standard form f
  407. if null f or q=1 then q
  408. else if domainp f or not member(mvar f,vars) then gcdf!*(q,f)
  409. else groelinscont1(gcdf!*(q,lc f),red f,vars);
  410. symbolic procedure groelinsub(s,a);
  411. % s is a standard form linear in the top level variables
  412. % a is an assiciation list (variable . sq) . ...
  413. % The value is the standard form, where all substitutions
  414. % from a are done in s (common denominator ignored).
  415. numr groelinsub1(s,a);
  416. symbolic procedure groelinsub1(s,a);
  417. if domainp s then s ./ 1
  418. else (if x then addsq(multsq(cdr x,lc s ./ 1),y)
  419. else addsq(lt s .+ nil ./ 1,y))
  420. where x=assoc(mvar s,a),y=groelinsub1(red s,a);
  421. endmodule;
  422. end;