groebnr2.red 90 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830
  1. module groebnr2; % Part 2 of the Groebner package.
  2. imports groebner,vdp2dip;
  3. create!-package('(groebnr2 groebman glexconv groebres groebmes
  4. groebrst groebtra groeweak hilberts hilbertp),
  5. '(contrib groebner));
  6. % Other packages needed.
  7. load!-package 'groebner;
  8. endmodule;
  9. module groebman; % Operators for manipulation of bases and
  10. % polynomials in Groebner style.
  11. fluid '(!*factor !*complex !*exp); % standard REDUCE switch
  12. fluid '( % switches from the user interface
  13. !*groebopt !*groebfac !*groebres !*trgroeb !*trgroebs !*groebrm
  14. !*trgroeb1 !*trgroebr !*groebprereduce groebrestriction!*
  15. !*fullreduction !*groebstat !*groebprot !*gltbasis
  16. !*groebsubs
  17. !*vdpinteger !*vdpmodular % indicating type of algorithm
  18. vdpsortmode!* % term ordering mode
  19. secondvalue!* thirdvalue!* % auxiliary: multiple return values
  20. fourthvalue!*
  21. factortime!* % computing time spent in factoring
  22. factorlvevel!* % bookkeeping of factor tree
  23. pairsdone!* % list of pairs already calculated
  24. probcount!* % counting subproblems
  25. vbccurrentmode!* % current domain for base coeffs.
  26. vbcmodule!* % for modular calculation: current prime
  27. );
  28. global '(groebrestriction % interface: name of function
  29. groebresmax % maximum number of internal results
  30. gvarslast % output: variable list
  31. groebprotfile
  32. gltb
  33. );
  34. flag ('(groebrestriction groebresmax gvarslast groebprotfile
  35. gltb),'share);
  36. % variables for counting and numbering
  37. fluid '(hcount!* pcount!* mcount!* fcount!* bcount!* b4count!*
  38. basecount!* hzerocount!*);
  39. % control of the polynomial arithmetic actually loaded
  40. fluid '(currentvdpmodule!*);
  41. symbolic procedure gsorteval pars;
  42. % reformat a polynomial or a list of polynomials by a distributive
  43. % ordering; a list will be sorted and zeros are elimiated
  44. begin scalar vars,u,v,w,oldorder,nolist,!*factor,!*exp;
  45. integer n,pcount!*; !*exp := t;
  46. n := length pars;
  47. u := reval car pars;
  48. v := if n>1 then reval cadr pars else nil;
  49. if not eqcar(u,'list) then
  50. <<nolist := t; u := list('list,u)>>;
  51. w := for each j in groerevlist u
  52. collect if eqexpr j then !*eqn2a j else j;
  53. vars :=
  54. if null v then
  55. for each j in gvarlis w collect !*a2k j
  56. else groerevlist v;
  57. if not vars then vdperr 'gsort;
  58. oldorder := vdpinit vars;
  59. w := for each j in w collect a2vdp j;
  60. w := vdplsort w;
  61. w := for each x in w collect vdp2a x;
  62. while member(0,w) do w := delete(0,w);
  63. setkorder oldorder;
  64. return if nolist and w then car w else 'list . w;
  65. end;
  66. put('gsort,'psopfn,'gsorteval);
  67. symbolic procedure gspliteval pars;
  68. % split a polynomial into leading monomial and reductum;
  69. begin scalar vars,x,u,v,w,oldorder,!*factor,!*exp;
  70. integer n,pcount!*; !*exp := t;
  71. n := length pars;
  72. u := reval car pars;
  73. v := if n>1 then reval cadr pars else nil;
  74. u := list('list,u);
  75. w := for each j in groerevlist u
  76. collect if eqexpr j then !*eqn2a j else j;
  77. vars :=
  78. if null v then
  79. for each j in gvarlis w collect !*a2k j
  80. else groerevlist v;
  81. if not vars then vdperr 'gsplit;
  82. oldorder := vdpinit vars;
  83. w := a2vdp car w;
  84. if vdpzero!? w then x := w else
  85. <<x := vdpfmon(vdplbc w,vdpevlmon w);
  86. w := vdpred w>>;
  87. w := list('list,vdp2a x,vdp2a w);
  88. setkorder oldorder;
  89. return w;
  90. end;
  91. put('gsplit,'psopfn,'gspliteval);
  92. symbolic procedure gspolyeval pars;
  93. % calculate the S Polynomial from two given polynomials
  94. begin scalar vars,u,u1,u2,v,w,oldorder,!*factor,
  95. !*exp;
  96. integer n,pcount!*; !*exp := t;
  97. n := length pars;
  98. if n<2 or n#>3 then
  99. rerror(groebnr2,1,"GSpoly, illegal number or parameters");
  100. u1:= car pars; u2:= cadr pars;
  101. u := list('list,u1,u2);
  102. v := if n>2 then groerevlist caddr pars else nil;
  103. w := for each j in groerevlist u
  104. collect if eqexpr j then !*eqn2a j else j;
  105. vars := if null v then
  106. for each j in gvarlis w collect !*a2k j
  107. else v;
  108. if not vars then vdperr 'gspoly;
  109. oldorder := vdpinit vars;
  110. w := for each j in w collect a2vdp j;
  111. w := vdp2a groebspolynom3 (car w,cadr w);
  112. setkorder oldorder;
  113. return w;
  114. end;
  115. put('gspoly,'psopfn,'gspolyeval);
  116. symbolic procedure gvarseval u;
  117. % u is a list of polynomials; gvars extracts the variables from u
  118. begin integer n; scalar v,!*factor,!*exp; !*exp := t;
  119. n := length u;
  120. v := for each j in groerevlist reval car u collect
  121. if eqexpr j then !*eqn2a j else j;
  122. v := for each j in gvarlis v collect !*a2k j;
  123. v := if n= 2 then
  124. intersection (v,groerevlist reval cadr u) else v;
  125. return 'list . v
  126. end;
  127. put('gvars,'psopfn,'gvarseval);
  128. symbolic procedure greduceeval pars;
  129. % Polynomial reduction modulo a Groebner basis driver. u is an
  130. % expression and v a list of expressions. Greduce calculates the
  131. % polynomial u reduced wrt the list of expressions v reduced to a
  132. % groebner basis modulo using the optional caddr argument as the
  133. % order of variables.
  134. % 1 expression to be reduced
  135. % 2 polynomials or equations; base for reduction
  136. % 3 optional: list of variables
  137. begin scalar vars,x,u,v,w,np,oldorder,!*factor,!*groebfac,!*exp;
  138. integer n,pcount!*; !*exp := t;
  139. if !*groebprot then groebprotfile := list 'list;
  140. n := length pars;
  141. x := reval car pars;
  142. u := reval cadr pars;
  143. v := if n>2 then reval caddr pars else nil;
  144. w := for each j in groerevlist u
  145. collect if eqexpr j then !*eqn2a j else j;
  146. if null w then rerror(groebnr2,2,"Empty list in Greduce");
  147. vars :=
  148. if null v then
  149. for each j in gvarlis w collect !*a2k j
  150. else groerevlist v;
  151. if not vars then vdperr 'greduce;
  152. oldorder := vdpinit vars;
  153. groedomainmode();
  154. % cancel common denominators
  155. w := for each j in w collect reorder numr simp j;
  156. % optimize varable sequence if desired
  157. if !*groebopt then<< w:=vdpvordopt (w,vars); vars := cdr w;
  158. w := car w; vdpinit vars>>;
  159. w := for each j in w collect f2vdp j;
  160. if !*groebprot then w := for each j in w collect vdpenumerate j;
  161. if not !*vdpinteger then
  162. <<np := t;
  163. for each p in w do
  164. np := if np then vdpcoeffcientsfromdomain!? p
  165. else nil;
  166. if not np then <<!*vdpmodular:= nil; !*vdpinteger := t>>;
  167. >>;
  168. w := groebner2(w,nil);
  169. x := a2vdp x;
  170. if !*groebprot then
  171. <<w := for each j in w collect vdpenumerate j;
  172. groebprotsetq('candidate,vdp2a x);
  173. for each j in w do groebprotsetq(mkid('poly,vdpnumber j),
  174. vdp2a j)>>;
  175. w := car w;
  176. !*vdpinteger := nil;
  177. w := groebnormalform(x , w, 'sort);
  178. w := vdp2a w;
  179. setkorder oldorder;
  180. gvarslast := 'list . vars;
  181. return if w then w else 0;
  182. end;
  183. put('greduce,'psopfn,'greduceeval);
  184. % preduceeval moved to groesolv.red
  185. put('preduce,'psopfn,'preduceeval);
  186. endmodule;
  187. module glexconv; % Newbase-Algorithm:
  188. % Faugere, Gianni, Lazard, Mora
  189. fluid '(!*factor !*complex !*exp !*gcd !*ezgcd); % REDUCE switch
  190. fluid '( % switches from the user interface
  191. !*groebopt !*groebfac !*groebres !*trgroeb !*trgroebs !*groebrm
  192. !*trgroeb1 !*trgroebr !*groebprereduce groebrestriction!*
  193. !*fullreduction !*groebstat !*groebprot !*gltbasis
  194. !*groebsubs
  195. !*vdpinteger !*vdpmodular % indicating type of algorithm
  196. vdpsortmode!* % term ordering mode
  197. secondvalue!* thirdvalue!* % auxiliary: multiple return values
  198. fourthvalue!*
  199. factortime!* % computing time spent in factoring
  200. factorlvevel!* % bookkeeping of factor tree
  201. pairsdone!* % list of pairs already calculated
  202. probcount!* % counting subproblems
  203. vbccurrentmode!* % current domain for base coeffs.
  204. vbcmodule!* % for modular calculation: current prime
  205. glexdomain!* % information wrt current domain
  206. );
  207. global '(groebrestriction % interface: name of function
  208. groebresmax % maximum number of internal results
  209. gvarslast % output: variable list
  210. groebprotfile
  211. gltb
  212. );
  213. flag ('(groebrestriction groebresmax gvarslast groebprotfile
  214. gltb),'share);
  215. switch groebopt,groebfac,groebres,trgroeb,trgroebs,trgroeb1,
  216. trgroebr,onlyheadtermreduction,groebprereduce,groebstat,
  217. gcheckpoint,gcdrart,gltbasis,groebsubs;
  218. % variables for counting and numbering
  219. fluid '(hcount!* pcount!* mcount!* fcount!* bcount!* b4count!*
  220. basecount!* hzerocount!*);
  221. % control of the polynomial arithmetic actually loaded
  222. fluid '(currentvdpmodule!*);
  223. fluid '(glexmat!*); % matrix for the indirect lex ordering
  224. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  225. %
  226. % interface functions
  227. % parameters;
  228. % glexconvert(basis,[vars],[maxdeg=n],[newvars={x,y,..}])
  229. symbolic procedure glexconverteval u;
  230. begin integer n; scalar !*groebfac,!*groebrm,!*factor,
  231. v, bas,vars,maxdeg,newvars,!*exp; !*exp := t;
  232. u := for each p in u collect reval p;
  233. bas := car u ; u := cdr u;
  234. while u do
  235. << v := car u; u := cdr u;
  236. if eqcar(v,'list) and null vars then vars := v
  237. else if eqcar(v,'equal) then
  238. if(v := cdr v)and eqcar(v,'maxdeg) then maxdeg := cadr v
  239. else if eqcar(v,'newvars) then newvars := cadr v
  240. else <<prin2 (car v);
  241. rerror(groebnr2,4,"Glexconvert, keyword unknown")>>
  242. else rerror(groebnr2,5,
  243. "Glexconvert, too many positional parameters")>>;
  244. return glexbase1(bas,vars,maxdeg,newvars);
  245. end;
  246. put('glexconvert,'psopfn,'glexconverteval);
  247. symbolic procedure glexbase1(u,v,maxdeg,nv);
  248. begin scalar vars,w,np,oldorder,!*gcd,!*ezgcd;
  249. integer pcount!*;
  250. !*gcd := t;
  251. w := for each j in groerevlist u
  252. collect if eqexpr j then !*eqn2a j else j;
  253. if null w then rerror(groebnr2,6,"Empty list in Groebner");
  254. vars := groebnervars(w,v);
  255. !*vdpinteger := !*vdpmodular := nil;
  256. if not flagp(dmode!*,'field) then !*vdpinteger := t
  257. else
  258. if !*modular then !*vdpmodular := t;
  259. if null vars then vdperr 'groebner;
  260. oldorder := vdpinit vars;
  261. % cancel common denominators
  262. w := for each j in w collect reorder numr simp j;
  263. % optimize varable sequence if desired
  264. w := for each j in w collect f2vdp j;
  265. if not !*vdpinteger then
  266. np := t;
  267. for each p in w do
  268. np := np and vdpcoeffcientsfromdomain!? p;
  269. if not np then <<!*vdpmodular:= nil;
  270. !*vdpinteger := t;
  271. glexdomain!* := 1>>;
  272. if glexdomain!*=1 and not !*vdpmodular then !*ezgcd:=t;
  273. if null maxdeg then maxdeg := 200;
  274. if nv then nv := groerevlist nv;
  275. if null nv then nv := vars else
  276. for each x in nv do if not member(x,vars) then
  277. <<rerror(groebnr2,7,list("new variable ",x,
  278. " is not a basis variable"))>>;
  279. u := for each v in nv collect a2vdp v;
  280. gbtest w;
  281. w := glexbase2(w,u,maxdeg);
  282. w := 'list . for each j in w collect prepf j;
  283. setkorder oldorder;
  284. gvarslast := 'list . vars;
  285. return w;
  286. end;
  287. fluid '(glexeqsys!* glexvars!* glexcount!* glexsub!*);
  288. symbolic procedure glexbase2(oldbase,vars,maxdeg);
  289. % in contrast to documented algorithm monbase ist a list of
  290. % triplets (mon.cof.vec)
  291. % such that cof * mon == vec modulo oldbase
  292. % (cof is needed because of the integer algoritm)
  293. begin scalar lexbase, staircase, monbase;
  294. scalar monom, listofnexts, vect,q,glexeqsys!*,glexvars!*,
  295. glexsub!*;
  296. integer n;
  297. if not groezerodim!?(oldbase,length vars) then
  298. prin2t "####### warning: ideal is not zerodimensional ######";
  299. % prepare matrix for the indirect lex ordering
  300. glexmat!* := for each u in vars collect vdpevlmon u;
  301. monbase := staircase := lexbase := nil;
  302. monom := a2vdp 1;
  303. listofnexts := nil;
  304. while not(monom = nil) do
  305. <<
  306. if not glexmultipletest(monom,staircase) then
  307. << vect := glexnormalform(monom,oldbase);
  308. q := glexlinrel(monom,vect,monbase);
  309. if q then
  310. <<lexbase := q . lexbase; maxdeg := nil;
  311. staircase := monom . staircase;
  312. >>
  313. else
  314. <<monbase := glexaddtomonbase(monom,vect,monbase);
  315. n := n #+1;
  316. if maxdeg and n#> maxdeg then
  317. rerror(groebnr2,8,
  318. "No univar. polynomial within degree bound");
  319. listofnexts :=
  320. glexinsernexts(monom,listofnexts,vars)>>;
  321. >>;
  322. if null listofnexts then monom := nil
  323. else << monom := car listofnexts ;
  324. listofnexts := cdr listofnexts >>;
  325. >>;
  326. return lexbase;
  327. end;
  328. symbolic procedure glexinsernexts(monom,l,vars);
  329. begin scalar x;
  330. for each v in vars do
  331. << x := vdpprod(monom,v);
  332. if not vdpmember(x,l) then
  333. <<vdpputprop(x,'factor,monom); vdpputprop(x,'monfac,v);
  334. l := glexinsernexts1(x,l);
  335. >>;
  336. >>;
  337. return l;
  338. end;
  339. symbolic procedure glexmultipletest(monom,staircase);
  340. if null staircase then nil
  341. else if vevmtest!?(vdpevlmon monom, vdpevlmon car staircase)
  342. then t
  343. else glexmultipletest(monom, cdr staircase);
  344. symbolic procedure glexinsernexts1(m,l);
  345. if null l then list m
  346. else if glexcomp(vdpevlmon m,vdpevlmon car l) then m.l
  347. else car l . glexinsernexts1(m,cdr l);
  348. symbolic procedure glexcomp(ev1,ev2);
  349. % true if ev1 is greater than ev2
  350. % we use an indirect ordering here (mapping via newbase variables)
  351. glexcomp0(glexcompmap(ev1,glexmat!*),
  352. glexcompmap(ev2,glexmat!*));
  353. symbolic procedure glexcomp0(ev1,ev2);
  354. if null ev1 then nil
  355. else if null ev2 then glexcomp0(ev1,'(0))
  356. else if (car ev1 #- car ev2) = 0
  357. then glexcomp0(cdr ev1,cdr ev2)
  358. else if car ev1 #< car ev2 then t
  359. else nil;
  360. symbolic procedure glexcompmap (ev,ma);
  361. if null ma then nil
  362. else glexcompmap1(ev,car ma) . glexcompmap(ev,cdr ma);
  363. symbolic procedure glexcompmap1(ev1,ev2);
  364. % the dot product of two vectors
  365. if null ev1 or null ev2 then 0
  366. else (car ev1 #* car ev2) #+ glexcompmap1(cdr ev1,cdr ev2);
  367. symbolic procedure glexaddtomonbase(monom,vect,monbase);
  368. % primary effect: (monom . vect) . monbase
  369. % secondary effect: builds the equation system
  370. begin scalar x;
  371. if null glexeqsys!* then
  372. <<glexeqsys!* := a2vdp 0; glexcount!*:=-1>>;
  373. x := mkid('gunivar,glexcount!*:=glexcount!*+1);
  374. glexeqsys!* := vdpsum(glexeqsys!*,vdpprod(a2vdp x,cdr vect));
  375. glexsub!* := (x .(monom . vect)) . glexsub!*;
  376. glexvars!* := x . glexvars!*;
  377. return (monom . vect) . monbase;
  378. end;
  379. symbolic procedure glexlinrelold(monom,vect,monbase);
  380. if monbase then
  381. begin scalar sys,sub,auxvars,r,v,x;
  382. integer n;
  383. v := cdr vect;
  384. for each b in reverse monbase do
  385. <<x := mkid('gunivar,n); n := n+1;
  386. v := vdpsum(v,vdpprod(a2vdp x,cddr b));
  387. sub := (x . b) . sub;
  388. auxvars := x . auxvars>>;
  389. while not vdpzero!? v do
  390. <<sys := vdp2f vdpfmon(vdplbc v,nil) . sys; v := vdpred v>>;
  391. x := sys;
  392. sys := groelinsolve(sys,auxvars);
  393. if null sys then return nil;
  394. % construct the lex polynomial
  395. if !*trgroeb
  396. then prin2t " ======= constructing new basis polynomial";
  397. r := vdp2f vdpprod(monom,car vect) ./ 1;
  398. for each s in sub do
  399. r:= addsq(r,multsq(vdp2f vdpprod(cadr s,caddr s) ./ 1,
  400. cdr assoc(car s,sys)));
  401. r := vdp2f vdpsimpcont f2vdp numr r;
  402. return r;
  403. end;
  404. symbolic procedure glexlinrel(monom,vect,monbase);
  405. if monbase then
  406. begin scalar sys,r,v,x;
  407. v := vdpsum(cdr vect,glexeqsys!*);
  408. while not vdpzero!? v do
  409. <<sys := vdp2f vdpfmon(vdplbc v,nil) . sys; v := vdpred v>>;
  410. x := sys;
  411. sys := groelinsolve(sys,glexvars!*);
  412. if null sys then return nil;
  413. % construct the lex polynomial
  414. r := vdp2f vdpprod(monom,car vect) ./ 1;
  415. for each s in glexsub!* do
  416. r:= addsq(r,multsq(vdp2f vdpprod(cadr s,caddr s) ./ 1,
  417. cdr assoc(car s,sys)));
  418. r := vdp2f vdpsimpcont f2vdp numr r;
  419. return r;
  420. end;
  421. symbolic procedure glexnormalform(m,g);
  422. % reduce m wrt basis G;
  423. % the reduction product is preserved in m for later usage
  424. begin scalar cof,vec,r,f,fac1;
  425. if !*trgroeb then prin2t " ======= reducing ";
  426. fac1 := vdpgetprop(m,'factor);
  427. if fac1 then vec := vdpgetprop(fac1,'vector);
  428. if vec then
  429. << f := vdpprod(cdr vec,vdpgetprop(m,'monfac));
  430. cof := car vec>>
  431. else
  432. << f := m; cof := a2vdp 1>>;
  433. r := glexnormalform1(f,g,cof);
  434. vdpputprop(m,'vector,r);
  435. if !*trgroeb then
  436. <<vdpprint vdpprod(car r,m); prin2t " =====> ";
  437. vdpprint cdr r>>;
  438. return r;
  439. end;
  440. symbolic procedure glexnormalform1(f,g,cof);
  441. begin scalar f1,c,vev,divisor,done,fold,a,b;
  442. integer n;
  443. fold := f; f1 := vdpzero(); a:= a2vdp 1;
  444. while not vdpzero!? f do
  445. begin
  446. vev:=vdpevlmon f; c:=vdplbc f;
  447. divisor := groebsearchinlist (vev,g);
  448. if divisor then done := t;
  449. if divisor then
  450. if !*vdpinteger then
  451. << f:=groebreduceonestepint(f,a,c,vev,divisor);
  452. b := secondvalue!*;
  453. cof := vdpprod(b,cof);
  454. if not vdpzero!? f1 then
  455. f1 := vdpprod(b,f1);
  456. >>
  457. else
  458. f := groebreduceonesteprat(f,nil,c,vev,divisor)
  459. else
  460. <<f1 := vdpappendmon (f1,vdplbc f,vdpevlmon f);
  461. f := vdpred f;
  462. >>;
  463. end;
  464. if not done then return cof . fold;
  465. f := groebsimpcont2(f1,cof); cof := secondvalue!*;
  466. return cof . f;
  467. end;
  468. symbolic procedure groelinsolve(equations,xvars);
  469. (begin scalar r,q,test,oldmod,oldmodulus;
  470. if !*trgroeb then prin2t " ======= testing linear dependency ";
  471. r := t;
  472. if not !*modular and glexdomain!*=1 then
  473. <<oldmod := dmode!*;
  474. if oldmod then setdmode(get(oldmod,'dname),nil);
  475. oldmodulus := current!-modulus;
  476. setmod list 16381; % = 2**14-3
  477. setdmode('modular,t);
  478. r := groelinsolve1(for each u in equations collect
  479. numr simp prepf u, xvars);
  480. setdmode('modular,nil);
  481. setmod list oldmodulus;
  482. if oldmod then setdmode(get(oldmod,'dname),t);
  483. >> where !*ezgcd=nil;
  484. if null r then return nil;
  485. r := groelinsolve1(equations,xvars);
  486. if null r then return nil;
  487. % divide out the common content
  488. for each s in r do
  489. if not(denr cdr s = 1) then test := t;
  490. if test then return r;
  491. q := numr cdr car r;
  492. % for each s in cdr r do
  493. % if q neq 1 then
  494. % q := gcdf!*(q,numr cdr s);
  495. % if q=1 then return r;
  496. % r := for each s in r collect
  497. % car s . (quotf(numr cdr s, q) ./ 1);
  498. return r;
  499. end) where !*ezgcd=!*ezgcd; % stack old value
  500. symbolic procedure groelinsolve1(equations,xvars);
  501. % Gaussian elimination in integer mode
  502. % free of unexact divisions (see Davenport et al,CA, pp86-87
  503. % special cases: trivial equations are ruled out early
  504. % INPUT:
  505. % equations: list of standard forms
  506. % xvars: variables for the solution
  507. % OUTPUT:
  508. % list of pairs (var . solu) where solu is a standard quotient
  509. %
  510. % internal data structure: standard forms as polynomials in xvars
  511. begin scalar oldorder,x,p,solutions,val,later,break,gc,field;
  512. oldorder := setkorder xvars;
  513. field := dmode!* and flagp(dmode!*,'field);
  514. equations := for each eqa in equations collect reorder eqa;
  515. for each eqa in equations do
  516. if eqa and domainp eqa then break:= t;
  517. if break then goto empty;
  518. equations := sort(equations,function grloelinord);
  519. again:
  520. break := nil;
  521. for each eqa in equations do if not break then
  522. % car step: eliminate equations of type 23 = 0
  523. % and 17 * u = 0
  524. % and 17 * u + 22 = 0;
  525. << if null eqa then equations := delete(eqa,equations)
  526. else if domainp eqa then break := t % inconsistent system
  527. else if not member(mvar eqa,xvars) then break := t
  528. else if domainp red eqa or not member(mvar red eqa,xvars) then
  529. <<equations := delete (eqa,equations);
  530. x := mvar eqa;
  531. val := if lc eqa = 1 then negf red eqa ./ 1
  532. else multsq(negf red eqa ./ 1, 1 ./lc eqa);
  533. solutions := (x . val) . solutions;
  534. equations := for each q in equations collect
  535. groelinsub(q,list(x.val));
  536. later :=
  537. for each q in later collect groelinsub(q,list(x.val));
  538. break := 0;
  539. >>;
  540. >>;
  541. if break = 0 then goto again else if break then goto empty;
  542. % perform an elimination loop
  543. if null equations then goto ready;
  544. equations := sort(equations,function grloelinord);
  545. p := car equations; x := mvar p;
  546. equations := for each eqa in cdr equations collect
  547. if mvar eqa = x then
  548. << if field then
  549. eqa := addf(eqa, negf multf(quotf(lc eqa,lc p),p))
  550. else
  551. <<gc := gcdf(lc p,lc eqa);
  552. eqa := addf(multf(quotf(lc p,gc),eqa),
  553. negf multf(quotf(lc eqa,gc),p))>>;
  554. if not domainp eqa then
  555. eqa := numr multsq(eqa ./ 1, 1 ./ lc eqa);
  556. %%%%%%eqa := groelinscont(eqa,xvars);
  557. eqa>>
  558. else eqa;
  559. later := p . later;
  560. goto again;
  561. ready: % do backsubstitutions
  562. while later do
  563. <<p := car later; later := cdr later;
  564. p := groelinsub(p,solutions);
  565. if domainp p or not member(mvar p,xvars) or
  566. (not domainp red p and member(mvar red p,xvars)) then
  567. <<break := t; later := nil>>;
  568. x := mvar p;
  569. val := if lc p = 1 then negf red p ./ 1
  570. else quotsq(negf red p ./ 1 , lc p ./ 1);
  571. solutions := (x . val) . solutions;
  572. >>;
  573. if break then goto empty else goto finis;
  574. empty: solutions := nil;
  575. finis: setkorder oldorder;
  576. solutions := for each s in solutions collect
  577. car s . (reorder numr cdr s ./ reorder denr cdr s);
  578. return solutions;
  579. end;
  580. symbolic procedure grloelinord(u,v);
  581. % apply ordop to the mainvars of u and v
  582. ordop(mvar u, mvar v);
  583. symbolic procedure groelinscont(f,vars);
  584. % reduce content from standard form f
  585. if domainp f then f else
  586. begin scalar c;
  587. c := groelinscont1(lc f,red f,vars);
  588. if c=1 then return f;
  589. prin2 "*************content: ";print c;
  590. return quotf(f,c);
  591. end;
  592. symbolic procedure groelinscont1(q,f,vars);
  593. % calculate the contents of standard form f
  594. if null f or q=1 then q
  595. else if domainp f or not member(mvar f,vars) then gcdf!*(q,f)
  596. else groelinscont1(gcdf!*(q,lc f),red f,vars);
  597. symbolic procedure groelinsub(s,a);
  598. % s is a standard form linear in the top level variables
  599. % a is an assiciation list (variable . sq) . ...
  600. % The value is the standard form, where all substitutions
  601. % from a are done in s (common denominator ignored).
  602. numr groelinsub1(s,a);
  603. symbolic procedure groelinsub1(s,a);
  604. if domainp s then s ./ 1
  605. else (if x then addsq(multsq(cdr x,lc s ./ 1),y)
  606. else addsq(lt s .+ nil ./ 1,y))
  607. where x=assoc(mvar s,a),y=groelinsub1(red s,a);
  608. endmodule;
  609. module groebres;
  610. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  611. %
  612. % optimization of h-Polynomials by resultant calculation and
  613. % factorization
  614. %
  615. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  616. fluid '(!*trgroeb );
  617. % the resultant is calculated from a h-polynomial and its predecessor
  618. % if both are bivariate in the same variables and if these variables
  619. % are the last ones in vdpvars*.
  620. expr procedure groebtestresultant(h1,h2,lv);
  621. begin scalar v1,hlist;
  622. v1 := indexcpl(vevsum0(lv,h1),1);
  623. if groebrescheck!?(2,v1,lv)
  624. and indexcpl(vevsum0(lv,h2),1)=v1
  625. then hlist :=
  626. reverse vdplsort
  627. groebhlistfromresultant
  628. (h1,h2,cadr reverse vdpvars!*)
  629. else
  630. if groebrescheck1!?(2,v1,lv)
  631. and indexcpl(vevsum0(lv,h2),1)=v1
  632. then hlist :=
  633. reverse vdplsort
  634. groebhlistfromresultant
  635. (h1,h2,caddr reverse vdpvars!*);
  636. if null hlist then return nil;
  637. return 'resultant .
  638. for each x in hlist collect list(h2,vdpenumerate x);
  639. end;
  640. expr procedure groebhlistfromresultant(h1,h0,x);
  641. % new h-polynomial calculation: calculate
  642. % the resultant of the two distributive polynomials h1 and h0
  643. % with respect to x.
  644. begin scalar ct00,hh,hh1,hs2;
  645. ct00:= time();
  646. hh:= vdpsimpcont groebresultant(h1,h0,x);
  647. if !*trgroeb then <<terpri();
  648. printb 57;
  649. prin2t " *** the resultant from ";
  650. vdpprint h1;
  651. prin2t " *** and";
  652. vdpprint h0;
  653. prin2t " *** is";
  654. vdpprint hh;
  655. printb 57;
  656. terprit 4 >>;
  657. hs2:= nil;
  658. if not vdpzero!? hh then
  659. << hh1:= vdp2a vdprectoint(hh,vdplcm hh);
  660. hh1:= factorf !*q2f simp hh1;
  661. if cdr hh1 and cddr hh1 then
  662. hs2:= for each p in cdr hh1 collect a2vdp prepf car p;
  663. if !*trgroeb and hs2 then
  664. <<prin2 " factorization of resultant successful:";
  665. terprit 2;
  666. for each x in hs2 do vdpprint x;
  667. terprit 2;
  668. ct00:= time() - ct00;
  669. prin2 " time for factorization:"; prin2 ct00;
  670. terpri() >>;
  671. >>;
  672. return hs2
  673. end;
  674. expr procedure groebresultant(p1,p2,x);
  675. begin scalar q1,q2,q;
  676. q1:=vdp2a vdprectoint(p1,vdplcm p1);
  677. q2:=vdp2a vdprectoint(p2,vdplcm p2);
  678. q:=a2vdp prepsq simpresultant list(q1,q2,x);
  679. return q;
  680. end;
  681. expr procedure groebrescheck!?(a,h1,vl);
  682. length h1 = a and car h1 = vl - 1;
  683. expr procedure groebrescheck1!?(a,h1,vl);
  684. length h1 = a and car h1 = vl - 2 and cadr h1 = vl - 1;
  685. endmodule;
  686. module groebmes;
  687. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  688. %
  689. % trace messages for the algorithms
  690. %
  691. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  692. fluid '(vdpvars!* !*trgroeb !*trgroebs !*trgroeb1 !*trgroebr hcount!*
  693. hzerocount!* factorlevel!* basecount!* groetime!* pcount!*);
  694. symbolic procedure groebpairprint (p);
  695. <<groebmessff(" pair(",cadr p,nil);
  696. groebmessff(",",caddr p,nil);
  697. prin2 "), ";
  698. prin2 " lcm = ";print car p;
  699. >>;
  700. symbolic procedure groetimeprint;
  701. << prin2 ">> accum. cpu time:";
  702. prin2 (time() - groetime!*);
  703. prin2t " ms";
  704. >>;
  705. symbolic procedure groebmessff (m1,f,m2);
  706. << prin2 m1; prin2 vdpnumber f; if m2 then prin2t m2 >>;
  707. symbolic procedure groebmess0 (p);
  708. if !*trgroeb then << vdpprint p; >>;
  709. symbolic procedure groebmess1 (g,d);
  710. if !*trgroeb then <<
  711. prin2 " variables: "; print vdpvars!*;
  712. printbl();
  713. prin2t " Start of ITERATION "; terpri (); >>;
  714. symbolic procedure groebmess2 f;
  715. if !*trgroeb then << terpri();
  716. groebmessff ("polynomial ",f," eliminated");
  717. groetimeprint()>>;
  718. symbolic procedure groebmess2a(f,cf,fn);
  719. if !*trgroeb then << terpri();
  720. groebmessff ("polynomial ",f,nil);
  721. groebmessff (" elim. with cofactor ",cf," to");
  722. vdpprint fn; terpri();
  723. groetimeprint()>>;
  724. symbolic procedure groebmess3(p,s);
  725. if !*trgroebs then <<
  726. prin2 "S-polynomial from ";
  727. groebpairprint p;
  728. vdpprint s; terpri();
  729. groetimeprint();
  730. terprit 3 >>;
  731. symbolic procedure groebmess4 (p,d);
  732. << hcount!* := hcount!*+1;
  733. hzerocount!* := hzerocount!*+1;
  734. if !*trgroeb then <<
  735. terpri(); printbl();
  736. groebmessff(" reduction (",cadr p,nil);
  737. groebmessff(",", caddr p,nil);
  738. prin2 ") leads to 0; ";
  739. << prin2 n;
  740. prin2 if n=1 then " pair" else " pairs">>
  741. where n=length d;
  742. prin2t " left";
  743. printbl(); groetimeprint()>>;
  744. >>;
  745. symbolic procedure groebmess41 (p);
  746. << hcount!* := hcount!*+1;
  747. hzerocount!* := hzerocount!*+1;
  748. if !*trgroeb then << terpri(); printbl();
  749. groebmessff(" polynomial(", p,nil);
  750. prin2 ") reduced to 0;";
  751. terpri(); printbl(); groetimeprint()>>;
  752. >>;
  753. symbolic procedure groebmess5(p,h);
  754. if car p then % print for true h-Polys
  755. << hcount!* := hcount!* + 1;
  756. if !*trgroeb then << terpri();
  757. prin2 "H-polynomial ";
  758. prin2 pcount!*;
  759. prin2 " ev:"; prin2 vdpevlmon h;
  760. groebmessff(" from pair (",cadr p,nil);
  761. groebmessff(",", caddr p,")");
  762. vdpprint h; terpri();
  763. groetimeprint() >> >>
  764. else
  765. if !*trgroeb then << % print for input polys
  766. prin2t "from actual problem input:";
  767. vdpprint h;
  768. groetimeprint() >>;
  769. symbolic procedure groebmess50(g);
  770. if !*trgroeb1 then <<
  771. prin2 "list of active polynomials:";
  772. for each d1 in g do
  773. <<prin2 vdpgetprop(d1,'number);
  774. prin2 " ">>;
  775. terprit 2 >>;
  776. symbolic procedure groebmess51(d);
  777. if !*trgroeb1 then <<
  778. prin2t "Candidates for pairs in this step:";
  779. for each d1 in d do groebpairprint (d1);
  780. terprit 2 >>;
  781. symbolic procedure groebmess52(d);
  782. if !*trgroeb1 then <<
  783. prin2t "Actual new pairs from this step:";
  784. for each d1 in d do groebpairprint (d1);
  785. terprit 2 >>;
  786. symbolic procedure groebmess7 h;
  787. if !*trgroebs then
  788. <<prin2t "Testing factorization for "; vdpprint h>>;
  789. symbolic procedure groebmess8 (g,d);
  790. if !*trgroeb1 then <<
  791. prin2t " actual pairs: ";
  792. if null d then prin2t "null"
  793. else for each d1 in d do groebpairprint d1;
  794. groetimeprint() >>
  795. else if !*trgroeb then <<
  796. prin2 n; prin2t if n=1 then " pair" else " pairs" >>
  797. where n=length d;
  798. symbolic procedure groebmess13(g,problems);
  799. if !*trgroeb or !*trgroebr then <<
  800. if g then
  801. <<
  802. basecount!* := basecount!* +1;
  803. printbl(); printbl();
  804. prin2 "end of iteration ";
  805. for each f in reverse factorlevel!* do
  806. <<prin2 f; prin2 ".">>;
  807. prin2 "; basis "; prin2 basecount!*; prin2t ":";
  808. prin2 "{";
  809. for each g1 in g do vdpprin3t g1;
  810. prin2t "}";
  811. printbl(); printbl(); groetimeprint();
  812. >>
  813. else
  814. << printbl();
  815. prin2 "end of iteration branch ";
  816. for each f in reverse factorlevel!* do
  817. <<prin2 f; prin2 ".">>;
  818. prin2t " "; printbl(); groetimeprint();
  819. >>;
  820. if problems and !*trgroeb then
  821. <<
  822. groetimeprint(); terpri(); printbl();
  823. prin2 " number of partial problems still to be solved:";
  824. prin2t length problems;
  825. terpri();
  826. prin2 " preparing next problem ";
  827. if car car problems = 'file then
  828. prin2 cdr car problems
  829. else
  830. if cadddr car problems then
  831. vdpprint car cadddr car problems; % head of list G
  832. terpri();
  833. >> >>;
  834. symbolic procedure groebmess14 (h,hf);
  835. if !*trgroeb then <<
  836. prin2 "******************* factorization of polynomial ";
  837. (if x then prin2t x else terpri() )
  838. where x = vdpnumber(h);
  839. % vdpprint h;
  840. prin2t " factors:";
  841. for each g in hf do vdpprint car g;
  842. groetimeprint();
  843. >>;
  844. symbolic procedure groebmess15 f;
  845. if !*trgroeb then
  846. <<prin2t "***** monomial factor reduced:";
  847. vdpprint vdpfmon(a2vbc 1,f)>>;
  848. symbolic procedure groebmess19(p,restr,u);
  849. if !*trgroeb then <<
  850. printbl();
  851. prin2 "calculation branch ";
  852. for each f in reverse factorlevel!* do
  853. <<prin2 f; prin2 ".">>;
  854. prin2t " cancelled because";
  855. vdpprint p;
  856. prin2t "is member of an actual abort condition";
  857. printbl(); printbl();
  858. >>;
  859. symbolic procedure groebmess19a(p,u);
  860. if !*trgroeb then <<
  861. printbl();
  862. prin2 "during branch preparation ";
  863. for each f in reverse u do
  864. <<prin2 f; prin2 ".">>;
  865. prin2t " cancelled because";
  866. vdpprint p;
  867. prin2t "was found in the ideal branch";
  868. printbl();
  869. >>;
  870. symbolic procedure groebmess20 (p);
  871. if !*trgroeb then <<
  872. terpri();
  873. prin2 "secondary reduction starting with";
  874. vdpprint p>>;
  875. symbolic procedure groebmess21(p1,p2);
  876. if !*trgroeb then <<
  877. prin2 "polynomial ";
  878. prin2 vdpnumber p1;
  879. prin2 " replaced during secondary reduction by ";
  880. vdpprint p2;
  881. >>;
  882. symbolic procedure groebmess22(factl,abort1,abort2);
  883. if null factl then nil
  884. else
  885. if !*trgroeb then
  886. begin integer n;
  887. prin2t "BRANCHING after factorization point";
  888. n := 0;
  889. for each x in reverse factl do
  890. << n := n+1;
  891. prin2 "branch ";
  892. for each f in reverse factorlevel!* do
  893. <<prin2 f;prin2 ".";>>;
  894. prin2t n;
  895. for each y in car x do vdpprint y;
  896. prin2t "simple IGNORE restrictions for this branch:";
  897. for each y in abort1 do vdpprint y;
  898. for each y in cadr x do vdpprint y;
  899. if abort2 or caddr x then
  900. <<prin2t
  901. "set type IGNORE restrictions for this branch:";
  902. for each y in abort2 do vdpprintset y;
  903. for each y in caddr x do vdpprintset y;
  904. >>;
  905. printbl()>>;
  906. end;
  907. symbolic procedure groebmess23 (g0,rest1,rest2);
  908. if !*trgroeb then
  909. if null factorlevel!* then
  910. prin2t "** starting calculation ******************************"
  911. else
  912. << prin2 "** resuming calculation for branch ";
  913. for each f in reverse factorlevel!* do
  914. <<prin2 f; prin2 ".">>;
  915. terpri();
  916. if rest1 or rest2 then
  917. <<
  918. prin2t "-------IGNORE restrictions for this branch:";
  919. for each x in rest1 do vdpprint x;
  920. for each x in rest2 do vdpprintset x;
  921. >>;
  922. >>;
  923. symbolic procedure groebmess24(h,problems1,restr);
  924. % if !*trgroeb then
  925. <<prin2t
  926. "**********polynomial affected by NONNEGATIVE/POSITIVE condition:";
  927. vdpprint h;
  928. if restr then prin2t "under current restrictions";
  929. for each x in restr do vdpprint x;
  930. if null problems1 then prin2t " CANCELLED"
  931. else
  932. <<prin2t "partitioned into";
  933. vdpprintset car problems1;
  934. >>;
  935. >>;
  936. symbolic procedure groebmess25 (h,abort2);
  937. % if !*trgroeb then
  938. <<prin2t "reduction of set type cancel conditions by";
  939. vdpprint h;
  940. prin2t "remaining:";
  941. for each x in abort2 do vdpprintset x;
  942. >>;
  943. symbolic procedure groebmess26 (f1,f2);
  944. if !*trgroebs and not vdpequal(f1,f2) then
  945. <<terpri();
  946. prin2t "during final reduction";
  947. vdpprint f1;
  948. prin2t "reduced to";
  949. vdpprint f2;
  950. terpri();>>;
  951. symbolic procedure groebmess27 r;
  952. if !*trgroeb then
  953. <<terpri();
  954. prin2t "factor ignored (considered already):";
  955. vdpprint r>>;
  956. symbolic procedure groebmess27a (h,r);
  957. if !*trgroeb then
  958. <<terpri();
  959. vdpprint h;
  960. prin2t " reduced to zero by factor";
  961. vdpprint r>>;
  962. symbolic procedure groebmess28 r;
  963. if !*trgroeb then
  964. <<prin2 "interim content reduction:"; print r>>;
  965. symbolic procedure terprit n;
  966. % print blank lines.
  967. for i:=1:n do << terpri() >>;
  968. symbolic procedure printbl(); printb (linelength nil #- 2);
  969. symbolic procedure printb n; <<for i:=1:n do prin2 "-"; terpri()>>;
  970. symbolic procedure vdpprintset l;
  971. % print polynomials in one line;
  972. if l then
  973. << prin2 "{"; vdpprin2 car l;
  974. for each x in cdr l do
  975. <<prin2 "; "; vdpprin2 x>>;
  976. prin2t "}";>>;
  977. symbolic procedure vdpprin2l u;
  978. <<prin2 "("; vdpprin2 car u;
  979. for each x in cdr u do <<prin2 ","; vdpprin2 x;>>;
  980. prin2 ")";>>;
  981. endmodule;
  982. module groebrst;
  983. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  984. %
  985. % restrictions for polynomials during Groebner base calculation
  986. %
  987. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  988. fluid '(groebrestriction!*);
  989. expr procedure groebtestrestriction (h,arg);
  990. if groebrestriction!* = 'nonnegative then groebnonneg(h,arg)
  991. else
  992. if groebrestriction!* = 'positive then groebpos(h,arg)
  993. else
  994. rerror(groebnr2,9,
  995. "Groebner: general restrictions not yet implemented");
  996. expr procedure groebnonneg(h,arg);
  997. % test if h is a polynomial which can have the value zero with
  998. % only nonnegative variable settings.
  999. begin scalar x,break,vev1,vevl,problems,problems1,r;
  1000. if vdpzero!? h then return nil
  1001. else
  1002. if vevzero!? vdpevlmon h then goto finish;
  1003. % car test the coefficients
  1004. if vdpredzero!? h then return nil; % simple monomial
  1005. break := nil;
  1006. x := h;
  1007. while not vdpzero!? x and not break do
  1008. <<vev1 := vdpevlmon x;
  1009. if not vbcplus!? vdplbc x then break := t;
  1010. if not break then x := vdpred x>>;
  1011. if break then return nil; % at least one negative coeff
  1012. if vevzero!? vev1 then goto finish; % nonneg. solution imposs.
  1013. % homogenous polynomial: find combinations of
  1014. % variables which are solutions
  1015. x := h;
  1016. vev1 := vdpevlmon x;
  1017. vevl := vevsplit(vev1);
  1018. problems := for each x in vevl collect list x;
  1019. x := vdpred x;
  1020. while not vdpzero!? x do
  1021. << vev1 := vdpevlmon x;
  1022. vevl := vevsplit(vev1);
  1023. problems1 := nil;
  1024. for each e in vevl do
  1025. for each p in problems do
  1026. <<r := if not member(e,p) then e . p else p;
  1027. problems1 := union(list r, problems1)>>;
  1028. problems := problems1;
  1029. x := vdpred x;
  1030. >>;
  1031. problems := % lift vevs to polynomials
  1032. for each p in problems collect
  1033. for each e in p collect
  1034. vdpfmon(a2vbc 1,e);
  1035. % rule out problems contained in others
  1036. for each x in problems do
  1037. for each y in problems do
  1038. if not eq(x,y) and subset!?(x,y) then
  1039. problems := delete (y,problems);
  1040. % rule out some by cdr
  1041. problems1 := nil;
  1042. while problems do
  1043. <<if vdpdisjoint!? (car problems,arg)
  1044. then problems1 := car problems . problems1;
  1045. problems := cdr problems;
  1046. >>;
  1047. finish:
  1048. groebmess24(h,problems1,arg);
  1049. return
  1050. if null problems1 then 'cancel
  1051. else 'restriction . problems1;
  1052. end;
  1053. expr procedure groebpos(h,dummy);
  1054. % test if h is a polynomial which can have the value zero with
  1055. % only positive (nonnegative and nonzero) variable settings.
  1056. begin scalar x,break,vev1;
  1057. if vdpzero!? h then return nil
  1058. else
  1059. if vevzero!? vdpevlmon h then return nil;
  1060. % a simple monomial can never have pos. zeros
  1061. if vdpredzero!? h then return groebposcancel(h);
  1062. break := nil;
  1063. x := h;
  1064. % test coefficients
  1065. while not vdpzero!? x and not break do
  1066. <<vev1 := vdpevlmon x;
  1067. if not vbcplus!? vdplbc x then break := t;
  1068. if not break then x := vdpred x>>;
  1069. if not break then return groebposcancel(h);
  1070. if not groebposvevaluate h then groebposcancel(h);
  1071. return nil;
  1072. end;
  1073. expr procedure groebposvevaluate h; t;
  1074. % test if a polynomial can become zero under user restrictions
  1075. % here a dummy to be rplaced elsewhere
  1076. expr procedure groebposcancel(h);
  1077. << groebmess24(h,nil,nil); 'cancel>>;
  1078. endmodule;
  1079. module groebtra;
  1080. % calculation of a Groebner base with the Buchberger algorithm
  1081. % including the backtracking information which denotes the
  1082. % dependency between base and input polynomials
  1083. % Authors: H. Melenk, H.M. Moeller, W. Neun
  1084. % November 1988
  1085. fluid '( % switches from the user interface
  1086. !*groebopt !*groebfac !*groebres !*trgroeb !*trgroebs !*groebrm
  1087. !*trgroeb1 !*trgroebr !*groebprereduce groebrestriction!*
  1088. !*onlyheadtermreduction !*groebstat !*groebdivide !*groebprot
  1089. vdpvars!* % external names of the variables
  1090. !*vdpinteger !*vdpmodular % indicating type of algorithm
  1091. vdpsortmode!* % term ordering mode
  1092. secondvalue!* thirdvalue!* % auxiliary: multiple return values
  1093. fourthvalue!*
  1094. factortime!* % computing time spent in factoring
  1095. factorlvevel!* % bookkeeping of factor tree
  1096. pairsdone!* % list of pairs already calculated
  1097. probcount!* % counting subproblems
  1098. vbccurrentmode!* % current domain for base coeffs.
  1099. groetags!* % starting point of tag variables
  1100. groetime!*
  1101. );
  1102. global '(gvarslast);
  1103. switch groebopt,groebfac,groebrm,groebres,trgroeb,trgroebs,trgroeb1,
  1104. trgroebr,onlyheadtermreduction,groebprereduce,groebstat,
  1105. gcheckpoint,gcdrart,groebdivide,groebprot;
  1106. % variables for counting and numbering
  1107. fluid '(hcount!* pcount!* mcount!* fcount!* bcount!* b4count!*
  1108. basecount!* hzerocount!*);
  1109. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1110. % Interface
  1111. symbolic procedure groebnertraeval u;
  1112. % backtracking Groebner calculation
  1113. begin integer n; scalar !*groebfac,!*groebrm,!*groebprot;
  1114. n := length u;
  1115. if n=1 then return groebnertra1(reval car u,nil,nil)
  1116. else if n neq 2
  1117. then rerror(groebnr2,10,
  1118. "GROEBNERT called with wrong number of arguments")
  1119. else return groebnertra1(reval car u,reval cadr u,nil)
  1120. end;
  1121. put('groebnert,'psopfn,'groebnertraeval);
  1122. smacro procedure vdpnumber f;
  1123. vdpgetprop(f,'number) ;
  1124. symbolic procedure groebnertra1(u,v,mod);
  1125. % Buchberger algorithm system driver. u is a list of expressions
  1126. % and v a list of variables or NIL in which case the variables in u
  1127. % are used.
  1128. begin scalar vars,w,y,z,x,np,oldorder,groetags!*,tagvars;
  1129. integer pcount!*,nmod;
  1130. u := for each j in getrlist u
  1131. collect
  1132. <<if not eqcar(j,'equal) then 0 . j else
  1133. if not idp cadr j then
  1134. rerror(groebnr2,11,
  1135. "GROEBNERT parameter 1 not in form {id = polynomial,...}")
  1136. else cadr j . caddr j>>;
  1137. if null u then rerror(groebnr2,12,"Empty list in Groebner")
  1138. else if null cdr u then
  1139. return 'list . list('equal,cdar u,caar u);;
  1140. w := for each x in u collect cdr x;
  1141. if mod then
  1142. <<z := nil;
  1143. for each vect in w do
  1144. <<if not eqcar(vect,'list) then
  1145. rerror(groebnr2,13,"Non list given to GROEBNER");
  1146. if nmod=0 then nmod:= length cdr vect else
  1147. if nmod<(x:=length cdr vect) then nmod=x;
  1148. z := append(cdr vect,z);
  1149. >>;
  1150. if not eqcar(mod,'list) then
  1151. rerror(groebnr2,14,"Illegal column weights specified");
  1152. vars := groebnervars(z,v);
  1153. tagvars := for i:=1:nmod collect mkid('! col,i);
  1154. w := for each vect in w collect
  1155. <<z:=tagvars; y := cdr mod;
  1156. 'plus . for each p in cdr vect collect
  1157. 'times . list('expt,car z,car y) .
  1158. <<z := cdr z; y := cdr y;
  1159. if null y then y := '(1); list p>>
  1160. >>;
  1161. groetags!* := length vars + 1;
  1162. vars := append(vars,tagvars);
  1163. >>
  1164. else vars := groebnervars(w,v);
  1165. groedomainmode();
  1166. if null vars then vdperr 'groebner;
  1167. oldorder := vdpinit vars;
  1168. % cancel common denominators
  1169. u := pair(for each x in u collect car x,w);
  1170. u := for each x in u collect
  1171. <<z := simp cdr x;
  1172. multsq(simp car x,denr z ./ 1) . reorder numr z>>;
  1173. w := for each j in u collect cdr j;
  1174. % optimize varable sequence if desired
  1175. if !*groebopt then<< w:=vdpvordopt (w,vars); vars := cdr w;
  1176. w := car w; vdpinit vars>>;
  1177. w := pair (for each x in u collect car x,w);
  1178. w := for each j in w collect
  1179. <<z := f2vdp cdr j; vdpputprop(z,'cofact,car j)>>;
  1180. if not !*vdpinteger then
  1181. <<np := t;
  1182. for each p in w do
  1183. np := if np then vdpcoeffcientsfromdomain!? p else nil;
  1184. if not np then <<!*vdpmodular:= nil; !*vdpinteger := t>>;
  1185. >>;
  1186. w := groebtra2 w;
  1187. w := if mod then groebnermodres(w,nmod,tagvars) else
  1188. groebnertrares w;
  1189. setkorder oldorder;
  1190. gvarslast := 'list . vars;
  1191. return w;
  1192. end;
  1193. symbolic procedure groebnertrares w;
  1194. begin scalar c,u;
  1195. return
  1196. 'list . for each j in w collect
  1197. <<c := prepsq vdpgetprop(j,'cofact);
  1198. u := vdp2a j;
  1199. if c=0 then u else list('equal,u,c)
  1200. >>;
  1201. end;
  1202. symbolic procedure groebnermodres(w,n,tagvars);
  1203. begin scalar x,c,oldorder;
  1204. c := for each u in w collect prepsq vdpgetprop(u,'cofact);
  1205. oldorder := setkorder tagvars;
  1206. w := for each u in w collect
  1207. 'list .
  1208. <<u := numr simp vdp2a u;
  1209. for i := 1:n collect
  1210. prepf
  1211. if not domainp u and mvar u = nth(tagvars,i)
  1212. then <<x := lc u; u := red u; x>> else nil
  1213. >>;
  1214. setkorder oldorder;
  1215. % reestablish term order for output
  1216. w := for each u in w collect vdp2a a2vdp u;
  1217. w := pair(w,c);
  1218. return 'list .
  1219. for each p in w collect
  1220. if cdr p=0 then car p else
  1221. list('equal,car p,cdr p);
  1222. end;
  1223. symbolic procedure preduceteval pars;
  1224. % trace version of PREDUCE
  1225. % parameters:
  1226. % 1 expression to be reduced
  1227. % formula or equation
  1228. % 2 polynomials or equations; base for reduction
  1229. % must be equations with atomic lhs
  1230. % 3 optional: list of variables
  1231. begin scalar vars,x,y,u,v,w,z,oldorder,!*factor,!*exp;
  1232. integer n,pcount!*; !*exp := t;
  1233. pars := groeparams(pars,2,3);
  1234. y := car pars; u := cadr pars; v:= caddr pars;
  1235. u := for each j in getrlist u
  1236. collect
  1237. <<if not eqcar(j,'equal) then
  1238. j . j else cadr j . caddr j>>;
  1239. if null u then rerror(groebnr2,15,"Empty list in PREDUCET");
  1240. w := for each p in u collect cdr p; % the polynomials
  1241. groedomainmode();
  1242. vars :=
  1243. if null v then
  1244. for each j in gvarlis w collect !*a2k j
  1245. else getrlist v;
  1246. if not vars then vdperr 'preducet;
  1247. oldorder := vdpinit vars;
  1248. u := for each x in u collect
  1249. <<z := simp cdr x;
  1250. multsq(simp car x,denr z ./ 1) . reorder numr z>>;
  1251. w := for each j in u collect
  1252. <<z := f2vdp cdr j; vdpputprop(z,'cofact,car j)>>;
  1253. if not eqcar(y,'equal) then y := list('equal,y,y);
  1254. x := a2vdp caddr y; % the expression
  1255. vdpputprop(x,'cofact,simp cadr y); % the lhs (name etc.)
  1256. w := tranormalform(x,w, 'sort,'f);
  1257. u := list('equal,vdp2a w,prepsq vdpgetprop(w,'cofact));
  1258. setkorder oldorder;
  1259. return u;
  1260. end;
  1261. put('preducet,'psopfn,'preduceteval);
  1262. symbolic procedure groebnermodeval u;
  1263. % Groebner for moduli calculation
  1264. (if n=0 or n>3 then
  1265. rerror(groebnr2,16,
  1266. "GROEBNERM called with wrong number of arguments")
  1267. else
  1268. groebnertra1(reval car u,
  1269. if n>=2 then reval cadr u else nil,
  1270. if n>=3 then reval caddr u else '(list 1))
  1271. ) where n = length u;
  1272. put('groebnerm,'psopfn,'groebnermodeval);
  1273. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1274. % some macros for local usage only
  1275. smacro procedure tt(s1,s2);
  1276. % lcm of leading terms of s1 and s2
  1277. vevlcm(vdpevlmon s1,vdpevlmon s2);
  1278. symbolic procedure groebtra2 (p);
  1279. % setup all global variables for the Buchberger algorithm
  1280. % printing of statistics
  1281. begin scalar groetime!*,tim1,spac,spac1,p1,factortime!*,
  1282. pairsdone!*,factorlvevel!*;
  1283. factortime!* := 0;
  1284. groetime!* := time();
  1285. vdponepol(); % we construct dynamically
  1286. hcount!* := pcount!* := mcount!* := fcount!* :=
  1287. bcount!* := b4count!* := hzerocount!* := basecount!* := 0;
  1288. if !*trgroeb then
  1289. <<
  1290. prin2 "Groebner Calculation with Backtracking starts ";
  1291. terprit 2;
  1292. >>;
  1293. spac := gctime();
  1294. p1:= groebtra3 (p);
  1295. if !*trgroeb or !*trgroebr or !*groebstat then
  1296. <<
  1297. spac1 := gctime() - spac;
  1298. terpri();
  1299. prin2t "statistics for Groebner calculation";
  1300. prin2t "===================================";
  1301. prin2 " total computing time (including gc): ";
  1302. prin2((tim1 := time()) - groetime!*);
  1303. prin2t " milliseconds ";
  1304. prin2 " (time spent for garbage collection: ";
  1305. prin2 spac1;
  1306. prin2t " milliseconds)";
  1307. terprit 1;
  1308. prin2 "H-polynomials total: "; prin2t hcount!*;
  1309. prin2 "H-polynomials zero : "; prin2t hzerocount!*;
  1310. prin2 "Crit M hits: "; prin2t mcount!*;
  1311. prin2 "Crit F hits: "; prin2t fcount!*;
  1312. prin2 "Crit B hits: "; prin2t bcount!*;
  1313. prin2 "Crit B4 hits: "; prin2t b4count!*;
  1314. >>;
  1315. return p1;
  1316. end;
  1317. symbolic procedure groebtra3 (g0);
  1318. begin scalar x,g,d,d1,d2,p,p1,s,h,g99,one;
  1319. x := for each fj in g0 collect vdpenumerate trasimpcont fj;
  1320. for each fj in x do g := vdplsortin(fj,g0);
  1321. g0 := g; g := nil;
  1322. % iteration :
  1323. while (d or g0) and not one do
  1324. begin
  1325. if g0 then
  1326. << % take next poly from input
  1327. h := car g0; g0 := cdr g0;
  1328. p := list(nil,h,h);
  1329. >>
  1330. else
  1331. << % take next poly from pairs
  1332. p := car d; d := cdr d;
  1333. s := traspolynom (cadr p, caddr p); tramess3(p,s);
  1334. h := groebnormalform(s,g99,'tree); %piloting wo cofact
  1335. if vdpzero!? h then groebmess4(p,d)
  1336. else h := trasimpcont tranormalform(s,g99,'tree,'h);
  1337. >>;
  1338. if vdpzero!? h then goto bott;
  1339. if vevzero!? vdpevlmon h then % base 1 found
  1340. << tramess5(p,h);
  1341. g0 := d := nil; g:= list h;
  1342. goto bott>>;
  1343. s:= nil;
  1344. % h polynomial is accepted now
  1345. h := vdpenumerate h;
  1346. tramess5(p,h);
  1347. % construct new critical pairs
  1348. d1 := nil;
  1349. for each f in g do
  1350. if groebmoducrit(f,h) then
  1351. <<d1 := groebcplistsortin( list(tt(f,h),f,h) , d1);
  1352. if tt(f,h) = vdpevlmon(f) then
  1353. <<g := delete (f,g); groebmess2 f>>;
  1354. >>;
  1355. groebmess51(d1);
  1356. d2 := nil;
  1357. while d1 do
  1358. <<d1 := groebinvokecritf d1;
  1359. p1 := car d1;
  1360. d1 := cdr d1;
  1361. if groebbuchcrit4(cadr p1,caddr p1,car p1)
  1362. then d2 := append (d2, list p1);
  1363. d1 := groebinvokecritm (p1,d1);
  1364. >>;
  1365. d := groebinvokecritb (h,d);
  1366. d := groebcplistmerge(d,d2);
  1367. g := h . g;
  1368. g99 := groebstreeadd(h, g99);
  1369. groebmess8(g,d);
  1370. bott:
  1371. end; % ITERATION
  1372. return groebtra3post g;
  1373. end;
  1374. symbolic procedure groebtra3post (g);
  1375. % final reduction
  1376. begin scalar r,p;
  1377. g := vdplsort g;
  1378. while g do
  1379. <<p := tranormalform(car g,cdr g,'sort,'f);
  1380. if not vdpzero!? p then r := trasimpcont p . r;
  1381. g := cdr g>>;
  1382. return reversip r;
  1383. end;
  1384. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1385. %
  1386. % Reduction of polynomials
  1387. %
  1388. symbolic procedure tranormalform(f,g,type,mode);
  1389. % general procedure for reduction of one polynomial from a set
  1390. % f is a polynomial, G is a Set of polynomials either in
  1391. % a search tree or in a sorted list
  1392. % type describes the ordering of the set G:
  1393. % 'TREE G is a search tree
  1394. % 'SORT G is a sorted list
  1395. % 'LIST G is a list, but not sorted
  1396. % f has to be reduced modulo G
  1397. % version for idealQuotient: doing side effect calculations for
  1398. % the cofactors; only headterm reduction
  1399. begin scalar c,vev,divisor,break;
  1400. while not vdpzero!? f and not break do
  1401. begin
  1402. vev:=vdpevlmon f; c:=vdplbc f;
  1403. divisor :=
  1404. if type = 'tree then groebsearchinstree (vev,g)
  1405. else groebsearchinlist (vev,g);
  1406. if divisor and !*trgroebs then
  1407. << prin2 "//-";
  1408. prin2 vdpnumber divisor;
  1409. >>;
  1410. if divisor then
  1411. if !*vdpinteger then
  1412. f := trareduceonestepint(f,nil,c,vev,divisor)
  1413. else
  1414. f := trareduceonesteprat(f,nil,c,vev,divisor)
  1415. else
  1416. break := t;
  1417. end;
  1418. if mode = 'f then f := tranormalform1(f,g,type,mode);
  1419. return f;
  1420. end;
  1421. symbolic procedure tranormalform1(f,g,type,mode);
  1422. % reduction of subsequent terms
  1423. begin scalar c,vev,divisor,break,f1;
  1424. f1 := f;
  1425. while not vdpzero!? f and not vdpzero!? f1 do
  1426. <<f1 := f; break := nil;
  1427. while not vdpzero!? f1 and not break do
  1428. <<vev:=vdpevlmon f1; c:=vdplbc f1;
  1429. f1 := vdpred f1;
  1430. divisor :=
  1431. if type = 'tree then groebsearchinstree (vev,g)
  1432. else groebsearchinlist (vev,g);
  1433. if divisor and !*trgroebs then
  1434. << prin2 "//-";
  1435. prin2 vdpnumber divisor;
  1436. >>;
  1437. if divisor then
  1438. << if !*vdpinteger then
  1439. f := trareduceonestepint(f,nil,c,vev,divisor)
  1440. else
  1441. f := trareduceonesteprat(f,nil,c,vev,divisor);
  1442. break := t>>;
  1443. >>;
  1444. >>;
  1445. return f;
  1446. end;
  1447. % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % %
  1448. %
  1449. % special reduction procedures
  1450. symbolic procedure trareduceonestepint(f,dummy,c,vev,g1);
  1451. % reduction step for integer case:
  1452. % calculate f= a*f - b*g a,b such that leading term vanishes
  1453. % (vev of lvbc g divides vev of lvbc f)
  1454. %
  1455. % and calculate f1 = a*f1
  1456. % return value=f, secondvalue=f1
  1457. begin scalar vevlcm,a,b,cg,x,fcofa,gcofa;
  1458. fcofa := vdpgetprop(f,'cofact);
  1459. if null fcofa then fcofa := nil ./ 1;
  1460. gcofa := vdpgetprop(g1,'cofact);
  1461. if null gcofa then gcofa := nil ./ 1;
  1462. vevlcm := vevdif(vev,vdpevlmon g1);
  1463. cg := vdplbc g1;
  1464. % calculate coefficient factors
  1465. x := vbcgcd(c,cg);
  1466. a := vbcquot(cg,x);
  1467. b := vbcquot(c,x);
  1468. f:= vdpilcomb1 (f, a, vevzero(),
  1469. g1,vbcneg b, vevlcm);
  1470. x := vdpilcomb1tra (fcofa, a, vevzero(),
  1471. gcofa ,vbcneg b, vevlcm);
  1472. vdpputprop(f,'cofact,x);
  1473. return f;
  1474. end;
  1475. symbolic procedure trareduceonesteprat(f,dummy,c,vev,g1);
  1476. % reduction step for rational case:
  1477. % calculate f= f - g/vdpLbc(f)
  1478. %
  1479. begin scalar x,fcofa,gcofa,vev;
  1480. fcofa := vdpgetprop(f,'cofact);
  1481. gcofa := vdpgetprop(g1,'cofact);
  1482. vev := vevdif(vev,vdpevlmon g1);
  1483. x := vbcneg vbcquot(c,vdplbc g1);
  1484. f := vdpilcomb1(f,a2vbc 1,vevzero(),
  1485. g1,x,vev);
  1486. x := vdpilcomb1tra (fcofa,a2vbc 1 , vevzero(),
  1487. gcofa,x,vev);
  1488. vdpputprop(f,'cofact,x);
  1489. return f;
  1490. end;
  1491. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1492. %
  1493. % calculation of an S-polynomial
  1494. %
  1495. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1496. symbolic procedure traspolynom (p1,p2);
  1497. begin scalar s,ep1,ep2,ep,rp1,rp2,db1,db2,x,cofac1,cofac2;
  1498. if vdpzero!? p1 then return p1; if vdpzero!? p1 then return p2;
  1499. cofac1 := vdpgetprop(p1,'cofact); cofac2 := vdpgetprop(p2,'cofact);
  1500. ep1 := vdpevlmon p1; ep2 := vdpevlmon p2;
  1501. ep := vevlcm(ep1, ep2);
  1502. rp1 := vdpred p1; rp2 := vdpred p2;
  1503. db1 := vdplbc p1; db2 := vdplbc p2;
  1504. if !*vdpinteger then
  1505. <<x:=vbcgcd(db1,db2); db1:=vbcquot(db1,x); db2:=vbcquot(db2,x)>>;
  1506. ep1 := vevdif(ep,ep1); ep2 := vevdif(ep,ep2); db2 := vbcneg db2;
  1507. s := vdpilcomb1 (rp2,db1,ep2,rp1,db2,ep1);
  1508. x := vdpilcomb1tra (cofac2,db1,ep2,cofac1,db2,ep1);
  1509. vdpputprop(s,'cofact,x);
  1510. return s;
  1511. end;
  1512. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1513. %
  1514. % Normalisation with cofactors taken into account
  1515. %
  1516. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1517. symbolic procedure trasimpcont(p);
  1518. if !*vdpinteger then trasimpconti p else trasimpcontr p;
  1519. % routines for integer coefficient case:
  1520. % calculation of contents and dividing all coefficients by it
  1521. symbolic procedure trasimpconti (p);
  1522. % calculate the contents of p and divide all coefficients by it
  1523. begin scalar res,num,cofac;
  1524. if vdpzero!? p then return p;
  1525. cofac := vdpgetprop(p,'cofact);
  1526. num := car vdpcontenti p;
  1527. if not vbcplus!? num then num := vbcneg num;
  1528. if not vbcplus!? vdplbc p then num:=vbcneg num;
  1529. if vbcone!? num then return p;
  1530. res := vdpreduceconti (p,num,nil);
  1531. cofac:=vdpreducecontitra(cofac,num,nil);
  1532. res := vdpputprop(res,'cofact,cofac);
  1533. return res;
  1534. end;
  1535. % routines for rational coefficient case:
  1536. % calculation of contents and dividing all coefficients by it
  1537. symbolic procedure trasimpcontr (p);
  1538. % calculate the contents of p and divide all coefficients by it
  1539. begin scalar res,cofac;
  1540. cofac := vdpgetprop(p,'cofact);
  1541. if vdpzero!? p then return p;
  1542. if vbcone!? vdplbc p then return p;
  1543. res := vdpreduceconti (p,vdplbc p,nil);
  1544. cofac:=vdpreducecontitra(cofac,vdplbc p,nil);
  1545. res := vdpputprop(res,'cofact,cofac);
  1546. return res;
  1547. end;
  1548. symbolic procedure vdpilcomb1tra (cofac1,db1,ep1,cofac2,db2,ep2);
  1549. % the linear combination, here done for the cofactors
  1550. % (standard quotients)
  1551. addsq(multsq(cofac1,vdp2f vdpfmon(db1,ep1) ./ 1),
  1552. multsq(cofac2,vdp2f vdpfmon(db2,ep2) ./ 1));
  1553. symbolic procedure vdpreducecontitra(cofac,num,dummy);
  1554. % divide the cofactor by a number
  1555. quotsq(cofac,simp vbc2a num);
  1556. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1557. %
  1558. % special handling of moduli
  1559. %
  1560. symbolic procedure groebmoducrit(p1,p2);
  1561. null groetags!*
  1562. or pnth(vdpevlmon p1,groetags!*) = pnth(vdpevlmon p2,groetags!*);
  1563. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1564. %
  1565. % trace messages
  1566. %
  1567. symbolic procedure tramess0 x;
  1568. if !*trgroeb then
  1569. <<prin2t "adding member to intermediate quotient base:";
  1570. vdpprint x;
  1571. terpri()>>;
  1572. symbolic procedure tramess1 (x,p1,p2);
  1573. if !*trgroeb then
  1574. <<prin2 "pair ("; prin2 vdpnumber p1; prin2 ",";
  1575. prin2 vdpnumber p2;
  1576. prin2t ") adding member to intermediate quotient base:";
  1577. vdpprint x;
  1578. terpri()>>;
  1579. symbolic procedure tramess5(p,h);
  1580. if car p then % print for true h-Polys
  1581. << hcount!* := hcount!* + 1;
  1582. if !*trgroeb then <<
  1583. terpri();
  1584. prin2 "H-polynomial ";
  1585. prin2 pcount!*;
  1586. groebmessff(" from pair (",cadr p,nil);
  1587. groebmessff(",", caddr p,")");
  1588. vdpprint h;
  1589. prin2t "with cofactor";
  1590. writepri(mkquote prepsq vdpgetprop(h,'cofact),'only);
  1591. groetimeprint() >> >>
  1592. else
  1593. if !*trgroeb then << % print for input polys
  1594. prin2t "candidate from input:";
  1595. vdpprint h;
  1596. groetimeprint() >>;
  1597. symbolic procedure tramess3(p,s);
  1598. if !*trgroebs then <<
  1599. prin2 "S-polynomial ";
  1600. prin2 " from ";
  1601. groebpairprint p;
  1602. vdpprint s;
  1603. prin2t "with cofactor";
  1604. writepri(mkquote prepsq vdpgetprop(s,'cofact),'only);
  1605. groetimeprint();
  1606. terprit 3 >>;
  1607. endmodule;
  1608. module groeweak; % weak test for f ~ 0 modulo G
  1609. fluid '(!*groebweak current!-modulus pairsdone!* !*vdpinteger
  1610. groebmodular!* !*groebfac);
  1611. switch groebweak;
  1612. symbolic procedure groebweakzerotest(f,g,type);
  1613. % test f==0 modulo G with ON MODULAR
  1614. begin scalar f1,c,vev,divisor,oldmode,a;
  1615. integer n,oldprim;
  1616. if vdpzero!? f then return f;
  1617. if current!-modulus= 1 then setmod list 2097143;
  1618. oldmode := setdmode('modular,t);
  1619. f := groebvdp2mod f;
  1620. f1 := vdpzero(); a:= vbcfi 1;
  1621. while not vdpzero!? f and vdpzero!? f1 do
  1622. begin
  1623. vev:=vdpevlmon f; c:=vdplbc f;
  1624. if type = 'sort then
  1625. while g
  1626. and vevcompless!? (vev,vdpevlmon (car g))
  1627. do g := cdr g;
  1628. divisor :=
  1629. if type = 'tree then groebsearchinstree(vev,g)
  1630. else groebsearchinlist (vev,g);
  1631. if divisor and !*trgroebs then
  1632. << prin2 "//m-";
  1633. prin2 vdpnumber divisor;
  1634. >>;
  1635. if divisor then
  1636. if vdplength divisor = 1 then
  1637. f := vdpcancelmvev(f,vdpevlmon divisor)
  1638. else
  1639. <<divisor := groebvdp2mod(divisor);
  1640. if divisor then f :=
  1641. groebreduceonesteprat(f,nil,c,vev,divisor)
  1642. else f1 := f>>
  1643. else
  1644. f1 := f;
  1645. % ready:
  1646. end;
  1647. if not vdpzero!? f1 and !*trgroebs then
  1648. <<prin2t " - nonzero result in modular reduction:";
  1649. vdpprint f1;
  1650. >>;
  1651. setdmode('modular,nil);
  1652. if oldmode then setdmode(get(oldmode,'dname),t);
  1653. return vdpzero!? f1;
  1654. end;
  1655. smacro procedure tt(s1,s2);
  1656. % lcm of leading terms of s1 and s2
  1657. vevlcm(vdpevlmon s1,vdpevlmon s2);
  1658. symbolic procedure groebweaktestbranch!=1(poly,g,d);
  1659. % test GB(G) == {1} in modular style
  1660. groebweakbasistest(list poly,g,d);
  1661. symbolic procedure groebweakbasistest(g0,g,d);
  1662. begin scalar oldmode,d,d1,d2,p,p1,s,h;
  1663. scalar !*vdpinteger; % switch to field type calclulation
  1664. return nil;
  1665. if not !*groebfac then return nil;
  1666. if current!-modulus= 1 then setmod list 2097143;
  1667. if !*trgroeb then
  1668. prin2t "---------------- modular test of branch ------";
  1669. oldmode := setdmode('modular,t);
  1670. g0 := for each p in g0 collect groebvdp2mod p;
  1671. g := for each p in g collect groebvdp2mod p;
  1672. d := for each p in d collect list (car p,
  1673. groebvdp2mod cadr p, groebvdp2mod caddr p);
  1674. while d or g0 do
  1675. begin
  1676. if g0 then
  1677. << % take next poly from input
  1678. h := car g0; g0 := cdr g0; p := list(nil,h,h);
  1679. >>
  1680. else
  1681. << % take next poly from pairs
  1682. p := car d;
  1683. d := delete (p,d);
  1684. s := groebspolynom (cadr p, caddr p);
  1685. h:=groebsimpcontnormalform groebnormalform(s,g,'sort);
  1686. if vdpzero!? h then !*trgroeb and groebmess4(p,d);
  1687. >>;
  1688. if vdpzero!? h then
  1689. <<pairsdone!* := (vdpnumber cadr p . vdpnumber caddr p)
  1690. . pairsdone!*;
  1691. goto bott>>;
  1692. if vevzero!? vdpevlmon h then % base 1 found
  1693. << !*trgroeb and groebmess5(p,h);
  1694. goto stop>>;
  1695. s:= nil;
  1696. h := vdpenumerate h; !*trgroeb and groebmess5(p,h);
  1697. % construct new critical pairs
  1698. d1 := nil;
  1699. for each f in g do
  1700. <<d1 := groebcplistsortin(list(tt(f,h),f,h),d1);
  1701. if tt(f,h) = vdpevlmon(f) then
  1702. <<g := delete (f,g);
  1703. !*trgroeb and groebmess2 f>>;
  1704. >>;
  1705. !*trgroeb and groebmess51(d1);
  1706. d2 := nil;
  1707. while d1 do
  1708. <<d1 := groebinvokecritf d1;
  1709. p1 := car d1; d1 := cdr d1;
  1710. d2 := groebinvokecritbuch4 (p1,d2);
  1711. d1 := groebinvokecritm (p1,d1);
  1712. >>;
  1713. d := groebinvokecritb (h,d);
  1714. d := groebcplistmerge(d,d2);
  1715. g := h . g;
  1716. goto bott;
  1717. stop: d := g := g0 := nil;
  1718. bott:
  1719. end;
  1720. if !*trgroeb and null g then
  1721. prin2t "**** modular test detects empty branch!";
  1722. if !*trgroeb then
  1723. prin2t "------ end of modular test of branch ------";
  1724. setdmode('modular,nil);
  1725. if oldmode then setdmode(get(oldmode,'dname),t);
  1726. return null g;
  1727. end;
  1728. fluid '(!*localtest);
  1729. symbolic procedure groebfasttest(g0,g,d,g99);
  1730. if !*localtest then
  1731. <<!*localtest := nil;
  1732. groebweakbasistest(g0,g,d)>>
  1733. else if !*groebweak and g and vdpunivariate!? car g
  1734. then groebweakbasistest(g0,g,d);
  1735. symbolic procedure groebvdp2mod f;
  1736. %convert a vdp in modular form
  1737. % in case of headterm loss, nil is returned
  1738. begin scalar u,c,mf;
  1739. u := vdpgetprop(f,'modimage);
  1740. if u then return if u='nasty then nil else u;
  1741. mf := vdpresimp f;
  1742. c := errorset!*(list('vbcinv,mkquote vdplbc mf),nil);
  1743. if not pairp c then
  1744. <<prin2t "************** nasty module (loss of headterm) ****";
  1745. print f; print u; vdpprint f; vdpprint u;
  1746. vdpputprop(f,'modimage,'nasty);
  1747. return nil>>;
  1748. u := vdpvbcprod(mf,car c);
  1749. vdpputprop(u,'number,vdpgetprop(f,'number));
  1750. vdpputprop(f,'modimage,u);
  1751. return u;
  1752. end;
  1753. symbolic procedure groebmodeval(f,break);
  1754. % evaluate LISP form r with REDUCE modular domain
  1755. begin scalar oldmode,a,!*vdpinteger,groebmodular!*;
  1756. groebmodular!* := t;
  1757. if current!-modulus= 1 then setmod list 2097143;
  1758. oldmode := setdmode('modular,t);
  1759. a := errorset!*(f,t);
  1760. setdmode('modular,nil);
  1761. if oldmode then setdmode(get(oldmode,'dname),t);
  1762. return if atom a then nil else car a;
  1763. end;
  1764. endmodule;
  1765. module hilberts; % Hilbert series of a set of Monomials.
  1766. % Author: Joachim Hollman, Royal Institute for Technology,
  1767. % Stockholm, Sweden
  1768. % email: <joachim@nada.kth.se>
  1769. Comment
  1770. --------------------------------------------------------
  1771. A very brief "description" of the method used.
  1772. M=k[x,y,z]/(x^2*y,x*z^2,y^2)
  1773. x.
  1774. 0 --> ker(x.) --> M --> M --> M/x --> 0
  1775. M/x = k[x,y,z]/(x^2*y,x*z^2,y^2,x) = k[x,y,z]/(x,y^2)
  1776. ker(x.) = ((x) + (x^2*y,x*z^2,y^2))/(x^2*y,x*z^2,y^2) =
  1777. = (x,y^2)/(x^2*y,x*z^2,y^2)
  1778. Hilb(ker(x.)) = Hilb - Hilb
  1779. (x,y^2) (x^2*y,x*z^2,y^2)
  1780. = 1/(1-t)^3 - Hilb -
  1781. k[x,y,z]/(x,y^2)
  1782. - (1/(1-t)^3 - Hilb
  1783. k[x,y,z]/(x^2*y,x*z^2,y^2)
  1784. = Hilb -Hilb
  1785. M k[x,y,z]/(x,y^2)
  1786. If you only keep the numerator in Hilb = N(t)/(1-t)^3
  1787. M
  1788. then you get
  1789. (1-t)N (t) = N (t) - t (N (t) - N (t) )
  1790. I I+(x) I Ann(x) + I
  1791. i.e.
  1792. N (t) = N (t) + t N (t) (*)
  1793. I I+(x) Ann(x) + I
  1794. Where
  1795. I = (x^2*y,x*z^2,y^2)
  1796. I + (x) = (x,y^2)
  1797. I + Ann(x) = (x*y,z^2,y^2)
  1798. N (t) is the numerator polynomial in Hilb
  1799. I k[x,y,z]/I
  1800. Equation (*) is what we use to compute the numerator polynomial, i.e.
  1801. we "divide out" one variable at a time until we reach a base case.
  1802. (One is not limited to single variables but I don't know of any good
  1803. strategy for selecting a monomial.)
  1804. Usage: hilb({monomial_1,...,monomial_n} [,variable])
  1805. ;
  1806. fluid '(nvars!*);
  1807. % ************** MACROS ETC. **************
  1808. smacro procedure term(c,v,e);
  1809. list('times,c,list('expt,v,e));
  1810. % -------------- safety check --------------
  1811. smacro procedure var!-p(m);
  1812. and(m,atom(m),not(numberp(m)));
  1813. smacro procedure check!-expt(m);
  1814. and(eqcar(m,'expt),var!-p(cadr(m)),numberp(caddr(m)));
  1815. smacro procedure check!-single!-var(m);
  1816. if var!-p(m) then t
  1817. else check!-expt(m);
  1818. smacro procedure check!-mon(m);
  1819. if check!-single!-var(m) then t
  1820. else if eqcar(m,'times) then check!-times(cdr(m))
  1821. else nil;
  1822. smacro procedure check!-args(monl,var);
  1823. and(listp monl,eqcar(monl,'list),var!-p(var), check!-monl(monl));
  1824. symbolic procedure make!-vector (n,pat);
  1825. begin scalar v;
  1826. v:=mkvect n;
  1827. for i:=1:n do putv(v,i,pat);
  1828. return v;
  1829. end;
  1830. % -------------- monomials --------------
  1831. smacro procedure alloc!-mon(n);
  1832. make!-vector(n,0);
  1833. smacro procedure get!-nth!-exp(mon,n);
  1834. getv(mon,n);
  1835. smacro procedure set!-nth!-exp(mon,n,d);
  1836. putv(mon,n,d);
  1837. smacro procedure get!-tdeg(mon);
  1838. getv(mon,0);
  1839. smacro procedure set!-tdeg(mon,d);
  1840. putv(mon,0,d);
  1841. % -------------- ideals --------------
  1842. smacro procedure the!-empty!-ideal();
  1843. list(nil,nil);
  1844. smacro procedure get!-next!-mon(ideal);
  1845. <<x:=caadr ideal;
  1846. if cdadr ideal then ideal:=list(car ideal,cdadr ideal)
  1847. else ideal:=the!-empty!-ideal();
  1848. x>>;
  1849. smacro procedure not!-empty!-ideal(ideal);
  1850. cadr ideal;
  1851. smacro procedure first!-mon(ideal);
  1852. caadr ideal;
  1853. smacro procedure append!-ideals(ideal1,ideal2);
  1854. list(car ideal2,append(cadr ideal1,cadr ideal2));
  1855. symbolic procedure insert!-var(var,ideal);
  1856. % inserts variable var as last generator of ideal
  1857. begin
  1858. scalar last;
  1859. last:=list(make!-one!-var!-mon(var));
  1860. return(list(last,append(cadr ideal,last)));
  1861. end;
  1862. symbolic procedure add!-to!-ideal(mon,ideal);
  1863. % add mon as generator to the ideal
  1864. begin
  1865. scalar last;
  1866. last := list(mon);
  1867. if ideal = the!-empty!-ideal() then
  1868. rplaca(cdr(ideal),last)
  1869. else
  1870. rplacd(car(ideal),last);
  1871. rplaca(ideal,last);
  1872. end;
  1873. % ************** END OF MACROS ETC. **************
  1874. % ************** INTERFACE TO ALGEBRAIC MODE **************
  1875. symbolic procedure hilbsereval(u);
  1876. begin
  1877. scalar l,monl,var;
  1878. l:=length(u);
  1879. if l < 1 or l > 2 then
  1880. rerror(groebnr2,17,
  1881. "Usage: hilb({monomial_1,...,monomial_n} [,variable])")
  1882. else if l = 1 then
  1883. <<
  1884. monl:= reval car u;
  1885. var:= 'x;
  1886. >>
  1887. else
  1888. <<
  1889. monl:= reval car u;
  1890. var:= reval cadr u;
  1891. >>;
  1892. monl := 'list . for each aa in (cdr monl) collect reval aa;
  1893. if not check!-args(monl,var) then
  1894. rerror(groebnr2,18,
  1895. "Usage: hilb({monomial_1,...,monomial_n} [,variable])");
  1896. % return(aeval
  1897. % list('QUOTIENT,
  1898. % coefflist2prefix(NPol(gltb2arrideal(monl)), var),
  1899. % list('EXPT,list('PLUS,1,list('TIMES,-1,var)),
  1900. % nvars!*)));
  1901. return(aeval
  1902. coefflist2prefix(npol(gltb2arrideal(monl)), var));
  1903. end;
  1904. % define "hilb" to be the algebraic mode function
  1905. put('hilb,'psopfn,'hilbsereval);
  1906. symbolic procedure check!-monl(monl);
  1907. begin
  1908. scalar flag,tmp;
  1909. flag:=t;
  1910. monl:=gltb!-fix(monl);
  1911. while monl and flag do
  1912. <<
  1913. tmp:=car monl;
  1914. flag:=check!-mon(tmp);
  1915. monl:=cdr monl;
  1916. >>;
  1917. return(flag);
  1918. end;
  1919. symbolic procedure check!-times(m);
  1920. begin
  1921. scalar flag,tmp;
  1922. flag:=t;
  1923. while m and flag do
  1924. <<
  1925. tmp:= car m;
  1926. flag:=check!-single!-var(tmp);
  1927. m:=cdr m;
  1928. >>;
  1929. return(flag);
  1930. end;
  1931. symbolic procedure coefflist2prefix(cl,var);
  1932. begin
  1933. scalar i,poly;
  1934. i:=0;
  1935. for each c in cl do
  1936. <<
  1937. poly:= cons(term(c,var,i),poly);
  1938. i:=i+1;
  1939. >>;
  1940. return (cons('plus,poly));
  1941. end;
  1942. symbolic procedure indets(l);
  1943. % "indets" returns a list containing all the
  1944. % indeterminates of l.
  1945. % l is supposed to have a form similar to the variable
  1946. % GLTB in the Groebner basis package.
  1947. % (LIST (EXPT Z 2) (EXPT X 2) Y)
  1948. begin
  1949. scalar varlist;
  1950. for each m in l do
  1951. if m neq 'list then
  1952. if atom(m) then varlist:=union(list(m),varlist)
  1953. else if eqcar(m,'expt)
  1954. then varlist:=union(list(cadr(m)),varlist)
  1955. else varlist:=union(indets(cdr(m)),varlist);
  1956. return(varlist);
  1957. end;
  1958. symbolic procedure build!-assoc(l);
  1959. % Given a list of indeterminates (x1 x2 ...xn) we produce
  1960. % an a-list of the form ((x1.1) (x2.2)... (xn.n))
  1961. begin
  1962. scalar i;
  1963. i:=0;
  1964. return(for each var in l collect progn(i:=i+1,cons(var,i)));
  1965. end;
  1966. symbolic procedure mons(l);
  1967. % rewrite the leading monomials (i.e. GLTB).
  1968. % the result is a list of monomials of the form:
  1969. % (variable . exponent) or ((variable1 . exponent1) ...
  1970. % (variablen . exponentn))
  1971. %
  1972. % mons('(LIST (EXPT Z 2) (EXPT X 2) (TIMES Y (EXPT X 3))));
  1973. % (((Y . 1) (X . 3)) (X . 2) (Z . 2))
  1974. begin
  1975. scalar monlist;
  1976. for each m in l do
  1977. if m neq 'list then monlist:=
  1978. if atom(m) then cons(cons(m,1),monlist)
  1979. else if eqcar(m,'expt)
  1980. then cons(cons(cadr(m),caddr(m)),monlist)
  1981. else (for each x in cdr(m) collect mons!-aux(x)) . monlist;
  1982. return(monlist);
  1983. end;
  1984. symbolic procedure mons!-aux(m);
  1985. if atom(m) then cons(m,1)
  1986. else if eqcar(m,'expt) then cons(cadr(m),caddr(m));
  1987. symbolic procedure lmon2arrmon(m);
  1988. % list-monomial to array-monomial
  1989. % a list-monomial has the form: (variable_number . exponent)
  1990. % or is a list with entries of this form.
  1991. % "variable_number" is the number associated with the variable,
  1992. % see build!-assoc()
  1993. begin
  1994. scalar tdeg,mon;
  1995. mon:=alloc!-mon(nvars!*);
  1996. tdeg:=0;
  1997. if listp m then
  1998. for each varnodotexp in m do
  1999. <<
  2000. set!-nth!-exp(mon,car varnodotexp, cdr varnodotexp);
  2001. tdeg:=tdeg+cdr varnodotexp;
  2002. >>
  2003. else
  2004. <<
  2005. set!-nth!-exp(mon,car m, cdr m);
  2006. tdeg:=tdeg+cdr m;
  2007. >>;
  2008. set!-tdeg(mon,tdeg);
  2009. return(mon);
  2010. end;
  2011. symbolic procedure gltb!-fix(l);
  2012. % sometimes GLTB has the form (list (list...))
  2013. % instead of (list ...)
  2014. if and(listp cadr l,caadr(l) = 'list) then cadr l else l;
  2015. symbolic procedure ge(m1,m2);
  2016. if get!-tdeg(m1) >= get!-tdeg(m2) then t else nil;
  2017. symbolic procedure get!-end!-ptr(l);
  2018. begin
  2019. scalar ptr;
  2020. while l do
  2021. <<
  2022. ptr:=l;
  2023. l:=cdr l;
  2024. >>;
  2025. return(ptr);
  2026. end;
  2027. symbolic procedure gltb2arrideal(xgltb);
  2028. % Convert the monomial ideal given by GLTB (in list form)
  2029. % to a list of vectors where each vector represents a monomial.
  2030. begin
  2031. scalar l;
  2032. l:=indets(gltb!-fix(xgltb));
  2033. nvars!* := length(l);
  2034. l:= sublis(build!-assoc(l),mons(gltb!-fix(xgltb)));
  2035. l:=for each m in l collect lmon2arrmon(m);
  2036. l:=sort(l,'ge);
  2037. return(list(get!-end!-ptr(l),l));
  2038. end;
  2039. % ************** END OF INTERFACE TO ALGEBRAIC MODE **************
  2040. %************** PROCEDURES **************
  2041. symbolic procedure npol(ideal);
  2042. % recursively computes the numerator of the Hilbert series
  2043. begin
  2044. scalar v,si;
  2045. v:=next!-var(ideal);
  2046. if not v then return(base!-case!-pol(ideal));
  2047. si:=split!-ideal(ideal,v);
  2048. return(shift!-add(npol(car si),npol(cadr si)));
  2049. end;
  2050. symbolic procedure divides!-by!-var(var,mon);
  2051. begin
  2052. scalar div;
  2053. if get!-nth!-exp(mon,var) = 0 then return(nil);
  2054. div:=alloc!-mon(nvars!*);
  2055. for i:=1 : nvars!* do set!-nth!-exp(div,i,get!-nth!-exp(mon,i));
  2056. set!-nth!-exp(div,var,get!-nth!-exp(mon,var)-1);
  2057. set!-tdeg(div,get!-tdeg(mon)-1);
  2058. return(div);
  2059. end;
  2060. symbolic procedure divides(m1,m2);
  2061. % does m1 divide m2?
  2062. % m1 and m2 are monomials
  2063. % result: either nil (when m1 does not divide m2) or m2/m1
  2064. begin
  2065. scalar m,d,i;
  2066. i:=1;
  2067. m:=alloc!-mon(nvars!*);
  2068. set!-tdeg(m,d:=get!-tdeg(m2)-get!-tdeg(m1));
  2069. while d >= 0 and i <= nvars!* do
  2070. <<
  2071. set!-nth!-exp(m,i,d:=get!-nth!-exp(m2,i) - get!-nth!-exp(m1,i));
  2072. i:= i+1;
  2073. >>;
  2074. if d < 0 then
  2075. return (nil)
  2076. else
  2077. return(m);
  2078. end;
  2079. symbolic procedure shift!-add(p1,p2);
  2080. % p1+z*p2
  2081. % p1 and p2 are polynomials (nonempty coefficient lists)
  2082. begin
  2083. scalar p,pptr;
  2084. pptr:=p:=cons(car p1,nil);
  2085. p1:=cdr p1;
  2086. while p1 and p2 do
  2087. <<
  2088. rplacd(pptr,cons(car p1 + car p2,nil));
  2089. p1:=cdr p1;
  2090. p2:=cdr p2;
  2091. pptr:=cdr pptr;
  2092. >>;
  2093. if p1 then
  2094. rplacd(pptr,p1)
  2095. else
  2096. rplacd(pptr,p2);
  2097. return(p);
  2098. end;
  2099. symbolic procedure rem!-mult(ipp1,ipp2);
  2100. % the union of two ideals with redundancy of generators eliminated
  2101. begin
  2102. scalar fmon,inew,isearch,primeflag,x;
  2103. % fix; x is used in the macro...
  2104. inew := the!-empty!-ideal();
  2105. while not!-empty!-ideal(ipp1) and not!-empty!-ideal(ipp2) do
  2106. begin
  2107. if get!-tdeg(first!-mon(ipp2)) < get!-tdeg(first!-mon (ipp1))
  2108. then <<
  2109. fmon:=get!-next!-mon(ipp1);
  2110. isearch:=ipp2;
  2111. >>
  2112. else
  2113. <<
  2114. fmon:=get!-next!-mon(ipp2);
  2115. isearch:=ipp1;
  2116. >>;
  2117. primeflag:=t;
  2118. while primeflag and not!-empty!-ideal(isearch) do
  2119. if divides(get!-next!-mon(isearch),fmon) then primeflag:=nil;
  2120. if primeflag then add!-to!-ideal(fmon,inew);
  2121. end;
  2122. if not!-empty!-ideal(ipp1) then return(append!-ideals(inew,ipp1))
  2123. else return(append!-ideals(inew,ipp2));
  2124. end;
  2125. symbolic procedure next!-var(ideal);
  2126. % extracts a variable in the ideal suitable for division
  2127. begin
  2128. scalar x,m,var;
  2129. repeat
  2130. << m:=get!-next!-mon(ideal);
  2131. var:=get!-var!-if!-not!-single(m);
  2132. >> until var or ideal = the!-empty!-ideal();
  2133. return(var);
  2134. end;
  2135. symbolic procedure get!-var!-if!-not!-single(mon);
  2136. % returns nil if the monomial is in a single variable,
  2137. % otherwise the index of the second variable of the monomial
  2138. begin
  2139. scalar i,foundvarflag,exp;
  2140. i := 0;
  2141. foundvarflag:=nil;
  2142. while not foundvarflag do
  2143. <<
  2144. i:=i+1;
  2145. exp:=get!-nth!-exp(mon,i);
  2146. if exp > 0 then foundvarflag:=t;
  2147. >>;
  2148. foundvarflag:=nil;
  2149. while i < nvars!* and not foundvarflag do
  2150. <<
  2151. i:=i+1;
  2152. exp:=get!-nth!-exp(mon,i);
  2153. if exp > 0 then foundvarflag:=t;
  2154. >>;
  2155. if foundvarflag then return(i)
  2156. else return(nil);
  2157. end;
  2158. symbolic procedure make!-one!-var!-mon(vindex);
  2159. % returns the monomial consisting of the single variable vindex
  2160. begin
  2161. scalar mon;
  2162. mon := alloc!-mon(nvars!*);
  2163. for i := 1:nvars!* do set!-nth!-exp(mon,i,0);
  2164. set!-nth!-exp(mon,vindex,1);
  2165. set!-tdeg(mon,1);
  2166. return(mon);
  2167. end;
  2168. symbolic procedure split!-ideal(ideal,var);
  2169. % splits the ideal into two simpler ideals
  2170. begin
  2171. scalar div,ideal1,ideal2,m,x;
  2172. ideal1 := the!-empty!-ideal();
  2173. ideal2 := the!-empty!-ideal();
  2174. while not!-empty!-ideal(ideal) do
  2175. <<
  2176. m:=get!-next!-mon(ideal);
  2177. if div:=divides!-by!-var(var,m) then
  2178. add!-to!-ideal(div,ideal2)
  2179. else
  2180. add!-to!-ideal(m,ideal1);
  2181. >>;
  2182. ideal2:=rem!-mult(ideal1,ideal2);
  2183. ideal1:=insert!-var(var,ideal1);
  2184. return(list(ideal1,ideal2));
  2185. end;
  2186. symbolic procedure base!-case!-pol(ideal);
  2187. % in the base case every monomial is of the form Xi^ei
  2188. % result : the numerator polynomial of the Hilbert series
  2189. % i.e. (1-z^e1)*(1-z^e2)*...
  2190. begin
  2191. scalar p,degsofar,e,tdeg;
  2192. tdeg:=0;
  2193. for each mon in cadr ideal do tdeg:=tdeg + get!-tdeg(mon);
  2194. p:=make!-vector(tdeg,0);
  2195. putv(p,0,1);
  2196. degsofar:=0;
  2197. for each mon in cadr ideal do
  2198. <<
  2199. e:=get!-tdeg(mon);
  2200. for j:= degsofar step -1 until 0 do
  2201. putv(p,j+e,getv(p,j+e)-getv(p,j));
  2202. degsofar:=degsofar+e;
  2203. >>;
  2204. return(vector2list(p));
  2205. end;
  2206. symbolic procedure vector2list v;
  2207. % Convert a vector v to a list. No type checking is done.
  2208. begin scalar u;
  2209. for i:= upbv v step -1 until 0 do u := getv(v,i) . u;
  2210. return u;
  2211. end;
  2212. endmodule;
  2213. module hilbertp; % Computing Hilbert Polynomial from the Hilbert series.
  2214. Comment
  2215. Authors: H. Michael Moeller, Fernuniversitaet
  2216. Hagen, Germany
  2217. email: MA105@DHAFEU11.bitnet
  2218. H. Melenk, Konrad-Zuse-Zentrum
  2219. Berlin, Germany
  2220. email: melenk@sc.ZIB-Berlin.de
  2221. ;
  2222. symbolic procedure newhilbi (bas,var,vars);
  2223. begin scalar baslt,n,u,grad,h,joa,a,ii,dim0,varx;
  2224. % extract leading terms
  2225. baslt:= for each p in cdr bas collect
  2226. <<u := hgspliteval list (p,vars); cadr u>>;
  2227. % replace non atomic elements in the varlist by gensyms
  2228. for each x in cdr vars do
  2229. if (pairp x) then
  2230. baslt := cdr subeval list(list('equal,x,gensym()),
  2231. 'list . baslt);
  2232. % compute the Hilbertseries
  2233. joa := hilbsereval list ('list . baslt,var);
  2234. % get the Hilbert polynomial
  2235. grad := deg(joa,var);
  2236. a:= for i:=0:grad collect coeffn (joa,var,i);
  2237. n:= length cdr vars;
  2238. %dim0 := (for i:=1:n product (var + i))/( for i:=1:n product i);
  2239. varx := !*a2f var;
  2240. dim0 := 1;
  2241. for i:=1:n do dim0:= multf (addd(i,varx),dim0);
  2242. dim0 := multsq(dim0 ./ 1,1 ./ (for i:=1:n product i));
  2243. h := multsq(car(a) ./ 1,dim0);
  2244. a := cdr(a);
  2245. ii := 0;
  2246. while a do
  2247. << dim0 := multsq (dim0, addf(varx,numr simp (minus ii) )
  2248. ./ addf(varx,numr simp (n -ii)));
  2249. ii := ii + 1;
  2250. if not (car a = 0) then h := addsq (h , multsq(car(a) ./ 1 ,dim0));
  2251. a := cdr(a) >>;
  2252. return mk!*sq h;
  2253. end;
  2254. symbolic procedure psnewhilbi (u);
  2255. begin scalar zz;
  2256. zz := 'list . gvarlis groerevlist reval car u;
  2257. if length (u) = 2
  2258. then return newhilbi ( reval car u, 'x, reval cadr u )
  2259. else if length (u) = 1 then return newhilbi(reval car u,'x,zz)
  2260. else rerror(groebnr2,19,"Wrong call to hilbertpolynomial");
  2261. end;
  2262. put ('hilbertpolynomial , 'psopfn ,'psnewhilbi);
  2263. symbolic procedure hgspliteval pars;
  2264. % A variant of Gsplit from grinterf.red.
  2265. % Split a polynomial into leading monomial and reductum.
  2266. begin scalar vars,x,u,v,w,oldorder,!*factor,!*exp;
  2267. integer n,pcount!*; !*exp := t;
  2268. n := length pars;
  2269. u := reval car pars;
  2270. v := if n>1 then reval cadr pars else nil;
  2271. u := list('list,u);
  2272. w := for each j in groerevlist u
  2273. collect if eqexpr j then !*eqn2a j else j;
  2274. vars :=
  2275. if null v then
  2276. for each j in gvarlis w collect !*a2k j
  2277. else groerevlist v;
  2278. if not vars then vdperr 'gsplit;
  2279. oldorder := vdpinit vars;
  2280. w := a2vdp car w;
  2281. if vdpzero!? w then x := w else
  2282. % <<x := vdpfmon(vdplbc w,vdpevlmon w);
  2283. <<x := vdpfmon('( 1 . 1),vdpevlmon w);
  2284. w := vdpred w>>;
  2285. w := list('list,vdp2a x,vdp2a w);
  2286. setkorder oldorder;
  2287. return w;
  2288. end;
  2289. % simple Array access method for one- and two-dimensional arrays
  2290. % NO check against misusage is done!
  2291. % Usage: Rar:=makeRarray list dim1; Rar:=makeRarray list(dim1,dim2);
  2292. % val:=getRarray(Rar,ind1); val:=getrarray(Rar,ind1,ind2);
  2293. % putRarray(Rar,ind1,val); PutRarray(Rar,in1,ind2,val);
  2294. % for two dimensional array access only !
  2295. macro procedure functionindex2(u);
  2296. begin scalar dims,ind1,ind2;
  2297. dims := cadr u;
  2298. ind1 := caddr u;
  2299. ind2 := cadddr u;
  2300. return %%%% ((ind1 #- 1) #* cadr dims) #+ ind2;
  2301. list ('iplus,ind2,list('itimes,list('cadr,dims),
  2302. list('iplus,ind1,-1)));
  2303. end;
  2304. macro procedure getrarray u;
  2305. begin scalar arry,inds;
  2306. arry := cadr(u);
  2307. inds := cddr u;
  2308. if length(inds) = 1 then
  2309. return list('getv,list('cdr,arry),car inds)
  2310. else
  2311. return list('getv,list('cdr,arry),
  2312. 'functionindex2 . list('car,arry) . inds);
  2313. end;
  2314. symbolic procedure makerarray dims;
  2315. begin scalar u,n;
  2316. n := for each i in dims product i;
  2317. u := mkvect n;
  2318. return dims . u;
  2319. end;
  2320. macro procedure putrarray u;
  2321. begin scalar arry,inds, val;
  2322. arry := cadr(u);
  2323. inds := cddr u;
  2324. val := nth (u,length u); % PSL: lastcar u;
  2325. if length(inds) = 2 then
  2326. return list('putv,list('cdr,arry),car inds,val)
  2327. else
  2328. return list('putv,list('cdr,arry), 'functionindex2 .
  2329. list('car,arry).car inds. cadr inds . nil , val);
  2330. end;
  2331. procedure hilbertzerodimp(nrall, n, rarray);
  2332. begin integer i, k, count, vicount;
  2333. count := 0;
  2334. i := 0;
  2335. while ((i:= i+1) <= nrall and count < n) do
  2336. begin vicount := 1;
  2337. for k := 1:n do
  2338. if (getrarray(rarray,i,k) = 0) then vicount := vicount + 1;
  2339. if vicount = n then count := count + 1;
  2340. end;
  2341. return count = n;
  2342. end;
  2343. symbolic procedure groezerodim!?(f,n);
  2344. begin scalar explist,a;
  2345. integer r;
  2346. %explist:= list( vev(lt(f1)),...,vev(lt(fr)) );
  2347. explist:= for each fi in f collect vdpevlmon fi;
  2348. r:= length(f);
  2349. a := makerarray list(r,n);
  2350. for i:=1 step 1 until r do
  2351. for k:=1 step 1 until n do
  2352. putrarray(a ,i,k, nth(nth(explist,i),k));
  2353. return hilbertzerodimp (r, n, a);
  2354. end;
  2355. symbolic procedure gzerodimeval u;
  2356. begin integer n;
  2357. n := length u;
  2358. if n = 2 then return gzerodim1(reval car u,reval cadr u)
  2359. else
  2360. rerror(groebnr2,20,
  2361. "GZERODIM? called with wrong number of arguments")
  2362. end;
  2363. put('gzerodim!?,'psopfn,'gzerodimeval);
  2364. symbolic procedure gzerodim1(u,v);
  2365. begin scalar vars,w,z,dv,oldorder;
  2366. w := for each j in getrlist u
  2367. collect if eqexpr j then !*eqn2a j else j;
  2368. if null w then rerror(groebnr2,21,
  2369. "Empty list in HilbertPolynomial");
  2370. vars :=
  2371. if null v then for each j in gvarlis(w) collect !*a2k j
  2372. else % test, if vars are really used
  2373. << z := gvarlis (w);
  2374. for each j in (v:= getrlist v) do
  2375. if member(j,z) then dv := !*a2k j . dv;
  2376. dv := reversip dv;
  2377. if not (length v = length dv) then
  2378. << prin2 " HilbertPolynomial: ";
  2379. prin2 (length v - length dv);
  2380. prin2t " of the variables not used";
  2381. terpri () >>;
  2382. dv>>;
  2383. if not vars then vdperr 'gzerodim!?;
  2384. oldorder := vdpinit vars;
  2385. w := for each j in w collect numr simp j;
  2386. w := for each j in w collect f2vdp j;
  2387. w := groezerodim!? (w,length vars);
  2388. setkorder oldorder;
  2389. return if w then newhilbi(u,'x,'list . v) else nil;
  2390. end;
  2391. symbolic procedure gbtest(g);
  2392. % test, if the given set of polynomials is a Groebner basis.
  2393. % only fast to compute plausilbility test.
  2394. begin scalar fredu,g1,r,s;
  2395. g := vdplsort g;
  2396. % make abbreviated version of G
  2397. g1:= for each p in g collect
  2398. << r := vdpred p;
  2399. if vdpzero!? r then p else
  2400. vdpsum(vdpfmon(vdplbc p,vdpevlmon p),
  2401. vdpfmon(vdplbc r,vdpevlmon r))
  2402. >>;
  2403. while g1 do
  2404. <<for each p in cdr g1 do
  2405. if not groebbuchcrit4t(vdpevlmon car g1,vdpevlmon p) then
  2406. <<s := groebspolynom(car g1,p);
  2407. if not vdpzero!? s and
  2408. null groebsearchinlist (vdpevlmon s,cddr g1)
  2409. then rerror(groebnr2,22,
  2410. "****** Not a GROEBNER basis wrt current ordering");
  2411. >>;
  2412. if groebsearchinlist(vdpevlmon car g1,cdr g1) then
  2413. fredu := t;
  2414. g1 := cdr g1;
  2415. >>;
  2416. if fredu then
  2417. <<terpri!* t;
  2418. prin2t "WARNING:system is not a fully reduced GROEBNER basis";
  2419. prin2t "with current term ordering";
  2420. >>;
  2421. end;
  2422. endmodule;
  2423. end;