xgroeb.red 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. module xgroeb;
  2. % GB calculation
  3. % Authors: David Hartley and Philip A Tuckey
  4. fluid '(!*xfullreduce !*trxideal !*twosided !*trxmod
  5. xpolylist!* xvarlist!* zerodivs!* xtruncate!*
  6. xdegreelist!*);
  7. global '(dimex!*);
  8. put('xideal,'rtypefn,'quotelist);
  9. put('xideal,'listfn,'xideallist);
  10. symbolic procedure xideallist(u,v);
  11. % u:list of prefix,v:bool -> xideallist:prefix
  12. % Syntax is xideal({poly,...} [,{var,...}] [,degree])
  13. begin scalar x,y;
  14. xtruncate!* := nil; % don't truncate GB
  15. if atom u
  16. then rerror(xideal,0,"Wrong number of arguments to xideal");
  17. if eqcar(x := aeval car u,'list) then
  18. <<x := cdr x;
  19. u := cdr u>>
  20. else typerr(car u,'list);
  21. if u and eqcar(y := reval car u,'list) then
  22. <<xvars y; % partition variables
  23. u := cdr u>>;
  24. if u then
  25. if fixp(y := reval car u) then
  26. <<xtruncate!* := y; % truncation degree
  27. u := cdr u>>
  28. else typerr(y,"truncation degree");
  29. if u then rerror(xideal,0,"Wrong number of arguments to xideal");
  30. x := xidealpf for each f in x join if f := xpartitop f then {f};
  31. return makelist for each g in x collect !*q2a1(!*pf2sq repartit g,v);
  32. end;
  33. symbolic procedure xidealpf p;
  34. % p:list of pf -> xidealpf:list of pf
  35. xideal0 storexvars p
  36. where xvarlist!* = {}, xdegreelist!* = {};
  37. symbolic procedure storexvars p;
  38. % p:list of pf -> storexvars:list of pf
  39. % Result is identical to input. Side-effects are to store all pform
  40. % variables in xvarlist!*, all zero divisors in zerodivs!*, and check
  41. % whether input is homogeneous in degree or in conflict with dimex!*.
  42. begin
  43. xvarlist!* := nil;
  44. foreach f in p do % collect all variables present in p
  45. <<if xtruncate!* and not xhomogeneous f then
  46. <<lprim "inhomogeneous input - truncation not possible";
  47. xtruncate!* := nil>>;
  48. xvarlist!* := union(allxvars f,xvarlist!*)>>;
  49. xvarlist!* := sort(xvarlist!*,'worderp);
  50. xdegreelist!*
  51. := (1 . 0) . foreach k in xvarlist!* collect k . xdegree k;
  52. zerodivs!*:= foreach v in xvarlist!* join if oddp xdegree v then {v};
  53. if fixp dimex!* and dimex!* < foreach v in xvarlist!* sum xdegree v
  54. then rerror(xideal,0,
  55. "too many independent p-forms in XIDEAL (check SPACEDIM)");
  56. return p;
  57. end;
  58. symbolic procedure allxvars f;
  59. % f:pf -> allxvars:list of <kernel>
  60. if null f or lpow f = 1 then nil
  61. else append(wedgefax lpow f,allxvars red f);
  62. symbolic procedure xideal0 F;
  63. % F:list of pf -> xideal0:list of pf
  64. % GB algorithm
  65. begin scalar G,F0,P;
  66. if !*trxideal then xprint_basis("Input Basis",F);
  67. if !*xfullreduce then F := weak_xautoreduce1(F,{});
  68. if !*trxideal and not xequiv(F,xpolylist!*) then
  69. xprint_basis("New Basis",F);
  70. P := critical_pairs(F,{},empty_xset());
  71. while not empty_xsetp P do
  72. begin scalar cp,k;
  73. cp := remove_least_item P;
  74. if !*trxideal then xprint_pair cp;
  75. if not xriterion_1(cp,F,P) and not xriterion_2(cp,zerodivs!*,P)
  76. then if k := weak_xreduce(critical_element cp,F) then
  77. if lpow k = 1 then % quick exit for trivial ideal
  78. <<P := empty_xset();
  79. F := {xregister(!*k2pf 1,cp)}>>
  80. else
  81. <<k := xregister(xnormalise k,cp);
  82. G := if !*xfullreduce then weak_xautoreduce1({k},F)
  83. else k . F;
  84. F0 := intersection(F,G);
  85. P := remove_critical_pairs(setdiff(F,F0),P);
  86. if !*trxideal and not xequiv(G,xpolylist!*) then
  87. xprint_basis("New Basis",G);
  88. P := critical_pairs(setdiff(G,F0),F0,P);
  89. F := G>>
  90. else if !*trxideal and not !*trxmod then writepri(0,'last);
  91. end;
  92. return if !*xfullreduce then xautoreduce1 F
  93. else reversip sort(F,'pfordp);
  94. end;
  95. symbolic procedure xriterion_1(cp,G,P);
  96. if null G then nil
  97. else if pr_type cp neq 'spoly_pair then nil
  98. else x neq pr_lhs cp
  99. and x neq pr_rhs cp
  100. and xdiv(xval x,xkey cp)
  101. and (null pr or not find_item(pr,P)
  102. where pr = make_spoly_pair(x,pr_lhs cp))
  103. and (null pr or not find_item(pr,P)
  104. where pr = make_spoly_pair(x,pr_rhs cp))
  105. and <<if !*trxideal then writepri("criterion 1 hit",'last); t>>
  106. or xriterion_1(cp,cdr G,P) where x = car G;
  107. symbolic procedure xriterion_2(cp,G,P);
  108. % G = zerodivs!* at the start
  109. % I don't believe this ever returns t for our case
  110. if null G then nil
  111. else if pr_type cp neq 'wedge_pair then nil
  112. else !*k2pf x neq pr_lhs cp
  113. and xdiv({x,x},xkey cp)
  114. and (null pr or not find_item(pr,P)
  115. where pr = make_wedge_pair(x,pr_rhs cp))
  116. and <<if !*trxideal then writepri("criterion 2 hit",'last); t>>
  117. or xriterion_2(cp,cdr G,P) where x = car G;
  118. % The remaining procedure are for tracing and debugging
  119. symbolic procedure xequiv(F,G);
  120. % F,G:list of pf -> xequiv:bool
  121. % true if F and G have equal contents, possibly reordered
  122. length F = length G and sublistp(F,G);
  123. symbolic procedure xregister(k,pr);
  124. % k:pf, pr:crit_pr -> xregister:pf
  125. % returns k unchanged
  126. % xpolylist!* updated as side-effect
  127. begin
  128. eval {mkid('xregister_,pr_type pr)};
  129. if !*trxideal then
  130. <<xpolylist!* := append(xpolylist!*,{k});
  131. writepri(mkquote{'equal,{'xpoly,xpolyindex k},
  132. preppf k},'last)>>;
  133. return k;
  134. end;
  135. symbolic procedure xregister_spoly_pair; nil; % Just for counting calls.
  136. symbolic procedure xregister_wedge_pair; nil;
  137. symbolic procedure xregister_xcomm_pair; nil;
  138. symbolic procedure xprint_basis(s,p);
  139. % s:string, p:list of pf -> xprint_basis:nil
  140. % Prints heading s, followed by basis p.
  141. % xpolylist!* updated as a side-effect. Used for tracing.
  142. begin
  143. xpolylist!* := p;
  144. writepri(s,'only);
  145. foreach f in p do
  146. mathprint {'equal,{'xpoly,xpolyindex f},preppf f};
  147. end;
  148. symbolic procedure xpolyindex x;
  149. length(x member reverse xpolylist!*);
  150. symbolic procedure xprint_pair cp;
  151. begin
  152. writepri(mkquote pr_type cp,'first);
  153. if pr_type cp = 'spoly_pair then
  154. writepri(mkquote makelist {xpolyindex pr_lhs cp,
  155. xpolyindex pr_rhs cp},
  156. nil)
  157. else if pr_type cp = 'wedge_pair then
  158. writepri(mkquote makelist {lpow pr_lhs cp,
  159. xpolyindex pr_rhs cp},
  160. nil)
  161. else
  162. writepri(mkquote makelist {lpow pr_lhs cp,
  163. xpolyindex pr_rhs cp},
  164. nil);
  165. writepri(" -> ",nil);
  166. end;
  167. endmodule;
  168. end;