groeb.red 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598
  1. module groeb;
  2. COMMENT
  3. ##############################
  4. ## ##
  5. ## GROEBNER PACKAGE ##
  6. ## ##
  7. ##############################
  8. This is now a common package, covering both the noetherian and the
  9. local term orders.
  10. The trace intensity can be managed with cali_trace() by the following
  11. rules :
  12. cali_trace() >= 0 no trace
  13. 2 show actual step
  14. 10 show input and output
  15. 20 show new base elements
  16. 30 show pairs
  17. 40 show actual pairlist
  18. 50 show S-polynomials
  19. Pair lists have the following informal syntax :
  20. <spairlist>::= list of spairs
  21. < spair > ::= (komp groeb!=weight lcm p_i p_j)
  22. with lcm = lcm(lt(bas_dpoly p_i),lt(bas_dpoly p_j)).
  23. The pair selection strategy is by first matching in the pair list.
  24. It can be changed overloading groeb!=better, the relation according to
  25. what pair lists are sorted. Standard is the sugar strategy.
  26. cali!=monset :
  27. One can manage a list of variables, that are allowed to be canceled
  28. out, if they appear as common factors in a dpoly. This is possible if
  29. these variables are non zero divisors (e.g. for prime ideals) and
  30. affects "pure" Groebner basis computation only.
  31. END COMMENT;
  32. % ############ The outer Groebner engine #################
  33. put('cali,'groeb!=rf,'groeb!=rf1); % First initialization.
  34. symbolic operator gbtestversion;
  35. symbolic procedure gbtestversion n; % Choose the corresponding driver
  36. if member(n,{1,2,3}) then
  37. put('cali,'groeb!=rf,mkid('groeb!=rf,n));
  38. symbolic procedure groeb!=postprocess pol;
  39. % Postprocessing for irreducible H-Polynomials. The switches got
  40. % appropriate local values in the Groebner engine.
  41. begin
  42. if !*bcsimp then pol:=car bas_simpelement pol;
  43. if not !*noetherian then
  44. if !*factorunits then pol:=bas_factorunits pol
  45. else if !*detectunits then pol:=bas_detectunits pol;
  46. if cali!=monset then pol:=bas_make(bas_nr pol,
  47. car dp_mondelete(bas_dpoly pol,cali!=monset));
  48. return pol
  49. end;
  50. symbolic procedure groeb_stbasis(bas,comp_mgb,comp_ch,comp_syz);
  51. groeb!=choose_driver(bas,comp_mgb,comp_ch,comp_syz,
  52. function groeb!=generaldriver);
  53. symbolic procedure
  54. groeb!=choose_driver(bas,comp_mgb,comp_ch,comp_syz,driver);
  55. % Returns { mgb , change , syz } with
  56. % dpmat mgb = (if comp_mgb=true the minimal)
  57. % Groebner basis of the dpmat bas.
  58. % dpmat change defined by mgb = change * bas
  59. % if comp_ch = true.
  60. % dpmat syz = (not interreduced) syzygy matrix of the dpmat bas
  61. % if comp_syz = true.
  62. % Changes locally !*factorunits, !*detectunits and cali!=monset.
  63. if dpmat_zero!? bas then
  64. {bas,dpmat_unit(dpmat_rows bas,nil),
  65. dpmat_unit(dpmat_rows bas,nil)}
  66. else (begin scalar u, gb, syz, change, syz1;
  67. % ------- Syzygies for the zero base elements.
  68. if comp_syz then
  69. << u:=setdiff(for i:=1:dpmat_rows bas collect i,
  70. for each x in
  71. bas_zerodelete dpmat_list bas collect bas_nr x);
  72. syz1:=for each x in u collect bas_make(0,dp_from_ei x);
  73. >>;
  74. % ------- Initialize the Groebner computation.
  75. gb:=bas_zerodelete dpmat_list bas;
  76. % makes a copy (!) of the base list.
  77. if comp_ch or comp_syz then
  78. << !*factorunits:=!*detectunits:=cali!=monset:=nil;
  79. bas_setrelations gb;
  80. >>;
  81. if cali_trace() > 5 then
  82. << terpri(); write" Compute GBasis of"; bas_print gb >>
  83. else if cali_trace() > 0 then
  84. << terpri(); write" Computing GBasis ";terpri() >>;
  85. u:=apply(driver,{dpmat_rows bas,dpmat_cols bas,gb,comp_syz});
  86. syz:=second u;
  87. if comp_mgb then
  88. << u:=groeb_mingb car u;
  89. if !*red_total then
  90. u:=dpmat_make(dpmat_rows u,dpmat_cols u,
  91. red_straight dpmat_list u,
  92. cali!=degrees,t);
  93. >>
  94. else u:=car u;
  95. cali!=degrees:=dpmat_rowdegrees bas;
  96. if comp_ch then
  97. change:=dpmat_make(dpmat_rows u,dpmat_rows bas,
  98. bas_neworder bas_getrelations dpmat_list u,
  99. cali!=degrees,nil);
  100. bas_removerelations dpmat_list u;
  101. if comp_syz then
  102. << syz:=nconc(syz,syz1);
  103. syz:= dpmat_make(length syz,dpmat_rows bas,
  104. bas_neworder bas_renumber syz,cali!=degrees,nil);
  105. >>;
  106. cali!=degrees:=dpmat_coldegs u;
  107. return {u,change,syz}
  108. end) where cali!=degrees:=dpmat_coldegs bas,
  109. !*factorunits:=!*factorunits,
  110. !*detectunits:=!*detectunits,
  111. cali!=monset:=cali!=monset;
  112. % ######### The General Groebner driver ###############
  113. Comment
  114. It returns {gb,syz,trace} with change on the relation part of gb,
  115. where
  116. INPUT : r, c, gb = rows, columns, base list
  117. OUTPUT :
  118. <dpmat> gb is the Groebner basis
  119. <base list> syz is the dpmat_list of the syzygy matrix
  120. <spairlist> trace is the Groebner trace.
  121. There are three different versions of the general driver that branche
  122. according to a reduction function
  123. rf : {pol,simp} |---> {pol,simp}
  124. found with get('cali,'groeb!=rf):
  125. 1. Total reduction with local simplifier lists. For local term orders
  126. this is (almost) Mora's first version for the tangent cone.
  127. 2. Total reduction with global simplifier list. For local term orders
  128. this is (almost) Mora's SimpStBasis.
  129. 3. Total reduction with bounded ecart. This needs no extra simplifier
  130. list.
  131. end Comment;
  132. symbolic procedure groeb!=generaldriver(r,c,gb,comp_syz);
  133. begin scalar u, q, syz, p, pl, pol, trace, return_by_unit,
  134. simp, rf, Ccrit;
  135. Ccrit:=(not comp_syz) and (c<2); % don't reduce main syzygies
  136. simp:=sort(listminimize(gb,function red!=cancelsimp),
  137. function red_better);
  138. pl:=groeb_makepairlist(gb,Ccrit);
  139. rf:=get('cali,'groeb!=rf);
  140. if cali_trace() > 30 then groeb_printpairlist pl;
  141. if cali_trace() > 5 then
  142. <<terpri(); write" New base elements :";terpri() >>;
  143. % -------- working out pair list
  144. while pl and not return_by_unit do
  145. << % ------- Choose a pair
  146. p:=car pl; pl:=cdr pl;
  147. % ------ compute S-polynomial (which is a base element)
  148. if cali_trace() > 10 then groeb_printpair(p,pl);
  149. u:=apply2(rf,groeb_spol p,simp);
  150. pol:=first u; simp:=second u;
  151. if cali_trace() > 70 then
  152. << terpri(); write" Reduced S.-pol. : ";
  153. dp_print2 bas_dpoly pol
  154. >>;
  155. if bas_dpoly pol then
  156. % --- the S-polynomial doesn't reduce to zero
  157. << pol:=groeb!=postprocess pol;
  158. r:=r+1;
  159. pol:=bas_newnumber(r,pol);
  160. % --- update the tracelist
  161. q:=bas_dpoly pol;
  162. trace:=list(groeb!=i p,groeb!=j p,r,dp_lmon q) . trace;
  163. if cali_trace() > 20 then
  164. << terpri(); write r,". ---> "; dp_print2 q >>;
  165. if Ccrit and (dp_unit!? q) then return_by_unit:=t;
  166. % ----- update
  167. if not return_by_unit then
  168. << pl:=groeb_updatePL(pl,gb,pol,Ccrit);
  169. if cali_trace() > 30 then
  170. << terpri(); groeb_printpairlist pl >>;
  171. gb:=pol.gb;
  172. simp:=red_update(simp,pol);
  173. >>;
  174. >>
  175. else % ------ S-polynomial reduces to zero
  176. if comp_syz then
  177. syz:=car bas_simpelement(bas_make(0,bas_rep pol)) . syz
  178. >>;
  179. % -------- updating the result
  180. if cali_trace()>0 then
  181. << terpri(); write " Simplifier list has length ",length simp >>;
  182. if return_by_unit then return
  183. % --- no syzygies are to be computed
  184. {dpmat_from_dpoly pol,nil,reversip trace};
  185. gb:=dpmat_make(length gb,c,gb,cali!=degrees,t);
  186. return {gb,syz,reversip trace}
  187. end;
  188. % --- The different reduction functions.
  189. symbolic procedure groeb!=rf1(pol,simp); {red_TotalRed(simp,pol),simp};
  190. symbolic procedure groeb!=rf2(pol,simp);
  191. if (null bas_dpoly pol) or (null simp) then {pol,simp}
  192. else begin scalar v,q;
  193. % Make first reduction with bounded ecart.
  194. pol:=red_TopRedBE(simp,pol);
  195. % Now loop into reduction with minimal ecart.
  196. while (q:=bas_dpoly pol) and (v:=red_divtest(simp,dp_lmon q)) do
  197. << v:=red_subst(pol,v);
  198. % Updating the simplifier list could make sense even
  199. % for the noetherian case, since it is a global list.
  200. simp:=red_update(simp,pol);
  201. pol:=red_TopRedBE(simp,v);
  202. >>;
  203. % Now make tail reduction
  204. if !*red_total and bas_dpoly pol then pol:=red_TailRed(simp,pol);
  205. return {pol,simp};
  206. end;
  207. symbolic procedure groeb!=rf3(pol,simp);
  208. % Total reduction with bounded ecart.
  209. if (null bas_dpoly pol) or (null simp) then {pol,simp}
  210. else begin
  211. pol:=red_TopRedBE(simp,pol);
  212. if bas_dpoly pol then
  213. pol:=red_TailRedDriver(simp,pol,function red_TopRedBE);
  214. return {pol,simp};
  215. end;
  216. % ######### The Lazy Groebner driver ###############
  217. Comment
  218. The lazy groebner driver implements the lazy strategy for local
  219. standard bases, i.e. stepwise reduction of S-Polynomials according to
  220. a refinement of the (ascending) division order on leading terms.
  221. end Comment;
  222. symbolic procedure groeb_lazystbasis(bas,comp_mgb,comp_ch,comp_syz);
  223. groeb!=choose_driver(bas,comp_mgb,comp_ch,comp_syz,
  224. function groeb!=lazydriver);
  225. symbolic procedure groeb!=lazymocompare(a,b);
  226. % A dpoly with leading monomial a should be processed before dpolys
  227. % with leading monomial b.
  228. mo_ecart a < mo_ecart b;
  229. symbolic procedure groeb!=queuesort(a,b);
  230. % Sort criterion for the queue.
  231. groeb!=lazymocompare(dp_lmon bas_dpoly a,dp_lmon bas_dpoly b);
  232. symbolic procedure groeb!=nextspol(pl,queue);
  233. % True <=> take first pl next.
  234. if null queue then t
  235. else if null pl then nil
  236. else groeb!=lazymocompare(nth(car pl,3),dp_lmon bas_dpoly car queue);
  237. symbolic procedure groeb!=lazydriver(r,c,gb,comp_syz);
  238. % The lazy version of the driver.
  239. begin scalar syz, Ccrit, queue, v, simp, p, pl, pol, return_by_unit;
  240. simp:=sort(listminimize(gb,function red!=cancelsimp),
  241. function red_better);
  242. Ccrit:=(not comp_syz) and (c<2); % don't reduce main syzygies
  243. pl:=groeb_makepairlist(gb,Ccrit);
  244. if cali_trace() > 30 then groeb_printpairlist pl;
  245. if cali_trace() > 5 then
  246. <<terpri(); write" New base elements :";terpri() >>;
  247. % -------- working out pair list
  248. while (pl or queue) and not return_by_unit do
  249. if groeb!=nextspol(pl,queue) then
  250. << p:=car pl; pl:=cdr pl;
  251. if cali_trace() > 10 then groeb_printpair(p,pl);
  252. pol:=groeb_spol p;
  253. if bas_dpoly pol then % back into the queue
  254. if Ccrit and dp_unit!? bas_dpoly pol then
  255. return_by_unit:=t
  256. else queue:=merge(list pol, queue,
  257. function groeb!=queuesort)
  258. else if comp_syz then % pol reduced to zero.
  259. syz:=bas_simpelement bas_make(0,bas_rep pol).syz;
  260. >>
  261. else
  262. << pol:=car queue; queue:=cdr queue;
  263. % Try one top reduction step
  264. if (v:=red_divtestBE(simp,dp_lmon bas_dpoly pol,
  265. bas_dpecart pol)) then ()
  266. % do nothing with simp !
  267. else if (v:=red_divtest(simp,dp_lmon bas_dpoly pol)) then
  268. simp:=red_update(simp,pol);
  269. % else v:=nil;
  270. if v then % do one top reduction step
  271. << pol:=red_subst(pol,v);
  272. if bas_dpoly pol then % back into the queue
  273. queue:=merge(list pol, queue,
  274. function groeb!=queuesort)
  275. else if comp_syz then % pol reduced to zero.
  276. syz:=bas_simpelement bas_make(0,bas_rep pol).syz;
  277. >>
  278. else % no reduction possible
  279. << % make a tail reduction with bounded ecart and the
  280. % usual postprocessing :
  281. pol:=groeb!=postprocess
  282. if !*red_total then
  283. red_TailRedDriver(gb,pol,function red_TopRedBE)
  284. else pol;
  285. if dp_unit!? bas_dpoly pol then return_by_unit:=t
  286. else % update the computation
  287. << r:=r+1; pol:=bas_newnumber(r,pol);
  288. if cali_trace() > 20 then
  289. << terpri(); write r,". --> "; dp_print2 bas_dpoly pol>>;
  290. pl:=groeb_updatePL(pl,gb,pol,Ccrit);
  291. simp:=red_update(simp,pol);
  292. gb:=pol.gb;
  293. >>
  294. >>
  295. >>;
  296. % -------- updating the result
  297. if cali_trace()>0 then
  298. << terpri(); write " Simplifier list has length ",length simp >>;
  299. if return_by_unit then return {dpmat_from_dpoly pol,nil,nil}
  300. else return
  301. {dpmat_make(length simp,c,simp,cali!=degrees,t), syz, nil}
  302. end;
  303. % ################ The Groebner Tools ##############
  304. % ---------- Critical pair criteria -----------------------
  305. symbolic procedure groeb!=critA(p);
  306. % p is a pair list {(i.k):i running} of pairs with equal module
  307. % component number. Choose those pairs among them that are minimal wrt.
  308. % division order on lcm(i.k).
  309. listminimize(p,function groeb!=testA);
  310. symbolic procedure groeb!=testA(p,q); mo_divides!?(nth(p,3),nth(q,3));
  311. symbolic procedure groeb!=critB(e,p);
  312. % Delete pairs from p, for which testB is false.
  313. for each x in p join if not groeb!=testB(e,x) then {x};
  314. symbolic procedure groeb!=testB(e,a);
  315. % e=lt(f_k). Test, whether for a=pair (i j)
  316. % komp(a)=komp(e) and Syz(i,j,k)=[ 1 * * ].
  317. (mo_comp e=car a)
  318. and mo_divides!?(e,nth(a,3))
  319. and (not mo_equal!?(mo_lcm(dp_lmon bas_dpoly nth(a,5),e),
  320. nth(a,3)))
  321. and (not mo_equal!?(mo_lcm(dp_lmon bas_dpoly nth(a,4),e),
  322. nth(a,3)));
  323. symbolic procedure groeb!=critC(p);
  324. % Delete main syzygies.
  325. for each x in p join if not groeb!=testC1 x then {x};
  326. symbolic procedure groeb!=testC1 el;
  327. mo_equal!?(
  328. mo_sum(dp_lmon bas_dpoly nth(el,5),
  329. dp_lmon bas_dpoly nth(el,4)),
  330. nth(el,3));
  331. symbolic procedure groeb_updatePL(p,gb,be,Ccrit);
  332. % Update the pairlist p with the new base element be and the old ones
  333. % in the base list gb. Discard pairs where both base elements have
  334. % number part 0.
  335. begin scalar p1,k,a,n; n:=(bas_nr be neq 0);
  336. a:=dp_lmon bas_dpoly be; k:=mo_comp a;
  337. for each b in gb do
  338. if (k=mo_comp dp_lmon bas_dpoly b)
  339. and(n or (bas_nr b neq 0)) then
  340. p1:=groeb!=newpair(k,b,be).p1;
  341. p1:=groeb!=critA(sort(p1,function groeb!=better));
  342. if Ccrit then p1:=groeb!=critC p1;
  343. return
  344. merge(p1,
  345. groeb!=critB(a,p), function groeb!=better);
  346. end;
  347. symbolic procedure groeb_makepairlist(gb,Ccrit);
  348. begin scalar newgb,p;
  349. while gb do
  350. << p:=groeb_updatePL(p,newgb,car gb,Ccrit);
  351. newgb:=car gb . newgb; gb:=cdr gb
  352. >>;
  353. return p;
  354. end;
  355. % -------------- Pair Management --------------------
  356. symbolic procedure groeb!=i p; bas_nr nth(p,4);
  357. symbolic procedure groeb!=j p; bas_nr nth(p,5);
  358. symbolic procedure groeb!=better(a,b);
  359. % True if the Spair a is better than the Spair b.
  360. if (cadr a < cadr b) then t
  361. else if (cadr a = cadr b) then mo_compare(nth(a,3),nth(b,3))<=0
  362. else nil;
  363. symbolic procedure groeb!=weight(lcm,p1,p2);
  364. mo_ecart(lcm) + min2(bas_dpecart p1,bas_dpecart p2);
  365. symbolic procedure groeb!=newpair(k,p1,p2);
  366. % Make an spair from base elements with common component number k.
  367. list(k,groeb!=weight(lcm,p1,p2),lcm, p1,p2)
  368. where lcm =mo_lcm(dp_lmon bas_dpoly p1,dp_lmon bas_dpoly p2);
  369. symbolic procedure groeb_printpairlist p;
  370. begin
  371. for each x in p do
  372. << write groeb!=i x,".",groeb!=j x; print_lf " | " >>;
  373. terpri();
  374. end;
  375. symbolic procedure groeb_printpair(pp,p);
  376. begin terpri();
  377. write"Investigate (",groeb!=i pp,".",groeb!=j pp,") ",
  378. "Pair list has length ",length p; terpri()
  379. end;
  380. % ------------- S-polynomial constructions -----------------
  381. symbolic procedure groeb_spol pp;
  382. % Make an S-polynomial from the spair pp, i.e. return
  383. % a base element with
  384. % dpoly = ( zi*mi*(red) pi - zj*mj*(red) pj )
  385. % rep = (zi*mi*rep_i - zj*mj*rep_j),
  386. %
  387. % where mi=lcm/lm(pi), mj=lcm/lm(pj)
  388. % and zi and zj are appropriate scalars.
  389. %
  390. begin scalar pi,pj,ri,rj,zi,zj,lcm,mi,mj,a,b;
  391. a:=nth(pp,4); b:=nth(pp,5); lcm:=nth(pp,3);
  392. pi:=bas_dpoly a; pj:=bas_dpoly b; ri:=bas_rep a; rj:=bas_rep b;
  393. mi:=mo_diff(lcm,dp_lmon pi); mj:=mo_diff(lcm,dp_lmon pj);
  394. zi:=dp_lc pj; zj:=bc_neg dp_lc pi;
  395. a:=dp_sum(dp_times_bcmo(zi,mi, cdr pi),
  396. dp_times_bcmo(zj,mj, cdr pj));
  397. b:=dp_sum(dp_times_bcmo(zi,mi, ri),
  398. dp_times_bcmo(zj,mj, rj));
  399. a:=bas_make1(0,a,b);
  400. if !*bcsimp then a:=car bas_simpelement a;
  401. if cali_trace() > 70 then
  402. << terpri(); write" S.-pol : "; dp_print2 bas_dpoly a >>;
  403. return a;
  404. end;
  405. symbolic procedure groeb_mingb gb;
  406. % Returns the min. Groebner basis dpmat mgb of the dpmat gb
  407. % discarding base elements with bas_nr<=0.
  408. begin scalar u;
  409. u:=for each x in car red_collect dpmat_list gb join
  410. if bas_nr x>0 then {x};
  411. % Choosing base elements with minimal leading terms only.
  412. return dpmat_make(length u,dpmat_cols gb,bas_renumber u,
  413. dpmat_coldegs gb,dpmat_gbtag gb);
  414. end;
  415. % ------- Minimizing a basis using its syszgies ---------
  416. symbolic procedure groeb!=delete(l,bas);
  417. % Delete base elements from the base list bas with number in the
  418. % integer list l.
  419. begin scalar b;
  420. while bas do
  421. << if not memq(bas_nr car bas,l) then b:=car bas . b;
  422. bas:= cdr bas
  423. >>;
  424. return reverse b
  425. end;
  426. symbolic procedure groeb_minimize(bas,syz);
  427. % Minimize the dpmat pair bas,syz deleting superfluous base elements
  428. % from bas using syzygies from syz containing unit entries.
  429. (begin scalar drows, dcols, s,s1,i,j,p,q,y;
  430. cali!=degrees:=dpmat_coldegs syz;
  431. s1:=dpmat_list syz; j:=0;
  432. while j < dpmat_rows syz do
  433. << j:=j+1;
  434. if (q:=bas_dpoly bas_getelement(j,s1)) then
  435. << i:=0;
  436. while leq(i,dpmat_cols syz) and
  437. (memq(i,dcols) or not dp_unit!?(p:=dp_comp(i,q)))
  438. do i:=i+1;
  439. if leq(i,dpmat_cols syz) then
  440. << drows:=j . drows;
  441. dcols:=i . dcols;
  442. s1:=for each x in s1 collect
  443. if memq(bas_nr x,drows) then x
  444. else (bas_make(bas_nr x,
  445. dp_diff(dp_prod(y,p),dp_prod(q,dp_comp(i,y))))
  446. where y:=bas_dpoly x);
  447. >>
  448. >>
  449. >>;
  450. % --- s1 becomes the new syzygy part, s the new base part.
  451. s1:=bas_renumber bas_simp groeb!=delete(drows,s1);
  452. s1:=dpmat_make(length s1,dpmat_cols syz,s1,cali!=degrees,nil);
  453. % The new syzygy matrix of the old basis.
  454. s:=dpmat_renumber
  455. dpmat_make(dpmat_rows bas,dpmat_cols bas,
  456. groeb!=delete(dcols,dpmat_list bas),
  457. dpmat_coldegs bas,nil);
  458. s1:=dpmat_mult(s1,dpmat_transpose cdr s);
  459. % The new syzygy matrix of the new basis, but not yet in the
  460. % right form since cali!=degrees is empty.
  461. s:=car s; % The new basis.
  462. cali!=degrees:=dpmat_rowdegrees s;
  463. s1:=interreduce!* dpmat_make(dpmat_rows s1,dpmat_cols s1,
  464. bas_neworder dpmat_list s1,cali!=degrees,nil);
  465. return s.s1;
  466. end) where cali!=degrees:=cali!=degrees;
  467. % ------ Computing standard bases via homogenization ----------------
  468. symbolic procedure groeb_homstbasis(m,comp_mgb,comp_ch,comp_syz);
  469. (begin scalar v,c,u;
  470. c:=cali!=basering; v:=list gensym();
  471. if not(comp_ch or comp_syz) then cali!=monset:=append(v,cali!=monset);
  472. setring!* ring_sum(c,ring_define(v,nil,'lex,'(1)));
  473. cali!=degrees:=mo_degneworder dpmat_coldegs m;
  474. if cali_trace()>0 then print" Homogenize input ";
  475. u:=(groeb_stbasis(mathomogenize!*(m,car v),
  476. comp_mgb,comp_ch,comp_syz) where !*noetherian=t);
  477. if cali_trace()>0 then print" Dehomogenize output ";
  478. u:=for each x in u collect if x then matdehomogenize!*(x,car v);
  479. setring!* c; cali!=degrees:=dpmat_coldegs m;
  480. return {if first u then dpmat_neworder(first u,t),
  481. if second u then dpmat_neworder(second u,nil),
  482. if third u then dpmat_neworder(third u,nil)};
  483. end) where cali!=basering:=cali!=basering,
  484. cali!=monset:=cali!=monset,
  485. cali!=degrees:=cali!=degrees;
  486. % Two special versions for standard basis computations, not included
  487. % in full generality into the algebraic interface.
  488. symbolic operator homstbasis;
  489. symbolic procedure homstbasis m;
  490. if !*mode='algebraic then dpmat_2a homstbasis!* dpmat_from_a m
  491. else homstbasis!* m;
  492. symbolic procedure homstbasis!* m;
  493. groeb_mingb car groeb_homstbasis(m,t,nil,nil);
  494. symbolic operator lazystbasis;
  495. symbolic procedure lazystbasis m;
  496. if !*mode='algebraic then dpmat_2a lazystbasis!* dpmat_from_a m
  497. else lazystbasis!* m;
  498. symbolic procedure lazystbasis!* m;
  499. car groeb_lazystbasis(m,t,nil,nil);
  500. endmodule; % groeb
  501. end;