xx 245 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065
  1. module bas;
  2. COMMENT
  3. #######################
  4. #### ####
  5. #### IDEAL BASES ####
  6. #### ####
  7. #######################
  8. Ideal bases are lists of vector polynomials (with additional
  9. information), constituting the rows of a dpmat (see below). In a
  10. rep. part there can be stored vectors representing each base element
  11. according to a fixed basis. Usually rep=nil.
  12. Informal syntax :
  13. <bas> ::= list of base elements
  14. <base element> ::= list(nr dpoly length ecart rep)
  15. END COMMENT;
  16. % -------- Reference operators for the base element b ---------
  17. symbolic procedure bas_dpoly b; cadr b;
  18. symbolic procedure bas_dplen b; caddr b;
  19. symbolic procedure bas_nr b; car b;
  20. symbolic procedure bas_dpecart b; cadddr b;
  21. symbolic procedure bas_rep b; nth(b,5);
  22. % ----- Elementary constructors for the base element be --------
  23. symbolic procedure bas_newnumber(nr,be);
  24. % Returns be with new number part.
  25. nr . cdr be;
  26. symbolic procedure bas_make(nr,pol);
  27. % Make base element with rep=nil.
  28. list(nr,pol, length pol,dp_ecart pol,nil);
  29. symbolic procedure bas_make1(nr,pol,rep);
  30. % Make base element with prescribed rep.
  31. list(nr,pol, length pol,dp_ecart pol,rep);
  32. symbolic procedure bas_getelement(i,bas);
  33. % Returns the base element with number i from bas (or nil).
  34. if null bas then list(i,nil,0,0,nil)
  35. else if eqn(i,bas_nr car bas) then car bas
  36. else bas_getelement(i,cdr bas);
  37. % ---------- Operations on base lists ---------------
  38. symbolic procedure bas_sort b;
  39. % Sort the base list b.
  40. sort(b,function red_better);
  41. symbolic procedure bas_print u;
  42. % Prints a list of distributive polynomials using dp_print.
  43. begin terpri();
  44. if null u then print 'empty
  45. else for each v in u do
  46. << write bas_nr v, " --> "; dp_print2 bas_dpoly v >>
  47. end;
  48. symbolic procedure bas_renumber u;
  49. % Renumber base list u.
  50. if null u then nil
  51. else begin scalar i; i:=0;
  52. return for each x in u collect <<i:=i+1; bas_newnumber(i,x) >>
  53. end;
  54. symbolic procedure bas_setrelations u;
  55. % Set in the base list u the relation part rep of base element nr. i
  56. % to e_i (provided i>0).
  57. for each x in u do
  58. if bas_nr x > 0 then rplaca(cddddr x, dp_from_ei bas_nr x);
  59. symbolic procedure bas_removerelations u;
  60. % Remove relation parts.
  61. for each x in u do rplaca(cddddr x, nil);
  62. symbolic procedure bas_getrelations u;
  63. % Returns the relations of the base list u as a separate base list.
  64. begin scalar w;
  65. for each x in u do w:=bas_make(bas_nr x,bas_rep x) . w;
  66. return reversip w;
  67. end;
  68. symbolic procedure bas_from_a u;
  69. % Converts the algebraic (prefix) form u to a base list clearing
  70. % denominators. Only for lists.
  71. bas_renumber for each v in cdr u collect
  72. bas_make(0,dp_from_a prepf numr simp v);
  73. symbolic procedure bas_2a u;
  74. % Converts the base list u to its algebraic prefix form.
  75. append('(list),for each x in u collect dp_2a bas_dpoly x);
  76. symbolic procedure bas_neworder u;
  77. % Returns reordered base list u (e.g. after change of term order).
  78. for each x in u collect
  79. bas_make1(bas_nr x,dp_neworder bas_dpoly x,
  80. dp_neworder bas_rep x);
  81. symbolic procedure bas_zerodelete u;
  82. % Returns base list u with zero elements deleted but not renumbered.
  83. if null u then nil
  84. else if null bas_dpoly car u then bas_zerodelete cdr u
  85. else car u.bas_zerodelete cdr u;
  86. symbolic procedure bas_simpelement b;
  87. % Returns (b_new . z) with
  88. % bas_dpoly b_new having leading coefficient 1 or
  89. % gcd(dp_content bas_poly,dp_content bas_rep) canceled out
  90. % and dpoly_old = z * dpoly_new , rep_old= z * rep_new.
  91. if null bas_dpoly b then b . bc_fi 1
  92. else begin scalar z,z1,pol,rep;
  93. if (z:=bc_inv (z1:=dp_lc bas_dpoly b)) then
  94. return bas_make1(bas_nr b,
  95. dp_times_bc(z,bas_dpoly b),
  96. dp_times_bc(z,bas_rep b))
  97. . z1;
  98. % -- now we assume that base coefficients are a gcd domain ----
  99. z:=bc_gcd(dp_content bas_dpoly b,dp_content bas_rep b);
  100. if bc_minus!? z1 then z:=bc_neg z;
  101. pol:=for each x in bas_dpoly b collect
  102. car x . car bc_divmod(cdr x,z);
  103. rep:=for each x in bas_rep b collect
  104. car x . car bc_divmod(cdr x,z);
  105. return bas_make1(bas_nr b,pol,rep) . z;
  106. end;
  107. symbolic procedure bas_simp u;
  108. % Applies bas_simpelement to each dpoly in the base list u.
  109. for each x in u collect car bas_simpelement x;
  110. symbolic procedure bas_zero!? b;
  111. % Test whether all base elements are zero.
  112. null b or (null bas_dpoly car b and bas_zero!? cdr b);
  113. symbolic procedure bas_sieve(bas,vars);
  114. % Sieve out all base elements from the base list bas with leading
  115. % term containing a variable from the list of var. names vars and
  116. % renumber the result.
  117. begin scalar m; m:=mo_zero();
  118. for each x in vars do
  119. if member(x,ring_names cali!=basering) then
  120. m:=mo_sum(m,mo_from_a x)
  121. else typerr(x,"variable name");
  122. return bas_renumber for each x in bas_zerodelete bas join
  123. if mo_zero!? mo_gcd(m,dp_lmon bas_dpoly x) then {x};
  124. end;
  125. symbolic procedure bas_homogenize(b,var);
  126. % Homogenize the base list b using the var. name var.
  127. % Note that the rep. part is correct only upto a power of var !
  128. for each x in b collect
  129. bas_make1(bas_nr x,dp_homogenize(bas_dpoly x,var),
  130. dp_homogenize(bas_rep x,var));
  131. symbolic procedure bas_dehomogenize(b,var);
  132. % Set the var. name var in the base list b equal to one.
  133. begin scalar u,v;
  134. if not member(var,v:=ring_all_names cali!=basering) then
  135. typerr(var,"dpoly variable");
  136. u:=setdiff(v,list var);
  137. return for each x in b collect
  138. bas_make1(bas_nr x,dp_seed(bas_dpoly x,u),
  139. dp_seed(bas_rep x,u));
  140. end;
  141. % ---------------- Special tools for local algebra -----------
  142. symbolic procedure bas!=factorunits p;
  143. if null p then nil
  144. else bas!=delprod
  145. for each y in cdr (fctrf numr simp dp_2a p where !*factor=t)
  146. collect (dp_from_a prepf car y . cdr y);
  147. symbolic procedure bas!=delprod u;
  148. begin scalar p; p:=dp_fi 1;
  149. for each x in u do
  150. if not dp_unit!? car x then p:=dp_prod(p,dp_power(car x,cdr x));
  151. return p
  152. end;
  153. symbolic procedure bas!=detectunits p;
  154. if null p then nil
  155. else if listtest(cdr p,dp_lmon p,
  156. function(lambda(x,y);not mo_vdivides!?(y,car x))) then p
  157. else list dp_term(bc_fi 1,dp_lmon p);
  158. symbolic procedure bas_factorunits b;
  159. bas_make(bas_nr b,bas!=factorunits bas_dpoly b);
  160. symbolic procedure bas_detectunits b;
  161. bas_make(bas_nr b,bas!=detectunits bas_dpoly b);
  162. endmodule; % bas
  163. end;
  164. module bcsf;
  165. COMMENT
  166. #######################
  167. # #
  168. # BASE COEFFICIENTS #
  169. # #
  170. #######################
  171. These base coefficients are standard forms.
  172. A list of REPLACEBY rules may be supplied with the setrules command
  173. that will be applied in an additional simplification process.
  174. This rules list is a list of s.f. pairs, where car should replace cdr.
  175. END COMMENT;
  176. % Standard is :
  177. !*hardzerotest:=nil;
  178. symbolic operator setrules;
  179. symbolic procedure setrules m; setrules!* cdr reval m;
  180. symbolic procedure setrules!* m;
  181. begin scalar r; r:=ring_names cali!=basering;
  182. m:=for each x in m collect
  183. if not eqcar(x,'replaceby) then
  184. typerr(makelist m,"rules list")
  185. else (numr simp second x . numr simp third x);
  186. for each x in m do
  187. if domainp car x or member(mvar car x,r) then
  188. rederr"no substitution for ring variables allowed";
  189. put('cali,'rules,m);
  190. return getrules();
  191. end;
  192. symbolic operator getrules;
  193. symbolic procedure getrules();
  194. makelist for each x in get('cali,'rules) collect
  195. list('replaceby,prepf car x,prepf cdr x);
  196. symbolic procedure bc!=simp u;
  197. (if r0 then
  198. begin scalar r,c; integer i;
  199. i:=0; r:=r0;
  200. while r and (i<1000) do
  201. << c:=qremf(u,caar r);
  202. if null car c then r:=cdr r
  203. else
  204. << u:=addf(multf(car c,cdar r),cdr c);
  205. i:=i+1; r:=r0;
  206. >>;
  207. >>;
  208. if (i<1000) then return u
  209. else rederr"recursion depth of bc!=simp too high"
  210. end
  211. else u) where r0:=get('cali,'rules);
  212. symbolic procedure bc_minus!? u; minusf u;
  213. symbolic procedure bc_zero!? u;
  214. if (null u or u=0) then t
  215. else if !*hardzerotest and pairp u then
  216. null bc!=simp numr simp prepf u
  217. else nil;
  218. symbolic procedure bc_fi a; if a=0 then nil else a;
  219. symbolic procedure bc_one!? u; (u = 1);
  220. symbolic procedure bc_inv u;
  221. % Test, whether u is invertible. Return the inverse of u or nil.
  222. if (u=1) or (u=-1) then u
  223. else begin scalar v; v:=qremf(1,u);
  224. if cdr v then return nil else return car v;
  225. end;
  226. symbolic procedure bc_neg u; negf u;
  227. symbolic procedure bc_prod (u,v); bc!=simp multf(u,v);
  228. symbolic procedure bc_quot (u,v);
  229. (if null cdr w then bc!=simp car w else typerr(v,"denominator"))
  230. where w=qremf(u,v);
  231. symbolic procedure bc_sum (u,v); addf(u,v);
  232. symbolic procedure bc_diff(u,v); addf(u,negf v);
  233. symbolic procedure bc_power(u,n); bc!=simp exptf(u,n);
  234. symbolic procedure bc_from_a u; bc!=simp numr simp!* u;
  235. symbolic procedure bc_2a u; prepf u;
  236. symbolic procedure bc_prin u;
  237. % Prints a base coefficient in infix form
  238. ( if domainp u then
  239. if dmode!*='!:mod!: then prin2 prepf u
  240. else printsf u
  241. else << write"("; printsf u; write")" >>) where !*nat=nil;
  242. symbolic procedure bc_divmod(u,v); % Returns quot . rem.
  243. qremf(u,v);
  244. symbolic procedure bc_gcd(u,v); gcdf!*(u,v);
  245. symbolic procedure bc_lcm(u,v);
  246. car bc_divmod(bc_prod(u,v),bc_gcd(u,v));
  247. endmodule; % bcsf
  248. end;
  249. module cali;
  250. % Author H.-G. Graebe | Univ. Leipzig
  251. % graebe@informatik.uni-leipzig.de
  252. % terpri(); write "CALI 2.2.1 Last update June 22, 1995"; terpri();
  253. COMMENT
  254. #########################
  255. #### ####
  256. #### HEADER MODULE ####
  257. #### ####
  258. #########################
  259. This is the header module of the package CALI, a package for
  260. computational commutative algebra.
  261. Author : H.-G. Graebe
  262. Univ. Leipzig
  263. Institut fuer Informatik
  264. Augustusplatz 10 - 11
  265. D - 04109 Leipzig
  266. Germany
  267. email : graebe@informatik.uni-leipzig.de
  268. Version : 2.2.1, finished at June 22, 1995.
  269. See cali.chg for change's documentation.
  270. Please send all Comments, bugs, hints, wishes, criticisms etc. to the
  271. above email address.
  272. Abstract :
  273. This package contains algorithms for computations in commutative
  274. algebra closely related to the Groebner algorithm for ideals and
  275. modules. There are facilities for local computations, using a modern
  276. implementation of Mora's standard basis algorithm, that works for
  277. arbitrary term orders. This reflects the full analogy between modules
  278. over local rings and homogeneous (in fact H-local) modules over
  279. polynomial rings.
  280. CALI extends also the term order facilities of the REDUCE internal
  281. groebner package, defining term orders by degree vector lists, and
  282. the rigid implementation of the sugar idea, by a more flexible ecart
  283. vector, in particular useful for local computations. Version 2.2. has
  284. also a common view on normal forms for noetherian and non-noetherian
  285. term orders.
  286. The package was designed mainly as a symbolic mode programming
  287. environment extending the build-in facilities of REDUCE for the
  288. computational approach to problems arising naturally in commutative
  289. algebra. An algebraic mode interface allows to access (in a more
  290. rigid frame) all important features implemented symbolically.
  291. As main topics CALI contains facilities for
  292. -- defining rings, ideals and modules,
  293. -- computing Groebner bases and local standard bases,
  294. -- computing syzygies, resolutions and (graded) Betti numbers,
  295. -- computing (also weighted) Hilbert series, multiplicities,
  296. independent sets, dimensions,
  297. -- computing normal forms and representations,
  298. -- computing sums, products, intersections, elimination ideals etc.,
  299. -- primality tests, computation of radicals, unmixed radicals,
  300. equidimensional parts, primary decompositions etc. of ideals
  301. and modules,
  302. -- advanced applications of Groebner bases (blowup, associated graded
  303. ring, analytic spread, symmetric algebra, monomial curves),
  304. -- applications of linear algebra techniques to zerodimensional
  305. ideals, as e.g. the FGLM change of term orders, border bases
  306. and affine and projective ideals of sets of points,
  307. -- splitting polynomial systems of equations mixing factorization and
  308. Groebner algorithm, triangular systems, and different versions
  309. of the extended Groebner factorizer.
  310. Reduce version required :
  311. The program was tested under v. 3.4 - 3.6.
  312. (I had some trouble with the module dualbases under 3.4.1)
  313. Relevant publications :
  314. See the bibliography in the manual.
  315. Key words :
  316. Groebner algorithm for ideals and modules, local standard bases,
  317. Groebner factorizer, extended Groebner factorizer, triangular systems,
  318. normal forms, ideal and module operations, Hilbert series, independent
  319. sets, dual bases, border bases, affine and projective sets of points,
  320. free resolution, constructive commutative algebra, primality test,
  321. radical, unmixed radical, equidimensional part, primary decomposition,
  322. blowup, associated graded ring, analytic spread, symmetric algebra,
  323. monomial curves.
  324. To be done :
  325. eo(vars) : test cali!=basering for eliminationorder according to vars
  326. -> eliminate
  327. Remind :
  328. Never "put" variables, that are subject to rebounding via "where" !
  329. end comment;
  330. create!-package( '(
  331. cali % This header module.
  332. bcsf % Base coeff. arithmetics.
  333. ring % Base ring and monomial arithmetics.
  334. mo % Monomial arithmetic.
  335. dpoly % Distr. polynomial (and vector) arithmetics.
  336. bas % Polynomial lists.
  337. dpmat % dpmat's arithmetic.
  338. red % Normal form algorithms and related topics.
  339. groeb % Groebner algorithm and related topics.
  340. groebf % Groebner factorizer and extensions.
  341. matop % Module operations on dpmats.
  342. quot % Different quotients.
  343. moid % Lead. term ideal algorithms.
  344. hf % Hilbert series.
  345. res % Resolutions.
  346. intf % Interface to algebraic mode.
  347. odim % Alg. for zerodimensional ideals and
  348. % modules.
  349. prime % Primality test, radical, and primary
  350. % decomposition.
  351. scripts % Advanced applications, inspired by the
  352. % scripts of Bayer/Stillman.
  353. calimat % CALI's extension of the matrix package.
  354. lf % The dual bases approach (FGLM etc.).
  355. triang % (Zero dimensional) triangular systems.
  356. ),'(contrib cali));
  357. load!-package 'matrix;
  358. fluid '(
  359. cali!=basering % see rings
  360. cali!=degrees % see mons in rings
  361. cali!=monset % see groeb
  362. );
  363. % Default :
  364. switch
  365. hardzerotest, % (off) see bcsf, try simp for each zerotest.
  366. red_total, % (on) see red, do total reductions.
  367. bcsimp, % (on) see red, cancel coefficient's gcd.
  368. noetherian, % (on) see interf, test term orders and
  369. % choose non local algorithms.
  370. factorprimes, % (on) see primes, invoke groebfactor during
  371. % prime decomposition.
  372. factorunits, % (off) see groeb, try to remove units from
  373. % polynomials by factorization.
  374. detectunits, % (off) see groeb, detect generators of the form
  375. % monomial * unit.
  376. lexefgb; % (off) see groebf, invoke the extended
  377. % Groebner factorizer with pure
  378. % lex zerosolve.
  379. % The first initialization :
  380. put('cali,'trace,0); % No tracing.
  381. % linelength 79; % This is much more convenient than 80.
  382. % However, it causes problems in window sys.
  383. % The new tracing. We hope that this shape will easily interface to a
  384. % forthcoming general trace utility.
  385. symbolic operator setcalitrace;
  386. symbolic procedure setcalitrace(n);
  387. % Set trace intensity.
  388. put('cali,'trace,n);
  389. symbolic operator setcaliprintterms;
  390. symbolic procedure setcaliprintterms(n);
  391. % Set number of terms to be printed in intermediate output.
  392. if n<=0 then typerr(n,"number of terms to be printed")
  393. else put('cali,'printterms,n);
  394. symbolic operator clearcaliprintterms;
  395. symbolic procedure clearcaliprintterms;
  396. % Set intermediate output printing to "all".
  397. << remprop('cali,'printterms); write"Term print bound cleared";
  398. terpri();
  399. >>;
  400. symbolic procedure cali_trace();
  401. % Get the trace intensity.
  402. get('cali,'trace);
  403. % ---- Some useful things, probably implemented also elsewhere
  404. % ---- in the system.
  405. % symbolic procedure first x; car x;
  406. % symbolic procedure second x; cadr x;
  407. % symbolic procedure third x; caddr x;
  408. symbolic procedure strcat l;
  409. % Concatenate the items in the list l to a string.
  410. begin scalar u;
  411. u:=for each x in l join explode x;
  412. while memq('!!,u) do u:=delete('!!,u);
  413. while memq('!",u) do u:=delete('!",u);
  414. return compress append(append('(!"),u),'(!"));
  415. end;
  416. symbolic procedure numberlistp l;
  417. % l is a list of numbers.
  418. if null l then t
  419. else fixp car l and numberlistp cdr l;
  420. symbolic procedure merge(l1,l2,fn);
  421. % Returns the (physical) merge of the two sorted lists l1 and l2.
  422. if null l1 then l2
  423. else if null l2 then l1
  424. else if apply2(fn,car l1,car l2) then rplacd(l1,merge(cdr l1,l2,fn))
  425. else rplacd(l2,merge(l1,cdr l2,fn));
  426. symbolic procedure listexpand(fn,l); eval expand(l,fn);
  427. symbolic procedure listtest(a,b,f);
  428. % Return the first u in a s.th. f(u,b) or nil.
  429. if null a then nil
  430. else if apply2(f,car a,b) then if car a=nil then t else car a
  431. else listtest(cdr a,b,f);
  432. symbolic procedure listminimize(a,f);
  433. % Returns a minimal list b such that for all v in a ex. u in b such
  434. % that f(u,v). The elements are in the same order as in a.
  435. if null a then nil else reverse cali!=min(nil,a,f);
  436. symbolic procedure cali!=min(b,a,f);
  437. if null a then b
  438. else if listtest(b,car a,f) or listtest(cdr a,car a,f) then
  439. cali!=min(b,cdr a,f)
  440. else cali!=min(car a . b,cdr a,f);
  441. % symbolic procedure makelist u; 'list . u;
  442. symbolic procedure subsetp(u,v);
  443. % true :<=> u \subset v
  444. if null u then t else member(car u,v) and subsetp(cdr u,v);
  445. symbolic procedure disjoint(a,b);
  446. if null a then t else not member(car a,b) and disjoint(cdr a,b);
  447. symbolic procedure print_lf u;
  448. % Line feed after about 70 characters.
  449. <<if posn()>69 then <<terpri();terpri()>>; prin2 u>>;
  450. symbolic procedure cali_choose(m,k);
  451. % Returns the list of k-subsets of m.
  452. if (length m < k) then nil
  453. else if k=1 then for each x in m collect list x
  454. else nconc(
  455. for each x in cali_choose(cdr m,k-1) collect (car m . x),
  456. cali_choose(cdr m,k));
  457. endmodule;
  458. end;
  459. module calimat;
  460. Comment
  461. #######################
  462. # #
  463. # MATRIX SUPPLEMENT #
  464. # #
  465. #######################
  466. Supplement to the REDUCE matrix package.
  467. Matrices are transformed into nested lists of s.q.'s.
  468. end comment;
  469. % ------ The Jacobian matrix -------------
  470. symbolic operator matjac;
  471. symbolic procedure matjac(m,l);
  472. % Returns the Jacobian matrix from the ideal m in prefix form
  473. % (given as an algebraic mode list) with respect to the var. list l.
  474. if not eqcar(m,'list) then typerr(m,"ideal basis")
  475. else if not eqcar(l,'list) then typerr(l,"variable list")
  476. else 'mat . for each x in cdr l collect
  477. for each y in cdr m collect prepsq difff(numr simp reval y,x);
  478. % ---------- Random linear forms -------------
  479. symbolic operator random_linear_form;
  480. symbolic procedure random_linear_form(vars,bound);
  481. % Returns a random linear form in algebraic prefix form.
  482. if not eqcar(vars,'list) then typerr(vars,"variable list")
  483. else 'plus . for each x in cdr vars collect
  484. {'times,random(2*bound)-bound,x};
  485. % ----- Singular locus -----------
  486. symbolic operator singular_locus;
  487. symbolic procedure singular_locus(m,c);
  488. if !*mode='algebraic then
  489. (if not numberp c then
  490. rederr"Syntax : singular_locus(polynomial list, codimension)"
  491. else dpmat_2a singular_locus!*(m,c))
  492. else singular_locus!*(m,c);
  493. symbolic procedure singular_locus!*(m,c);
  494. % m must be a complete intersection of codimension c given as a list
  495. % of polynomials in prefix form. Returns the singular locus computing
  496. % the corresponding jacobian.
  497. matsum!* {dpmat_from_a m, mat2list!* dpmat_from_a
  498. minors(matjac(m,makelist ring_names cali!=basering),c)};
  499. % ------------- Minors --------------
  500. symbolic operator minors;
  501. symbolic procedure minors(m,k);
  502. % Returns the matrix of k-minors of the matrix m.
  503. if not eqcar(m,'mat) then typerr(m,"matrix")
  504. else begin scalar r,c;
  505. m:=for each x in cdr m collect for each y in x collect simp y;
  506. r:=cali_choose(for i:=1:length m collect i,k);
  507. c:=cali_choose(for i:=1:length car m collect i,k);
  508. return 'mat . for each x in r collect for each y in c collect
  509. mk!*sq detq calimat!=submat(m,x,y);
  510. end;
  511. symbolic operator ideal_of_minors;
  512. symbolic procedure ideal_of_minors(m,k);
  513. % The ideal of the k-minors of the matrix m.
  514. if !*mode='algebraic then dpmat_2a ideal_of_minors!*(m,k)
  515. else ideal_of_minors!*(m,k);
  516. symbolic procedure ideal_of_minors!*(m,k);
  517. if not eqcar(m,'mat) then typerr(m,"matrix") else
  518. interreduce!* mat2list!* dpmat_from_a minors(m,k);
  519. symbolic procedure calimat!=submat(m,x,y);
  520. for each a in x collect for each b in y collect nth(nth(m,a),b);
  521. symbolic procedure calimat!=sum(a,b);
  522. for each x in pair(a,b) collect
  523. for each y in pair(car x,cdr x) collect addsq(car y,cdr y);
  524. symbolic procedure calimat!=neg a;
  525. for each x in a collect for each y in x collect negsq y;
  526. symbolic procedure calimat!=tp a;
  527. tp1 append(a,nil); % since tp1 is destructive.
  528. symbolic procedure calimat!=zero!? a;
  529. begin scalar b; b:=t;
  530. for each x in a do for each y in x do b:=b and null car y;
  531. return b;
  532. end;
  533. % -------------- Pfaffians ---------------
  534. symbolic procedure calimat!=skewsymmetric!? m;
  535. calimat!=zero!? calimat!=sum(m,calimat!=tp m);
  536. symbolic operator pfaffian;
  537. symbolic procedure pfaffian m;
  538. % The pfaffian of a skewsymmetric matrix m.
  539. if not eqcar(m,'mat) then typerr(m,"matrix") else
  540. begin scalar m1;
  541. m1:=for each x in cdr m collect for each y in x collect simp y;
  542. if not calimat!=skewsymmetric!? m1
  543. then typerr(m,"skewsymmetic matrix");
  544. return mk!*sq calimat!=pfaff m1;
  545. end;
  546. symbolic procedure calimat!=pfaff m;
  547. if length m=1 then nil . 1
  548. else if length m=2 then cadar m
  549. else begin scalar a,b,p,c,d,ind,sgn;
  550. b:=for each x in cdr m collect cdr x;
  551. a:=cdar m; ind:=for i:=1:length a collect i;
  552. p:=nil . 1;
  553. for i:=1:length a do
  554. << c:=delete(i,ind); d:=calimat!=pfaff calimat!=submat(b,c,c);
  555. if sgn then d:=negsq d; sgn:=not sgn;
  556. p:=addsq(p,multsq(nth(a,i),d));
  557. >>;
  558. return p;
  559. end;
  560. symbolic operator ideal_of_pfaffians;
  561. symbolic procedure ideal_of_pfaffians(m,k);
  562. % The ideal of the 2k-pfaffians of the skewsymmetric matrix m.
  563. if !*mode='algebraic then dpmat_2a ideal_of_pfaffians!*(m,k)
  564. else ideal_of_pfaffians!*(m,k);
  565. symbolic procedure ideal_of_pfaffians!*(m,k);
  566. % The same, but for a dpmat m.
  567. if not eqcar(m,'mat) then typerr(m,"matrix") else
  568. begin scalar m1,u;
  569. m1:=for each x in cdr m collect for each y in x collect simp y;
  570. if not calimat!=skewsymmetric!? m1
  571. then typerr(m,"skewsymmetic matrix");
  572. u:=cali_choose(for i:=1:length m1 collect i,2*k);
  573. return interreduce!* dpmat_from_a makelist
  574. for each x in u collect
  575. prepsq calimat!=pfaff calimat!=submat(m1,x,x);
  576. end;
  577. endmodule; % calimat
  578. end;
  579. module dpmat;
  580. COMMENT
  581. #####################
  582. ### ###
  583. ### MATRICES ###
  584. ### ###
  585. #####################
  586. This module introduces special dpoly matrices with its own matrix
  587. syntax.
  588. Informal syntax :
  589. <matrix> ::= list('DPMAT,#rows,#cols,baslist,column_degrees,gb-tag)
  590. Dpmat's are the central data structure exploited in the modules of
  591. this package. Each such matrix describes a map
  592. f : R^rows --> R^cols,
  593. that gives rise for the definition of two modules,
  594. im f = the submodule of R^cols generated by the rows
  595. of the matrix
  596. and coker f = R^cols/im f.
  597. Conceptually dpmat's are identified with im f.
  598. END COMMENT;
  599. % ------------- Reference operators ----------------
  600. symbolic procedure dpmat_rows m; cadr m;
  601. symbolic procedure dpmat_cols m; caddr m;
  602. symbolic procedure dpmat_list m; cadddr m;
  603. symbolic procedure dpmat_coldegs m; nth(m,5);
  604. symbolic procedure dpmat_gbtag m; nth(m,6);
  605. % ------------- Elementary operations --------------
  606. symbolic procedure dpmat_rowdegrees m;
  607. % Returns the row degrees of the dpmat m as an assoc. list.
  608. (for each x in dpmat_list m join
  609. if (bas_nr x > 0) and bas_dpoly x then
  610. {(bas_nr x).(mo_getdegree(dp_lmon bas_dpoly x,l))})
  611. where l=dpmat_coldegs m;
  612. symbolic procedure dpmat_make(r,c,bas,degs,gbtag);
  613. list('dpmat,r,c,bas,degs,gbtag);
  614. symbolic procedure dpmat_element(r,c,mmat);
  615. % Returns mmat[r,c].
  616. dp_neworder
  617. dp_comp(c, bas_dpoly bas_getelement(r,dpmat_list mmat));
  618. symbolic procedure dpmat_print m; mathprint dpmat_2a m;
  619. symbolic procedure getleadterms!* m;
  620. % Returns the dpmat with the leading terms of m.
  621. (begin scalar b;
  622. b:=for each x in dpmat_list m collect
  623. bas_make(bas_nr x,list(car bas_dpoly x));
  624. return dpmat_make(dpmat_rows m,dpmat_cols m,b,cali!=degrees,t);
  625. end) where cali!=degrees:=dpmat_coldegs m;
  626. % -------- Symbolic mode file transfer --------------
  627. symbolic procedure savemat!*(m,name);
  628. % Save the dpmat m under the name <name>.
  629. begin scalar nat,c;
  630. if not (stringp name or idp name) then typerr(name,"file name");
  631. if not eqcar(m,'dpmat) then typerr(m,"dpmat");
  632. nat:=!*nat; !*nat:=nil;
  633. write"Saving as ",name;
  634. out name$
  635. write"algebraic(setring "$
  636. % mathprint prints lists without terminator, but matrices with
  637. % terminator.
  638. mathprint ring_2a cali!=basering$ write")$"$
  639. write"algebraic(<<basis :="$ dpmat_print m$
  640. if dpmat_cols m=0 then write"$"$ write">>)$"$
  641. if (c:=dpmat_coldegs m) then
  642. << write"algebraic(degrees:="$
  643. mathprint moid_2a for each x in c collect cdr x$ write")$"$
  644. >>;
  645. write"end$"$ terpri()$
  646. shut name; terpri(); !*nat:=nat;
  647. end;
  648. symbolic procedure initmat!* name;
  649. % Initialize a dpmat from <name>.
  650. if not (stringp name or idp name) then typerr(name,"file name")
  651. else begin scalar m,c; integer i;
  652. write"Initializing ",name; terpri();
  653. in name$ m:=reval 'basis; cali!=degrees:=nil;
  654. if eqcar(m,'list) then
  655. << m:=bas_from_a m; m:=dpmat_make(length m,0,m,nil,nil)>>
  656. else if eqcar(m,'mat) then
  657. << c:=moid_from_a reval 'degrees; i:=0;
  658. cali!=degrees:=for each x in c collect <<i:=i+1; i . x >>;
  659. m:=dpmat_from_a m;
  660. >>
  661. else typerr(m,"basis or matrix");
  662. dpmat_print m;
  663. return m;
  664. end;
  665. % ---- Algebraic mode file transfer ---------
  666. symbolic operator savemat;
  667. symbolic procedure savemat(m,name);
  668. if !*mode='algebraic then savemat!*(dpmat_from_a m,name)
  669. else savemat!*(m,name);
  670. symbolic operator initmat;
  671. symbolic procedure initmat name;
  672. if !*mode='algebraic then dpmat_2a initmat!* name
  673. else initmat!* name;
  674. % --------------- Arithmetics for dpmat's ----------------------
  675. symbolic procedure dpmat!=dpsubst(a,b);
  676. % Substitute in the dpoly a each e_i by b_i from the base list b.
  677. begin scalar v;
  678. for each x in b do
  679. v:=dp_sum(v,dp_prod(dp_comp(bas_nr x,a),bas_dpoly x));
  680. return v;
  681. end;
  682. symbolic procedure dpmat_mult(a,b);
  683. % Returns a * b.
  684. if not eqn(dpmat_cols a,dpmat_rows b) then
  685. rerror('dpmat,1," matrices don't match for MATMULT")
  686. else dpmat_make( dpmat_rows a, dpmat_cols b,
  687. for each x in dpmat_list a collect
  688. bas_make(bas_nr x,
  689. dpmat!=dpsubst(bas_dpoly x,dpmat_list b)),
  690. cali!=degrees,nil)
  691. where cali!=degrees:=dpmat_coldegs b;
  692. symbolic procedure dpmat_times_dpoly(f,m);
  693. % Returns f * m for the dpoly f and the dpmat m.
  694. dpmat_make(dpmat_rows m,dpmat_cols m,
  695. for each x in dpmat_list m collect
  696. bas_make1(bas_nr x, dp_prod(f,bas_dpoly x),
  697. dp_prod(f,bas_rep x)),
  698. cali!=degrees,nil) where cali!=degrees:=dpmat_coldegs m;
  699. symbolic procedure dpmat_neg a;
  700. % Returns - a.
  701. dpmat_make(
  702. dpmat_rows a,
  703. dpmat_cols a,
  704. for each x in dpmat_list a collect
  705. bas_make1(bas_nr x,dp_neg bas_dpoly x, dp_neg bas_rep x),
  706. cali!=degrees,dpmat_gbtag a)
  707. where cali!=degrees:=dpmat_coldegs a;
  708. symbolic procedure dpmat_diff(a,b);
  709. % Returns a - b.
  710. dpmat_sum(a,dpmat_neg b);
  711. symbolic procedure dpmat_sum(a,b);
  712. % Returns a + b.
  713. if not (eqn(dpmat_rows a,dpmat_rows b)
  714. and eqn(dpmat_cols a, dpmat_cols b)
  715. and equal(dpmat_coldegs a,dpmat_coldegs b)) then
  716. rerror('dpmat,2,"matrices don't match for MATSUM")
  717. else (begin scalar u,v,w;
  718. u:=dpmat_list a; v:=dpmat_list b;
  719. w:=for i:=1:dpmat_rows a collect
  720. (bas_make1(i,dp_sum(bas_dpoly x,bas_dpoly y),
  721. dp_sum(bas_rep x,bas_rep y))
  722. where y= bas_getelement(i,v),
  723. x= bas_getelement(i,u));
  724. return dpmat_make(dpmat_rows a,dpmat_cols a,w,cali!=degrees,
  725. nil);
  726. end) where cali!=degrees:=dpmat_coldegs a;
  727. symbolic procedure dpmat_from_dpoly p;
  728. if null p then dpmat_make(0,0,nil,nil,t)
  729. else dpmat_make(1,0,list bas_make(1,p),nil,t);
  730. symbolic procedure dpmat_unit(n,degs);
  731. % Returns the unit dpmat of size n.
  732. dpmat_make(n,n, for i:=1:n collect bas_make(i,dp_from_ei i),degs,t);
  733. symbolic procedure dpmat_unitideal!? m;
  734. (dpmat_cols m = 0) and null matop_pseudomod(dp_fi 1,m);
  735. symbolic procedure dpmat_transpose m;
  736. % Returns transposed m with consistent column degrees.
  737. if (dpmat_cols m = 0) then dpmat!=transpose ideal2mat!* m
  738. else dpmat!=transpose m;
  739. symbolic procedure dpmat!=transpose m;
  740. (begin scalar b,p,q;
  741. cali!=degrees:=
  742. for each x in dpmat_rowdegrees m collect
  743. (car x).(mo_neg cdr x);
  744. for i:=1:dpmat_cols m do
  745. << p:=nil;
  746. for j:=1:dpmat_rows m do
  747. << q:=dpmat_element(j,i,m);
  748. if q then p:=dp_sum(p,dp_times_ei(j,q))
  749. >>;
  750. if p then b:=bas_make(i,p) . b;
  751. >>;
  752. return dpmat_make(dpmat_cols m,dpmat_rows m,reverse b,
  753. cali!=degrees,nil);
  754. end) where cali!=degrees:=cali!=degrees;
  755. symbolic procedure ideal2mat!* u;
  756. % Returns u as column vector if dpmat_cols u = 0.
  757. if dpmat_cols u neq 0 then
  758. rerror('dpmat,4,"IDEAL2MAT only for ideal bases")
  759. else dpmat_make(dpmat_rows u,1,
  760. for each x in dpmat_list u collect
  761. bas_make(bas_nr x,dp_times_ei(1,bas_dpoly x)),
  762. nil,dpmat_gbtag u) where cali!=degrees:=nil;
  763. symbolic procedure dpmat_renumber old;
  764. % Renumber dpmat_list old.
  765. % Returns (new . change) with new = change * old.
  766. if null dpmat_list old then (old . dpmat_unit(dpmat_rows old,nil))
  767. else (begin scalar i,u,v,w;
  768. cali!=degrees:=dpmat_rowdegrees old;
  769. i:=0; u:=dpmat_list old;
  770. while u do
  771. <<i:=i+1; v:=bas_newnumber(i,car u) . v;
  772. w:=bas_make(i,dp_from_ei bas_nr car u) . w ; u:=cdr u>>;
  773. return dpmat_make(i,dpmat_cols old,
  774. reverse v,dpmat_coldegs old,dpmat_gbtag old) .
  775. dpmat_make(i,dpmat_rows old,reverse w,cali!=degrees,t);
  776. end) where cali!=degrees:=cali!=degrees;
  777. symbolic procedure mathomogenize!*(m,var);
  778. % Returns m with homogenized rows using the var. name var.
  779. dpmat_make(dpmat_rows m, dpmat_cols m,
  780. bas_homogenize(dpmat_list m,var), cali!=degrees,nil)
  781. where cali!=degrees:=dpmat_coldegs m;
  782. symbolic operator mathomogenize;
  783. symbolic procedure mathomogenize(m,v);
  784. % Returns the homogenized matrix of m with respect to the variable v.
  785. if !*mode='algebraic then
  786. dpmat_2a mathomogenize!*(dpmat_from_a reval m,v)
  787. else matdehomogenize!*(m,v);
  788. symbolic procedure matdehomogenize!*(m,var);
  789. % Returns m with var. name var set equal to one.
  790. dpmat_make(dpmat_rows m, dpmat_cols m,
  791. bas_dehomogenize(dpmat_list m,var), cali!=degrees,nil)
  792. where cali!=degrees:=dpmat_coldegs m;
  793. symbolic procedure dpmat_sieve(m,vars,gbtag);
  794. % Apply bas_sieve to dpmat_list m. The gbtag slot allows to set the
  795. % gbtag of the result.
  796. dpmat_make(length x,dpmat_cols m,x,cali!=degrees,gbtag)
  797. where x=bas_sieve(dpmat_list m,vars)
  798. where cali!=degrees:=dpmat_coldegs m;
  799. symbolic procedure dpmat_neworder(m,gbtag);
  800. % Apply bas_neworder to dpmat_list m with current cali!=degrees.
  801. % The gbtag sets the gbtag part of the result.
  802. dpmat_make(dpmat_rows m,dpmat_cols m,
  803. bas_neworder dpmat_list m,cali!=degrees,gbtag);
  804. symbolic procedure dpmat_zero!? m;
  805. % Test whether m is a zero dpmat.
  806. bas_zero!? dpmat_list m;
  807. symbolic procedure dpmat_project(m,k);
  808. % Project the dpmat m onto its first k components.
  809. dpmat_make(dpmat_rows m,k,
  810. for each x in dpmat_list m collect
  811. bas_make(bas_nr x,dp_project(bas_dpoly x,k)),
  812. dpmat_coldegs m,nil);
  813. % ---------- Interface to algebraic mode
  814. symbolic procedure dpmat_2a m;
  815. % Convert the dpmat m to a matrix (c>0) or a polynomial list (c=0) in
  816. % algebraic (pseudo)prefix form.
  817. if dpmat_cols m=0 then bas_2a dpmat_list m
  818. else 'mat .
  819. if dpmat_rows m=0 then list for j:=1:dpmat_cols m collect 0
  820. else for i:=1:dpmat_rows m collect
  821. for j:=1:dpmat_cols m collect
  822. dp_2a dpmat_element(i,j,m);
  823. symbolic procedure dpmat_from_a m;
  824. % Convert an algebraic polynomial list or matrix expression into a
  825. % dpmat with respect to the current setting of cali!=degrees.
  826. if eqcar(m,'mat) then
  827. begin integer i; scalar u,p; m:=cdr m;
  828. for each x in m do
  829. << i:=1; p:=nil;
  830. for each y in x do
  831. << p:=dp_sum(p,dp_times_ei(i,dp_from_a reval y)); i:=i+1 >>;
  832. u:=bas_make(0,p).u
  833. >>;
  834. return dpmat_make(length m,length car m,
  835. bas_renumber reversip u, cali!=degrees,nil);
  836. end
  837. else if eqcar(m,'list) then
  838. ((begin scalar x; x:=bas_from_a reval m;
  839. return dpmat_make(length x,0,x,nil,nil)
  840. end) where cali!=degrees:=nil)
  841. else typerr(m,"polynomial list or matrix");
  842. % ---- Substitution in dpmats --------------
  843. symbolic procedure dpmat_sub(a,m);
  844. % a=list of (var . alg. prefix form) to be substituted into the dpmat
  845. % m.
  846. dpmat_from_a subeval1(a,dpmat_2a m)
  847. where cali!=degrees:=dpmat_coldegs m;
  848. % ------------- Determinant ------------------------
  849. symbolic procedure dpmat_det m;
  850. % Returns the determinant of the dpmat m.
  851. if dpmat_rows m neq dpmat_cols m then rederr "non-square matrix"
  852. else dp_from_a prepf numr detq matsm dpmat_2a m;
  853. endmodule; % dpmat
  854. end;
  855. module dpoly;
  856. COMMENT
  857. ##################
  858. ## ##
  859. ## POLYNOMIALS ##
  860. ## ##
  861. ##################
  862. Polynomial vectors and polynomials are handled in a unique way using
  863. the module component of monomials to store the vector component. If
  864. the component is 0, we have a polynomial, otherwise a vector. They
  865. are represented in a distributive form (dpoly for short).
  866. Informal syntax of (vector) polynomials :
  867. <dpoly> ::= list of <term>s
  868. <term> ::= ( <monomial> . <base coefficient> )
  869. END COMMENT;
  870. % ----------- constructors and selectors -------------------
  871. symbolic procedure dp_lc p;
  872. % Leading base coefficient of the dpoly p.
  873. cdar p;
  874. symbolic procedure dp_lmon p;
  875. % Leading monomial of the dpoly p.
  876. caar p;
  877. symbolic procedure dp_term (a,e);
  878. % Constitutes a term from a:base coeff. and e:monomial.
  879. (e . a);
  880. symbolic procedure dp_from_ei n;
  881. % Returns e_i as dpoly.
  882. list dp_term(bc_fi 1,mo_from_ei n);
  883. symbolic procedure dp_fi n;
  884. % dpoly from integer
  885. if n=0 then nil else
  886. list dp_term(bc_fi n,mo_zero());
  887. symbolic procedure dp_fbc c;
  888. % Converts the base coefficient c into a dpoly.
  889. if bc_zero!? c then nil else
  890. list dp_term(c,mo_zero());
  891. % ------------ dpoly arithmetics ---------------------------
  892. symbolic procedure dp!=comp(i,v);
  893. if null v then nil
  894. else if eqn(mo_comp dp_lmon v,i) then car v . dp!=comp(i,cdr v)
  895. else dp!=comp(i,cdr v);
  896. symbolic procedure dp_comp(i,v);
  897. % Returns the (polynomial) component i of the vector v.
  898. for each x in dp!=comp(i,v) collect (mo_deletecomp car x) . cdr x;
  899. symbolic procedure dp!=mocompare (t1,t2);
  900. % true <=> term t1 is smaller than term t2 in the current term order.
  901. eqn(mo_compare (car t1, car t2),1);
  902. symbolic procedure dp_neworder p;
  903. % Returns reordered dpoly p after change of the term order.
  904. sort(for each x in p collect (mo_neworder car x) . cdr x,
  905. function dp!=mocompare);
  906. symbolic procedure dp_neg p;
  907. % Returns - p for the dpoly p.
  908. for each x in p collect (car x . bc_neg cdr x);
  909. symbolic procedure dp_times_mo (mo,p);
  910. % Returns p * x^mo for the dpoly p and the monomial mo.
  911. for each x in p collect (mo_sum(mo,car x) . cdr x);
  912. symbolic procedure dp_times_bc (bc,p);
  913. % Returns p * bc for the dpoly p and the base coeff. bc.
  914. for each x in p collect (car x . bc_prod(bc,cdr x));
  915. symbolic procedure dp_times_bcmo (bc,mo,p);
  916. % Returns p * bc * x^mo for the dpoly p, the monomial mo and the base
  917. % coeff. bc.
  918. for each x in p collect (mo_sum(mo,car x) . bc_prod(bc,cdr x));
  919. symbolic procedure dp_times_ei(i,p);
  920. % Returns p * e_i for the dpoly p.
  921. dp_neworder for each x in p collect (mo_times_ei(i,car x) . cdr x);
  922. symbolic procedure dp_project(p,k);
  923. % Delete all terms x^a*e_i with i>k.
  924. for each x in p join if mo_comp car x <= k then {x};
  925. symbolic procedure dp_content p;
  926. % Returns the leading coefficient, if invertible, or the content of
  927. % p.
  928. if null p then bc_fi 0
  929. else begin scalar w;
  930. w:=dp_lc p; p:=cdr p;
  931. while p and not bc_inv w do
  932. << w:=bc_gcd(w,dp_lc p); p:=cdr p >>;
  933. return w
  934. end;
  935. symbolic procedure dp_mondelete(p,s);
  936. % Returns (p.m) with common monomial factor m with support in the
  937. % var. list s deleted.
  938. if null p or null s then (p . mo_zero()) else
  939. begin scalar cmf;
  940. cmf:=dp!=cmf(p,s);
  941. if mo_zero!? cmf then return (p . cmf)
  942. else return
  943. cons(for each x in p collect mo_diff(car x,cmf) . cdr x,cmf)
  944. end;
  945. symbolic procedure dp!=cmf(p,s);
  946. begin scalar a;
  947. a:=mo_seed(dp_lmon p,s); p:=cdr p;
  948. while p and (not mo_zero!? a) do
  949. << a:=mo_gcd(a,mo_seed(dp_lmon p,s)); p:=cdr p >>;
  950. return a
  951. end;
  952. symbolic procedure dp_unit!? p;
  953. % Tests whether lt p of the dpoly p is a unit.
  954. % This means : p is a unit, if the t.o. is noetherian
  955. % or : p is a local unit, if the t.o. is a tangentcone order.
  956. p and (mo_zero!? dp_lmon p);
  957. symbolic procedure dp_simp pol;
  958. % Returns (pol_new . z) with
  959. % pol_new having leading coefficient 1 or
  960. % dp_content pol canceled out
  961. % and pol_old = z * dpoly_new .
  962. if null pol then pol . bc_fi 1
  963. else begin scalar z,z1;
  964. if (z:=bc_inv (z1:=dp_lc pol)) then
  965. return dp_times_bc(z,pol) . z1;
  966. % -- now we assume that base coefficients are a gcd domain ----
  967. z:=dp_content pol;
  968. if bc_minus!? z1 then z:=bc_neg z;
  969. pol:=for each x in pol collect
  970. car x . car bc_divmod(cdr x,z);
  971. return pol . z;
  972. end;
  973. symbolic procedure dp_prod(p1,p2);
  974. % Returns p1 * p2 for the dpolys p1 and p2.
  975. if length p1 <= length p2 then dp!=prod(p1,p2)
  976. else dp!=prod(p2,p1);
  977. symbolic procedure dp!=prod(p1,p2);
  978. if null p1 or null p2 then nil
  979. else
  980. begin scalar v;
  981. for each x in p1 do
  982. v:=dp_sum( dp_times_bcmo(cdr x,car x, p2 ),v);
  983. return v;
  984. end;
  985. symbolic procedure dp_sum(p1,p2);
  986. % Returns p1 + p2 for the dpolys p1 and p2.
  987. if null p1 then p2
  988. else if null p2 then p1
  989. else begin scalar sl,al;
  990. sl := mo_compare(dp_lmon p1, dp_lmon p2);
  991. if sl = 1 then return car p1 . dp_sum(cdr p1, p2);
  992. if sl = -1 then return car p2 . dp_sum(p1, cdr p2);
  993. al := bc_sum(dp_lc p1, dp_lc p2);
  994. if bc_zero!? al then return dp_sum(cdr p1, cdr p2)
  995. else return dp_term(al,dp_lmon p1) . dp_sum(cdr p1, cdr p2)
  996. end;
  997. symbolic procedure dp_diff(p1,p2);
  998. % Returns p1 - p2 for the dpolys p1 and p2.
  999. dp_sum(p1, dp_neg p2);
  1000. symbolic procedure dp_power(p,n);
  1001. % Returns p^n for the dpoly p.
  1002. if (not fixp n) or (n < 0) then typerr(n," exponent")
  1003. else if n=0 then dp_fi 1
  1004. else if n=1 then p
  1005. else if null cdr p then dp!=power1(p,n)
  1006. else dp!=power(p,n);
  1007. symbolic procedure dp!=power1(p,n); % For monomials.
  1008. list dp_term(bc_power(dp_lc p,n),mo_power(dp_lmon p,n));
  1009. symbolic procedure dp!=power(p,n);
  1010. if n=1 then p
  1011. else if evenp n then dp!=power(dp_prod(p,p),n/2)
  1012. else dp_prod(p,dp!=power(dp_prod(p,p),n/2));
  1013. symbolic procedure dp_tcpart p;
  1014. % Return the homogeneous degree part of p of highest degree.
  1015. if null p then nil
  1016. else begin scalar d,u; d:=car mo_deg caar p;
  1017. while p and (d=car mo_deg caar p) do
  1018. << u:=car p . u; p:=cdr p >>;
  1019. return reversip u;
  1020. end;
  1021. symbolic procedure dp_deletecomp p;
  1022. % delete the component part from all terms.
  1023. dp_neworder for each x in p collect mo_deletecomp car x . cdr x;
  1024. symbolic procedure dp_factor p;
  1025. for each y in cdr ((fctrf numr simp dp_2a p) where !*factor=t)
  1026. collect dp_from_a prepf car y;
  1027. % ------ Converting prefix forms into dpolys ------------------
  1028. symbolic procedure dp_from_a u;
  1029. % Converts the algebraic (prefix) form u into a dpoly.
  1030. if eqcar(u,'list) or eqcar(u,'mat) then typerr(u,"dpoly")
  1031. else if atom u then dp!=a2dpatom u
  1032. else if not atom car u or not idp car u
  1033. then typerr(car u,"dpoly operator")
  1034. else (if x='dp!=fnpow then dp!=fnpow(dp_from_a cadr u,caddr u)
  1035. else if x then
  1036. apply(x,list for each y in cdr u collect dp_from_a y)
  1037. else dp!=a2dpatom u)
  1038. where x = get(car u,'dp!=fn);
  1039. symbolic procedure dp!=a2dpatom u;
  1040. % Converts the atom (or kernel) u into a dpoly.
  1041. if u=0 then nil
  1042. else if numberp u or not member(u, ring_all_names cali!=basering)
  1043. then list dp_term(bc_from_a u,mo_zero())
  1044. else list dp_term(bc_fi 1,mo_from_a u);
  1045. symbolic procedure dp!=fnsum u;
  1046. % U is a list of dpoly expressions. The result is the dpoly
  1047. % representation for the sum. Analogously for the other symbolic
  1048. % procedures below.
  1049. (<<for each y in cdr u do x := dp_sum(x,y); x>>) where x = car u;
  1050. put('plus,'dp!=fn,'dp!=fnsum);
  1051. put('plus2,'dp!=fn,'dp!=fnsum);
  1052. symbolic procedure dp!=fnprod u;
  1053. (<<for each y in cdr u do x := dp_prod(x,y); x>>) where x = car u;
  1054. put('times,'dp!=fn,'dp!=fnprod);
  1055. put('times2,'dp!=fn,'dp!=fnprod);
  1056. symbolic procedure dp!=fndif u; dp_diff(car u, cadr u);
  1057. put('difference,'dp!=fn,'dp!=fndif);
  1058. symbolic procedure dp!=fnpow(u,n); dp_power(u,n);
  1059. put('expt,'dp!=fn,'dp!=fnpow);
  1060. symbolic procedure dp!=fnneg u;
  1061. ( if null v then v else dp_term(bc_neg dp_lc v,dp_lmon v) . cdr v)
  1062. where v = car u;
  1063. put('minus,'dp!=fn,'dp!=fnneg);
  1064. symbolic procedure dp!=fnquot u;
  1065. if null cadr u or not null cdadr u
  1066. or not mo_zero!? dp_lmon cadr u
  1067. then typerr(dp_2a cadr u,"distributive polynomial denominator")
  1068. else dp!=fnquot1(car u,dp_lc cadr u);
  1069. symbolic procedure dp!=fnquot1(u,v);
  1070. if null u then u
  1071. else dp_term(bc_quot(dp_lc u,v), dp_lmon u) .
  1072. dp!=fnquot1(cdr u,v);
  1073. put('quotient,'dp!=fn,'dp!=fnquot);
  1074. % -------- Converting dpolys into prefix forms -------------
  1075. % ------ Authors: R. Gebauer, A. C. Hearn, H. Kredel -------
  1076. symbolic procedure dp_2a u;
  1077. % Returns the prefix equivalent of the dpoly u.
  1078. if null u then 0 else dp!=replus dp!=2a u;
  1079. symbolic procedure dp!=2a u;
  1080. if null u then nil
  1081. else ((if bc_minus!? x then
  1082. list('minus,dp!=retimes(bc_2a bc_neg x . y))
  1083. else dp!=retimes(bc_2a x . y))
  1084. where x = dp_lc u, y = mo_2a dp_lmon u)
  1085. . dp!=2a cdr u;
  1086. symbolic procedure dp!=replus u;
  1087. if atom u then u else if null cdr u then car u else 'plus . u;
  1088. symbolic procedure dp!=retimes u;
  1089. % U is a list of prefix expressions the first of which is a number.
  1090. % The result is the prefix representation for their product.
  1091. if car u = 1 then if cdr u then dp!=retimes cdr u else 1
  1092. else if null cdr u then car u
  1093. else 'times . u;
  1094. % ----------- Printing routines for dpolys --------------
  1095. % ---- Authors: R. Gebauer, A. C. Hearn, H. Kredel ------
  1096. symbolic procedure dp_print u;
  1097. % Prints a distributive polynomial in infix form.
  1098. << terpri(); dp_print1(u,nil); terpri(); terpri() >>;
  1099. symbolic procedure dp_print1(u,v);
  1100. % Prints a dpoly in infix form.
  1101. % U is a distributive form. V is a flag which is true if a term
  1102. % has preceded current form.
  1103. if null u then if null v then print_lf 0 else nil
  1104. else begin scalar bool,w;
  1105. w := dp_lc u;
  1106. if bc_minus!? w then <<bool := t; w := bc_neg w>>;
  1107. if bool then print_lf " - " else if v then print_lf " + ";
  1108. ( if not bc_one!? w or mo_zero!? x then
  1109. << bc_prin w; mo_prin(x,t)>>
  1110. else mo_prin(x,nil))
  1111. where x = dp_lmon u;
  1112. dp_print1(cdr u,t)
  1113. end;
  1114. symbolic procedure dp_print2 u;
  1115. % Prints a dpoly with restricted number of terms.
  1116. (if c and (length u>c) then
  1117. begin scalar i,v,x;
  1118. v:=for i:=1:c collect <<x:=car u; u:=cdr u; x>>;
  1119. dp_print1(v,nil); write" + # ",length u," terms #"; terpri();
  1120. end
  1121. else << dp_print1(u,nil); terpri() >>)
  1122. where c:=get('cali,'printterms);
  1123. % -------------- Auxiliary dpoly operations -------------------
  1124. symbolic procedure dp_ecart p;
  1125. % Returns the ecart of the dpoly p.
  1126. if null p then 0 else (dp!=ecart p) - (mo_ecart dp_lmon p);
  1127. symbolic procedure dp!=ecart p;
  1128. if null p then 0
  1129. else max2(mo_ecart dp_lmon p,dp!=ecart cdr p);
  1130. symbolic procedure dp_homogenize(p,x);
  1131. % Homogenize (according to mo_ecart) the dpoly p using the variable x.
  1132. if null p then p
  1133. else begin integer maxdeg;
  1134. maxdeg:=0;
  1135. for each y in p do maxdeg:=max2(maxdeg,mo_ecart car y);
  1136. return dp!=compact dp_neworder for each y in p collect
  1137. mo_inc(car y,x,maxdeg-mo_ecart car y) . cdr y;
  1138. end;
  1139. symbolic procedure dp_seed(p,s);
  1140. % Returns the dpoly p with all vars outside the list s set equal to 1.
  1141. if null p then p
  1142. else dp!=compact dp_neworder
  1143. for each x in p collect mo_seed(car x,s).cdr x;
  1144. symbolic procedure dp!=compact p;
  1145. % Collect equal terms in the sorted dpoly p.
  1146. if null p then p else dp_sum(list car p,dp!=compact cdr p);
  1147. symbolic procedure dp_xlt(p,x);
  1148. % x is the main variable. Returns the leading term of p wrt. x or p,
  1149. % if p is free of x.
  1150. if null p then p
  1151. else begin scalar d,m;
  1152. d:=mo_varexp(x,dp_lmon p);
  1153. if d=0 then return p;
  1154. return for each m in p join
  1155. if mo_varexp(x,car m)=d then {mo_inc(car m,x,-d) . cdr m};
  1156. end;
  1157. % -- dpoly operations based on computation with ideal bases.
  1158. symbolic procedure dp_pseudodivmod(g,f);
  1159. % Returns a dpoly list {q,r,z} such that z * g = q * f + r and
  1160. % z is a dpoly unit. Computes redpol({[f.e_1]},[g.0]).
  1161. % g, f and r must belong to the same free module.
  1162. begin scalar u;
  1163. f:=list bas_make1(1,f,dp_from_ei 1);
  1164. g:=bas_make(0,g);
  1165. u:=red_redpol(f,g);
  1166. return {dp_neg dp_deletecomp bas_rep car u,bas_dpoly car u,cdr u};
  1167. end;
  1168. symbolic operator dpgcd;
  1169. symbolic procedure dpgcd(u,v);
  1170. if !*mode='algebraic then dp_2a dpgcd!*(dp_from_a u,dp_from_a v)
  1171. else dpgcd!*(u,v);
  1172. symbolic procedure dpgcd!*(u,v);
  1173. % Compute the gcd of two polynomials by the syzygy method :
  1174. % 0 = u*u1 + v*v1 => gcd = u/v1 = -v/u1 .
  1175. if dp_unit!? u or dp_unit!? v then dp_fi 1
  1176. else begin scalar w;
  1177. w:=bas_dpoly first dpmat_list
  1178. syzygies!* dpmat_make(2,0,{bas_make(1,u),bas_make(2,v)},nil,nil);
  1179. return car dp_pseudodivmod(u,dp_comp(2,w));
  1180. end;
  1181. endmodule; % dpoly
  1182. end;
  1183. module groeb;
  1184. COMMENT
  1185. ##############################
  1186. ## ##
  1187. ## GROEBNER PACKAGE ##
  1188. ## ##
  1189. ##############################
  1190. This is now a common package, covering both the noetherian and the
  1191. local term orders.
  1192. The trace intensity can be managed with cali_trace() by the following
  1193. rules :
  1194. cali_trace() >= 0 no trace
  1195. 2 show actual step
  1196. 10 show input and output
  1197. 20 show new base elements
  1198. 30 show pairs
  1199. 40 show actual pairlist
  1200. 50 show S-polynomials
  1201. Pair lists have the following informal syntax :
  1202. <spairlist>::= list of spairs
  1203. < spair > ::= (komp groeb!=weight lcm p_i p_j)
  1204. with lcm = lcm(lt(bas_dpoly p_i),lt(bas_dpoly p_j)).
  1205. The pair selection strategy is by first matching in the pair list.
  1206. It can be changed overloading groeb!=better, the relation according to
  1207. what pair lists are sorted. Standard is the sugar strategy.
  1208. cali!=monset :
  1209. One can manage a list of variables, that are allowed to be canceled
  1210. out, if they appear as common factors in a dpoly. This is possible if
  1211. these variables are non zero divisors (e.g. for prime ideals) and
  1212. affects "pure" Groebner basis computation only.
  1213. END COMMENT;
  1214. % ############ The outer Groebner engine #################
  1215. put('cali,'groeb!=rf,'groeb!=rf1); % First initialization.
  1216. symbolic operator gbtestversion;
  1217. symbolic procedure gbtestversion n; % Choose the corresponding driver
  1218. if member(n,{1,2,3}) then
  1219. put('cali,'groeb!=rf,mkid('groeb!=rf,n));
  1220. symbolic procedure groeb!=postprocess pol;
  1221. % Postprocessing for irreducible H-Polynomials. The switches got
  1222. % appropriate local values in the Groebner engine.
  1223. begin
  1224. if !*bcsimp then pol:=car bas_simpelement pol;
  1225. if not !*noetherian then
  1226. if !*factorunits then pol:=bas_factorunits pol
  1227. else if !*detectunits then pol:=bas_detectunits pol;
  1228. if cali!=monset then pol:=bas_make(bas_nr pol,
  1229. car dp_mondelete(bas_dpoly pol,cali!=monset));
  1230. return pol
  1231. end;
  1232. symbolic procedure groeb_stbasis(bas,comp_mgb,comp_ch,comp_syz);
  1233. groeb!=choose_driver(bas,comp_mgb,comp_ch,comp_syz,
  1234. function groeb!=generaldriver);
  1235. symbolic procedure
  1236. groeb!=choose_driver(bas,comp_mgb,comp_ch,comp_syz,driver);
  1237. % Returns { mgb , change , syz } with
  1238. % dpmat mgb = (if comp_mgb=true the minimal)
  1239. % Groebner basis of the dpmat bas.
  1240. % dpmat change defined by mgb = change * bas
  1241. % if comp_ch = true.
  1242. % dpmat syz = (not interreduced) syzygy matrix of the dpmat bas
  1243. % if comp_syz = true.
  1244. % Changes locally !*factorunits, !*detectunits and cali!=monset.
  1245. if dpmat_zero!? bas then
  1246. {bas,dpmat_unit(dpmat_rows bas,nil),
  1247. dpmat_unit(dpmat_rows bas,nil)}
  1248. else (begin scalar u, gb, syz, change, syz1;
  1249. % ------- Syzygies for the zero base elements.
  1250. if comp_syz then
  1251. << u:=setdiff(for i:=1:dpmat_rows bas collect i,
  1252. for each x in
  1253. bas_zerodelete dpmat_list bas collect bas_nr x);
  1254. syz1:=for each x in u collect bas_make(0,dp_from_ei x);
  1255. >>;
  1256. % ------- Initialize the Groebner computation.
  1257. gb:=bas_zerodelete dpmat_list bas;
  1258. % makes a copy (!) of the base list.
  1259. if comp_ch or comp_syz then
  1260. << !*factorunits:=!*detectunits:=cali!=monset:=nil;
  1261. bas_setrelations gb;
  1262. >>;
  1263. if cali_trace() > 5 then
  1264. << terpri(); write" Compute GBasis of"; bas_print gb >>
  1265. else if cali_trace() > 0 then
  1266. << terpri(); write" Computing GBasis ";terpri() >>;
  1267. u:=apply(driver,{dpmat_rows bas,dpmat_cols bas,gb,comp_syz});
  1268. syz:=second u;
  1269. if comp_mgb then
  1270. << u:=groeb_mingb car u;
  1271. if !*red_total then
  1272. u:=dpmat_make(dpmat_rows u,dpmat_cols u,
  1273. red_straight dpmat_list u,
  1274. cali!=degrees,t);
  1275. >>
  1276. else u:=car u;
  1277. cali!=degrees:=dpmat_rowdegrees bas;
  1278. if comp_ch then
  1279. change:=dpmat_make(dpmat_rows u,dpmat_rows bas,
  1280. bas_neworder bas_getrelations dpmat_list u,
  1281. cali!=degrees,nil);
  1282. bas_removerelations dpmat_list u;
  1283. if comp_syz then
  1284. << syz:=nconc(syz,syz1);
  1285. syz:= dpmat_make(length syz,dpmat_rows bas,
  1286. bas_neworder bas_renumber syz,cali!=degrees,nil);
  1287. >>;
  1288. cali!=degrees:=dpmat_coldegs u;
  1289. return {u,change,syz}
  1290. end) where cali!=degrees:=dpmat_coldegs bas,
  1291. !*factorunits:=!*factorunits,
  1292. !*detectunits:=!*detectunits,
  1293. cali!=monset:=cali!=monset;
  1294. % ######### The General Groebner driver ###############
  1295. Comment
  1296. It returns {gb,syz,trace} with change on the relation part of gb,
  1297. where
  1298. INPUT : r, c, gb = rows, columns, base list
  1299. OUTPUT :
  1300. <dpmat> gb is the Groebner basis
  1301. <base list> syz is the dpmat_list of the syzygy matrix
  1302. <spairlist> trace is the Groebner trace.
  1303. There are three different versions of the general driver that branche
  1304. according to a reduction function
  1305. rf : {pol,simp} |---> {pol,simp}
  1306. found with get('cali,'groeb!=rf):
  1307. 1. Total reduction with local simplifier lists. For local term orders
  1308. this is (almost) Mora's first version for the tangent cone.
  1309. 2. Total reduction with global simplifier list. For local term orders
  1310. this is (almost) Mora's SimpStBasis.
  1311. 3. Total reduction with bounded ecart. This needs no extra simplifier
  1312. list.
  1313. end Comment;
  1314. symbolic procedure groeb!=generaldriver(r,c,gb,comp_syz);
  1315. begin scalar u, q, syz, p, pl, pol, trace, return_by_unit,
  1316. simp, rf, Ccrit;
  1317. Ccrit:=(not comp_syz) and (c<2); % don't reduce main syzygies
  1318. simp:=sort(listminimize(gb,function red!=cancelsimp),
  1319. function red_better);
  1320. pl:=groeb_makepairlist(gb,Ccrit);
  1321. rf:=get('cali,'groeb!=rf);
  1322. if cali_trace() > 30 then groeb_printpairlist pl;
  1323. if cali_trace() > 5 then
  1324. <<terpri(); write" New base elements :";terpri() >>;
  1325. % -------- working out pair list
  1326. while pl and not return_by_unit do
  1327. << % ------- Choose a pair
  1328. p:=car pl; pl:=cdr pl;
  1329. % ------ compute S-polynomial (which is a base element)
  1330. if cali_trace() > 10 then groeb_printpair(p,pl);
  1331. u:=apply2(rf,groeb_spol p,simp);
  1332. pol:=first u; simp:=second u;
  1333. if cali_trace() > 70 then
  1334. << terpri(); write" Reduced S.-pol. : ";
  1335. dp_print2 bas_dpoly pol
  1336. >>;
  1337. if bas_dpoly pol then
  1338. % --- the S-polynomial doesn't reduce to zero
  1339. << pol:=groeb!=postprocess pol;
  1340. r:=r+1;
  1341. pol:=bas_newnumber(r,pol);
  1342. % --- update the tracelist
  1343. q:=bas_dpoly pol;
  1344. trace:=list(groeb!=i p,groeb!=j p,r,dp_lmon q) . trace;
  1345. if cali_trace() > 20 then
  1346. << terpri(); write r,". ---> "; dp_print2 q >>;
  1347. if Ccrit and (dp_unit!? q) then return_by_unit:=t;
  1348. % ----- update
  1349. if not return_by_unit then
  1350. << pl:=groeb_updatePL(pl,gb,pol,Ccrit);
  1351. if cali_trace() > 30 then
  1352. << terpri(); groeb_printpairlist pl >>;
  1353. gb:=pol.gb;
  1354. simp:=red_update(simp,pol);
  1355. >>;
  1356. >>
  1357. else % ------ S-polynomial reduces to zero
  1358. if comp_syz then
  1359. syz:=car bas_simpelement(bas_make(0,bas_rep pol)) . syz
  1360. >>;
  1361. % -------- updating the result
  1362. if cali_trace()>0 then
  1363. << terpri(); write " Simplifier list has length ",length simp >>;
  1364. if return_by_unit then return
  1365. % --- no syzygies are to be computed
  1366. {dpmat_from_dpoly pol,nil,reversip trace};
  1367. gb:=dpmat_make(length gb,c,gb,cali!=degrees,t);
  1368. return {gb,syz,reversip trace}
  1369. end;
  1370. % --- The different reduction functions.
  1371. symbolic procedure groeb!=rf1(pol,simp); {red_TotalRed(simp,pol),simp};
  1372. symbolic procedure groeb!=rf2(pol,simp);
  1373. if (null bas_dpoly pol) or (null simp) then {pol,simp}
  1374. else begin scalar v,q;
  1375. % Make first reduction with bounded ecart.
  1376. pol:=red_TopRedBE(simp,pol);
  1377. % Now loop into reduction with minimal ecart.
  1378. while (q:=bas_dpoly pol) and (v:=red_divtest(simp,dp_lmon q)) do
  1379. << v:=red_subst(pol,v);
  1380. % Updating the simplifier list could make sense even
  1381. % for the noetherian case, since it is a global list.
  1382. simp:=red_update(simp,pol);
  1383. pol:=red_TopRedBE(simp,v);
  1384. >>;
  1385. % Now make tail reduction
  1386. if !*red_total and bas_dpoly pol then pol:=red_TailRed(simp,pol);
  1387. return {pol,simp};
  1388. end;
  1389. symbolic procedure groeb!=rf3(pol,simp);
  1390. % Total reduction with bounded ecart.
  1391. if (null bas_dpoly pol) or (null simp) then {pol,simp}
  1392. else begin
  1393. pol:=red_TopRedBE(simp,pol);
  1394. if bas_dpoly pol then
  1395. pol:=red_TailRedDriver(simp,pol,function red_TopRedBE);
  1396. return {pol,simp};
  1397. end;
  1398. % ######### The Lazy Groebner driver ###############
  1399. Comment
  1400. The lazy groebner driver implements the lazy strategy for local
  1401. standard bases, i.e. stepwise reduction of S-Polynomials according to
  1402. a refinement of the (ascending) division order on leading terms.
  1403. end Comment;
  1404. symbolic procedure groeb_lazystbasis(bas,comp_mgb,comp_ch,comp_syz);
  1405. groeb!=choose_driver(bas,comp_mgb,comp_ch,comp_syz,
  1406. function groeb!=lazydriver);
  1407. symbolic procedure groeb!=lazymocompare(a,b);
  1408. % A dpoly with leading monomial a should be processed before dpolys
  1409. % with leading monomial b.
  1410. mo_ecart a < mo_ecart b;
  1411. symbolic procedure groeb!=queuesort(a,b);
  1412. % Sort criterion for the queue.
  1413. groeb!=lazymocompare(dp_lmon bas_dpoly a,dp_lmon bas_dpoly b);
  1414. symbolic procedure groeb!=nextspol(pl,queue);
  1415. % True <=> take first pl next.
  1416. if null queue then t
  1417. else if null pl then nil
  1418. else groeb!=lazymocompare(nth(car pl,3),dp_lmon bas_dpoly car queue);
  1419. symbolic procedure groeb!=lazydriver(r,c,gb,comp_syz);
  1420. % The lazy version of the driver.
  1421. begin scalar syz, Ccrit, queue, v, simp, p, pl, pol, return_by_unit;
  1422. simp:=sort(listminimize(gb,function red!=cancelsimp),
  1423. function red_better);
  1424. Ccrit:=(not comp_syz) and (c<2); % don't reduce main syzygies
  1425. pl:=groeb_makepairlist(gb,Ccrit);
  1426. if cali_trace() > 30 then groeb_printpairlist pl;
  1427. if cali_trace() > 5 then
  1428. <<terpri(); write" New base elements :";terpri() >>;
  1429. % -------- working out pair list
  1430. while (pl or queue) and not return_by_unit do
  1431. if groeb!=nextspol(pl,queue) then
  1432. << p:=car pl; pl:=cdr pl;
  1433. if cali_trace() > 10 then groeb_printpair(p,pl);
  1434. pol:=groeb_spol p;
  1435. if bas_dpoly pol then % back into the queue
  1436. if Ccrit and dp_unit!? bas_dpoly pol then
  1437. return_by_unit:=t
  1438. else queue:=merge(list pol, queue,
  1439. function groeb!=queuesort)
  1440. else if comp_syz then % pol reduced to zero.
  1441. syz:=bas_simpelement bas_make(0,bas_rep pol).syz;
  1442. >>
  1443. else
  1444. << pol:=car queue; queue:=cdr queue;
  1445. % Try one top reduction step
  1446. if (v:=red_divtestBE(simp,dp_lmon bas_dpoly pol,
  1447. bas_dpecart pol)) then ()
  1448. % do nothing with simp !
  1449. else if (v:=red_divtest(simp,dp_lmon bas_dpoly pol)) then
  1450. simp:=red_update(simp,pol);
  1451. % else v:=nil;
  1452. if v then % do one top reduction step
  1453. << pol:=red_subst(pol,v);
  1454. if bas_dpoly pol then % back into the queue
  1455. queue:=merge(list pol, queue,
  1456. function groeb!=queuesort)
  1457. else if comp_syz then % pol reduced to zero.
  1458. syz:=bas_simpelement bas_make(0,bas_rep pol).syz;
  1459. >>
  1460. else % no reduction possible
  1461. << % make a tail reduction with bounded ecart and the
  1462. % usual postprocessing :
  1463. pol:=groeb!=postprocess
  1464. if !*red_total then
  1465. red_TailRedDriver(gb,pol,function red_TopRedBE)
  1466. else pol;
  1467. if dp_unit!? bas_dpoly pol then return_by_unit:=t
  1468. else % update the computation
  1469. << r:=r+1; pol:=bas_newnumber(r,pol);
  1470. if cali_trace() > 20 then
  1471. << terpri(); write r,". --> "; dp_print2 bas_dpoly pol>>;
  1472. pl:=groeb_updatePL(pl,gb,pol,Ccrit);
  1473. simp:=red_update(simp,pol);
  1474. gb:=pol.gb;
  1475. >>
  1476. >>
  1477. >>;
  1478. % -------- updating the result
  1479. if cali_trace()>0 then
  1480. << terpri(); write " Simplifier list has length ",length simp >>;
  1481. if return_by_unit then return {dpmat_from_dpoly pol,nil,nil}
  1482. else return
  1483. {dpmat_make(length simp,c,simp,cali!=degrees,t), syz, nil}
  1484. end;
  1485. % ################ The Groebner Tools ##############
  1486. % ---------- Critical pair criteria -----------------------
  1487. symbolic procedure groeb!=critA(p);
  1488. % p is a pair list {(i.k):i running} of pairs with equal module
  1489. % component number. Choose those pairs among them that are minimal wrt.
  1490. % division order on lcm(i.k).
  1491. listminimize(p,function groeb!=testA);
  1492. symbolic procedure groeb!=testA(p,q); mo_divides!?(nth(p,3),nth(q,3));
  1493. symbolic procedure groeb!=critB(e,p);
  1494. % Delete pairs from p, for which testB is false.
  1495. for each x in p join if not groeb!=testB(e,x) then {x};
  1496. symbolic procedure groeb!=testB(e,a);
  1497. % e=lt(f_k). Test, whether for a=pair (i j)
  1498. % komp(a)=komp(e) and Syz(i,j,k)=[ 1 * * ].
  1499. (mo_comp e=car a)
  1500. and mo_divides!?(e,nth(a,3))
  1501. and (not mo_equal!?(mo_lcm(dp_lmon bas_dpoly nth(a,5),e),
  1502. nth(a,3)))
  1503. and (not mo_equal!?(mo_lcm(dp_lmon bas_dpoly nth(a,4),e),
  1504. nth(a,3)));
  1505. symbolic procedure groeb!=critC(p);
  1506. % Delete main syzygies.
  1507. for each x in p join if not groeb!=testC1 x then {x};
  1508. symbolic procedure groeb!=testC1 el;
  1509. mo_equal!?(
  1510. mo_sum(dp_lmon bas_dpoly nth(el,5),
  1511. dp_lmon bas_dpoly nth(el,4)),
  1512. nth(el,3));
  1513. symbolic procedure groeb_updatePL(p,gb,be,Ccrit);
  1514. % Update the pairlist p with the new base element be and the old ones
  1515. % in the base list gb. Discard pairs where both base elements have
  1516. % number part 0.
  1517. begin scalar p1,k,a,n; n:=(bas_nr be neq 0);
  1518. a:=dp_lmon bas_dpoly be; k:=mo_comp a;
  1519. for each b in gb do
  1520. if (k=mo_comp dp_lmon bas_dpoly b)
  1521. and(n or (bas_nr b neq 0)) then
  1522. p1:=groeb!=newpair(k,b,be).p1;
  1523. p1:=groeb!=critA(sort(p1,function groeb!=better));
  1524. if Ccrit then p1:=groeb!=critC p1;
  1525. return
  1526. merge(p1,
  1527. groeb!=critB(a,p), function groeb!=better);
  1528. end;
  1529. symbolic procedure groeb_makepairlist(gb,Ccrit);
  1530. begin scalar newgb,p;
  1531. while gb do
  1532. << p:=groeb_updatePL(p,newgb,car gb,Ccrit);
  1533. newgb:=car gb . newgb; gb:=cdr gb
  1534. >>;
  1535. return p;
  1536. end;
  1537. % -------------- Pair Management --------------------
  1538. symbolic procedure groeb!=i p; bas_nr nth(p,4);
  1539. symbolic procedure groeb!=j p; bas_nr nth(p,5);
  1540. symbolic procedure groeb!=better(a,b);
  1541. % True if the Spair a is better than the Spair b.
  1542. if (cadr a < cadr b) then t
  1543. else if (cadr a = cadr b) then mo_compare(nth(a,3),nth(b,3))<=0
  1544. else nil;
  1545. symbolic procedure groeb!=weight(lcm,p1,p2);
  1546. mo_ecart(lcm) + min2(bas_dpecart p1,bas_dpecart p2);
  1547. symbolic procedure groeb!=newpair(k,p1,p2);
  1548. % Make an spair from base elements with common component number k.
  1549. list(k,groeb!=weight(lcm,p1,p2),lcm, p1,p2)
  1550. where lcm =mo_lcm(dp_lmon bas_dpoly p1,dp_lmon bas_dpoly p2);
  1551. symbolic procedure groeb_printpairlist p;
  1552. begin
  1553. for each x in p do
  1554. << write groeb!=i x,".",groeb!=j x; print_lf " | " >>;
  1555. terpri();
  1556. end;
  1557. symbolic procedure groeb_printpair(pp,p);
  1558. begin terpri();
  1559. write"Investigate (",groeb!=i pp,".",groeb!=j pp,") ",
  1560. "Pair list has length ",length p; terpri()
  1561. end;
  1562. % ------------- S-polynomial constructions -----------------
  1563. symbolic procedure groeb_spol pp;
  1564. % Make an S-polynomial from the spair pp, i.e. return
  1565. % a base element with
  1566. % dpoly = ( zi*mi*(red) pi - zj*mj*(red) pj )
  1567. % rep = (zi*mi*rep_i - zj*mj*rep_j),
  1568. %
  1569. % where mi=lcm/lm(pi), mj=lcm/lm(pj)
  1570. % and zi and zj are appropriate scalars.
  1571. %
  1572. begin scalar pi,pj,ri,rj,zi,zj,lcm,mi,mj,a,b;
  1573. a:=nth(pp,4); b:=nth(pp,5); lcm:=nth(pp,3);
  1574. pi:=bas_dpoly a; pj:=bas_dpoly b; ri:=bas_rep a; rj:=bas_rep b;
  1575. mi:=mo_diff(lcm,dp_lmon pi); mj:=mo_diff(lcm,dp_lmon pj);
  1576. zi:=dp_lc pj; zj:=bc_neg dp_lc pi;
  1577. a:=dp_sum(dp_times_bcmo(zi,mi, cdr pi),
  1578. dp_times_bcmo(zj,mj, cdr pj));
  1579. b:=dp_sum(dp_times_bcmo(zi,mi, ri),
  1580. dp_times_bcmo(zj,mj, rj));
  1581. a:=bas_make1(0,a,b);
  1582. if !*bcsimp then a:=car bas_simpelement a;
  1583. if cali_trace() > 70 then
  1584. << terpri(); write" S.-pol : "; dp_print2 bas_dpoly a >>;
  1585. return a;
  1586. end;
  1587. symbolic procedure groeb_mingb gb;
  1588. % Returns the min. Groebner basis dpmat mgb of the dpmat gb
  1589. % discarding base elements with bas_nr<=0.
  1590. begin scalar u;
  1591. u:=for each x in car red_collect dpmat_list gb join
  1592. if bas_nr x>0 then {x};
  1593. % Choosing base elements with minimal leading terms only.
  1594. return dpmat_make(length u,dpmat_cols gb,bas_renumber u,
  1595. dpmat_coldegs gb,dpmat_gbtag gb);
  1596. end;
  1597. % ------- Minimizing a basis using its syszgies ---------
  1598. symbolic procedure groeb!=delete(l,bas);
  1599. % Delete base elements from the base list bas with number in the
  1600. % integer list l.
  1601. begin scalar b;
  1602. while bas do
  1603. << if not memq(bas_nr car bas,l) then b:=car bas . b;
  1604. bas:= cdr bas
  1605. >>;
  1606. return reverse b
  1607. end;
  1608. symbolic procedure groeb_minimize(bas,syz);
  1609. % Minimize the dpmat pair bas,syz deleting superfluous base elements
  1610. % from bas using syzygies from syz containing unit entries.
  1611. (begin scalar drows, dcols, s,s1,i,j,p,q,y;
  1612. cali!=degrees:=dpmat_coldegs syz;
  1613. s1:=dpmat_list syz; j:=0;
  1614. while j < dpmat_rows syz do
  1615. << j:=j+1;
  1616. if (q:=bas_dpoly bas_getelement(j,s1)) then
  1617. << i:=0;
  1618. while leq(i,dpmat_cols syz) and
  1619. (memq(i,dcols) or not dp_unit!?(p:=dp_comp(i,q)))
  1620. do i:=i+1;
  1621. if leq(i,dpmat_cols syz) then
  1622. << drows:=j . drows;
  1623. dcols:=i . dcols;
  1624. s1:=for each x in s1 collect
  1625. if memq(bas_nr x,drows) then x
  1626. else (bas_make(bas_nr x,
  1627. dp_diff(dp_prod(y,p),dp_prod(q,dp_comp(i,y))))
  1628. where y:=bas_dpoly x);
  1629. >>
  1630. >>
  1631. >>;
  1632. % --- s1 becomes the new syzygy part, s the new base part.
  1633. s1:=bas_renumber bas_simp groeb!=delete(drows,s1);
  1634. s1:=dpmat_make(length s1,dpmat_cols syz,s1,cali!=degrees,nil);
  1635. % The new syzygy matrix of the old basis.
  1636. s:=dpmat_renumber
  1637. dpmat_make(dpmat_rows bas,dpmat_cols bas,
  1638. groeb!=delete(dcols,dpmat_list bas),
  1639. dpmat_coldegs bas,nil);
  1640. s1:=dpmat_mult(s1,dpmat_transpose cdr s);
  1641. % The new syzygy matrix of the new basis, but not yet in the
  1642. % right form since cali!=degrees is empty.
  1643. s:=car s; % The new basis.
  1644. cali!=degrees:=dpmat_rowdegrees s;
  1645. s1:=interreduce!* dpmat_make(dpmat_rows s1,dpmat_cols s1,
  1646. bas_neworder dpmat_list s1,cali!=degrees,nil);
  1647. return s.s1;
  1648. end) where cali!=degrees:=cali!=degrees;
  1649. % ------ Computing standard bases via homogenization ----------------
  1650. symbolic procedure groeb_homstbasis(m,comp_mgb,comp_ch,comp_syz);
  1651. (begin scalar v,c,u;
  1652. c:=cali!=basering; v:=list gensym();
  1653. if not(comp_ch or comp_syz) then cali!=monset:=append(v,cali!=monset);
  1654. setring!* ring_sum(c,ring_define(v,nil,'lex,'(1)));
  1655. cali!=degrees:=mo_degneworder dpmat_coldegs m;
  1656. if cali_trace()>0 then print" Homogenize input ";
  1657. u:=(groeb_stbasis(mathomogenize!*(m,car v),
  1658. comp_mgb,comp_ch,comp_syz) where !*noetherian=t);
  1659. if cali_trace()>0 then print" Dehomogenize output ";
  1660. u:=for each x in u collect if x then matdehomogenize!*(x,car v);
  1661. setring!* c; cali!=degrees:=dpmat_coldegs m;
  1662. return {if first u then dpmat_neworder(first u,t),
  1663. if second u then dpmat_neworder(second u,nil),
  1664. if third u then dpmat_neworder(third u,nil)};
  1665. end) where cali!=basering:=cali!=basering,
  1666. cali!=monset:=cali!=monset,
  1667. cali!=degrees:=cali!=degrees;
  1668. % Two special versions for standard basis computations, not included
  1669. % in full generality into the algebraic interface.
  1670. symbolic operator homstbasis;
  1671. symbolic procedure homstbasis m;
  1672. if !*mode='algebraic then dpmat_2a homstbasis!* dpmat_from_a m
  1673. else homstbasis!* m;
  1674. symbolic procedure homstbasis!* m;
  1675. groeb_mingb car groeb_homstbasis(m,t,nil,nil);
  1676. symbolic operator lazystbasis;
  1677. symbolic procedure lazystbasis m;
  1678. if !*mode='algebraic then dpmat_2a lazystbasis!* dpmat_from_a m
  1679. else lazystbasis!* m;
  1680. symbolic procedure lazystbasis!* m;
  1681. car groeb_lazystbasis(m,t,nil,nil);
  1682. endmodule; % groeb
  1683. end;
  1684. module groebf;
  1685. Comment
  1686. ##############################
  1687. ### ###
  1688. ### GROEBNER FACTORIZER ###
  1689. ### ###
  1690. ##############################
  1691. The Groebner algorithm with factorization and constraint lists.
  1692. New in version 2.2 :
  1693. syntax for groebfactor
  1694. listgroebfactor!*
  1695. extendedgroebfactor!*
  1696. There are two versions of the extended groebner factorizer.
  1697. One needs the lex. term order, the other supports arbitrary ones (the
  1698. default). Switch between both versions via switch lexefgb.
  1699. Internal data structure
  1700. result::={dpmat, constraint list }
  1701. extendedresult::=
  1702. {dpmat, constraint list, (dimension | indepvarset) }
  1703. problem::={dpmat, constraint list, pair list, easydim}
  1704. aggregate::=
  1705. { (list of problems) , (list of results) }
  1706. For a system with constraints m=(b,c) V(m)=V(b,c) denotes the zero set
  1707. V(b)\setminus D(c).
  1708. The Groebner algorithm supports only the classical reduction
  1709. principle.
  1710. end Comment;
  1711. % --- The side effect switching lexefgb on or off :
  1712. put('lexefgb,'simpfg,'((t (put 'cali 'efgb 'lex))
  1713. (nil (remprop 'cali 'efgb))));
  1714. symbolic procedure groebf!=problemsort(a,b);
  1715. % Sorted by ascending easydim to force depth first search.
  1716. (nth(a,4)<nth(b,4))
  1717. or (nth(a,4)=nth(b,4)) and (length second a<= length second b);
  1718. symbolic procedure groebf!=resultsort(a,b);
  1719. % Sort extendedresults by descending true dimension, assuming the
  1720. % third part being the dimension.
  1721. third a > third b;
  1722. put('groebfactor,'psopfn,'intf!=groebfactor);
  1723. symbolic procedure intf!=groebfactor m;
  1724. begin scalar bas,con;
  1725. bas:=dpmat_from_a reval first m;
  1726. if length m=1 then con:=nil
  1727. else if length m=2 then
  1728. con:=for each x in cdr reval second m collect dp_from_a x
  1729. else rederr("Syntax : GROEBFACTOR(base list [,constraint list])");
  1730. return makelist
  1731. for each x in groebfactor!*(bas,con) collect dpmat_2a first x;
  1732. end;
  1733. symbolic operator listgroebfactor;
  1734. symbolic procedure listgroebfactor l;
  1735. % l is a list of polynomial systems. We look for the union of the
  1736. % solution sets.
  1737. if !*mode='algebraic then
  1738. makelist for each x in listgroebfactor!*
  1739. for each y in cdr reval l collect dpmat_from_a y
  1740. collect dpmat_2a x
  1741. else listgroebfactor!* l;
  1742. symbolic procedure listgroebfactor!* l;
  1743. % Proceed a whole list of dpmats at once.
  1744. begin scalar gbs;
  1745. gbs:=for each x in
  1746. groebf!=preprocess(nil,for each x in l collect {x,nil})
  1747. collect groebf!=initproblem x;
  1748. gbs:=sort(gbs,function groebf!=problemsort);
  1749. return for each x in groebf!=masterprocess(gbs,nil) collect first x;
  1750. end;
  1751. symbolic procedure groebfactor!*(bas,poly);
  1752. % Returns a list l of results (b,c) such that
  1753. % V(bas,poly) = \union { V(b,c) : (b,c) \in l }
  1754. if dpmat_cols bas > 0 then
  1755. rederr "GROEBFACTOR only for ideal bases"
  1756. else if null !*noetherian then
  1757. rederr "GROEBFACTOR only for noetherian term orders"
  1758. else if dpmat_zero!? bas then list({bas,poly})
  1759. else begin scalar gbs;
  1760. if cali_trace() > 5 then
  1761. << write"GROEBFACTOR the system "; dpmat_print bas >>;
  1762. gbs:=for each x in groebf!=preprocess(nil,list {bas,poly}) collect
  1763. groebf!=initproblem x;
  1764. gbs:=sort(gbs,function groebf!=problemsort);
  1765. return groebf!=masterprocess(gbs,nil);
  1766. end;
  1767. put('extendedgroebfactor,'psopfn,'intf!=extendedgroebfactor);
  1768. symbolic procedure intf!=extendedgroebfactor m;
  1769. begin scalar bas,con;
  1770. bas:=dpmat_from_a reval first m;
  1771. if length m=1 then con:=nil
  1772. else if length m=2 then
  1773. con:=for each x in cdr reval second m collect dp_from_a x
  1774. else rederr
  1775. "Syntax : EXTENDEDGROEBFACTOR(base list [,constraint list])";
  1776. return makelist
  1777. for each x in extendedgroebfactor!*(bas,con) collect
  1778. makelist {first x,makelist second x,makelist third x};
  1779. end;
  1780. symbolic procedure extendedgroebfactor!*(bas,poly);
  1781. % Returns a list l of extendedresults (b,c,vars) in prefix form such
  1782. % that V(bas,poly) = \union { V(b,c) : (b,c) \in l }
  1783. % and b:<\prod c> is puredimensional with independent variable set vars.
  1784. if dpmat_cols bas > 0 then
  1785. rederr "EXTENDEDGROEBFACTOR only for ideal bases"
  1786. else if null !*noetherian then
  1787. rederr "EXTENDEDGROEBFACTOR only for noetherian term orders"
  1788. else if dpmat_zero!? bas then
  1789. list({dpmat_2a bas,nil,ring_names cali!=basering})
  1790. else begin scalar gbs;
  1791. if cali_trace() > 5 then
  1792. << write"EXTENDEDGROEBFACTOR the system "; dpmat_print bas >>;
  1793. gbs:=for each x in groebf!=preprocess(nil,list {bas,poly}) collect
  1794. groebf!=initproblem x;
  1795. return groebf!=extendedmasterprocess gbs;
  1796. end;
  1797. symbolic procedure groebf!=extendedmasterprocess gbs;
  1798. % gbs is a list of problems to process. Returns a list of
  1799. % extendedresults in prefix form.
  1800. % If {m,con,vars} is such an extendedresult then m:<\prod con> is the
  1801. % (puredimensional) recontraction of m\tensor k(vars).
  1802. begin scalar res,res1,u;
  1803. while gbs or res do
  1804. if gbs then
  1805. % The hard postprocessing is done only at the end.
  1806. << gbs:=sort(gbs,function groebf!=problemsort);
  1807. % Convert results to extendedresults and sort them :
  1808. res:=for each x in groebf!=masterprocess(gbs,res) collect
  1809. if (length x=3) then x
  1810. else {first x,second x,dim!* first x};
  1811. res:=sort(res,function groebf!=resultsort);
  1812. gbs:=nil
  1813. >>
  1814. else % Do the first (hard) postprocessing
  1815. << % process result by result :
  1816. u:=groebf!=postprocess2 car res; res:=cdr res;
  1817. % Extract and preprocess new problems from u.
  1818. % This needs descent by dimension of the results proceeded.
  1819. gbs:=for each x in groebf!=preprocess(res,second u)
  1820. collect groebf!=initproblem x;
  1821. % Extract extendedresults from u.
  1822. % They may be non-GB wrt t h i s term order, see above.
  1823. res1:=nconc(first u,res1);
  1824. >>;
  1825. return res1;
  1826. end;
  1827. % --------- Another version of the extended Groebner factorizer -------
  1828. put('extendedgroebfactor1,'psopfn,'intf!=extendedgroebfactor1);
  1829. symbolic procedure intf!=extendedgroebfactor1 m;
  1830. begin scalar bas,con;
  1831. bas:=dpmat_from_a reval first m;
  1832. if length m=1 then con:=nil
  1833. else if length m=2 then
  1834. con:=for each x in cdr reval second m collect dp_from_a x
  1835. else rederr
  1836. "Syntax : EXTENDEDGROEBFACTOR1(base list [,constraint list])";
  1837. return makelist
  1838. for each x in extendedgroebfactor1!*(bas,con) collect
  1839. makelist {first x,makelist second x,makelist third x};
  1840. end;
  1841. symbolic procedure extendedgroebfactor1!*(bas,poly);
  1842. % Returns a list l of extendedresults (b,c,vars) in prefix form such
  1843. % that V(bas,poly) = \union { V(b,c) : (b,c) \in l }
  1844. % and b:<\prod c> is puredimensional with independent variable set vars.
  1845. if dpmat_cols bas > 0 then
  1846. rederr "EXTENDEDGROEBFACTOR1 only for ideal bases"
  1847. else if null !*noetherian then
  1848. rederr "EXTENDEDGROEBFACTOR1 only for noetherian term orders"
  1849. else if dpmat_zero!? bas then
  1850. list({dpmat_2a bas,nil,ring_names cali!=basering})
  1851. else begin scalar gbs;
  1852. if cali_trace() > 5 then
  1853. << write"EXTENDEDGROEBFACTOR1 the system "; dpmat_print bas >>;
  1854. gbs:=for each x in groebf!=preprocess(nil,list {bas,poly}) collect
  1855. groebf!=initproblem x;
  1856. return for each x in groebf!=extendedmasterprocess1 gbs collect
  1857. nth(x,4);
  1858. end;
  1859. symbolic procedure groebf!=extendedmasterprocess1 gbs;
  1860. % Version that computes the retraction of each intermediate result
  1861. % to apply FGB shortcuts. gbs is a list of problems to process.
  1862. % Returns a list of extendedresults in prefix form.
  1863. % If {m,con,vars} is such an extendedresult then m:<\prod con> is the
  1864. % (puredimensional) recontraction of m\tensor k(vars).
  1865. % internally they are incorporated into res as
  1866. % {dpmat, nil (since no constraints), dim, prefix form}.
  1867. begin scalar res,u,v,p;
  1868. while gbs or
  1869. (p:=listtest(res,nil,function (lambda(x,y); length x<4))) do
  1870. if gbs then
  1871. % The hard postprocessing is done only at the end.
  1872. << gbs:=sort(gbs,function groebf!=problemsort);
  1873. % Convert results to extendedresults and sort them :
  1874. res:=for each x in groebf!=masterprocess(gbs,res) collect
  1875. if (length x>2) then x
  1876. else {first x,second x,dim!* first x};
  1877. res:=sort(res,function groebf!=resultsort);
  1878. gbs:=nil
  1879. >>
  1880. else % Do the first (hard) postprocessing
  1881. << % process result by result :
  1882. u:=groebf!=postprocess2 p; res:=delete(p,res);
  1883. % Extract extendedresults from u and convert them
  1884. % with postprocess3 to quotient ideals.
  1885. v:=for each x in first u collect
  1886. {groebf!=postprocess3 x, nil, length third x,x};
  1887. for each y in v do
  1888. if not groebf!=redtest(res,y) then
  1889. res:=merge({y},groebf!=sieve(res,y),
  1890. function groebf!=resultsort);
  1891. % Extract and preprocess new problems from u.
  1892. gbs:=for each x in groebf!=preprocess(res,second u) collect
  1893. groebf!=initproblem x;
  1894. >>;
  1895. return res;
  1896. end;
  1897. % ------- end of the second version ------------------------
  1898. symbolic procedure groebf!=masterprocess(gbs,res);
  1899. % gbs = list of problems, res = list of results (since several times
  1900. % involved in the extendedmasterprocess).
  1901. % Returns a list of results already postprocessed with (the easy)
  1902. % groebf!=postpocess1 where the elements surviving from res may
  1903. % change only in the constraints part.
  1904. begin scalar u,v;
  1905. while gbs do
  1906. << if cali_trace()>10 then
  1907. print for each x in gbs collect nth(x,4);
  1908. u:=groebf!=slave car gbs; gbs:=cdr gbs;
  1909. if u then % u is an aggregate.
  1910. << % postprocess the result part returning a list of aggregates.
  1911. v:=for each x in second u collect groebf!=postprocess1(res,x);
  1912. % split up into the problems u and results v
  1913. u:=nconc(car u,for each x in v join car x);
  1914. v:=for each x in v join second x;
  1915. for each y in v do
  1916. if cali_trace() > 5 then
  1917. << write"partial result :"; terpri();
  1918. dpmat_print car y ;
  1919. prin2"constraints : ";
  1920. for each x in second y do dp_print2 x;
  1921. >>;
  1922. for each y in v do
  1923. if not groebf!=redtest(res,y) then
  1924. res:=y . groebf!=sieve(res,y);
  1925. for each x in u do
  1926. if not groebf!=redtest(res,x) then
  1927. gbs:=merge({x},groebf!=sieve(gbs,x),
  1928. function groebf!=problemsort);
  1929. if cali_trace()>20 then
  1930. << terpri(); write length gbs," remaining branches. ",
  1931. length res," partial results"; terpri()
  1932. >>;
  1933. >>
  1934. else % branch discarded
  1935. if cali_trace()>20 then print"Branch discarded";
  1936. >>;
  1937. return res;
  1938. end;
  1939. symbolic procedure groebf!=initproblem x;
  1940. % Converts a result into a problem.
  1941. list(car x,second x, groeb_makepairlist(dpmat_list car x,t),
  1942. easydim!* car x);
  1943. % The following two procedures make destructive changes
  1944. % on the cdr of some of the list elements.
  1945. symbolic procedure groebf!=redtest(a,c);
  1946. % Ex. u \in a : car u \submodule car c ?
  1947. % If so, update the constraints of u.
  1948. begin scalar u;
  1949. u:=listtest(a,c,function(lambda(x,y); submodulep!*(car x,car y)));
  1950. if u then cdr u:=intersection(second u,second c).cddr u;
  1951. return u;
  1952. end;
  1953. symbolic procedure groebf!=sieve(a,c);
  1954. % Remove u \in a with car c \submodule car u
  1955. % and update the constraints of c.
  1956. for each x in a join if not submodulep!*(car c,car x) then {x}
  1957. else << cdr c:=intersection(second x,second c).cddr c; >>;
  1958. symbolic procedure groebf!=test(con,m);
  1959. % nil <=> ex. f \in con : f mod m = 0. m is a baslist.
  1960. if null m then t
  1961. else if dp_unit!? bas_dpoly first m then nil
  1962. else if null con then t
  1963. else begin scalar p; p:=t;
  1964. while p and con do
  1965. << p:=p and bas_dpoly car red_redpol(m,bas_make(0,car con));
  1966. con:=cdr con
  1967. >>;
  1968. return p;
  1969. end;
  1970. symbolic procedure groebf!=newcon(r,d);
  1971. % r=(m,c) is a result, d a list of polynomials. Returns the
  1972. % (slightly optimized) result list ( (m+(p),c+(q|q<p)) | p \in d ).
  1973. begin scalar m,c,u;
  1974. m:=first r; c:=second r;
  1975. return for each p in d join
  1976. if not member(p,c) then
  1977. << u:={matsum!* {m, dpmat_from_dpoly(p)}, c}; c:=p.c; {u} >>;
  1978. end;
  1979. symbolic procedure groebf!=preprocess(a1,b);
  1980. % Try to split (factor) each polynomial in each problem of the list b.
  1981. % Returns a list of results.
  1982. % a1 is a list of results already computed.
  1983. begin scalar a,c,d,back,u;
  1984. if cali_trace()>20 then prin2"preprocessing started";
  1985. while b do
  1986. << if cali_trace()>20 then
  1987. << terpri(); write length a," ready. ";
  1988. write length b," left."; terpri()
  1989. >>;
  1990. c:=car b; b:=cdr b;
  1991. if not (null groebf!=test(second c,dpmat_list car c)
  1992. or groebf!=redtest(a1,c)
  1993. or groebf!=redtest(a,c)) then
  1994. << d:=dpmat_list car c; back:=nil;
  1995. while d and not back do
  1996. << u:=((fctrf numr simp dp_2a bas_dpoly car d)
  1997. where !*factor=t);
  1998. if (length u>2) or (cdadr u>1) then
  1999. << back:=t;
  2000. b:=append(groebf!=newcon(c,
  2001. for each y in cdr u collect
  2002. dp_from_a prepf car y),b);
  2003. >>
  2004. else d:=cdr d
  2005. >>;
  2006. if not back then
  2007. << if cali_trace()>20 then
  2008. << terpri(); write"Subproblem :"; dpmat_print car c >>;
  2009. if not groebf!=redtest(a,c) then a:=c . groebf!=sieve(a,c);
  2010. >>
  2011. >>
  2012. >>;
  2013. if cali_trace()>20 then prin2"preprocessing finished...";
  2014. return a;
  2015. end;
  2016. symbolic procedure groebf!=slave c;
  2017. % Proceed upto the first splitting. Returns an aggregate.
  2018. begin scalar be,back,p,u,v,a,b,gb,pl,nr,pol,con;
  2019. back:=nil;
  2020. gb:=bas_sort dpmat_list first c;
  2021. con:=second c; pl:=third c; nr:=length gb;
  2022. while pl and not back do
  2023. << p:=car pl; pl:=cdr pl;
  2024. if cali_trace() > 10 then groeb_printpair(p,pl);
  2025. pol:=groeb_spol p;
  2026. if cali_trace() > 70 then
  2027. << terpri(); write"S.-pol : "; dp_print2 bas_dpoly pol >>;
  2028. pol:=bas_dpoly car red_redpol(gb,pol);
  2029. if cali_trace() > 70 then
  2030. << terpri(); write"Reduced S.-pol. : "; dp_print2 pol >>;
  2031. if pol then
  2032. << if !*bcsimp then pol:=car dp_simp pol;
  2033. if dp_unit!? pol then
  2034. << if cali_trace()>20 then print "unit ideal";
  2035. back:=t
  2036. >>
  2037. else
  2038. << % -- factorize pol
  2039. u:=((fctrf numr simp dp_2a pol) where !*factor=t);
  2040. nr:=nr+1;
  2041. if length cdr u=1 then % only one factor
  2042. << pol:=dp_from_a prepf caadr u;
  2043. be:=bas_make(nr,pol);
  2044. u:=be.gb;
  2045. if null groebf!=test(con,u) then
  2046. << back:=t;
  2047. if cali_trace()>20 then print" zero constraint";
  2048. >>
  2049. else
  2050. << if cali_trace()>20 then
  2051. << terpri(); write nr,". "; dp_print2 pol >>;
  2052. pl:=groeb_updatePL(pl,gb,be,t);
  2053. if cali_trace() > 30 then
  2054. << terpri(); groeb_printpairlist pl >>;
  2055. gb:=merge(list be,gb,function red_better);
  2056. >>
  2057. >>
  2058. else % more than one factor
  2059. << for each x in cdr u do
  2060. << pol:=dp_from_a prepf car x;
  2061. be:=bas_make(nr,pol);
  2062. a:=be.gb;
  2063. if groebf!=test(con,a) then
  2064. << if cali_trace()>20 then
  2065. << terpri(); write nr; write". "; dp_print2 pol >>;
  2066. p:=groeb_updatePL(append(pl,nil),gb,be,t);
  2067. if cali_trace() > 30 then
  2068. << terpri(); groeb_printpairlist p >>;
  2069. b:=merge(list be,append(gb,nil),
  2070. function red_better);
  2071. b:=dpmat_make(length b,0,b,nil,nil);
  2072. v:={b,con,p}.v;
  2073. >>
  2074. else if cali_trace()>20 then print" zero constraint";
  2075. if not member(pol,con) then con:=pol . con;
  2076. >>;
  2077. if null v then
  2078. << if cali_trace()>20 then print "Branch canceled";
  2079. back:=t
  2080. >>
  2081. else if length v=1 then
  2082. << c:=car v; gb:=dpmat_list first c; con:=second c;
  2083. pl:=third c; v:=nil;
  2084. >>
  2085. else
  2086. << back:=t;
  2087. if cali_trace()>20 then
  2088. << write" Branching into ",length v," parts ";
  2089. terpri();
  2090. >>;
  2091. >>;
  2092. >>;
  2093. >>;
  2094. >>;
  2095. >>;
  2096. if not back then % pl exhausted => new partial result.
  2097. return
  2098. {nil,list {groeb_mingb dpmat_make(length gb,0,gb,nil,t),con}}
  2099. else if v then return
  2100. {for each x in v collect
  2101. {first x,second x,third x,easydim!* first x},
  2102. nil}
  2103. else return nil;
  2104. end;
  2105. symbolic procedure groebf!=postprocess1(res,x);
  2106. % Easy postprocessing a result. Returns an aggregate.
  2107. % res is a list of results, already obtained.
  2108. begin scalar p,r,v;
  2109. % ---- interreduce and try factorization once more.
  2110. if !*red_total then
  2111. << v:=groebf!=preprocess(res,
  2112. list {dpmat_make(dpmat_rows car x,0,
  2113. red_straight dpmat_list car x,nil,
  2114. dpmat_gbtag car x),
  2115. second x});
  2116. if (length v=1) and dpmat_gbtag caar v then r:=v
  2117. else p:=for each x in v collect groebf!=initproblem x;
  2118. >>
  2119. else r:={x};
  2120. return {p,r};
  2121. end;
  2122. symbolic procedure groebf!=postprocess2 m;
  2123. (begin scalar d,vars,u,v,c1,m1,m1a,m2,p,con;
  2124. con:=second m; d:=third m; m:=first m;
  2125. v:=moid_goodindepvarset m;
  2126. if neq(length v,d) then
  2127. rederr"In POSTPROCESS2 the dimension is wrong";
  2128. if null v then return
  2129. {for each x in groebf!=zerosolve(m,con)
  2130. collect {x,nil,nil},nil};
  2131. % -- Prepare data for change to dimension zero :
  2132. % Recompute gbases wrt. the elimination order for u and
  2133. % take only those components for which v remains independent.
  2134. vars:=ring_names(c1:=cali!=basering);
  2135. u:=setdiff(vars,v);
  2136. if get('cali,'efgb)='lex then setring!* ring_lp(c1,u)
  2137. else setring!* ring_rlp(c1,u);
  2138. m1:=for each u in groebfactor!*(dpmat_neworder(m,nil),
  2139. for each x in con collect dp_neworder x) collect
  2140. {first u,second u,dim!* first u};
  2141. for each x in m1 do
  2142. if (third x = d) and member(v,indepvarsets!* car x)
  2143. then m1a := x . m1a
  2144. else m2:=x.m2;
  2145. % m1a : components with indepvarset v
  2146. % m2 : components with v being dependent variables.
  2147. % -- Change to dimension zero.
  2148. m1:=for each x in m1a collect
  2149. {dpmat_2a first x,for each p in second x collect dp_2a p};
  2150. if get('cali,'efgb)='lex then
  2151. setring!* ring_define(u,nil,'lex,for each x in u collect 1)
  2152. else setring!* ring_define(u,degreeorder!* u,'revlex,
  2153. for each x in u collect 1);
  2154. m1:=for each x in m1 collect
  2155. {groeb_mingb dpmat_from_a first x,
  2156. for each p in second x collect dp_from_a p};
  2157. % Extract the lc's of the lifted Groebner bases and save them
  2158. % for NewCon on the list m1a, since in the zerodimensional part
  2159. % lc's are assumed to be invertible.
  2160. m1a:=pair(m1a,for each x in m1 collect groebf!=elcbe first x);
  2161. % Compute the zerodimensional TriangSets from m1 and their lists
  2162. % of lc's and prepare them for lifting.
  2163. m1:=for each x in m1 join groebf!=zerosolve(first x,second x);
  2164. m1:=for each x in m1 collect {x,groebf!=elcbe dpmat_from_a x};
  2165. % -- Lift all stuff back to c1.
  2166. setring!* c1;
  2167. % Extract the TriangSets as extendedresults in prefix form (!).
  2168. m1:=for each x in m1 collect {first x,second x,v};
  2169. % List of new problems found during recomputation of GB :
  2170. m2:=for each x in m2 collect
  2171. {dpmat_neworder(first x,nil),
  2172. for each y in second x collect dp_neworder y};
  2173. % List of new problems, derived from nonzero conditions for
  2174. % lc's in dimension zero.
  2175. m1a:=for each x in m1a join
  2176. groebf!=newcon({dpmat_neworder(first car x,nil),
  2177. for each p in second car x collect dp_neworder p},
  2178. for each p in cdr x collect dp_from_a p);
  2179. Comment The list of results :
  2180. m1 : The list of TriangSets wrt. v produced in this run. They are in
  2181. alg. prefix form to remember that they are Groebner bases only
  2182. wrt. the pure lex. term order.
  2183. m2 : Results (in prefix form), for which v is dependent.
  2184. m1a : Branches, where some of the critical lc's of the TriangSets
  2185. vanish.
  2186. Both m2 and m1a should be returned in the pool of problems.
  2187. end comment;
  2188. return {m1,nconc(m1a,m2)};
  2189. end)
  2190. where cali!=degrees:=cali!=degrees,
  2191. cali!=basering:=cali!=basering;
  2192. symbolic procedure groebf!=elcbe(m);
  2193. % Extract list of leading coefficients in algebraic prefix form
  2194. % from base elements of the dpmat m.
  2195. for each x in dpmat_list m join
  2196. if domainp dp_lc bas_dpoly x then {}
  2197. else {bc_2a dp_lc bas_dpoly x};
  2198. symbolic procedure groebf!=postprocess3 u;
  2199. % Compute for the extendedresult u={m,con,vars} in prefix form
  2200. % m:<\prod con>.
  2201. matqquot!*(dpmat_from_a first u,
  2202. groebf!=prod for each x in second u collect dp_from_a x);
  2203. symbolic procedure groebf!=prod l;
  2204. begin scalar p; p:=dp_fi 1;
  2205. l:=listminimize(for each x in l join dp_factor x,function equal);
  2206. for each x in l do p:=dp_prod(x,p);
  2207. return p;
  2208. end;
  2209. symbolic procedure groebf!=zerosolve(m,con);
  2210. % Hook for the zerodimensional solver.
  2211. % Input : m = zerodimensional dpmat (not to be checked),
  2212. % con = list of dpoly constraints.
  2213. % Output : a list of dpmats in prefix form.
  2214. begin scalar u;
  2215. % Look up the constraints, since during the change to dimension zero
  2216. % some of them may trivialize :
  2217. con:=for each x in con join if not dp_unit!? x then {x};
  2218. % Factorized radical computation.
  2219. u:=groebf_zeroprimes1(m,con);
  2220. % Apply the zerosolver to each of these results.
  2221. return for each x in u join
  2222. if get('cali,'efgb)='lex then zerosolve!* x else zerosolve1!* x;
  2223. end;
  2224. symbolic procedure groebf_zeroprimes1(m,con);
  2225. % Returns a list of gbases for the zerodimensional ideal m,
  2226. % incorporating as in the Groebner factorizer the factors of the
  2227. % univariate polynomials in m according to such variables, that don't
  2228. % appear as leading terms in m.
  2229. begin scalar m1,m2,p,u,l;
  2230. l:=list {m,con};
  2231. for each x in ring_names cali!=basering do
  2232. << m1:=m2:=nil;
  2233. for each y in l do
  2234. % The following checks, whether x is a leading term of first
  2235. % y. Such x may be skipped, since embedding dimension may be
  2236. % reduced. On the other hand, computing univariate polynomials
  2237. % for them is often quite nasty.
  2238. if not member(x,for each v in dpmat_list first y join
  2239. {mo_linear dp_lmon bas_dpoly v}) then
  2240. << p:=odim_up(x,first y); u:=dp_factor p;
  2241. if (length u>1) or not equal(first u,p) then
  2242. m1:=nconc(groebf!=newcon(y,u),m1)
  2243. else m2:=y.m2;
  2244. >>
  2245. else m2:=y.m2;
  2246. l:=groebf!=masterprocess(
  2247. sort(for each x in m1 collect groebf!=initproblem x,
  2248. function groebf!=problemsort),
  2249. m2);
  2250. >>;
  2251. return for each x in l join
  2252. if second x then {matqquot!*(first x,groebf!=prod second x)}
  2253. % Here one can use the linear algebra quotient algorithm, since
  2254. % first x is known to be zerodimensional radical.
  2255. else {first x};
  2256. end;
  2257. endmodule; % groebf
  2258. end;
  2259. module hf;
  2260. COMMENT
  2261. ###################################
  2262. ## ##
  2263. ## WEIGHTED HILBERT SERIES ##
  2264. ## ##
  2265. ###################################
  2266. This module supports (weighted) Hilbert series computations and
  2267. related topics. It contains
  2268. - Two algorithms computing Hilbert series of ideals and
  2269. modules.
  2270. Lit.:
  2271. [BS] Bayer, Stillman : J. Symb. Comp. 14 (1992), 31 - 50.
  2272. [BCRT] Bigatti, Conti, Robbiano, Traverso . LNCS 673 (1993), 76 - 88.
  2273. The version of the algorithm is chosen through the 'hf!=hf entry on
  2274. the property list of 'cali.
  2275. END COMMENT;
  2276. % Choosing the version of the algorithm and first initialization :
  2277. put('cali,'hf!=hf,'hf!=whilb1);
  2278. symbolic operator hftestversion;
  2279. symbolic procedure hftestversion n;
  2280. if member(n,{1,2}) then
  2281. put('cali,'hf!=hf,mkid('hf!=whilb,n));
  2282. % --- first variant : [BS]
  2283. symbolic procedure hf!=whilb1(m,w);
  2284. % Compute the weighted Hilbert series of the moideal m by the rule
  2285. % H(m + (M)) = H((M)) - t^ec(m) * H((M):m)
  2286. if null m then dp_fi 1
  2287. else begin scalar m1,m2;
  2288. for each x in m do
  2289. if mo_linear x then m1:=x . m1 else m2:=x . m2;
  2290. if null m2 then return hf!=whilbmon(m1,w)
  2291. else if null cdr m2 then return hf!=whilbmon(car m2 . m1,w)
  2292. else if hf!=powers m2 then return hf!=whilbmon(append(m1,m2),w)
  2293. else return dp_prod(hf!=whilbmon(m1,w),
  2294. dp_diff(hf!=whilb1(cdr m2,w),
  2295. dp_times_mo(mo_wconvert(car m2,w),
  2296. hf!=whilb1(moid_quot(cdr m2,car m2),w))));
  2297. end;
  2298. symbolic procedure hf!=whilbmon(m,w);
  2299. % Returns the product of the converted dpolys 1 - mo for the
  2300. % monomials mo in m.
  2301. if null m then dp_fi 1
  2302. else begin scalar p;
  2303. m:=for each x in m collect
  2304. dp_sum(dp_fi 1,list dp_term(bc_fi(-1),mo_wconvert(x,w)));
  2305. p:=car m;
  2306. for each x in cdr m do p:=dp_prod(p,x);
  2307. return p;
  2308. end;
  2309. symbolic procedure hf!=powers m;
  2310. % m contains only powers of variables.
  2311. if null m then t
  2312. else (length mo_support car m<2) and hf!=powers cdr m;
  2313. Comment
  2314. Second variant : by induction on the number of variables using the
  2315. exactness of the sequence
  2316. 0 --> S/(I:(x))[-deg x] --> S/I --> S/(I+(x)) --> 0
  2317. [BCRT] do even better, choosing x not as variable, but as splitting
  2318. monomial. I hope to return to that later on.
  2319. end Comment;
  2320. symbolic procedure hf!=whilb2(m,w);
  2321. if null m then dp_fi 1
  2322. else begin scalar m1,m2,x,p;
  2323. for each x in m do
  2324. if mo_linear x then m1:=x . m1 else m2:=x . m2;
  2325. if null m2 then return hf!=whilbmon(m1,w)
  2326. else if null cdr m2 then return hf!=whilbmon(car m2 . m1,w)
  2327. else if hf!=powers m2 then return hf!=whilbmon(append(m1,m2),w)
  2328. else begin scalar x;
  2329. x:=mo_from_a car mo_support car m2;
  2330. p:=dp_prod(hf!=whilbmon(m1,w),
  2331. dp_sum(hf!=whilb2(moid_red(x . m2),w),
  2332. dp_times_mo(mo_wconvert(x,w),
  2333. hf!=whilb2(moid_quot(m2,x),w))))
  2334. end;
  2335. return p;
  2336. end;
  2337. % -------- Weighted Hilbert series from a free resolution --------
  2338. symbolic procedure hf_whilb3(u,w);
  2339. % Weighted Hilbert series numerator from the resolution u.
  2340. begin scalar sgn,p; sgn:=t;
  2341. for each x in u do
  2342. << if sgn then p:=dp_sum(p,hf!=whilb3(x,w))
  2343. else p:=dp_diff(p,hf!=whilb3(x,w));
  2344. sgn:=not sgn;
  2345. >>;
  2346. return p;
  2347. end;
  2348. symbolic procedure hf!=whilb3(u,w);
  2349. % Convert column degrees of the dpmat u to a generating polynomial.
  2350. (if length c = dpmat_cols u then
  2351. begin scalar p;
  2352. for each x in c do
  2353. p:=dp_sum(p,{dp_term(bc_fi 1,mo_wconvert(cdr x,w))});
  2354. return p
  2355. end else dp_fi max(1,dpmat_cols u))
  2356. where c:=dpmat_coldegs u;
  2357. % ------- The common interface ----------------
  2358. symbolic procedure hf_whilb(m,wt);
  2359. % Returns the weighted Hilbert series numerator of the dpmat m as
  2360. % a dpoly using the internal Hilbert series computation
  2361. % get('cali,'hf!=hf) for moideals. m must be a Groebner basis.
  2362. (begin scalar fn,w,lt,p,p1; integer i;
  2363. if null(fn:=get('cali,'hf!=hf)) then
  2364. rederr"No version for the Hilbert function algorithm chosen";
  2365. if dpmat_cols m = 0 then
  2366. return apply2(fn,moid_from_bas dpmat_list m,wt);
  2367. lt:=moid_from_dpmat m;
  2368. for i:=1:dpmat_cols m do
  2369. << p1:=atsoc(i,lt);
  2370. if null p1 then rederr"WHILB with wrong leading term list"
  2371. else p1:=apply2(fn,cdr p1,wt);
  2372. w:=atsoc(i,cali!=degrees);
  2373. if w then p1:=dp_times_mo(mo_wconvert(cdr w,wt),p1);
  2374. p:=dp_sum(p,p1);
  2375. >>;
  2376. return p;
  2377. end) where cali!=degrees:=dpmat_coldegs m;
  2378. symbolic procedure hf!=whilb2hs(h,w);
  2379. % Converts the Hilbert series numerator h into a rational expression
  2380. % with denom = prod ( 1-w(x) | x in ringvars ) and cancels common
  2381. % factors. Uses gcdf and returns a s.q.
  2382. begin scalar a,g,den,num;
  2383. num:=numr simp dp_2a h; % This is the numerator as a s.f.
  2384. den:=1;
  2385. for each x in ring_names cali!=basering do
  2386. << a:=numr simp dp_2a hf!=whilbmon({mo_from_a x},w);
  2387. g:=gcdf!*(num,a);
  2388. num:=quotf(num,g); den:=multf(den,quotf(a,g));
  2389. >>;
  2390. return num ./ den;
  2391. end;
  2392. symbolic procedure weightedhilbertseries!*(m,w);
  2393. % m must be a Gbasis.
  2394. hf!=whilb2hs(hf_whilb(m,w),w);
  2395. symbolic procedure hf_whs_from_resolution(u,w);
  2396. % u must be a resolution.
  2397. hf!=whilb2hs(hf_whilb3(u,w),w);
  2398. symbolic procedure hilbertseries!* m;
  2399. % m must be a Gbasis.
  2400. weightedhilbertseries!*(m,{ring_ecart cali!=basering});
  2401. % --------- Multiplicity and dimension ---------------------
  2402. symbolic procedure hf_mult n;
  2403. % Get the sum of the coefficients of the s.f. (car n). For homogeneous
  2404. % ideals and "good" weight vectors this is the multiplicity.
  2405. prepf absf hf!=sum_up car n;
  2406. symbolic procedure hf!=sum_up f;
  2407. if numberp f then f else hf!=sum_up car subf(f,list (mvar f . 1));
  2408. symbolic procedure hf_dim f;
  2409. % Returns the dimension as the pole order at 1 of the HF f.
  2410. if domainp denr f then 0
  2411. else begin scalar g,x,d; integer n;
  2412. f:=denr f; x:=mvar f; n:=0; d:=(((x.1).-1).1);
  2413. while null cdr (g:=qremf(f,d)) do
  2414. << n:=n+1; f:=car g >>;
  2415. return n;
  2416. end;
  2417. symbolic procedure degree!* m; hf_mult hilbertseries!* m;
  2418. % ------- Algebraic Mode Interface for weighted Hilbert series.
  2419. symbolic operator weightedhilbertseries;
  2420. symbolic procedure weightedhilbertseries(m,w);
  2421. % m must be a gbasis, w a list of weight lists.
  2422. if !*mode='algebraic then
  2423. begin scalar w1,l;
  2424. w1:=for each x in cdr reval w collect cdr x;
  2425. l:=length ring_names cali!=basering;
  2426. for each x in w1 do
  2427. if (not numberlistp x) or (length x neq l)
  2428. then typerr(w,"weight list");
  2429. m:=dpmat_from_a reval m;
  2430. l:=mk!*sq weightedhilbertseries!*(m,w1);
  2431. return l;
  2432. end else weightedhilbertseries!*(m,w);
  2433. endmodule; % hf
  2434. end;
  2435. module intf;
  2436. COMMENT
  2437. #####################################
  2438. ### ###
  2439. ### INTERFACE TO ALGEBRAIC MODE ###
  2440. ### ###
  2441. #####################################
  2442. There are two types of procedures :
  2443. The first type takes polynomial lists or polynomial matrices as
  2444. input, converts them into dpmats, computes the result and
  2445. reconverts it to algebraic mode.
  2446. The second type is property driven, i.e. Basis, Gbasis, Syzygies
  2447. etc. are attached via properties to an identifier.
  2448. For them, the 'ring property watches, that cali!=basering hasn't
  2449. changed (including the term order). Otherwise the results must be
  2450. reevaluated using setideal(name,name) or setmodule(name,name) since
  2451. otherwise results may become wrong.
  2452. The switch "noetherian" controls whether the term order satisfies
  2453. the chain condition (default is "on") and chooses either the
  2454. groebner algorithm or the local standard basis algorithm.
  2455. END COMMENT;
  2456. % ----- The properties managed upto now ---------
  2457. fluid '(intf!=properties);
  2458. intf!=properties:='(basis ring gbasis syzygies resolution hs
  2459. independentsets);
  2460. % --- Some useful common symbolic procedures --------------
  2461. symbolic procedure intf!=clean u;
  2462. % Removes all properties.
  2463. for each x in intf!=properties do remprop(u,x);
  2464. symbolic procedure intf_test m;
  2465. if (length m neq 1)or(not idp car m) then typerr(m,"identifier");
  2466. symbolic procedure intf_get m;
  2467. % Get the 'basis.
  2468. begin scalar c;
  2469. if not (c:=get(m,'basis)) then typerr(m,"dpmat variable");
  2470. if not equal(get(m,'ring),cali!=basering) then
  2471. rederr"invalid base ring";
  2472. cali!=degrees:=dpmat_coldegs c;
  2473. return c;
  2474. end;
  2475. symbolic procedure intf!=set(m,v);
  2476. % Attach the dpmat value v to the variable m.
  2477. << put(m,'ring,cali!=basering);
  2478. put(m,'basis,v);
  2479. if dpmat_cols v = 0 then
  2480. << put(m,'rtype,'list); put(m,'avalue,'list.{dpmat_2a v})>>
  2481. else
  2482. <<put(m,'rtype,'matrix); put(m,'avalue,'matrix.{dpmat_2a v})>>;
  2483. >>;
  2484. % ------ setideal -------------------
  2485. put('setideal,'psopfn,'intf!=setideal);
  2486. symbolic procedure intf!=setideal u;
  2487. % setideal(name,base list)
  2488. begin scalar l;
  2489. if length u neq 2 then rederr "Syntax : setideal(identifier,ideal)";
  2490. if not idp car u then typerr(car u,"ideal name");
  2491. l:=reval cadr u;
  2492. if not eqcar(l,'list) then typerr(l,"ideal basis");
  2493. intf!=clean(car u);
  2494. put(car u,'ring,cali!=basering);
  2495. put(car u,'basis,l:=dpmat_from_a l);
  2496. put(car u,'avalue,'list.{l:=dpmat_2a l});
  2497. put(car u,'rtype,'list);
  2498. return l;
  2499. end;
  2500. % --------------- setmodule -----------------------
  2501. put('setmodule,'psopfn,'intf!=setmodule);
  2502. symbolic procedure intf!=setmodule u;
  2503. % setmodule(name,matrix)
  2504. begin scalar l;
  2505. if length u neq 2 then
  2506. rederr "Syntax : setmodule(identifier,module basis)";
  2507. if not idp car u then typerr(car u,"module name");
  2508. l:=reval cadr u;
  2509. if not eqcar(l,'mat) then typerr(l,"module basis");
  2510. intf!=clean(car u);
  2511. put(car u,'ring,cali!=basering);
  2512. put(car u,'basis,dpmat_from_a l);
  2513. put(car u,'avalue,'matrix.{l});
  2514. put(car u,'rtype,'matrix);
  2515. return l;
  2516. end;
  2517. % ------------ setring ------------------------
  2518. put('setring,'psopfn,'intf!=setring);
  2519. % Setring(vars,term order degrees,tag <,ecart>) sets the internal
  2520. % variable cali!=basering. The term order is at first by the degrees
  2521. % and then by the tag. The tag must be LEX or REVLEX.
  2522. % If ecart is not supplied the ecart is set to the default, i.e. the
  2523. % first degree vector (noetherian degree order) or to (1 1 .. 1).
  2524. % The ring may also be supplied as a list of its arguments as e.g.
  2525. % output by "getring".
  2526. symbolic procedure intf!=setring u;
  2527. begin
  2528. if length u = 1 then u:=cdr reval car u;
  2529. if not memq(length u,'(3 4)) then
  2530. rederr "Syntax : setring(vars,term order,tag[,ecart])";
  2531. setring!* ring_from_a ('list . u);
  2532. return ring_2a cali!=basering;
  2533. end;
  2534. % ----------- getring --------------------
  2535. put('getring,'psopfn,'intf!=getring);
  2536. % Get the base ring of an object as the algebraic list
  2537. % {vars,tord,tag,ecart}.
  2538. symbolic procedure intf!=getring u;
  2539. if null u then ring_2a cali!=basering
  2540. else begin scalar c; c:=get(car u,'ring);
  2541. if null c then typerr(car u,"dpmat variable");
  2542. return ring_2a c;
  2543. end;
  2544. % ------- The algebraic interface -------------
  2545. symbolic operator ideal2mat;
  2546. symbolic procedure ideal2mat m;
  2547. % Convert the list of polynomials m into a matrix column.
  2548. if !*mode='symbolic then rederr"only for algebraic mode"
  2549. else if not eqcar(m,'list) then typerr(m,'list)
  2550. else 'mat . for each x in cdr m collect {x};
  2551. symbolic operator mat2list;
  2552. symbolic procedure mat2list m;
  2553. % Flatten the matrix m.
  2554. if !*mode='symbolic then rederr"only for algebraic mode"
  2555. else if not eqcar(m,'mat) then typerr(m,'matrix)
  2556. else 'list . for each x in cdr m join for each y in x collect y;
  2557. put('setgbasis,'psopfn,'intf!=setgbasis);
  2558. symbolic procedure intf!=setgbasis m;
  2559. % Say that the basis is already a Gbasis.
  2560. begin scalar c;
  2561. intf_test m; m:=car m; c:=intf_get m;
  2562. put(m,'gbasis,c);
  2563. return reval m;
  2564. end;
  2565. symbolic operator setdegrees;
  2566. symbolic procedure setdegrees m;
  2567. % Set a term list as actual column degrees. Execute this before
  2568. % setmodule to supply a module with prescribed column degrees.
  2569. if !*mode='symbolic then rederr"only for algebraic mode"
  2570. else begin scalar i,b;
  2571. b:=moid_from_a reval m; i:=0;
  2572. cali!=degrees:= for each x in b collect <<i:=i+1; i . x>>;
  2573. return moid_2a for each x in cali!=degrees collect cdr x;
  2574. end;
  2575. put('getdegrees,'psopfn,'intf!=getdegrees);
  2576. symbolic procedure intf!=getdegrees m;
  2577. begin
  2578. if m then <<intf_test m; intf_get car m>>;
  2579. return moid_2a for each x in cali!=degrees collect cdr x
  2580. end;
  2581. symbolic operator getecart;
  2582. symbolic procedure getecart;
  2583. if !*mode='algebraic then makelist ring_ecart cali!=basering
  2584. else ring_ecart cali!=basering;
  2585. put('gbasis,'psopfn,'intf!=gbasis);
  2586. symbolic procedure intf!=gbasis m;
  2587. begin scalar c,c1;
  2588. intf_test m; m:=car m; c1:=intf_get m;
  2589. if (c:=get(m,'gbasis)) then return dpmat_2a c;
  2590. c:=gbasis!* c1;
  2591. put(m,'gbasis,c);
  2592. return dpmat_2a c;
  2593. end;
  2594. symbolic operator setmonset;
  2595. symbolic procedure setmonset m;
  2596. if !*mode='algebraic then makelist setmonset!* cdr reval m
  2597. else setmonset!* m;
  2598. symbolic procedure setmonset!* m;
  2599. if subsetp(m,ring_names cali!=basering) then cali!=monset:=m
  2600. else typerr(m,"monset list");
  2601. symbolic operator getmonset;
  2602. symbolic procedure getmonset(); makelist cali!=monset;
  2603. put('resolve,'psopfn,'intf!=resolve);
  2604. symbolic procedure intf!=resolve m;
  2605. begin scalar c,c1,d;
  2606. intf_test m; if length m=2 then d:=reval cadr m else d:=10;
  2607. m:=car m; c1:=intf_get m;
  2608. if ((c:=get(m,'resolution)) and (car c >= d)) then
  2609. return makelist for each x in cdr c collect dpmat_2a x;
  2610. c:=Resolve!*(c1,d);
  2611. put(m,'resolution,d.c);
  2612. if not get(m,'syzygies) then put(m,'syzygies,cadr c);
  2613. return makelist for each x in c collect dpmat_2a x;
  2614. end;
  2615. put('syzygies,'psopfn,'intf!=syzygies);
  2616. symbolic procedure intf!=syzygies m;
  2617. begin scalar c,c1;
  2618. intf_test m; m:=car m; c1:=intf_get m;
  2619. if (c:=get(m,'syzygies)) then return dpmat_2a c;
  2620. c:=syzygies!* c1;
  2621. put(m,'syzygies,c);
  2622. return dpmat_2a c;
  2623. end;
  2624. put('indepvarsets,'psopfn,'intf!=indepvarsets);
  2625. symbolic procedure intf!=indepvarsets m;
  2626. begin scalar c;
  2627. intf_test m; m:=car m; intf_get m;
  2628. if (c:=get(m,'independentsets)) then
  2629. return makelist for each x in c collect makelist x;
  2630. if not (c:=get(m,'gbasis)) then
  2631. put(m,'gbasis,c:=gbasis!* get(m,'basis));
  2632. c:=indepvarsets!* c;
  2633. put(m,'independentsets,c);
  2634. return makelist for each x in c collect makelist x;
  2635. end;
  2636. put('getleadterms,'psopfn,'intf_getleadterms);
  2637. symbolic procedure intf_getleadterms m;
  2638. begin scalar c;
  2639. intf_test m; m:=car m; intf_get m;
  2640. if not (c:=get(m,'gbasis)) then
  2641. put(m,'gbasis,c:=gbasis!* get(m,'basis));
  2642. c:=getleadterms!* c;
  2643. return dpmat_2a c;
  2644. end;
  2645. put('hilbertseries,'psopfn,'intf!=hilbertseries);
  2646. symbolic procedure intf!=hilbertseries m;
  2647. % Returns the Hilbert series of m.
  2648. begin scalar c;
  2649. intf_test m; m:=car m; intf_get m;
  2650. if (c:=get(m,'hs)) then return mk!*sq c;
  2651. if not(c:=get(m,'gbasis)) then
  2652. put(m,'gbasis,c:=gbasis!* get(m,'basis));
  2653. put(m,'hs,c:=hilbertseries!* c);
  2654. return mk!*sq c;
  2655. end;
  2656. put('degree,'psopfn,'intf_getmult);
  2657. symbolic procedure intf_getmult m;
  2658. % Returns the multiplicity of m.
  2659. begin scalar c;
  2660. intf_test m; m:=car m; intf_get m;
  2661. if (c:=get(m,'hs)) then return hf_mult c;
  2662. if not(c:=get(m,'gbasis)) then
  2663. put(m,'gbasis,c:=gbasis!* get(m,'basis));
  2664. put(m,'hs,c:=hilbertseries!* c);
  2665. return hf_mult c;
  2666. end;
  2667. put('dim,'psopfn,'intf!=dim);
  2668. put('codim,'psopfn,'intf!=codim);
  2669. symbolic procedure intf!=dim m;
  2670. % Returns the dimension of coker m.
  2671. begin scalar c;
  2672. intf_test m; m:=car m; intf_get m;
  2673. if (c:=get(m,'hs)) then return hf_dim c;
  2674. if (c:=get(m,'independentsets)) then return length moid_max c;
  2675. if not(c:=get(m,'gbasis)) then
  2676. put(m,'gbasis,c:=gbasis!* get(m,'basis));
  2677. c:=indepvarsets!* c; put(m,'independentsets,c);
  2678. return length moid_max c;
  2679. end;
  2680. symbolic procedure intf!=codim m;
  2681. % Returns the codimension of coker m.
  2682. length ring_names cali!=basering - intf!=dim m;
  2683. put('BettiNumbers,'psopfn,'intf!=BettiNumbers);
  2684. symbolic procedure intf!=BettiNumbers m;
  2685. begin scalar c;
  2686. intf_test m; m:=car m; intf_get m;
  2687. if (c:=get(m,'resolution)) then return makelist BettiNumbers!* cdr c
  2688. else rederr"Compute a resolution first";
  2689. end;
  2690. put('GradedBettiNumbers,'psopfn,'intf!=GradedBettiNumbers);
  2691. symbolic procedure intf!=GradedBettiNumbers m;
  2692. begin scalar c;
  2693. intf_test m; m:=car m; intf_get m;
  2694. if (c:=get(m,'resolution)) then return
  2695. makelist for each x in GradedBettiNumbers!* cdr c collect makelist x
  2696. else rederr"Compute a resolution first";
  2697. end;
  2698. put('degsfromresolution,'psopfn,'intf!=degsfromresolution);
  2699. symbolic procedure intf!=degsfromresolution m;
  2700. begin scalar c;
  2701. intf_test m; m:=car m;
  2702. if not equal(get(m,'ring),cali!=basering) then
  2703. rederr"invalid base ring";
  2704. if not (c:=get(m,'resolution)) then
  2705. rederr"compute a resolution first";
  2706. return makelist for each x in cdr c collect
  2707. moid_2a for each y in dpmat_coldegs x collect cdr y;
  2708. end;
  2709. symbolic operator sieve;
  2710. symbolic procedure sieve(m,vars);
  2711. % Sieve out all base elements from m containing one of the variables
  2712. % in vars in their leading term.
  2713. if !*mode='algebraic then
  2714. dpmat_2a dpmat_sieve(dpmat_from_a reval m,cdr vars,nil)
  2715. else dpmat_sieve(m,vars,nil);
  2716. endmodule; % intf
  2717. end;
  2718. module lf;
  2719. COMMENT
  2720. ###############################
  2721. #### ####
  2722. #### DUAL BASES APPROACH ####
  2723. #### ####
  2724. ###############################
  2725. The general idea for the dual bases approach :
  2726. Given a finite collection of linear functionals L : M=S^n --> k^N, we
  2727. want to compute a basis for Ker L as in
  2728. [MMM] : Marinari et al., Proc. ISSAC'91, p. 55-63
  2729. This generalizes the approach from
  2730. [FGLM] : Faugere, Gianni, Lazard, Mora: JSC 16 (1993), 329 - 344.
  2731. L is given through values on the generators,
  2732. {[e_i,L(e_i)], i=1 ... n},
  2733. and an evaluation function evlf([p,L(p)],x), that evaluates L(p*x)
  2734. from L(p) for p in M and the variable x .
  2735. We process a queue of elements of M with increasing leading terms,
  2736. evaluating each time L on them. Different to [MMM] the queue is stored
  2737. as
  2738. {[p,L(p)], l=list of potential multipliers, lt(p*(x:=first l))}
  2739. for the potential evaluation of L(p*x) and sorted by the term order
  2740. wrt. the third slot. Since we proceed by increasing lt, Gaussian
  2741. elimination doesn't disturb leading terms. Hence leading terms of the
  2742. result are linearly independent and thus the result a Groebner basis.
  2743. This approach applies to very different problem settings, see
  2744. [MMM]. CALI manages this variety of applications through different
  2745. values on the property list of 'cali.
  2746. There are general entries with information about the computation
  2747. 'varlessp -- a sort predicate for lf variable names
  2748. 'evlf -- the evaluation function
  2749. and special entries, depending on the problem to be solved.
  2750. [p,L(p)] is handled as data type lf (linear functions)
  2751. < dpoly > . < list of (var. name).(base coeff.) >
  2752. The lf cdr list is the list of the values of the linear functionals
  2753. on the given car lf dpoly.
  2754. evlf(lf,var) evaluates lf*var and returns a new lf.
  2755. There are the following order functions :
  2756. varlessp = (cdr lf) variable order
  2757. lf!=sort = lf queue order
  2758. term order = (car lf) dpoly order
  2759. end comment;
  2760. symbolic procedure lf_dualbasis(q);
  2761. % q is the dual generator set given as a list of input lf values.
  2762. % l is the queue to be processed and updated, g the list of kernel
  2763. % elements, produced so far.
  2764. begin scalar g,l,q,r,p,v,u,vars,rf,q1;
  2765. v:=ring_names cali!=basering;
  2766. if null(rf:=get('cali,'evlf)) then
  2767. rederr"For DUALBASIS no evaluation function defined";
  2768. for each ev1 in q do
  2769. if lf!=zero ev1 then
  2770. << if cali_trace()>20 then dp_print2 car q; g:=car q . g >>
  2771. else
  2772. << vars:=v; q1:=ev1.q1;
  2773. while vars do
  2774. << l:={ev1, vars, mo_from_a car vars}.l; vars:=cdr vars >>;
  2775. >>;
  2776. q:=sort(q1,function lf!=less); % The reducer in triangular order.
  2777. l:=sort(l, function lf!=sort); % The queue in increasing term order.
  2778. while l do
  2779. << r:=car l; l:=cdr l;
  2780. vars:=second r; r:=car r;
  2781. p:=lf!=reduce(apply2(rf,r,car vars),q);
  2782. if lf!=zero p then
  2783. << if cali_trace()>20 then dp_print2 car p; g:=car p . g >>
  2784. else
  2785. << q:=merge({p},q,function lf!=less);
  2786. u:=nil; v:=dp_lmon car p;
  2787. while vars do
  2788. << u:={p,vars,mo_sum(v,mo_from_a car vars)}.u;
  2789. vars:=cdr vars
  2790. >>;
  2791. l:=merge(sort(u,function lf!=sort),l,function lf!=sort);
  2792. >>;
  2793. >>;
  2794. g:=bas_renumber bas_zerodelete for each x in g collect bas_make(0,x);
  2795. return interreduce!* groeb_mingb dpmat_make(length g,0,g,nil,t);
  2796. end;
  2797. symbolic procedure lf!=sort(a,b);
  2798. % Term order on the third slot. Niermann proposes another order here.
  2799. mo_compare(third a,third b)=-1;
  2800. symbolic procedure lf_dualhbasis(q,s);
  2801. % The homogenized version.
  2802. % s is the length of the dual homogenized basis.
  2803. % For modules with column degrees not yet correct.
  2804. begin scalar a,d,g,l,l1,r,p,v,u,vars,rf,q1;
  2805. v:=ring_names cali!=basering; d:=0;
  2806. if null(rf:=get('cali,'evlf)) then
  2807. rederr"For DUALHBASIS no evaluation function defined";
  2808. for each ev1 in q do
  2809. if lf!=zero ev1 then
  2810. << if cali_trace()>20 then dp_print2 car q; g:=car q . g >>
  2811. else
  2812. << vars:=v; q1:=ev1.q1;
  2813. while vars do
  2814. << l:={ev1, vars, mo_from_a car vars}.l; vars:=cdr vars >>;
  2815. >>;
  2816. q:=sort(q1,function lf!=less); % The reducer in triangular order.
  2817. l1:=sort(l,function lf!=sort); % The queue in increasing term order.
  2818. repeat
  2819. << % Initialize the computation of the next degree.
  2820. l:=l1; q:=l1:=nil; d:=d+1;
  2821. while l do
  2822. << r:=car l; l:=cdr l;
  2823. vars:=second r; r:=car r;
  2824. p:=lf!=reduce(apply2(rf,r,car vars),q);
  2825. if lf!=zero p then
  2826. << if cali_trace()>20 then dp_print2 car p;
  2827. g:=bas_make(0,car p) . g
  2828. >>
  2829. else
  2830. << q:=merge({p},q,function lf!=less);
  2831. u:=nil; v:=dp_lmon car p;
  2832. while vars do
  2833. << u:={p,vars,mo_sum(v,mo_from_a car vars)}.u;
  2834. vars:=cdr vars
  2835. >>;
  2836. l1:=merge(sort(u,function lf!=sort),l1,function lf!=sort);
  2837. >>;
  2838. g:=bas_renumber bas_zerodelete g;
  2839. a:=dpmat_make(length g,0,g,nil,t);
  2840. >>;
  2841. >>
  2842. until (d>=s) or ((dim!* a = 1) and (length q = s));
  2843. return interreduce!* groeb_mingb a;
  2844. end;
  2845. symbolic procedure lf!=compact u;
  2846. % Sort the cdr of the lf u and remove zeroes.
  2847. sort(for each x in u join if not bc_zero!? cdr x then {x},
  2848. function (lambda(x,y);
  2849. apply2(get('cali,'varlessp),car x,car y)));
  2850. symbolic procedure lf!=zero l; null cdr l;
  2851. symbolic procedure lf!=sum(a,b);
  2852. dp_sum(car a,car b) . lf!=sum1(cdr a,cdr b);
  2853. symbolic procedure lf!=times_bc(z,a);
  2854. dp_times_bc(z,car a) . lf!=times_bc1(z,cdr a);
  2855. symbolic procedure lf!=times_bc1(z,a);
  2856. if bc_zero!? z then nil
  2857. else for each x in a collect car x . bc_prod(z,cdr x);
  2858. symbolic procedure lf!=sum1(a,b);
  2859. if null a then b
  2860. else if null b then a
  2861. else if equal(caar a,caar b) then
  2862. (if bc_zero!? u then lf!=sum1(cdr a,cdr b)
  2863. else (caar a . u).lf!=sum1(cdr a,cdr b))
  2864. where u:=bc_sum(cdar a,cdar b)
  2865. else if apply2(get('cali,'varlessp),caar a,caar b) then
  2866. (car a).lf!=sum1(cdr a,b)
  2867. else (car b).lf!=sum1(a,cdr b);
  2868. symbolic procedure lf!=simp a;
  2869. if null cdr a then car dp_simp car a. nil
  2870. else begin scalar z;
  2871. if (z:=bc_inv lf!=lc a) then return lf!=times_bc(z,a);
  2872. z:=dp_content car a;
  2873. for each x in cdr a do z:=bc_gcd(z,cdr x);
  2874. return (for each x in car a collect car x . bc_quot(cdr x,z)) .
  2875. (for each x in cdr a collect car x . bc_quot(cdr x,z));
  2876. end;
  2877. % Leading variable and coefficient assuming cdr a nonempty :
  2878. symbolic procedure lf!=lvar a; caadr a;
  2879. symbolic procedure lf!=lc a; cdadr a;
  2880. symbolic procedure lf!=less(a,b);
  2881. apply2(get('cali,'varlessp),lf!=lvar a,lf!=lvar b);
  2882. symbolic procedure lf!=reduce(a,l);
  2883. if lf!=zero a or null l or lf!=less(a, car l) then a
  2884. else if (lf!=lvar a = lf!=lvar car l) then
  2885. begin scalar z,z1,z2,b;
  2886. b:=car l; z1:=bc_neg lf!=lc a; z2:=lf!=lc b;
  2887. if !*bcsimp then
  2888. << if (z:=bc_inv z1) then <<z1:=bc_fi 1; z2:=bc_prod(z2,z)>>
  2889. else
  2890. << z:=bc_gcd(z1,z2);
  2891. z1:=bc_quot(z1,z);
  2892. z2:=bc_quot(z2,z);
  2893. >>;
  2894. >>;
  2895. a:=lf!=sum(lf!=times_bc(z2,a),lf!=times_bc(z1,b));
  2896. if !*bcsimp then a:=lf!=simp a;
  2897. return lf!=reduce(a,cdr l)
  2898. end
  2899. else lf!=reduce(a,cdr l);
  2900. % ------------ Application to point evaluation -------------------
  2901. % cali has additionally 'varnames and 'sublist.
  2902. % It works also for symbolic matrix entries.
  2903. symbolic operator affine_points;
  2904. symbolic procedure affine_points m;
  2905. % m is an algebraic matrix, which rows are the coordinates of points
  2906. % in the affine space with Spec = the current ring.
  2907. if !*mode='algebraic then dpmat_2a affine_points!* reval m
  2908. else affine_points!* m;
  2909. symbolic procedure affine_points!* m;
  2910. begin scalar names;
  2911. if length(names:=ring_names cali!=basering) neq length cadr m then
  2912. typerr(m,"coordinate matrix");
  2913. put('cali,'sublist,for each x in cdr m collect pair(names,x));
  2914. put('cali,'varnames, names:=for each x in cdr m collect gensym());
  2915. put('cali,'varlessp,'lf!=pointvarlessp);
  2916. put('cali,'evlf,'lf!=pointevlf);
  2917. return lf_dualbasis(
  2918. { dp_fi 1 . lf!=compact
  2919. for each x in names collect (x . bc_fi 1) });
  2920. end;
  2921. symbolic operator proj_points;
  2922. symbolic procedure proj_points m;
  2923. % m is an algebraic matrix, which rows are the coordinates of _points
  2924. % in the projective space with Proj = the current ring.
  2925. if !*mode='algebraic then dpmat_2a proj_points!* reval m
  2926. else proj_points!* m;
  2927. symbolic procedure proj_points!* m;
  2928. % Points must be different in proj. space. This will not be tested !
  2929. begin scalar u,names;
  2930. if length(names:=ring_names cali!=basering) neq length cadr m then
  2931. typerr(m,"coordinate matrix");
  2932. put('cali,'sublist,u:=for each x in cdr m collect pair(names,x));
  2933. put('cali,'varnames, names:=for each x in cdr m collect gensym());
  2934. put('cali,'varlessp,'lf!=pointvarlessp);
  2935. put('cali,'evlf,'lf!=pointevlf);
  2936. return lf_dualhbasis(
  2937. { dp_fi 1 . lf!=compact
  2938. for each x in names collect (x . bc_fi 1) },
  2939. length u);
  2940. end;
  2941. symbolic procedure lf!=pointevlf(p,x);
  2942. begin scalar q; p:=dp_2a (q:=dp_prod(car p,dp_from_a x));
  2943. return q . lf!=compact
  2944. pair(get('cali,'varnames),
  2945. for each x in get('cali,'sublist) collect
  2946. bc_from_a subeval1(x,p));
  2947. end;
  2948. symbolic procedure lf!=pointvarlessp(x,y); not ordp(x,y);
  2949. % ------ Application to Groebner bases under term order change ----
  2950. % ----- The version with borderbases :
  2951. % cali has additionally 'oldborderbasis.
  2952. put('change_termorder,'psopfn,'lf!=change_termorder);
  2953. symbolic procedure lf!=change_termorder m;
  2954. begin scalar c,r;
  2955. if (length m neq 2) then
  2956. rederr "Syntax : Change_TermOrder(dpmat identifier, new ring)";
  2957. if (not idp car m) then typerr(m,"dpmat identifier");
  2958. r:=ring_from_a reval second m;
  2959. m:=car m; intf_get m;
  2960. if not (c:=get(m,'gbasis)) then
  2961. put(m,'gbasis,c:=gbasis!* get(m,'basis));
  2962. c:=change_termorder!*(c,r);
  2963. return dpmat_2a c;
  2964. end;
  2965. symbolic procedure change_termorder!*(m,r);
  2966. % m must be a zerodimensional gbasis with respect to the current term
  2967. % order, r the new ring (with the same var. names).
  2968. % This procedure sets r as the current ring and computes a gbasis
  2969. % of m with respect to r.
  2970. if (dpmat_cols m neq 0) or not dimzerop!* m then
  2971. rederr("CHANGE_TERMORDER only for zerodimensional ideals")
  2972. else if ring_names r neq ring_names cali!=basering then
  2973. typerr(makelist ring_names r,"variable names")
  2974. else begin scalar b;
  2975. if cali_trace()>20 then print"Precomputing the border basis";
  2976. b:=for each x in odim_borderbasis m collect bas_dpoly x;
  2977. if cali_trace()>20 then print"Borderbasis computed";
  2978. setring!* r;
  2979. put('cali,'oldborderbasis, for each x in b collect
  2980. {mo_neworder dp_lmon x, dp_lc x,dp_neg dp_neworder cdr x});
  2981. put('cali,'varlessp,'lf!=tovarlessp);
  2982. put('cali,'evlf,'lf!=toevlf);
  2983. return lf_dualbasis({dp_fi 1 . dp_fi 1})
  2984. end;
  2985. symbolic procedure lf!=tovarlessp(a,b); mo_compare(a,b)=1;
  2986. symbolic procedure lf!=toevlf(p,x);
  2987. begin scalar a,b,c,d;
  2988. x:=mo_from_a x; c:=get('cali,'oldborderbasis);
  2989. p:=dp_times_mo(x,car p).dp_times_mo(x,cdr p);
  2990. % Now reduce the terms in cdr p with the old borderbasis.
  2991. for each x in cdr p do
  2992. % b is the list of terms already in canonical form,
  2993. % a is a list of (can. form) . (bc_quot), where bc_quot is
  2994. % a pair of bc's interpreted as a rational multiplier
  2995. % for the can. form.
  2996. if d:=assoc(car x,c) then a:=(third d . (cdr x . second d)) .a
  2997. else b:=x.b;
  2998. a:=for each x in a collect car x . lf!=reducebc cdr x;
  2999. d:=lf!=denom a;
  3000. a:=for each x in a collect
  3001. dp_times_bc(bc_quot(bc_prod(d,cadr x),cddr x),car x);
  3002. b:=dp_times_bc(d,reversip b);
  3003. for each x in a do b:=dp_sum(x,b);
  3004. return dp_times_bc(d,car p) . b;
  3005. end;
  3006. symbolic procedure lf!=reducebc z;
  3007. begin scalar g;
  3008. if g:=bc_inv cdr z then return bc_prod(g,car z) . bc_fi 1;
  3009. g:=bc_gcd(car z,cdr z);
  3010. return bc_quot(car z,g) . bc_quot(cdr z,g);
  3011. end;
  3012. symbolic procedure lf!=denom a;
  3013. if null a then bc_fi 1
  3014. else if null cdr a then cddar a
  3015. else bc_lcm(cddar a,lf!=denom cdr a);
  3016. % ----- The version without borderbases :
  3017. % cali has additionally 'oldring, 'oldbasis
  3018. put('change_termorder1,'psopfn,'lf!=change_termorder1);
  3019. symbolic procedure lf!=change_termorder1 m;
  3020. begin scalar c,r;
  3021. if (length m neq 2) then
  3022. rederr "Syntax : Change_TermOrder1(dpmat identifier, new ring)";
  3023. if (not idp car m) then typerr(m,"dpmat identifier");
  3024. r:=ring_from_a reval second m;
  3025. m:=car m; intf_get m;
  3026. if not (c:=get(m,'gbasis)) then
  3027. put(m,'gbasis,c:=gbasis!* get(m,'basis));
  3028. c:=change_termorder1!*(c,r);
  3029. return dpmat_2a c;
  3030. end;
  3031. symbolic procedure change_termorder1!*(m,r);
  3032. % m must be a zerodimensional gbasis with respect to the current term
  3033. % order, r the new ring (with the same var. names).
  3034. % This procedure sets r as the current ring and computes a gbasis
  3035. % of m with respect to r.
  3036. if (dpmat_cols m neq 0) or not dimzerop!* m then
  3037. rederr("change_termorder1 only for zerodimensional ideals")
  3038. else if ring_names r neq ring_names cali!=basering then
  3039. typerr(makelist ring_names r,"variable names")
  3040. else begin scalar c,d;
  3041. c:=if dpmat_cols m=0 then {dp_fi 1}
  3042. else for k:=1:dpmat_cols m collect dp_from_ei k;
  3043. put('cali,'varlessp,'lf!=tovarlessp1);
  3044. put('cali,'evlf,'lf!=toevlf1);
  3045. put('cali,'oldring,cali!=basering);
  3046. put('cali,'oldbasis,m);
  3047. setring!* r;
  3048. d:=if dpmat_cols m=0 then {dp_fi 1}
  3049. else for k:=1:dpmat_cols m collect dp_from_ei k;
  3050. return lf_dualbasis(pair(d,c))
  3051. end;
  3052. symbolic procedure lf!=tovarlessp1(a,b);
  3053. (mo_compare(a,b)=1)
  3054. where cali!=basering=get('cali,'oldring);
  3055. symbolic procedure lf!=toevlf1(p,x);
  3056. % p = ( a . b ). Returns (c*a*x,d) where (d.c)=mod!*(b*x,m).
  3057. begin scalar a,b,c,d;
  3058. a:=dp_times_mo(mo_from_a x,car p);
  3059. (<< b:=dp_times_mo(mo_from_a x,cdr p);
  3060. b:=mod!*(b,get('cali,'oldbasis));
  3061. d:=car b; c:=dp_lc cdr b;
  3062. >>) where cali!=basering:=get('cali,'oldring);
  3063. return dp_times_bc(c,a) . d;
  3064. end;
  3065. endmodule; % lf
  3066. end;
  3067. module matop;
  3068. COMMENT
  3069. #############################
  3070. #### ####
  3071. #### MATRIX OPERATIONS ####
  3072. #### ####
  3073. #############################
  3074. This module contains operations on dpmats, that correspond to module
  3075. operations on the corresponding images resp. cokernels.
  3076. END COMMENT;
  3077. symbolic procedure matop!=testdpmatlist l;
  3078. % Test l to be a list of dpmats embedded into a common free module.
  3079. if null l then rederr"Empty DPMAT list"
  3080. else begin scalar c,d;
  3081. for each x in l do
  3082. if not eqcar(x,'dpmat) then typerr(x,"DPMAT");
  3083. c:=dpmat_cols car l; d:=dpmat_coldegs car l;
  3084. for each x in cdr l do
  3085. if not (eqn(c,dpmat_cols x) and equal(d,dpmat_coldegs x)) then
  3086. rederr"Matrices don't match in the DPMAT list";
  3087. end;
  3088. symbolic procedure matappend!* l;
  3089. % Appends rows of the dpmats in the dpmat list l.
  3090. (begin scalar u,r;
  3091. matop!=testdpmatlist l;
  3092. cali!=degrees:=dpmat_coldegs car l;
  3093. u:=dpmat_list car l; r:=dpmat_rows car l;
  3094. for each y in cdr l do
  3095. << u:=append(u, for each x in dpmat_list y collect
  3096. bas_newnumber(bas_nr x + r,x));
  3097. r:=r + dpmat_rows y;
  3098. >>;
  3099. return dpmat_make(r,dpmat_cols car l,u,cali!=degrees,nil)
  3100. end) where cali!=degrees:=cali!=degrees;
  3101. put('matappend,'psopfn,'matop!=matappend);
  3102. symbolic procedure matop!=matappend l;
  3103. % Append the dpmats in the list l.
  3104. dpmat_2a matappend!* for each x in l collect dpmat_from_a reval x;
  3105. symbolic procedure mat2list!* m;
  3106. % Returns the ideal of all elements of m.
  3107. if dpmat_cols m = 0 then m
  3108. else (begin scalar x;
  3109. x:=bas_renumber bas_zerodelete
  3110. for i:=1:dpmat_rows m join
  3111. for j:=1:dpmat_cols m collect
  3112. bas_make(0,dpmat_element(i,j,m));
  3113. return dpmat_make(length x,0,x,nil,
  3114. if dpmat_cols m=1 then dpmat_gbtag m else nil)
  3115. end) where cali!=degrees:=nil;
  3116. symbolic procedure matsum!* l;
  3117. % Returns the module sum of the dpmat list l.
  3118. interreduce!* matappend!* l;
  3119. put('matsum,'psopfn,'matop!=matsum);
  3120. put('idealsum,'psopfn,'matop!=matsum);
  3121. symbolic procedure matop!=matsum l;
  3122. % Returns the sum of the ideals/modules in the list l.
  3123. dpmat_2a matsum!* for each x in l collect dpmat_from_a reval x;
  3124. symbolic procedure matop!=idealprod2(a,b);
  3125. if (dpmat_cols a > 0) or (dpmat_cols b > 0 ) then
  3126. rederr"IDEALPROD only for ideals"
  3127. else (begin scalar x;
  3128. x:=bas_renumber
  3129. for each a1 in dpmat_list a join
  3130. for each b1 in dpmat_list b collect
  3131. bas_make(0,dp_prod(bas_dpoly a1,bas_dpoly b1));
  3132. return interreduce!* dpmat_make(length x,0,x,nil,nil)
  3133. end) where cali!=degrees:=nil;
  3134. symbolic procedure idealprod!* l;
  3135. % Returns the product of the ideals in the dpmat list l.
  3136. if null l then rederr"empty list in IDEALPROD"
  3137. else if length l=1 then car l
  3138. else begin scalar u;
  3139. u:=car l;
  3140. for each x in cdr l do u:=matop!=idealprod2(u,x);
  3141. return u;
  3142. end;
  3143. put('idealprod,'psopfn,'matop!=idealprod);
  3144. symbolic procedure matop!=idealprod l;
  3145. % Returns the product of the ideals in the list l.
  3146. dpmat_2a idealprod!* for each x in l collect dpmat_from_a reval x;
  3147. symbolic procedure idealpower!*(a,n);
  3148. if (dpmat_cols a > 0) or (not fixp n) or (n < 0) then
  3149. rederr" Syntax : idealpower(ideal,integer)"
  3150. else if (n=0) then dpmat_from_dpoly dp_fi 1
  3151. else begin scalar w; w:=a;
  3152. for i:=2:n do w:=matop!=idealprod2(w,a);
  3153. return w;
  3154. end;
  3155. symbolic operator idealpower;
  3156. symbolic procedure idealpower(m,l);
  3157. if !*mode='algebraic then
  3158. dpmat_2a idealpower!*(dpmat_from_a reval m,l)
  3159. else idealpower!*(m,l);
  3160. symbolic procedure matop!=shiftdegs(d,n);
  3161. % Shift column degrees d n places.
  3162. for each x in d collect ((car x + n) . cdr x);
  3163. symbolic procedure directsum!* l;
  3164. % Returns the direct sum of the modules in the dpmat list l.
  3165. if null l then rederr"Empty DPMAT list"
  3166. else (begin scalar r,c,u;
  3167. for each x in l do
  3168. if not eqcar(x,'dpmat) then typerr(x,"DPMAT")
  3169. else if dpmat_cols x=0 then
  3170. rederr"DIRECTSUM only for modules";
  3171. c:=r:=0; % Actual column resp. row index.
  3172. cali!=degrees:=nil;
  3173. for each x in l do
  3174. << cali!=degrees:=append(cali!=degrees,
  3175. matop!=shiftdegs(dpmat_coldegs x,c));
  3176. u:=append(u, for each y in dpmat_list x collect
  3177. bas_make(bas_nr y + r,dp_times_ei(c,bas_dpoly y)));
  3178. r:=r + dpmat_rows x;
  3179. c:=c + dpmat_cols x;
  3180. >>;
  3181. return dpmat_make(r,c,u,cali!=degrees,nil)
  3182. end) where cali!=degrees:=cali!=degrees;
  3183. put('directsum,'psopfn,'matop!=directsum);
  3184. symbolic procedure matop!=directsum l;
  3185. % Returns the direct sum of the modules in the list l.
  3186. dpmat_2a directsum!* for each x in l collect dpmat_from_a reval x;
  3187. symbolic operator deleteunits;
  3188. symbolic procedure deleteunits m;
  3189. if !*noetherian then m
  3190. else if !*mode='algebraic then dpmat_2a deleteunits!* dpmat_from_a m
  3191. else deleteunits!* m;
  3192. symbolic procedure deleteunits!* m;
  3193. % Delete units from the base elements of the ideal m.
  3194. if !*noetherian or (dpmat_cols m>0) then m
  3195. else dpmat_make(dpmat_rows m,0,
  3196. for each x in dpmat_list m collect
  3197. bas_factorunits x,nil,dpmat_gbtag m);
  3198. symbolic procedure interreduce!* m;
  3199. (begin scalar u;
  3200. u:=red_interreduce dpmat_list m;
  3201. return dpmat_make(length u, dpmat_cols m, bas_renumber u,
  3202. cali!=degrees, dpmat_gbtag m)
  3203. end) where cali!=degrees:=dpmat_coldegs m;
  3204. symbolic operator interreduce;
  3205. symbolic procedure interreduce m;
  3206. % Interreduce m.
  3207. if !*mode='algebraic then
  3208. dpmat_2a interreduce!* dpmat_from_a reval m
  3209. else interreduce!* m;
  3210. symbolic procedure gbasis!* m;
  3211. % Produce a minimal Groebner or standard basis of the dpmat m.
  3212. if dpmat_gbtag m then m else car groeb_stbasis(m,t,nil,nil);
  3213. put('tangentcone,'psopfn,'matop!=tangentcone);
  3214. symbolic procedure matop!=tangentcone m;
  3215. begin scalar c;
  3216. intf_test m; m:=car m; intf_get m;
  3217. if not (c:=get(m,'gbasis)) then
  3218. put(m,'gbasis,c:=gbasis!* get(m,'basis));
  3219. c:=tangentcone!* c;
  3220. return dpmat_2a c;
  3221. end;
  3222. symbolic procedure tangentcone!* m;
  3223. % Returns the tangent cone of m, provided the term order has degrees.
  3224. % m must be a gbasis.
  3225. if null ring_degrees cali!=basering then
  3226. rederr"tangent cone only for degree orders defined"
  3227. else (begin scalar b;
  3228. b:=for each x in dpmat_list m collect
  3229. bas_make(bas_nr x,dp_tcpart bas_dpoly x);
  3230. return dpmat_make(dpmat_rows m,
  3231. dpmat_cols m,b,cali!=degrees,dpmat_gbtag m);
  3232. end) where cali!=degrees:=dpmat_coldegs m;
  3233. symbolic procedure syzygies1!* bas;
  3234. % Returns the (not yet interreduced first) syzygy module of the dpmat
  3235. % bas.
  3236. begin
  3237. if cali_trace() > 0 then
  3238. << terpri(); write" Compute syzygies"; terpri() >>;
  3239. return third groeb_stbasis(bas,nil,nil,t);
  3240. end;
  3241. symbolic procedure syzygies!* bas;
  3242. % Returns the interreduced syzygy basis.
  3243. interreduce!* syzygies1!* bas;
  3244. symbolic procedure normalform!*(a,b);
  3245. % Returns {a1,r,z} with a1=z*a-r*b where the rows of the dpmat a1 are
  3246. % the normalforms of the rows of the dpmat a with respect to the
  3247. % dpmat b.
  3248. if not(eqn(dpmat_cols a,dpmat_cols b) and
  3249. equal(dpmat_coldegs a,dpmat_coldegs b)) then
  3250. rederr"dpmats don't match for NORMALFORM"
  3251. else (begin scalar a1,z,u,r;
  3252. bas_setrelations dpmat_list b;
  3253. a1:=for each x in dpmat_list a collect
  3254. << u:=red_redpol(dpmat_list b,x);
  3255. z:=bas_make(bas_nr x,dp_times_ei(bas_nr x,cdr u)).z;
  3256. car u
  3257. >>;
  3258. r:=bas_getrelations a1; bas_removerelations a1;
  3259. bas_removerelations dpmat_list b; z:=reversip z;
  3260. a1:=dpmat_make(dpmat_rows a,dpmat_cols a,a1,cali!=degrees,nil);
  3261. cali!=degrees:=dpmat_rowdegrees b;
  3262. r:=dpmat_make(dpmat_rows a,dpmat_rows b,bas_neworder r,
  3263. cali!=degrees,nil);
  3264. cali!=degrees:=nil;
  3265. z:=dpmat_make(dpmat_rows a,dpmat_rows a,bas_neworder z,nil,nil);
  3266. return {a1,r,z};
  3267. end) where cali!=degrees:=dpmat_coldegs b;
  3268. symbolic procedure matop_pseudomod(a,b); car mod!*(a,b);
  3269. symbolic procedure mod!*(a,b);
  3270. % Returns the normal form of the dpoly a modulo the dpmat b and the
  3271. % corresponding unit produced during pseudo division.
  3272. (begin scalar u;
  3273. a:=dp_neworder a; % to be on the safe side.
  3274. u:=red_redpol(dpmat_list b,bas_make(0,a));
  3275. return (bas_dpoly car u) . cdr u;
  3276. end) where cali!=degrees:=dpmat_coldegs b;
  3277. symbolic operator mod;
  3278. symbolic procedure mod(a,b);
  3279. % True normal form as s.q. also for matrices.
  3280. if !*mode='symbolic then rederr"only for algebraic mode"
  3281. else begin scalar u;
  3282. b:=dpmat_from_a reval b; a:=reval a;
  3283. if eqcar(a,'list) then
  3284. if dpmat_cols b>0 then rederr"entries don't match for MOD"
  3285. else a:=makelist for each x in cdr a collect
  3286. << u:=mod!*(dp_from_a x, b);
  3287. {'quotient,dp_2a car u,dp_2a cdr u}
  3288. >>
  3289. else if eqcar(a,'mat) then
  3290. begin a:=dpmat_from_a a;
  3291. if dpmat_cols a neq dpmat_cols b then
  3292. rederr"entries don't match for MOD";
  3293. a:=for each x in dpmat_list a collect mod!*(bas_dpoly x,b);
  3294. a:='mat.
  3295. for each x in a collect
  3296. << u:=dp_2a cdr x;
  3297. for i:=1:dpmat_cols b collect
  3298. {'quotient,dp_2a dp_comp(i,car x),u}
  3299. >>
  3300. end
  3301. else if dpmat_cols b>0 then rederr"entries don't match for MOD"
  3302. else << u:=mod!*(dp_from_a a, b);
  3303. a:={'quotient,dp_2a car u,dp_2a cdr u}
  3304. >>;
  3305. return a;
  3306. end;
  3307. infix mod;
  3308. symbolic operator normalform;
  3309. symbolic procedure normalform(a,b);
  3310. % Compute a normal form of the rows of a with respect to b :
  3311. % first result = third result * a + second result * b.
  3312. if !*mode='algebraic then
  3313. begin scalar m;
  3314. m:= normalform!*(dpmat_from_a reval a,dpmat_from_a reval b);
  3315. return {'list,dpmat_2a car m, dpmat_2a cadr m, dpmat_2a caddr m}
  3316. end
  3317. else normalform!*(a,b);
  3318. symbolic procedure eliminate!*(m,vars);
  3319. % Returns a (dpmat) basis of the elimination module of the dpmat m
  3320. % eliminating variables contained in the var. list vars.
  3321. % It sets temporary the standard elimination term order, but doesn't
  3322. % affect the ecart, and computes a Groebner basis of m.
  3323. % if dpmat_gbtag m and eo(vars) then dpmat_sieve(m,vars,t) else
  3324. (begin scalar c,e,bas,v;
  3325. c:=cali!=basering; e:=ring_ecart c;
  3326. v:=ring_names cali!=basering;
  3327. setring!* ring_define(v,eliminationorder!*(v,vars),'revlex,e);
  3328. cali!=degrees:=nil; % No degrees for proper result !!
  3329. bas:=(bas_sieve(dpmat_list
  3330. car groeb_stbasis(dpmat_neworder(m,nil),t,nil,nil), vars)
  3331. where !*noetherian=t);
  3332. setring!* c; cali!=degrees:=dpmat_coldegs m;
  3333. return dpmat_make(length bas,dpmat_cols m,bas_neworder bas,
  3334. cali!=degrees,nil);
  3335. end)
  3336. where cali!=degrees:=cali!=degrees,
  3337. cali!=basering:=cali!=basering;
  3338. symbolic operator eliminate;
  3339. symbolic procedure eliminate(m,l);
  3340. % Returns the elimination ideal/module of m with respect to the
  3341. % variables in the list l to be eliminated.
  3342. if !*mode='algebraic then
  3343. begin l:=reval l;
  3344. if not eqcar(l,'list) then typerr(l,"variable list");
  3345. m:=dpmat_from_a m; l:=cdr l;
  3346. return dpmat_2a eliminate!*(m,l);
  3347. end
  3348. else eliminate!*(m,l);
  3349. symbolic procedure matintersect!* l;
  3350. if null l then rederr"MATINTERSECT with empty list"
  3351. else if length l=1 then car l
  3352. else (begin scalar c,u,v,p,size;
  3353. matop!=testdpmatlist l;
  3354. size:=dpmat_cols car l;
  3355. v:=for each x in l collect gensym();
  3356. c:=cali!=basering;
  3357. setring!* ring_sum(c,
  3358. ring_define(v,degreeorder!* v,'lex,for each x in v collect 1));
  3359. cali!=degrees:=mo_degneworder dpmat_coldegs car l;
  3360. u:=for each x in pair(v,l) collect
  3361. dpmat_times_dpoly(dp_from_a car x,dpmat_neworder(cdr x,nil));
  3362. p:=dp_fi 1; for each x in v do p:=dp_diff(p,dp_from_a x);
  3363. if size=0 then p:=dpmat_from_dpoly p
  3364. else p:=dpmat_times_dpoly(p,dpmat_unit(size,cali!=degrees));
  3365. p:=gbasis!* matsum!* (p . u);
  3366. p:=dpmat_sieve(p,v,t);
  3367. setring!* c;
  3368. cali!=degrees:=dpmat_coldegs car l;
  3369. return dpmat_neworder(p,t);
  3370. end)
  3371. where cali!=degrees:=cali!=degrees,
  3372. cali!=basering:=cali!=basering;
  3373. put('matintersect,'psopfn,'matop!=matintersect);
  3374. put('idealintersect,'psopfn,'matop!=matintersect);
  3375. symbolic procedure matop!=matintersect l;
  3376. % Returns the intersection of the submodules of a fixed free module
  3377. % in the list l.
  3378. dpmat_2a matintersect!* for each x in l collect dpmat_from_a reval x;
  3379. % ------- Submodule property and equality test --------------
  3380. put('modequalp,'psopfn,'matop!=equalp);
  3381. % Test, whether a and b are module equal.
  3382. symbolic procedure matop!=equalp u;
  3383. if length u neq 2 then rederr"Syntax : MODEQUALP(dpmat,dpmat) "
  3384. else begin scalar a,b;
  3385. intf_get first u; intf_get second u;
  3386. if null(a:=get(first u,'gbasis)) then
  3387. put(first u,'gbasis,a:=gbasis!* get(first u,'basis));
  3388. if null(b:=get(second u,'gbasis)) then
  3389. put(second u,'gbasis,b:=gbasis!* get(second u,'basis));
  3390. if modequalp!*(a,b) then return 'yes else return 'no
  3391. end;
  3392. symbolic procedure modequalp!*(a,b);
  3393. submodulep!*(a,b) and submodulep!*(b,a);
  3394. put('submodulep,'psopfn,'matop!=submodulep);
  3395. % Test, whether a is a submodule of b.
  3396. symbolic procedure matop!=submodulep u;
  3397. if length u neq 2 then rederr"Syntax : SUBMODULEP(dpmat,dpmat)"
  3398. else begin scalar a,b;
  3399. intf_get second u;
  3400. if null(b:=get(second u,'gbasis)) then
  3401. put(second u,'gbasis,b:=gbasis!* get(second u,'basis));
  3402. a:=dpmat_from_a reval first u;
  3403. if submodulep!*(a,b) then return 'yes else return 'no
  3404. end;
  3405. symbolic procedure submodulep!*(a,b);
  3406. if not(dpmat_cols a=dpmat_cols b
  3407. and equal(dpmat_coldegs a,dpmat_coldegs b)) then
  3408. rederr"incompatible modules in SUBMODULEP"
  3409. else (begin
  3410. a:=for each x in dpmat_list a collect bas_dpoly x;
  3411. return not listtest(a,b,function matop_pseudomod)
  3412. end) where cali!=degrees:=dpmat_coldegs a;
  3413. endmodule; % matop
  3414. end;
  3415. module mo;
  3416. COMMENT
  3417. ##################
  3418. ## ##
  3419. ## MONOMIALS ##
  3420. ## ##
  3421. ##################
  3422. Monomials are of the form x^a*e_i with a multipower x^a and a module
  3423. component e_i. They belong either to the base ring R (i=0) or to a
  3424. free module R^c (c >= i > 0).
  3425. All computations are performed with respect to a "current module"
  3426. over a "current ring" (=cali!=basering).
  3427. To each module component e_i of the current module we assign a
  3428. "column degree", i.e. a monomial representing a certain multidegree
  3429. of the basis vector e_i. See the module dpmat for more details.
  3430. The column degrees of the current module are stored in the assoc.
  3431. list cali!=degrees.
  3432. Informal syntax :
  3433. <monomial> ::= (<exponential part> . <degree part>)
  3434. < .. part> ::= list of integer
  3435. Here exponent lists may have varying length since trailing zeroes are
  3436. assumed to be omitted. The zero component of <exp. part> contains the
  3437. module component. It correspond to the phantom var. name cali!=mk.
  3438. END COMMENT;
  3439. % ----------- manipulations of the degree part --------------------
  3440. symbolic procedure mo!=sprod(a,b);
  3441. % Scalar product of integer lists a and b .
  3442. if not a or not b then 0
  3443. else (car a)#*(car b) #+ mo!=sprod(cdr a,cdr b);
  3444. symbolic procedure mo!=deglist(a);
  3445. % a is an exponent list. Returns the degree list of a.
  3446. if null a then
  3447. for each x in ring_degrees cali!=basering collect 0
  3448. else (mo!=sum(
  3449. for each x in ring_degrees cali!=basering collect
  3450. mo!=sprod(cdr a,x),
  3451. if b then cddr b else nil)
  3452. where b = assoc(car a,cali!=degrees));
  3453. symbolic procedure mo_neworder m;
  3454. % Deletes trailing zeroes and returns m with new degree part.
  3455. (m1 . mo!=deglist m1) where m1 =mo!=shorten car m;
  3456. symbolic procedure mo_degneworder l;
  3457. % New degree parts in the degree list l.
  3458. for each x in l collect car x . mo_neworder cdr x;
  3459. symbolic procedure mo!=shorten m;
  3460. begin scalar m1;
  3461. m1:=reverse m;
  3462. while m1 and eqn(car m1,0) do m1:=cdr m1;
  3463. return reversip m1;
  3464. end;
  3465. % ------------- comparisions of monomials -----------------
  3466. symbolic procedure mo_zero; nil . mo!=deglist nil;
  3467. % Returns the unit monomial x^0.
  3468. symbolic procedure mo_zero!? u; mo!=zero car u;
  3469. symbolic procedure mo!=zero u;
  3470. null u or car u = 0 and mo!=zero cdr u;
  3471. symbolic procedure mo_equal!?(m1,m2);
  3472. % Test whether m1 = m2.
  3473. equal(mo!=shorten car m1,mo!=shorten car m2);
  3474. symbolic procedure mo_divides!?(m1,m2);
  3475. % m1,m2:monomial. true :<=> m1 divides m2
  3476. mo!=modiv1(car m1,car m2);
  3477. symbolic procedure mo!=modiv1(e1,e2);
  3478. if not e1 then t else if not e2 then nil
  3479. else leq(car e1,car e2) and mo!=modiv1(cdr e1, cdr e2);
  3480. symbolic procedure mo_compare(m1,m2);
  3481. % compare (m1,m2) . m1 < m2 => -1 | m1 = m2 => 0 | m1 > m2 => +1
  3482. begin scalar x;
  3483. x:=mo!=degcomp(cdr m1,cdr m2);
  3484. if x eq 0 then
  3485. x:=if equal(ring_tag cali!=basering,'revlex) then
  3486. mo!=revlexcomp(car m1, car m2)
  3487. else mo!=lexcomp(car m1,car m2);
  3488. return x;
  3489. end;
  3490. symbolic procedure mo_dlexcomp(a,b); mo!=lexcomp(car a,car b)=1;
  3491. % Descending lexicographic order, first by mo_comp.
  3492. symbolic procedure mo!=degcomp(d1,d2);
  3493. if null d1 then 0
  3494. else if car d1 = car d2 then mo!=degcomp(cdr d1,cdr d2)
  3495. else if car d1 #< car d2 then -1
  3496. else 1;
  3497. symbolic procedure mo!=revlexcomp(e1,e2);
  3498. if length e1 #> length e2 then -1
  3499. else if length e2 #> length e1 then 1
  3500. else - mo!=degcomp(reverse e1,reverse e2);
  3501. symbolic procedure mo!=lexcomp(e1,e2);
  3502. if null e1 then
  3503. if null e2 then 0 else mo!=lexcomp('(0),e2)
  3504. else if null e2 then mo!=lexcomp(e1,'(0))
  3505. else if car e1 = car e2 then mo!=lexcomp(cdr e1,cdr e2)
  3506. else if car e1 #> car e2 then 1
  3507. else -1;
  3508. % ---------- manipulation of the module component --------
  3509. symbolic procedure mo_comp v;
  3510. % Retuns the module component of v.
  3511. if null car v then 0 else caar v;
  3512. symbolic procedure mo_from_ei i;
  3513. % Make e_i.
  3514. if i=0 then mo_zero() else (x . mo!=deglist x) where x =list(i);
  3515. symbolic procedure mo_vdivides!?(v1,v2);
  3516. % Equal module component and v1 divides v2.
  3517. eqn(mo_comp v1,mo_comp v2) and mo_divides!?(v1,v2);
  3518. symbolic procedure mo_deletecomp v;
  3519. % Delete component part.
  3520. if null car v then v
  3521. else if null cdar v then (nil . mo!=deglist nil)
  3522. else ((x . mo!=deglist x) where x=cons(0,cdar v));
  3523. symbolic procedure mo_times_ei(i,m);
  3524. % Returns m * e_i or n*e_{i+k}, if m=n*e_k.
  3525. (x . mo!=deglist x)
  3526. where x=if null car m then list(i) else cons(i #+ caar m,cdar m);
  3527. symbolic procedure mo_deg m; cdr m;
  3528. % Returns the degree part of m.
  3529. symbolic procedure mo_getdegree(v,l);
  3530. % Compute the (virtual) degree of the monomial v with respect to the
  3531. % assoc. list l of column degrees.
  3532. mo_deletecomp(if a then mo_sum(v,cdr a) else v)
  3533. where a =assoc(mo_comp(v),l);
  3534. % --------------- monomial arithmetics -----------------------
  3535. symbolic procedure mo_lcm (m1,m2);
  3536. % Monomial least common multiple.
  3537. begin scalar x,e1,e2;
  3538. e1:=car m1; e2:=car m2;
  3539. while e1 and e2 do
  3540. <<x := (if car e1 #> car e2 then car e1 else car e2) . x;
  3541. e1 := cdr e1; e2 := cdr e2>>;
  3542. x:=append(reversip x,if e1 then e1 else e2);
  3543. return (mo!=shorten x) . (mo!=deglist x);
  3544. end;
  3545. symbolic procedure mo_gcd (m1,m2);
  3546. % Monomial greatest common divisor.
  3547. begin scalar x,e1,e2;
  3548. e1:=car m1; e2:=car m2;
  3549. while e1 and e2 do
  3550. <<x := (if car e1 #< car e2 then car e1 else car e2) . x;
  3551. e1 := cdr e1; e2 := cdr e2>>;
  3552. x:=reversip x; return (mo!=shorten x) . (mo!=deglist x);
  3553. end;
  3554. symbolic procedure mo_neg v;
  3555. % Return v^-1.
  3556. (for each x in car v collect -x).(for each x in cdr v collect -x);
  3557. symbolic procedure mo_sum(m1,m2);
  3558. % Monomial product.
  3559. ((mo!=shorten x) . (mo!=deglist x))
  3560. where x =mo!=sum(car m1,car m2);
  3561. symbolic procedure mo!=sum(e1,e2);
  3562. begin scalar x;
  3563. while e1 and e2 do
  3564. <<x := (car e1 #+ car e2) . x; e1 := cdr e1; e2 := cdr e2>>;
  3565. return append(reversip x,if e1 then e1 else e2);
  3566. end;
  3567. symbolic procedure mo_diff (m1,m2); mo_sum(m1,mo_neg m2);
  3568. symbolic procedure mo_qrem(m,n);
  3569. % m,n monomials. Returns (q . r) with m=n^q*r.
  3570. begin scalar m1,n1,q,q1;
  3571. q:=-1; m1:=cdar m; n1:=cdar n;
  3572. while m1 and n1 and (q neq 0) do
  3573. << if car n1 > 0 then
  3574. << q1:=car m1 / car n1;
  3575. if (q=-1) or (q>q1) then q:=q1;
  3576. >>;
  3577. n1:=cdr n1; m1:=cdr m1;
  3578. >>;
  3579. if n1 or (q=-1) then q:=0;
  3580. return q . mo_diff(m,mo_power(n,q));
  3581. end;
  3582. symbolic procedure mo_power(mo,n);
  3583. % Monomial power mo^n.
  3584. (for each x in car mo collect n #* x) .
  3585. (for each x in cdr mo collect n #* x);
  3586. symbolic procedure mo!=pair(a,b);
  3587. if null a or null b then nil
  3588. else (car a . car b) . mo!=pair(cdr a,cdr b);
  3589. symbolic procedure mo_2list m;
  3590. % Returns a list (var name . exp) for the monomial m.
  3591. begin scalar k; k:=car m;
  3592. return for each x in
  3593. mo!=pair(ring_names cali!=basering, if k then cdr k else nil)
  3594. join if cdr x neq 0 then {x};
  3595. end;
  3596. symbolic procedure mo_varexp(var,m);
  3597. % Returns the exponent of var:var. name in the monomial m.
  3598. if not member(var,ring_names cali!=basering) then
  3599. typerr(var,"variable name")
  3600. else begin scalar c;
  3601. c:=assoc(var,mo_2list m);
  3602. return if c then cdr c else 0
  3603. end;
  3604. symbolic procedure mo_inc(m,x,j);
  3605. % Return monomial m with power of var. x increased by j.
  3606. begin scalar n,v;
  3607. if not member(x,v:=ring_all_names cali!=basering) then
  3608. typerr(x,"dpoly variable");
  3609. m:=car m;
  3610. while x neq car v do
  3611. << if m then <<n:=car m . n; m:=cdr m>> else n:=0 . n;
  3612. v:=cdr v;
  3613. >>;
  3614. if m then
  3615. << n:=(car m #+ j).n; if m:=cdr m then n:=nconc(reverse m,n) >>
  3616. else n:=j . n;
  3617. while n and (car n = 0) do n:=cdr n;
  3618. n:=reversip n;
  3619. return n . mo!=deglist n
  3620. end;
  3621. symbolic procedure mo_linear m;
  3622. % Test whether the monomial m is linear and return the corresponding
  3623. % variable or nil.
  3624. (if (length u=1 and cdar u=1) then caar u else nil)
  3625. where u=mo_2list m;
  3626. symbolic procedure mo_ecart m;
  3627. % Returns the ecart of the monomial m.
  3628. if null car m then 0
  3629. else mo!=sprod(cdar (if a then mo_sum(cdr a,m) else m),
  3630. ring_ecart cali!=basering)
  3631. where a:=atsoc(mo_comp m,cali!=degrees);
  3632. symbolic procedure mo_radical m;
  3633. % Returns the radical of the monomial m.
  3634. (x . mo!=deglist x)
  3635. where x = for each y in car m collect if y=0 then 0 else 1;
  3636. symbolic procedure mo_seed(m,s);
  3637. % Set var's outside the list s equal to one.
  3638. begin scalar m1,x,v;
  3639. if not subsetp(s,v:=ring_all_names cali!=basering) then
  3640. typerr(s,"dpoly name's list");
  3641. m1:=car m;
  3642. while m1 and v do
  3643. << x:=cons(if member(car v,s) then car m1 else 0,x);
  3644. m1:=cdr m1; v:=cdr v
  3645. >>;
  3646. while x and eqn(car x,0) do x:=cdr x;
  3647. x:=reversip x;
  3648. return x . mo!=deglist x;
  3649. end;
  3650. symbolic procedure mo_wconvert(m,w);
  3651. % Conversion of monomials for weighted Hilbert series.
  3652. % w is a list of (integer) weight lists.
  3653. ( x . mo!=deglist x) where
  3654. x = mo!=shorten(0 . for each x in w collect
  3655. (if car m then mo!=sprod(cdar m,x) else 0));
  3656. % ---------------- monomial interface ---------------
  3657. symbolic procedure mo_from_a u;
  3658. % Convert a kernel to a monomial.
  3659. if not(u member ring_all_names cali!=basering) then
  3660. typerr(u,"dpoly variable")
  3661. else begin scalar x,y;
  3662. y:=mo!=shorten
  3663. for each x in ring_all_names cali!=basering collect
  3664. if x equal u then 1 else 0;
  3665. return y . mo!=deglist y;
  3666. end;
  3667. symbolic procedure mo_2a e;
  3668. % Convert a monomial to part of algebraic prefix form of a dpoly.
  3669. mo!=expvec2a1(car e,ring_all_names cali!=basering);
  3670. symbolic procedure mo!=expvec2a1(u,v);
  3671. if null u then nil
  3672. else if car u = 0 then mo!=expvec2a1(cdr u,cdr v)
  3673. else if car u = 1 then car v . mo!=expvec2a1(cdr u,cdr v)
  3674. else list('expt,car v,car u) . mo!=expvec2a1(cdr u,cdr v);
  3675. symbolic procedure mo_prin(e,v);
  3676. % Print monomial e in infix form. V is a boolean variable which is
  3677. % true if an element in a product has preceded this one
  3678. mo!=dpevlpri1(car e,ring_all_names cali!=basering,v);
  3679. symbolic procedure mo!=dpevlpri1(e,u,v);
  3680. if null e then nil
  3681. else if car e = 0 then mo!=dpevlpri1(cdr e,cdr u,v)
  3682. else <<if v then print_lf "*";
  3683. print_lf car u;
  3684. if car e #> 1 then <<print_lf "^"; print_lf car e>>;
  3685. mo!=dpevlpri1(cdr e,cdr u,t)>>;
  3686. symbolic procedure mo_support m;
  3687. % Returns the support of the monomial m as a list of var. names
  3688. % in the correct order.
  3689. begin scalar u;
  3690. for each x in ring_names cali!=basering do
  3691. if mo_divides!?(mo_from_a x,m) then u:=x . u;
  3692. return reversip u;
  3693. end;
  3694. endmodule; % mo
  3695. end;
  3696. module moid;
  3697. COMMENT
  3698. ###########################
  3699. ## ##
  3700. ## MONOMIAL IDEALS ##
  3701. ## ##
  3702. ###########################
  3703. This module supports computations with leading term ideals. Moideal
  3704. monomials are assumed to be without module component, since a module
  3705. moideal decomposes into the direct sum of ideal moideals.
  3706. Lit.:
  3707. [BS] Bayer, Stillman : J. Symb. Comp. 14 (1992), 31 - 50.
  3708. This module contains :
  3709. - A moideal prime decomposition along [BS]
  3710. - An algorithm to find all strongly independent sets using
  3711. moideal primes (also for modules),
  3712. - An algorithm to compute the dimension (dim M := dim in(M))
  3713. based on strongly independent sets.
  3714. - An easy dimension computation, correct for puredimensional
  3715. ideals and modules.
  3716. Monomial ideals have the following informal syntax :
  3717. <moideal> ::= list of monomials
  3718. To manage module moideals they are stored as assoc. list of
  3719. (<component number> . <ideal moideal>)
  3720. Moideals are kept ordered with respect to the descending lexicographic
  3721. order, see [BS].
  3722. END COMMENT;
  3723. % ------------- monomial ideal constructors --------------
  3724. symbolic procedure moid_from_bas bas;
  3725. % Returns the list of leading monomials of the base list bas
  3726. % not removing module components.
  3727. for each x in bas_zerodelete bas collect dp_lmon bas_dpoly x;
  3728. symbolic procedure moid_from_dpmat m;
  3729. % Returns the assoc. list of moideals of the columns of the dpmat m.
  3730. (if dpmat_cols m = 0 then list (0 . u)
  3731. else for i:=1:dpmat_cols m collect
  3732. i . for each x in u join if mo_comp(x)=i then {mo_deletecomp x})
  3733. where u=moid_from_bas dpmat_list m;
  3734. symbolic procedure moid_2a m;
  3735. % Convert the moideal m to algebraic mode.
  3736. 'list . for each x in m collect dp_2a list dp_term(bc_fi 1,x);
  3737. symbolic procedure moid_from_a m;
  3738. % Convert a moideal from algebraic mode.
  3739. if not eqcar(m,'list) then typerr(m,"moideal")
  3740. else for each x in cdr m collect dp_lmon dp_from_a x;
  3741. symbolic procedure moid_print m; mathprint moid_2a m;
  3742. % ------- moideal arithmetics ------------------------
  3743. symbolic procedure moid_sum(a,b);
  3744. % (Reduced) sum of two (v)moideals.
  3745. moid_red append(a,b);
  3746. symbolic procedure moid_intersect(a,b);
  3747. % Intersection of two (pure !) moideals.
  3748. begin scalar c;
  3749. while b do
  3750. << c:=nconc(for each x in a collect mo_lcm(x,car b),c);
  3751. b:=cdr b
  3752. >>;
  3753. return moid_red c
  3754. end;
  3755. symbolic procedure moid_sort m;
  3756. % Sorting by descending (pure) lexicographic order, first by mo_comp.
  3757. sort(m,function mo_dlexcomp);
  3758. symbolic procedure moid_red m;
  3759. % Returns a minimal generating set of the (v)moideal m.
  3760. moid!=red moid_sort m;
  3761. symbolic procedure moid!=red m;
  3762. begin scalar v;
  3763. while m do
  3764. << if not moid_member(car m,cdr m) then v:=car m . v;
  3765. m:=cdr m;
  3766. >>;
  3767. return reversip v;
  3768. end;
  3769. symbolic procedure moid_member(mo,m);
  3770. % true <=> c \in m vdivides mo.
  3771. if null m then nil
  3772. else mo_vdivides!?(car m,mo) or moid_member(mo,cdr m);
  3773. symbolic procedure moid_radical u;
  3774. % Returns the radical of the (pure) moideal u.
  3775. moid_red for each x in u collect mo_radical x;
  3776. symbolic procedure moid_quot(m,x);
  3777. % The quotient of the moideal m by the monomial x.
  3778. moid_red for each u in m collect mo_diff(u,mo_gcd(u,x));
  3779. % --------------- moideal prime decomposition --------------
  3780. % Returns the minimal primes of the moideal m as a list of variable
  3781. % lists.
  3782. symbolic procedure moid_primes m;
  3783. begin scalar c,m1,m2;
  3784. m:=listminimize(for each x in m collect mo_support x,
  3785. function subsetp);
  3786. for each x in m do
  3787. if length x=1 then m1:=car x . m1
  3788. else m2:=x . m2;
  3789. return for each x in moid!=primes(m2,ring_names cali!=basering)
  3790. collect append(m1,x);
  3791. end;
  3792. symbolic procedure moid!=primes(m,vars);
  3793. if null m then list nil
  3794. else begin scalar b; b:=t;
  3795. for each x in m do b:=b and intersection(x,vars);
  3796. if not b then return nil;
  3797. return listminimize(
  3798. for each x in intersection(car m,vars) join
  3799. for each y in moid!=primes(moid!=sps(x,cdr m),
  3800. vars:=delete(x,vars)) collect x . y,
  3801. function subsetp);
  3802. end;
  3803. symbolic procedure moid!=sps(x,m);
  3804. for each y in m join if not memq(x,y) then {y};
  3805. % ------------ (Strongly) independent sets -----------------
  3806. symbolic procedure moid_max l;
  3807. if null l then nil
  3808. else car sort(l,function (lambda(x,y);length x >= length y));
  3809. symbolic procedure indepvarsets!* m;
  3810. % Returns the sets of (strongly) independent variables for the
  3811. % dpmat m. m must be a Groebner basis.
  3812. begin scalar u,n;
  3813. u:=listminimize(
  3814. for each x in moid_from_dpmat m join moid_primes cdr x,
  3815. function subsetp);
  3816. n:=ring_names cali!=basering;
  3817. return for each x in u collect setdiff(n,x);
  3818. end;
  3819. % ---------- Dimension and codimension ------------
  3820. symbolic procedure moid_goodindepvarset m;
  3821. % Returns the lexicographically last maximal independent set of the
  3822. % dpmat m.
  3823. begin scalar l,n,l1;
  3824. l:=sort(indepvarsets!* m,
  3825. function (lambda(x,y);length x >= length y));
  3826. if null l then return nil;
  3827. n:=length first l;
  3828. l:=for each x in l join if length x = n then {x};
  3829. for each x in reverse ring_names cali!=basering do
  3830. if length l>1 then
  3831. << l1:=for each y in l join if member(x,y) then {y};
  3832. if l1 then l:=l1;
  3833. >>;
  3834. return first l;
  3835. end;
  3836. symbolic procedure dim!* m;
  3837. % The dpmat m must be a Groebner basis. Computes the dimension of
  3838. % Coker m as the greatest size of a strongly independent set.
  3839. if not eqcar(m,'dpmat) then typerr(m,"DPMAT")
  3840. else length moid_max indepvarsets!* m;
  3841. symbolic procedure codim!* m;
  3842. length ring_names cali!=basering - dim!* m;
  3843. % ---- An easy independent set procedure -------------
  3844. symbolic operator easyindepset;
  3845. symbolic procedure easyindepset m;
  3846. if !*mode='algebraic then
  3847. makelist easyindepset!* dpmat_from_a reval m
  3848. else easyindepset!* m;
  3849. symbolic procedure easyindepset!* m;
  3850. % Returns a maximal with respect to inclusion independent set for the
  3851. % moideal m.
  3852. begin scalar b,c,d;
  3853. m:=for each x in m collect mo_support x;
  3854. b:=c:=ring_names cali!=basering;
  3855. for each x in b do if moid!=ept(d:=delete(x,c),m) then c:=d;
  3856. return setdiff(ring_names cali!=basering,c);
  3857. end;
  3858. symbolic procedure moid!=ept(l,m);
  3859. if null m then t
  3860. else intersection(l,car m) and moid!=ept(l,cdr m);
  3861. symbolic operator easydim;
  3862. symbolic procedure easydim m;
  3863. if !*mode='algebraic then easydim!* dpmat_from_a reval m
  3864. else easydim!* m;
  3865. symbolic procedure easydim!* m;
  3866. % Returns a lower bound for the dimension. The bound is true for
  3867. % unmixed ideals (e.g. primes). m must be a gbasis.
  3868. if not eqcar(m,'dpmat) then typerr(m,"DPMAT")
  3869. else listexpand(function max2,
  3870. for each x in moid_from_dpmat m collect
  3871. length easyindepset!* cdr x);
  3872. endmodule; % moid
  3873. end;
  3874. module odim;
  3875. COMMENT
  3876. ##########################################
  3877. ## ##
  3878. ## Applications to zerodimensional ##
  3879. ## ideals and modules. ##
  3880. ## ##
  3881. ##########################################
  3882. getkbase returns a k-vector space basis of S^c/M,
  3883. odim_borderbasis computes a borderbasis of M,
  3884. odim_up finds univariate polynomials in zerodimensional ideals.
  3885. END COMMENT;
  3886. % -------------- Test for zero dimension -----------------
  3887. % For a true answer m must be a gbasis.
  3888. put('dimzerop,'psopfn,'odim!=zerop);
  3889. symbolic procedure odim!=zerop m;
  3890. begin scalar c;
  3891. intf_test m; intf_get(m:=car m);
  3892. if not (c:=get(m,'gbasis)) then
  3893. put(m,'gbasis,c:=gbasis!* get(m,'basis));
  3894. if dimzerop!* c then return 'yes else return 'no;
  3895. end;
  3896. symbolic procedure dimzerop!* m; null odim_parameter m;
  3897. symbolic procedure odim_parameter m;
  3898. % Return a parameter of the dpmat m or nil, if it is zerodimensional
  3899. % or (1).
  3900. odim!=parameter moid_from_dpmat m;
  3901. symbolic procedure odim!=parameter m;
  3902. if null m then nil
  3903. else odim!=parameter1 cdar m or odim!=parameter cdr m;
  3904. symbolic procedure odim!=parameter1 m;
  3905. if null m then
  3906. ((if u then car u else u)
  3907. where u:= reverse ring_names cali!=basering)
  3908. else if mo_zero!? car m then nil
  3909. else begin scalar b,u;
  3910. u:=for each x in m join if length(b:=mo_support x)=1 then b;
  3911. b:=reverse ring_names cali!=basering;
  3912. while b and member(car b,u) do b:=cdr b;
  3913. return if b then car b else nil;
  3914. end;
  3915. % --- Get a k-base of F/M as a list of monomials ----
  3916. % m must be a gbasis for the correct result.
  3917. put('getkbase,'psopfn,'odim!=evkbase);
  3918. symbolic procedure odim!=evkbase m;
  3919. begin scalar c;
  3920. intf_test m; intf_get(m:=car m);
  3921. if not (c:=get(m,'gbasis)) then
  3922. put(m,'gbasis,c:=gbasis!* get(m,'basis));
  3923. return moid_2a getkbase!* c;
  3924. end;
  3925. symbolic procedure getkbase!* m;
  3926. if not dimzerop!* m then rederr"dpmat not zerodimensional"
  3927. else for each u in moid_from_dpmat m join
  3928. odim!=kbase(mo_from_ei car u,ring_names cali!=basering,cdr u);
  3929. symbolic procedure odim!=kbase(mo,n,m);
  3930. if moid_member(mo,m) then nil
  3931. else mo . for each x on n join
  3932. odim!=kbase(mo_inc(mo,car x,1),append(x,nil),m);
  3933. % --- Produce an univariate polynomial inside the ideal m ---
  3934. symbolic procedure odim_up(a,m);
  3935. % Returns a univariate polynomial (of smallest possible degree if m
  3936. % is a gbasis) in the variable a inside the zerodimensional ideal m.
  3937. % Uses Buchberger's approach.
  3938. if dpmat_cols m>0 or not dimzerop!* m then
  3939. rederr"univariate polynomials only for zerodimensional ideals"
  3940. else if not member(a,ring_names cali!=basering) then
  3941. typerr(a,"variable name")
  3942. else if dpmat_unitideal!? m then dp_fi 1
  3943. else begin scalar b,v,p,l,q,r;
  3944. % l is a list of ( p(a) . NF p(a) ), sorted by lt NF p(a)
  3945. p:=(dp_fi 1 . dp_fi 1); b:=dpmat_list m; v:=mo_from_a a;
  3946. while cdr p do
  3947. << l:=merge(list p,l,function odim!=greater);
  3948. q:=dp_times_mo(v,car p);
  3949. r:=red_redpol(b,bas_make(0,dp_times_mo(v,cdr p)));
  3950. p:=odim!=reduce(dp_prod(cdr r,q) . bas_dpoly car r,l);
  3951. >>;
  3952. return
  3953. if !*bcsimp then car dp_simp car p
  3954. else car p;
  3955. end;
  3956. symbolic procedure odim!=greater(a,b);
  3957. mo_compare(dp_lmon cdr a,dp_lmon cdr b)=1;
  3958. symbolic procedure odim!=reduce(a,l);
  3959. if null cdr a or null l or odim!=greater(a, car l) then a
  3960. else if mo_equal!?(dp_lmon cdr a,dp_lmon cdar l) then
  3961. begin scalar z,z1,z2,b;
  3962. b:=car l; z1:=bc_neg dp_lc cdr a; z2:=dp_lc cdr b;
  3963. if !*bcsimp then
  3964. << if (z:=bc_inv z1) then <<z1:=bc_fi 1; z2:=bc_prod(z2,z)>>
  3965. else
  3966. << z:=bc_gcd(z1,z2);
  3967. z1:=car bc_divmod(z1,z);
  3968. z2:=car bc_divmod(z2,z);
  3969. >>;
  3970. >>;
  3971. a:=dp_sum(dp_times_bc(z2,car a),dp_times_bc(z1,car b)) .
  3972. dp_sum(dp_times_bc(z2,cdr a),dp_times_bc(z1,cdr b));
  3973. return odim!=reduce(a,cdr l)
  3974. end
  3975. else odim!=reduce(a,cdr l);
  3976. % ------------------------- Borderbasis -----------------------
  3977. symbolic procedure odim_borderbasis m;
  3978. % Returns a border basis of the zerodimensional dpmat m as list of
  3979. % base elements.
  3980. if not !*noetherian then
  3981. rederr"BORDERBASIS only for non noetherian term orders"
  3982. else if not dimzerop!* m then
  3983. rederr"BORDERBASIS only for zerodimensional ideals or modules"
  3984. else begin scalar b,v,u,mo,bas;
  3985. bas:=bas_zerodelete dpmat_list m;
  3986. mo:=for each x in bas collect dp_lmon bas_dpoly x;
  3987. v:=for each x in ring_names cali!=basering collect mo_from_a x;
  3988. u:=for each x in bas collect
  3989. {dp_lmon bas_dpoly x,red_tailred(bas,x)};
  3990. while u do
  3991. << b:=append(b,u);
  3992. u:=listminimize(
  3993. for each x in u join
  3994. for each y in v join
  3995. (begin scalar w; w:=mo_sum(first x,y);
  3996. if not listtest(b,w,function(lambda(x,y);car x=y))
  3997. and not odim!=interior(w,mo) then
  3998. return {{w,y,bas_dpoly second x}}
  3999. end),
  4000. function(lambda(x,y);car x=car y));
  4001. u:=for each x in u collect
  4002. {first x,
  4003. red_tailred(bas,bas_make(0,dp_times_mo(second x,third x)))};
  4004. >>;
  4005. return bas_renumber for each x in b collect second x;
  4006. end;
  4007. symbolic procedure odim!=interior(m,mo);
  4008. % true <=> monomial m is in the interior of the moideal mo.
  4009. begin scalar b; b:=t;
  4010. for each x in mo_support m do
  4011. b:=b and moid_member(mo_diff(m,mo_from_a x),mo);
  4012. return b;
  4013. end;
  4014. endmodule; % odim
  4015. end;
  4016. module prime; % corrected version | 15.6.1995
  4017. COMMENT
  4018. ####################################
  4019. # #
  4020. # PRIME DECOMPOSITION, RADICALS, #
  4021. # AND RELATED PROBLEMS #
  4022. # #
  4023. ####################################
  4024. This module contains algorithms
  4025. - for zerodimensional ideals :
  4026. - to test whether it is radical
  4027. - to compute its radical
  4028. - for a primality test
  4029. - for zerodimensional ideals and modules :
  4030. - to compute its primes
  4031. - to compute its primary decomposition
  4032. - for arbitrary ideals :
  4033. - for a primality test
  4034. - to compute its radical
  4035. - to test whether it is radical
  4036. - for arbitrary ideals and modules :
  4037. - to compute its isolated primes
  4038. - to compute its primary decomposition and
  4039. the associated primes
  4040. - a shortcut for the primary decomposition
  4041. computation for unmixed modules
  4042. The algorithms follow
  4043. Seidenberg : Trans. AMS 197 (1974), 273 - 313.
  4044. Kredel : in Proc. EUROCAL'87, Lecture Notes in Comp. Sci. 378
  4045. (1986), 270 - 281.
  4046. Gianni, Trager, Zacharias :
  4047. J. Symb. Comp. 6 (1988), 149 - 167.
  4048. The primary decomposition now proceeds as follows:
  4049. 1) compute the isolated primes
  4050. 2) compute by ideal separation quasi-primary components
  4051. 3) for each of them split off embedded components
  4052. 4) apply the decomposition recursively to them
  4053. 5) Decide in a last (global) step unnecessary components among
  4054. them
  4055. See Gr\"abe : Factorized Gr\"obner bases and primary
  4056. decomposition. To appear
  4057. The switch factorprimes switches between invokation of the Groebner
  4058. factorizer (on/ the default) and algorithms, that use only univariate
  4059. factorization as described in [GTZ] (off).
  4060. END COMMENT;
  4061. switch factorprimes; % (on) see primes
  4062. !*factorprimes:=t; % Invoke the Groebner factorizer first.
  4063. % ------ The radical of a zerodimensional ideal -----------
  4064. symbolic procedure prime!=mksqrfree(pol,x);
  4065. % Make the univariate dpoly p(x) squarefree.
  4066. begin scalar p;
  4067. p:=numr simp dp_2a pol;
  4068. return dp_from_a prepf car qremf(p,gcdf!*(p,numr difff(p,x)))
  4069. end;
  4070. put('zeroradical,'psopfn,'prime!=evzero);
  4071. symbolic procedure prime!=evzero m;
  4072. begin scalar c;
  4073. intf_test m; intf_get(m:=car m);
  4074. if not (c:=get(m,'gbasis)) then
  4075. put(m,'gbasis,c:=gbasis!* get(m,'basis));
  4076. return dpmat_2a zeroradical!* c;
  4077. end;
  4078. symbolic procedure zeroradical!* m;
  4079. % Returns the radical of the zerodim. ideal m. m must be a gbasis.
  4080. if dpmat_cols m>0 or not dimzerop!* m then
  4081. rederr"ZERORADICAL only for zerodimensional ideals"
  4082. else if dpmat_unitideal!? m then m
  4083. else begin scalar u;
  4084. u:=for each x in ring_names cali!=basering collect
  4085. bas_make(0,prime!=mksqrfree(odim_up(x,m),x));
  4086. u:=dpmat_make(length u,0,bas_renumber u,nil,nil);
  4087. return gbasis!* matsum!* {m,u};
  4088. end;
  4089. put('iszeroradical,'psopfn,'prime!=eviszero);
  4090. symbolic procedure prime!=eviszero m;
  4091. begin scalar c;
  4092. intf_test m; intf_get(m:=car m);
  4093. if not (c:=get(m,'gbasis)) then
  4094. put(m,'gbasis,c:=gbasis!* get(m,'basis));
  4095. return if iszeroradical!* c then 'yes else 'no;
  4096. end;
  4097. symbolic procedure iszeroradical!* m;
  4098. % Test whether the zerodim. ideal m is radical. m must be a gbasis.
  4099. if dpmat_cols m>0 or not dimzerop!* m then
  4100. rederr"ISZERORADICAL only for zerodimensional ideals"
  4101. else if dpmat_unitideal!? m then t
  4102. else begin scalar isradical;
  4103. isradical:=t;
  4104. for each x in ring_names cali!=basering do
  4105. isradical:=isradical and
  4106. null matop_pseudomod(prime!=mksqrfree(odim_up(x,m),x),m);
  4107. return isradical;
  4108. end;
  4109. % ---- The primes of a zerodimensional ideal or module ------
  4110. symbolic operator zeroprimes;
  4111. symbolic procedure zeroprimes m;
  4112. if !*mode='algebraic then
  4113. makelist for each x in zeroprimes!* dpmat_from_a reval m
  4114. collect dpmat_2a x
  4115. else zeroprimes!* m;
  4116. symbolic procedure zeroprimes!* m;
  4117. % The primes of the zerodimensional ideal Ann F/M.
  4118. % The unit ideal has no primes.
  4119. listminimize(for each x in
  4120. if !*factorprimes then groebf_zeroprimes1(annihilator2!* m,nil)
  4121. else prime_zeroprimes1 gbasis!* annihilator2!* m
  4122. join prime!=zeroprimes2 x, function submodulep!*);
  4123. symbolic procedure prime_iszeroprime m;
  4124. % Test a zerodimensiomal ideal to be prime. m must be a gbasis.
  4125. if dpmat_cols m>0 or not dimzerop!* m then
  4126. rederr "iszeroprime only for zerodimensional ideals"
  4127. else if dpmat_unitideal!? m then rederr"the ideal is the unit ideal"
  4128. else prime!=iszeroprime1 m and prime!=iszeroprime2 m;
  4129. symbolic procedure prime_zeroprimes1 m;
  4130. % A first approximation to the isolated primes in dim=0 : Factor all
  4131. % univariate polynomials in m.
  4132. % m must be a gbasis. Returns a reduced list of gbases.
  4133. if dpmat_cols m>0 then rederr"ZEROPRIMES only for ideals"
  4134. else if dpmat_unitideal!? m then nil
  4135. else if not dimzerop!* m then
  4136. rederr"ZEROPRIMES only for zerodimensional ideals"
  4137. else begin scalar l;
  4138. l:={m};
  4139. for each x in ring_names cali!=basering do
  4140. l:=for each y in l join
  4141. if not member(x,for each v in dpmat_list y join
  4142. {mo_linear dp_lmon bas_dpoly v}) then
  4143. (begin scalar u,p;
  4144. u:=dp_factor (p:=odim_up(x,y));
  4145. if (length u=1) and equal(car u,p) then return {y}
  4146. else return for each z in u join
  4147. if not dpmat_unitideal!?(p:=gbasis!* matsum!*
  4148. {y,dpmat_from_dpoly z}) then {p};
  4149. end)
  4150. else {y};
  4151. return l;
  4152. end;
  4153. symbolic procedure prime!=iszeroprime1 m;
  4154. % A first non primality test.
  4155. if dpmat_cols m>0 then rederr"ISZEROPRIME only for ideals"
  4156. else if dpmat_unitideal!? m then nil
  4157. else if not dimzerop!* m then
  4158. rederr"ISZEROPRIME only for zerodimensional ideals"
  4159. else begin scalar b; b:=t;
  4160. for each x in ring_names cali!=basering do
  4161. b:=b and
  4162. begin scalar u,p;
  4163. u:=dp_factor (p:=odim_up(x,m));
  4164. if (length u=1) and equal(car u,p) then return t
  4165. else return nil
  4166. end;
  4167. return b;
  4168. end;
  4169. symbolic procedure prime_gpchange(vars,v,m);
  4170. % Change to general position with respect to v. Only for pure lex.
  4171. % term order and radical ideal m.
  4172. if null vars or dpmat_unitideal!? m then m
  4173. else begin scalar s,x,a;
  4174. s:=0; x:=mo_from_a car vars;
  4175. a:=list (v.prepf addf(!*k2f v,!*k2f car vars));
  4176. % the substitution rule v -> v + x .
  4177. while not member(x,moid_from_bas dpmat_list m)
  4178. % i.e. m has a leading term equal to x
  4179. and ((s:=s+1) < 10)
  4180. % to avoid too much loops.
  4181. do m:=gbasis!* dpmat_sub(a,m);
  4182. if s=10 then rederr" change to general position failed";
  4183. return prime_gpchange(cdr vars,v,m);
  4184. end;
  4185. symbolic procedure prime!=zeroprimes2 m;
  4186. % Decompose the radical zerodimensional dmpat ideal m using a general
  4187. % position argument. Returns a reduced list of gbases.
  4188. (begin scalar c,v,vars,u,d,r;
  4189. c:=cali!=basering; vars:=ring_names c; v:=gensym();
  4190. u:=setdiff(vars,for each x in moid_from_bas dpmat_list m
  4191. join {mo_linear x});
  4192. if (length u)=1 then return prime!=zeroprimes3(m,first u);
  4193. if ring_tag c='revlex then % for proper ring_sum redefine it.
  4194. r:=ring_define(vars,ring_degrees c,'lex,ring_ecart c)
  4195. else r:=c;
  4196. setring!* ring_sum(r,ring_define(list v,nil,'lex,'(1)));
  4197. cali!=degrees:=nil;
  4198. m:=gbasis!* matsum!*
  4199. {dpmat_neworder(m,nil), dpmat_from_dpoly dp_from_a v};
  4200. u:=setdiff(v.vars,for each x in moid_from_bas dpmat_list m
  4201. join {mo_linear x});
  4202. if not dpmat_unitideal!? m then
  4203. << m:=prime_gpchange(u,v,m);
  4204. u:=for each x in prime!=zeroprimes3(m,v) join
  4205. if not dpmat_unitideal!? x and
  4206. not dpmat_unitideal!?(d:=eliminate!*(x,{v})) then {d}
  4207. % To recognize (1) even if x is not a gbasis.
  4208. >>
  4209. else u:=nil;
  4210. setring!* c;
  4211. return for each x in u collect gbasis!* dpmat_neworder(x,nil);
  4212. end)
  4213. where cali!=degrees:=cali!=degrees,
  4214. cali!=basering:=cali!=basering;
  4215. symbolic procedure prime!=zeroprimes3(m,v);
  4216. % m is in general position with univariate polynomial in v.
  4217. begin scalar u,p;
  4218. u:=dpmat_list m;
  4219. while u and not equal(mo_support dp_lmon (p:=bas_dpoly car u),
  4220. list v) do u:=cdr u;
  4221. if null u then rederr"univariate polynomial not found";
  4222. p:=for each x in cdr ((fctrf numr simp dp_2a p) where !*factor=t)
  4223. collect dpmat_from_dpoly dp_from_a prepf car x;
  4224. return for each x in p collect matsum!* {m,x};
  4225. end;
  4226. symbolic procedure prime!=iszeroprime2 m;
  4227. % Test the radical zerodimensional dmpat ideal m to be prime using a
  4228. % general position argument.
  4229. (begin scalar c,v,vars,u,r;
  4230. c:=cali!=basering; vars:=ring_names c; v:=gensym();
  4231. if ring_tag c='revlex then % for proper ring_sum redefine it.
  4232. r:=ring_define(vars,ring_degrees c,'lex,ring_ecart c)
  4233. else r:=c;
  4234. setring!* ring_sum(r,ring_define(list v,nil,'lex,'(1)));
  4235. cali!=degrees:=nil;
  4236. m:=matsum!* {dpmat_neworder(m,nil), dpmat_from_dpoly dp_from_a v};
  4237. m:=prime_gpchange(vars,v,gbasis!* m);
  4238. u:=prime!=iszeroprime3(m,v);
  4239. setring!* c; return u;
  4240. end)
  4241. where cali!=degrees:=cali!=degrees,
  4242. cali!=basering:=cali!=basering;
  4243. symbolic procedure prime!=iszeroprime3(m,v);
  4244. begin scalar u,p;
  4245. u:=dpmat_list m;
  4246. while u and not equal(mo_support dp_lmon (p:=bas_dpoly car u),
  4247. list v) do u:=cdr u;
  4248. if null u then rederr"univariate polynomial not found";
  4249. if (length(u:=cdr ((fctrf numr simp dp_2a p) where !*factor=t))>1)
  4250. or (cdar u>1) then return nil
  4251. else return t
  4252. end;
  4253. % --------- Primality test for an arbitrary ideal. ---------
  4254. put('isprime,'psopfn,'prime!=isprime);
  4255. symbolic procedure prime!=isprime m;
  4256. begin scalar c;
  4257. intf_test m; intf_get(m:=car m);
  4258. if not (c:=get(m,'gbasis)) then
  4259. put(m,'gbasis,c:=gbasis!* get(m,'basis));
  4260. return if isprime!* c then 'yes else 'no;
  4261. end;
  4262. symbolic procedure isprime!* m;
  4263. % Test an dpmat ideal m to be prime. m must be a gbasis.
  4264. if dpmat_cols m>0 then rederr"prime test only for ideals"
  4265. else (begin scalar vars,u,v,c1,c2,m1,m2,lc;
  4266. v:=moid_goodindepvarset m; cali!=degrees:=nil;
  4267. if null v then return prime_iszeroprime m;
  4268. vars:=ring_names(c1:=cali!=basering);
  4269. % Change to dimension zero.
  4270. u:=setdiff(ring_names c1,v);
  4271. setring!* ring_rlp(c1,u);
  4272. m1:=dpmat_2a gbasis!* dpmat_neworder(m,nil);
  4273. setring!*(c2:= ring_define(u,degreeorder!* u,'revlex,
  4274. for each x in u collect 1));
  4275. m1:=groeb_mingb dpmat_from_a m1;
  4276. if dpmat_unitideal!?(m1) then
  4277. << setring!* c1; rederr"Input must be a gbasis" >>;
  4278. lc:=bc_2a prime!=quot m1; setring!* c1;
  4279. % Test recontraction of m1 to be equal to m.
  4280. m2:=gbasis!* matqquot!*(m,dp_from_a lc);
  4281. if not submodulep!*(m2,m) then return nil;
  4282. % Test the zerodimensional ideal m1 to be prime
  4283. setring!* c2; u:=prime_iszeroprime m1; setring!* c1;
  4284. return u;
  4285. end)
  4286. where cali!=degrees:=cali!=degrees,
  4287. cali!=basering:=cali!=basering;
  4288. symbolic operator isolatedprimes;
  4289. symbolic procedure isolatedprimes m;
  4290. if !*mode='algebraic then
  4291. makelist for each x in isolatedprimes!* dpmat_from_a reval m
  4292. collect dpmat_2a x
  4293. else isolatedprimes!* m;
  4294. symbolic procedure isolatedprimes!* m;
  4295. % Returns the isolated primes of the dpmat m as a dpmat list.
  4296. if !*factorprimes then
  4297. listminimize(
  4298. for each x in groebfactor!*(annihilator2!* m,nil) join
  4299. prime!=factorisoprimes car x,
  4300. function submodulep!*)
  4301. else prime!=isoprimes gbasis!* annihilator2!* m;
  4302. symbolic procedure prime!=isoprimes m;
  4303. % m is a gbasis and an ideal.
  4304. if dpmat_zero!? m then nil else
  4305. (begin scalar u,c,v,vars,m1,m2,l,p;
  4306. if null(v:=odim_parameter m) then return
  4307. for each x in prime_zeroprimes1 m join prime!=zeroprimes2 x;
  4308. vars:=ring_names(c:=cali!=basering); cali!=degrees:=nil;
  4309. u:=delete(v,vars);
  4310. setring!* ring_rlp(c,u);
  4311. m1:=dpmat_2a gbasis!* dpmat_neworder(m,nil);
  4312. setring!* ring_define(u,degreeorder!* u,
  4313. 'revlex,for each x in u collect 1);
  4314. p:=bc_2a prime!=quot(m1:=groeb_mingb dpmat_from_a m1);
  4315. l:=for each x in prime!=isoprimes m1 collect
  4316. (dpmat_2a x . bc_2a prime!=quot x);
  4317. setring!* c;
  4318. l:=for each x in l collect
  4319. gbasis!* matqquot!*(dpmat_from_a car x,dp_from_a cdr x);
  4320. if dp_unit!?(p:=dp_from_a p) or
  4321. submodulep!*(matqquot!*(m,p),m) or
  4322. dpmat_unitideal!?(m2:=gbasis!* matsum!* {m,dpmat_from_dpoly p})
  4323. then return l
  4324. else return
  4325. listminimize(append(l,prime!=isoprimes m2),
  4326. function submodulep!*);
  4327. end)
  4328. where cali!=degrees:=cali!=degrees,
  4329. cali!=basering:=cali!=basering;
  4330. symbolic procedure prime!=factorisoprimes m;
  4331. % m is a gbasis and an ideal.
  4332. if dpmat_zero!? m then nil else
  4333. (begin scalar u,c,v,vars,m1,m2,l,p;
  4334. if null(v:=odim_parameter m) then
  4335. return for each x in groebf_zeroprimes1(m,nil) join
  4336. prime!=zeroprimes2 x;
  4337. vars:=ring_names(c:=cali!=basering); cali!=degrees:=nil;
  4338. u:=delete(v,vars);
  4339. setring!* ring_rlp(c,u);
  4340. m1:=dpmat_2a gbasis!* dpmat_neworder(m,nil);
  4341. setring!* ring_define(u,degreeorder!* u,
  4342. 'revlex,for each x in u collect 1);
  4343. p:=bc_2a prime!=quot(m1:=groeb_mingb dpmat_from_a m1);
  4344. l:=for each x in prime!=factorisoprimes m1 collect
  4345. (dpmat_2a x . bc_2a prime!=quot x);
  4346. setring!* c;
  4347. l:=listgroebfactor!* for each x in l collect
  4348. matqquot!*(dpmat_from_a car x,dp_from_a cdr x);
  4349. if dp_unit!?(p:=dp_from_a p) or
  4350. submodulep!*(matqquot!*(m,p),m) or
  4351. null (m2:=groebfactor!*(matsum!* {m,dpmat_from_dpoly p},nil))
  4352. then return l
  4353. else return
  4354. listminimize(append(l,for each x in m2 join
  4355. prime!=factorisoprimes car x), function submodulep!*);
  4356. end)
  4357. where cali!=degrees:=cali!=degrees,
  4358. cali!=basering:=cali!=basering;
  4359. symbolic procedure prime!=quot m;
  4360. % The lcm of the leading coefficients of m.
  4361. begin scalar p,u;
  4362. u:=for each x in dpmat_list m collect dp_lc bas_dpoly x;
  4363. if null u then return bc_fi 1;
  4364. p:=car u; for each x in cdr u do p:=bc_lcm(p,x);
  4365. return p
  4366. end;
  4367. % ------------------- The radical ---------------------
  4368. symbolic operator radical;
  4369. symbolic procedure radical m;
  4370. % Returns the radical of the dpmat ideal m.
  4371. if !*mode='algebraic then
  4372. dpmat_2a radical!* gbasis!* dpmat_from_a reval m
  4373. else radical!* m;
  4374. symbolic procedure radical!* m;
  4375. % m must be a gbasis.
  4376. if dpmat_cols m>0 then rederr"RADICAL only for ideals"
  4377. else (begin scalar u,c,v,vars,m1,l,p,p1;
  4378. if null(v:=odim_parameter m) then return zeroradical!* m;
  4379. vars:=ring_names (c:=cali!=basering);
  4380. cali!=degrees:=nil; u:=delete(v,vars);
  4381. setring!* ring_rlp(c,u);
  4382. m1:=dpmat_2a gbasis!* dpmat_neworder(m,nil);
  4383. setring!* ring_define(u,degreeorder!* u,
  4384. 'revlex,for each x in u collect 1);
  4385. p:=bc_2a prime!=quot(m1:=groeb_mingb dpmat_from_a m1);
  4386. l:=radical!* m1; p1:=bc_2a prime!=quot l;
  4387. l:=dpmat_2a l; setring!* c;
  4388. l:=gbasis!* matqquot!*(dpmat_from_a l,dp_from_a p1);
  4389. if dp_unit!?(p:=dp_from_a p) or
  4390. submodulep!*(matqquot!*(m,p),m) then return l
  4391. else << m1:=radical!* gbasis!* matsum!* {m,dpmat_from_dpoly p};
  4392. if submodulep!*(m1,l) then l:=m1
  4393. else if not submodulep!*(l,m1) then
  4394. l:= matintersect!* {l,m1};
  4395. >>;
  4396. return l;
  4397. end)
  4398. where cali!=degrees:=cali!=degrees,
  4399. cali!=basering:=cali!=basering;
  4400. % ------------------- The unmixed radical ---------------------
  4401. symbolic operator unmixedradical;
  4402. symbolic procedure unmixedradical m;
  4403. % Returns the radical of the dpmat ideal m.
  4404. if !*mode='algebraic then
  4405. dpmat_2a unmixedradical!* gbasis!* dpmat_from_a reval m
  4406. else unmixedradical!* m;
  4407. symbolic procedure unmixedradical!* m;
  4408. % m must be a gbasis.
  4409. if dpmat_cols m>0 then rederr"UNMIXEDRADICAL only for ideals"
  4410. else (begin scalar u,c,d,v,vars,m1,l,p,p1;
  4411. if null(v:=moid_goodindepvarset m) then return zeroradical!* m;
  4412. vars:=ring_names (c:=cali!=basering);
  4413. d:=length v; u:=setdiff(vars,v);
  4414. setring!* ring_rlp(c,u);
  4415. m1:=dpmat_2a gbasis!* dpmat_neworder(m,nil);
  4416. setring!* ring_define(u,degreeorder!* u,'revlex,
  4417. for each x in u collect 1);
  4418. p:=bc_2a prime!=quot(m1:=groeb_mingb dpmat_from_a m1);
  4419. l:=zeroradical!* m1; p1:=bc_2a prime!=quot l;
  4420. l:=dpmat_2a l; setring!* c;
  4421. l:=matqquot!*(dpmat_from_a l,dp_from_a p1);
  4422. if dp_unit!?(p:=dp_from_a p) then return l
  4423. else << m1:=gbasis!* matsum!* {m,dpmat_from_dpoly p};
  4424. if dim!* m1=d then
  4425. l:= matintersect!* {l,unmixedradical!* m1};
  4426. >>;
  4427. return l;
  4428. end)
  4429. where cali!=degrees:=cali!=degrees,
  4430. cali!=basering:=cali!=basering;
  4431. % ------------------- The equidimensional hull---------------------
  4432. symbolic operator eqhull;
  4433. symbolic procedure eqhull m;
  4434. % Returns the radical of the dpmat ideal m.
  4435. if !*mode='algebraic then
  4436. dpmat_2a eqhull!* gbasis!* dpmat_from_a reval m
  4437. else eqhull!* m;
  4438. symbolic procedure eqhull!* m;
  4439. % m must be a gbasis.
  4440. begin scalar d;
  4441. if (d:=dim!* m)=0 then return m
  4442. else return prime!=eqhull(m,d)
  4443. end;
  4444. symbolic procedure prime!=eqhull(m,d);
  4445. % d(>0) is the dimension of the dpmat m.
  4446. (begin scalar u,c,v,vars,m1,l,p;
  4447. v:=moid_goodindepvarset m;
  4448. if length v neq d then
  4449. rederr "EQHULL found a component of wrong dimension";
  4450. vars:=ring_names(c:=cali!=basering);
  4451. cali!=degrees:=nil; u:=setdiff(ring_names c,v);
  4452. setring!* ring_rlp(c,u);
  4453. m1:=dpmat_2a gbasis!* dpmat_neworder(m,nil);
  4454. setring!* ring_define(u,degreeorder!* u,'revlex,
  4455. for each x in u collect 1);
  4456. p:=bc_2a prime!=quot(m1:=groeb_mingb dpmat_from_a m1);
  4457. setring!* c; cali!=degrees:=dpmat_coldegs m;
  4458. if submodulep!*(l:=matqquot!*(m,dp_from_a p),m) then return m;
  4459. m1:=gbasis!* matstabquot!*(m,annihilator2!* l);
  4460. if dim!* m1=d then return matintersect!* {l,prime!=eqhull(m1,d)}
  4461. else return l;
  4462. end)
  4463. where cali!=degrees:=cali!=degrees,
  4464. cali!=basering:=cali!=basering;
  4465. % ---------- Primary Decomposition Algorithms ------------
  4466. Comment
  4467. by [GTZ]'s approach:
  4468. - Compute successively a list {(Q_i,p_i)} of pairs
  4469. (primary module, associated prime ideal)
  4470. such that
  4471. Q = \intersection{Q_i}
  4472. - figure out the superfluous components
  4473. (Note, that different to our former opinion (v. 2.2.) it is not
  4474. sufficient to extract the elements from that list, that are minimal
  4475. wrt. inclusion for the primary component. There may be components,
  4476. containing none of these minimal primaries, but containing their
  4477. intersection !!)
  4478. Primary decompositions return a list of {Q,P} pairs with prime
  4479. ideal P and corresponding primary component Q.
  4480. end comment;
  4481. % - The primary decomposition of a zerodimensional ideal or module -
  4482. symbolic procedure prime_separate l;
  4483. % l is a list of (gbases of) prime ideals.
  4484. % Returns a list of (p . f) with p \in l and dpoly f \in all q \in l
  4485. % except p.
  4486. for each x in l collect (x . prime!=polynomial(x,delete(x,l)));
  4487. symbolic procedure prime!=polynomial(x,l);
  4488. % Returns a dpoly f inside all q \in l and outside x.
  4489. if null l then dp_fi 1
  4490. else begin scalar u,p,q;
  4491. p:=prime!=polynomial(x,cdr l);
  4492. if null matop_pseudomod(p,car l) then return p;
  4493. u:=dpmat_list car l;
  4494. while u and null matop_pseudomod(q:=bas_dpoly car u,x) do u:=cdr u;
  4495. if null u then
  4496. rederr"prime ideal separation failed"
  4497. else return dp_prod(p,q);
  4498. end;
  4499. symbolic operator zeroprimarydecomposition;
  4500. symbolic procedure zeroprimarydecomposition m;
  4501. % Returns a list of {Q,p} with p a prime ideal and Q a p-primary
  4502. % component of m. For m=S^c the list is empty.
  4503. if !*mode='algebraic then
  4504. makelist for each x in
  4505. zeroprimarydecomposition!* dpmat_from_a reval m
  4506. collect makelist {dpmat_2a first x,dpmat_2a second x}
  4507. else zeroprimarydecomposition!* m;
  4508. symbolic procedure zeroprimarydecomposition!* m;
  4509. % The symbolic counterpart, returns a list of {Q,p}. m is not
  4510. % assumed to be a gbasis.
  4511. if not dimzerop!* m then rederr
  4512. "zeroprimarydecomposition only for zerodimensional ideals or modules"
  4513. else for each f in prime_separate
  4514. (for each y in zeroprimes!* m collect gbasis!* y)
  4515. collect {matqquot!*(m,cdr f),car f};
  4516. % -- Primary decomposition for modules without embedded components ---
  4517. symbolic operator easyprimarydecomposition;
  4518. symbolic procedure easyprimarydecomposition m;
  4519. if !*mode='algebraic then
  4520. makelist for each x in
  4521. easyprimarydecomposition!* dpmat_from_a reval m
  4522. collect makelist {dpmat_2a first x,dpmat_2a second x}
  4523. else easyprimarydecomposition!* m;
  4524. symbolic procedure easyprimarydecomposition!* m;
  4525. % Primary decomposition for a module without embedded components.
  4526. begin scalar u; u:=isolatedprimes!* m;
  4527. return if null u then nil
  4528. else if length u=1 then {{m,car u}}
  4529. else for each f in
  4530. prime_separate(for each y in u collect gbasis!* y)
  4531. collect {matqquot!*(m,cdr f),car f};
  4532. end;
  4533. % ---- General primary decomposition ----------
  4534. symbolic operator primarydecomposition;
  4535. symbolic procedure primarydecomposition m;
  4536. if !*mode='algebraic then
  4537. makelist for each x in
  4538. primarydecomposition!* gbasis!* dpmat_from_a reval m
  4539. collect makelist {dpmat_2a first x,dpmat_2a second x}
  4540. else primarydecomposition!* m;
  4541. symbolic procedure primarydecomposition!* m;
  4542. % m must be a gbasis. The [GTZ] approach.
  4543. if dpmat_cols m=0 then
  4544. for each x in prime!=decompose1 ideal2mat!* m collect
  4545. {mat2list!* first x,second x}
  4546. else prime!=decompose1 m;
  4547. % --------------- Implementation of the [GTZ] approach
  4548. symbolic procedure prime!=decompose1 m;
  4549. % The method as in the final version of the paper: Dropping dimension
  4550. % by one in each step.
  4551. (begin scalar u,c,v,vars,m1,l,l1,p,q;
  4552. if null(v:=odim_parameter m) then
  4553. return zeroprimarydecomposition!* m;
  4554. vars:=ring_names (c:=cali!=basering);
  4555. cali!=degrees:=nil; u:=delete(v,vars);
  4556. setring!* ring_rlp(c,u);
  4557. m1:=dpmat_2a gbasis!* dpmat_neworder(m,nil);
  4558. setring!* ring_define(u,degreeorder!* u,
  4559. 'revlex,for each x in u collect 1);
  4560. p:=bc_2a prime!=quot(m1:=groeb_mingb dpmat_from_a m1);
  4561. l:=for each x in prime!=decompose1 m1 collect
  4562. {(dpmat_2a first x . bc_2a prime!=quot first x),
  4563. (dpmat_2a second x . bc_2a prime!=quot second x)};
  4564. setring!* c;
  4565. l:=for each x in l collect
  4566. << cali!=degrees:=dpmat_coldegs m;
  4567. {gbasis!* matqquot!*(dpmat_from_a car first x,
  4568. dp_from_a cdr first x),
  4569. gbasis!* matqquot!*(dpmat_from_a car second x,
  4570. dp_from_a cdr second x)}
  4571. >>;
  4572. if dp_unit!?(p:=dp_from_a p) or
  4573. submodulep!*(m1:=matqquot!*(m,p),m) then return l
  4574. else
  4575. << q:=p; v:=1;
  4576. while not submodulep!*(m1:=dpmat_times_dpoly(p,m1),m)
  4577. and (v<15) do << q:=dp_prod(p,q); v:=v+1 >>;
  4578. if (v=15) then
  4579. rederr"Power detection in prime!=decompose1 failed";
  4580. l1:=prime!=decompose1 gbasis!* matsum!*
  4581. {m, dpmat_times_dpoly(q,
  4582. dpmat_unit(dpmat_cols m,dpmat_coldegs m))};
  4583. Comment
  4584. At this moment M = M:<p>\intersection (M,q*F), q=p^n, and
  4585. - l is the list of primary comp., lifted from the first part
  4586. (they are lifted from a localization and have p as non
  4587. zero divisor)
  4588. - l1 is the list of primary comp. of the second part
  4589. (which have p as zero divisor and should be tested
  4590. against M, whether they are indeed necessary)
  4591. end comment;
  4592. p:=append(for each x in l collect second x,
  4593. for each x in l1 collect second x);
  4594. l:=append(l,for each x in l1 join
  4595. if prime!=necessary(second x,m,p) then {x});
  4596. >>;
  4597. return l;
  4598. end)
  4599. where cali!=degrees:=cali!=degrees,
  4600. cali!=basering:=cali!=basering;
  4601. symbolic procedure prime!=decompose2 m;
  4602. % The method as in [BKW] : Reducing directly to dimension zero. This
  4603. % is usually a quite bad guess.
  4604. (begin scalar u,c,v,vars,m1,l,l1,p,q;
  4605. v:=moid_goodindepvarset m;
  4606. if null v then return zeroprimarydecomposition!* m;
  4607. vars:=ring_names (c:=cali!=basering);
  4608. cali!=degrees:=nil; u:=setdiff(vars,v);
  4609. setring!* ring_rlp(c,u);
  4610. m1:=dpmat_2a gbasis!* dpmat_neworder(m,nil);
  4611. setring!* ring_define(u,degreeorder!* u,
  4612. 'revlex,for each x in u collect 1);
  4613. p:=bc_2a prime!=quot(m1:=groeb_mingb dpmat_from_a m1);
  4614. l:=for each x in zeroprimarydecomposition!* m1 collect
  4615. {(dpmat_2a first x . bc_2a prime!=quot first x),
  4616. (dpmat_2a second x . bc_2a prime!=quot second x)};
  4617. setring!* c;
  4618. l:=for each x in l collect
  4619. << cali!=degrees:=dpmat_coldegs m;
  4620. {gbasis!* matqquot!*(dpmat_from_a car first x,
  4621. dp_from_a cdr first x),
  4622. gbasis!* matqquot!*(dpmat_from_a car second x,
  4623. dp_from_a cdr second x)}
  4624. >>;
  4625. if dp_unit!?(p:=dp_from_a p) or
  4626. submodulep!*(m1:=matqquot!*(m,p),m) then return l
  4627. else
  4628. << q:=p; v:=1;
  4629. while not submodulep!*(m1:=dpmat_times_dpoly(p,m1),m)
  4630. and (v<15) do << q:=dp_prod(p,q); v:=v+1 >>;
  4631. if (v=15) then
  4632. rederr"Power detection in prime!=decompose2 failed";
  4633. l1:=prime!=decompose2 gbasis!* matsum!*
  4634. {m, dpmat_times_dpoly(q,
  4635. dpmat_unit(dpmat_cols m,dpmat_coldegs m))};
  4636. p:=append(for each x in l collect second x,
  4637. for each x in l1 collect second x);
  4638. l:=append(l,for each x in l1 join
  4639. if prime!=necessary(second x,m,p) then {x});
  4640. >>;
  4641. return l;
  4642. end)
  4643. where cali!=degrees:=cali!=degrees,
  4644. cali!=basering:=cali!=basering;
  4645. symbolic procedure prime!=necessary(P,m,l);
  4646. % P a prime to be testet, M the original module, l the list of
  4647. % (possibly) associated primes of M, including P.
  4648. % Returns true <=> P is an embedded prime.
  4649. begin scalar l1,unit;
  4650. l1:=for each u in l join if (u=p) or submodulep!*(u,p) then {t};
  4651. if null l1 then
  4652. rederr"prime!=necessary: supplied prime's list incorrect";
  4653. if length l1 = 1 then % P is an isolated prime.
  4654. return t;
  4655. unit:=dpmat_unit(dpmat_cols m,cali!=degrees);
  4656. % Unit matrix for reference.
  4657. l1:=for each u in l join if not submodulep!*(u,p) then {u};
  4658. % L_1 = Primes not contained in P.
  4659. l:=delete(p,setdiff(l,l1)); % L = Primes contained in P.
  4660. m:=matqquot!*(m,prime!=polynomial(p,l1));
  4661. % Ass M is now contained in L \union (P).
  4662. return not submodulep!*(matstabquot!*(m,p),m);
  4663. end;
  4664. endmodule; % prime
  4665. end;
  4666. module quot;
  4667. COMMENT
  4668. #################
  4669. # #
  4670. # QUOTIENTS #
  4671. # #
  4672. #################
  4673. This module contains algorithms for different kinds of quotients of
  4674. ideals and modules.
  4675. END COMMENT;
  4676. % -------- Quotient of a module by a polynomial -----------
  4677. % Returns m : (f) for a polynomial f.
  4678. symbolic operator matquot;
  4679. symbolic procedure matquot(m,f);
  4680. if !*mode='algebraic then
  4681. if eqcar(f,'list) or eqcar(f,'mat) then
  4682. rederr("Syntax : matquot(dpmat,dpoly)")
  4683. else dpmat_2a matquot!*(dpmat_from_a reval m,dp_from_a reval f)
  4684. else matquot!*(m,f);
  4685. symbolic procedure matquot!*(m,f);
  4686. if dp_unit!? f then m
  4687. else if dpmat_cols m=0 then mat2list!* quot!=quot(ideal2mat!* m,f)
  4688. else quot!=quot(m,f);
  4689. symbolic procedure quot!=quot(m,f);
  4690. % Note that, if a is a gbasis, then also b.
  4691. begin scalar a,b;
  4692. a:=matintersect!* {m,
  4693. dpmat_times_dpoly(f,dpmat_unit(dpmat_cols m,dpmat_coldegs m))};
  4694. b:=for each x in dpmat_list a collect
  4695. bas_make(bas_nr x,car dp_pseudodivmod(bas_dpoly x,f));
  4696. return dpmat_make(dpmat_rows a,dpmat_cols a,b,
  4697. dpmat_coldegs m,dpmat_gbtag a);
  4698. end;
  4699. % -------- Quotient of a module by an ideal -----------
  4700. % Returns m:n as a module.
  4701. symbolic operator idealquotient;
  4702. symbolic procedure idealquotient(m,n);
  4703. if !*mode='algebraic then
  4704. dpmat_2a idealquotient2!*(dpmat_from_a reval m,
  4705. dpmat_from_a reval n)
  4706. else idealquotient2!*(m,n);
  4707. % -------- Quotient of a module by another module -----------
  4708. % Returns m:n as an ideal in S. m and n must be submodules of a common
  4709. % free module.
  4710. symbolic operator modulequotient;
  4711. symbolic procedure modulequotient(m,n);
  4712. if !*mode='algebraic then
  4713. dpmat_2a modulequotient2!*(dpmat_from_a reval m,
  4714. dpmat_from_a reval n)
  4715. else modulequotient2!*(m,n);
  4716. % ---- The annihilator of a module, i.e. Ann coker M := M : F ---
  4717. symbolic operator annihilator;
  4718. symbolic procedure annihilator m;
  4719. if !*mode='algebraic then
  4720. dpmat_2a annihilator2!* dpmat_from_a reval m
  4721. else annihilator2!* m;
  4722. % ---- Quotients as M:N = \intersect { M:f | f \in N } ------
  4723. symbolic procedure idealquotient2!*(m,n);
  4724. if dpmat_cols n>0 then rederr"Syntax : idealquotient(dpmat,ideal)"
  4725. else if dpmat_cols m=0 then modulequotient2!*(m,n)
  4726. else if dpmat_cols m=1 then
  4727. ideal2mat!* modulequotient2!*(m,ideal2mat!* n)
  4728. else matintersect!* for each x in dpmat_list n collect
  4729. quot!=quot(m,bas_dpoly x);
  4730. symbolic procedure modulequotient2!*(m,n);
  4731. (begin scalar c;
  4732. if not((c:=dpmat_cols m)=dpmat_cols n) then rederr
  4733. "MODULEQUOTIENT only for submodules of a common free module";
  4734. if not equal(dpmat_coldegs m,dpmat_coldegs n) then
  4735. rederr"matrices don't match for MODULEQUOTIENT";
  4736. if (c=0) then << m:=ideal2mat!* m; n:=ideal2mat!* n >>;
  4737. cali!=degrees:=dpmat_coldegs m;
  4738. n:=for each x in dpmat_list n collect matop_pseudomod(bas_dpoly x,m);
  4739. n:=for each x in n join if x then {x};
  4740. return if null n then dpmat_from_dpoly dp_fi 1
  4741. else matintersect!* for each x in n collect quot!=mquot(m,x);
  4742. end) where cali!=degrees:=cali!=degrees;
  4743. symbolic procedure quot!=mquot(m,f);
  4744. begin scalar a,b;
  4745. a:=matintersect!*
  4746. {m,dpmat_make(1,dpmat_cols m,list bas_make(1,f),dpmat_coldegs m,t)};
  4747. b:=for each x in dpmat_list a collect
  4748. bas_make(bas_nr x,car dp_pseudodivmod(bas_dpoly x,f));
  4749. return dpmat_make(dpmat_rows a,0,b,nil,nil);
  4750. end;
  4751. symbolic procedure annihilator2!* m;
  4752. if dpmat_cols m=0 then m
  4753. else if dpmat_cols m=1 then mat2list!* m
  4754. else modulequotient2!*(m,dpmat_unit(dpmat_cols m,dpmat_coldegs m));
  4755. % -------- Quotients by the general element method --------
  4756. symbolic procedure idealquotient1!*(m,n);
  4757. if dpmat_cols n>0 then rederr "second parameter must be an ideal"
  4758. else if dpmat_cols m=0 then modulequotient1!*(m,n)
  4759. else if dpmat_cols m=1 then
  4760. ideal2mat!* modulequotient1!*(m,ideal2mat!* n)
  4761. else (begin scalar u1,u2,f,v,r,m1;
  4762. v:=list gensym(); r:=cali!=basering;
  4763. setring!* ring_sum(r,ring_define(v,degreeorder!* v,'revlex,'(1)));
  4764. cali!=degrees:=mo_degneworder dpmat_coldegs m;
  4765. n:=for each x in dpmat_list n collect dp_neworder x;
  4766. u1:=u2:=dp_from_a car v; f:=car n;
  4767. for each x in n do
  4768. << f:=dp_sum(f,dp_prod(u1,x)); u1:=dp_prod(u1,u2) >>;
  4769. m1:=dpmat_sieve(gbasis!* quot!=quot(dpmat_neworder(m,nil),f),v,t);
  4770. setring!* r; cali!=degrees:=dpmat_coldegs m;
  4771. return dpmat_neworder(m1,t);
  4772. end)
  4773. where cali!=degrees:=cali!=degrees,
  4774. cali!=basering:=cali!=basering;
  4775. symbolic procedure modulequotient1!*(m,n);
  4776. (begin scalar c,u1,u2,f,v,r,m1;
  4777. if not((c:=dpmat_cols m)=dpmat_cols n) then rederr
  4778. "MODULEQUOTIENT only for submodules of a common free module";
  4779. if not equal(dpmat_coldegs m,dpmat_coldegs n) then
  4780. rederr"matrices don't match for MODULEQUOTIENT";
  4781. if (c=0) then << m:=ideal2mat!* m; n:=ideal2mat!* n >>;
  4782. cali!=degrees:=dpmat_coldegs m;
  4783. n:=for each x in dpmat_list n collect matop_pseudomod(bas_dpoly x,m);
  4784. n:=for each x in n join if x then {x};
  4785. if null n then return dpmat_from_dpoly dp_fi 1;
  4786. v:=list gensym(); r:=cali!=basering;
  4787. setring!* ring_sum(r,ring_define(v,degreeorder!* v,'revlex,'(1)));
  4788. cali!=degrees:=mo_degneworder cali!=degrees;
  4789. u1:=u2:=dp_from_a car v; f:=dp_neworder car n;
  4790. for each x in n do
  4791. << f:=dp_sum(f,dp_prod(u1,dp_neworder x));
  4792. u1:=dp_prod(u1,u2)
  4793. >>;
  4794. m1:=dpmat_sieve(gbasis!* quot!=mquot(dpmat_neworder(m,nil),f),v,t);
  4795. setring!* r; cali!=degrees:=dpmat_coldegs m;
  4796. return dpmat_neworder(m1,t);
  4797. end)
  4798. where cali!=degrees:=cali!=degrees,
  4799. cali!=basering:=cali!=basering;
  4800. symbolic procedure annihilator1!* m;
  4801. if dpmat_cols m=0 then m
  4802. else if dpmat_cols m=1 then m
  4803. else modulequotient1!*(m,dpmat_unit(dpmat_cols m,dpmat_coldegs m));
  4804. % --------------- Stable quotients ------------------------
  4805. symbolic operator matqquot;
  4806. symbolic procedure matqquot(m,f);
  4807. % Stable quotient of dpmat m with respect to a polynomial f, i.e.
  4808. % m : <f> = { v \in F | \exists n : f^n*v \in m }
  4809. if !*mode='algebraic then
  4810. if eqcar(f,'list) or eqcar(f,'mat) then
  4811. rederr("Syntax : matquot(dpmat,dpoly)")
  4812. else dpmat_2a matqquot!*(dpmat_from_a reval m,dp_from_a reval f)
  4813. else matqquot!*(m,f);
  4814. symbolic procedure matqquot!*(m,f);
  4815. if dp_unit!? f then m
  4816. else if dpmat_cols m=0 then
  4817. mat2list!* quot!=stabquot(ideal2mat!* m,{f})
  4818. else quot!=stabquot(m,{f});
  4819. symbolic operator matstabquot;
  4820. symbolic procedure matstabquot(m,f);
  4821. % Stable quotient of dpmat m with respect to an ideal f.
  4822. if !*mode='algebraic then dpmat_2a
  4823. matstabquot!*(dpmat_from_a reval m,dpmat_from_a reval f)
  4824. else matstabquot!*(m,f);
  4825. symbolic procedure matstabquot!*(m,f);
  4826. if dpmat_cols f > 0 then rederr "stable quotient only by ideals"
  4827. else begin scalar c;
  4828. if (c:=dpmat_cols m)=0 then
  4829. << f:=for each x in dpmat_list f collect
  4830. matop_pseudomod(bas_dpoly x,m);
  4831. f:=for each x in f join if x then {x}
  4832. >>
  4833. else f:=for each x in dpmat_list f collect bas_dpoly x;
  4834. if null f then return
  4835. if c=0 then dpmat_from_dpoly dp_fi 1
  4836. else dpmat_unit(c,dpmat_coldegs m);
  4837. if dp_unit!? car f then return m;
  4838. if c=0 then return mat2list!* quot!=stabquot(ideal2mat!* m,f)
  4839. else return quot!=stabquot(m,f);
  4840. end;
  4841. symbolic procedure quot!=stabquot(m,f);
  4842. % m must be a module.
  4843. if dpmat_cols m=0 then rederr"quot_stabquot only for cols>0"
  4844. else (begin scalar m1,p,p1,p2,v,v1,v2,c;
  4845. v1:=gensym(); v2:=gensym(); v:={v1,v2};
  4846. setring!* ring_sum(c:=cali!=basering,
  4847. ring_define(v,degreeorder!* v,'lex,'(1 1)));
  4848. cali!=degrees:=mo_degneworder dpmat_coldegs m;
  4849. p1:=p2:=dp_from_a v1;
  4850. f:=for each x in f collect dp_neworder x;
  4851. p:=car f;
  4852. for each x in cdr f do
  4853. << p:=dp_sum(dp_prod(p1,x),p); p1:=dp_prod(p1,p2) >>;
  4854. p:=dp_diff(dp_fi 1,dp_prod(dp_from_a v2,p));
  4855. % p = 1 - v2 * \sum{f_i * v1^i}
  4856. m1:=matsum!* {dpmat_neworder(m,nil),
  4857. dpmat_times_dpoly(p,
  4858. dpmat_unit(dpmat_cols m,cali!=degrees))};
  4859. m1:=dpmat_sieve(gbasis!* m1,v,t);
  4860. setring!* c; cali!=degrees:=dpmat_coldegs m;
  4861. return dpmat_neworder(m1,t);
  4862. end)
  4863. where cali!=degrees:=cali!=degrees,
  4864. cali!=basering:=cali!=basering;
  4865. endmodule; % quot
  4866. end;
  4867. module red;
  4868. COMMENT
  4869. #################
  4870. ## ##
  4871. ## NORMAL FORM ##
  4872. ## ALGORITHMS ##
  4873. ## ##
  4874. #################
  4875. This module contains normal form algorithms for base elements. All
  4876. reductions executed on the dpoly part, are repeated on the rep part,
  4877. hence tracing them up for further use. We do pseudoreduction, but
  4878. organized following up the multipliers in a different way than in the
  4879. version 2.1 :
  4880. For total reduction we hide terms prefixing the current lead term on the
  4881. negative slots of the rep part. This allows not to follow up the
  4882. multipliers, since head terms are multiplied automatically.
  4883. If You nevertheless need the multipliers, You can prepare the base
  4884. elements with "red_prepare" to keep track of them using the 0-slot of
  4885. the rep-part :
  4886. f --> (f,e_0) -NF-> (f',z*e_0) --> (f' . z)
  4887. Extract the multiplier back with "red_extract". This allows a unified
  4888. treating of the multipliers for both noetherian and non noetherian
  4889. term orders.
  4890. For NF : [f,r] |--> [f',r'] using B={[f_i,r_i]}
  4891. with representation parts r, r_i we get
  4892. f' = z*f + \sum a_i*f_i
  4893. r' = z*r + \sum a_i*r_i
  4894. The output trace intensity can be managed with cali_trace() that has
  4895. the following meaning :
  4896. cali_trace() >= 0 no trace
  4897. 10 '.' for each substitution
  4898. 70 trace interreduce!*
  4899. 80 trace redpol
  4900. 90 show substituents
  4901. The reduction strategy is first matching in the simplifier (base)
  4902. list. It can be changed overloading red_better, the relation
  4903. according to what base lists are sorted. Standard is minimal ecart,
  4904. breaking ties with minimal length (since such a strategy is good for
  4905. both the classical and the local case).
  4906. There are two (head) reduction functions, the usual one and one, that
  4907. allows reduction only by reducers with bounded ecart, i.e. where the
  4908. ecart of the reducer is leq the ecart of the poly to be reduced. This
  4909. allows a unified handling of noetherian and non-noetherian term orders.
  4910. Switches :
  4911. red_total : t compute total normal forms
  4912. nil reduce only until lt is standard
  4913. bcsimp : t apply bas_simp
  4914. END COMMENT;
  4915. % Standard is :
  4916. !*red_total:=t;
  4917. !*bcsimp:=t;
  4918. symbolic procedure red_better(a,b);
  4919. % Base list sort criterion. Simplifier lists are sorted such that the
  4920. % best substituent comes first. Due to reduction with bounded ecart we
  4921. % need no more lowest ecarts first.
  4922. bas_dplen a < bas_dplen b;
  4923. % ---- Preparing data for collecting multipliers ---
  4924. symbolic procedure red_prepare model;
  4925. % Prepare the zero rep-part to follow up multipliers
  4926. % in the pseudoreductions.
  4927. % if !*binomial then model else
  4928. bas_make1(bas_nr model,bas_dpoly model,
  4929. dp_sum(bas_rep model,dp_from_ei 0));
  4930. symbolic procedure red_extract model;
  4931. % Returns (model . dpoly), extracting the multiplier part from the
  4932. % zero rep-part.
  4933. % if !*binomial then (model . dp_fi 1) else
  4934. (bas_make1(bas_nr model, bas_dpoly model,
  4935. dp_diff(bas_rep model,z)) . z
  4936. where z=dp_comp(0,bas_rep model));
  4937. % -------- Substitution operations ----------------
  4938. symbolic procedure red_subst(model,basel);
  4939. % model and basel = base elements
  4940. % Returns a base element, such that
  4941. % pol_new := z * pol_old - z1 * mo * f_a
  4942. % rep_new := z * rep_old - z1 * mo * rep_a
  4943. % with appropriate base coeff. z and z1 and monomial mo.
  4944. % if !*binomial then red!=subst2(model,basel) else
  4945. red!=subst1(model,basel);
  4946. symbolic procedure red!=subst1(model,basel);
  4947. begin scalar polold,polnew,repold,repnew,gcd,mo,fa,z,z1;
  4948. polold:=bas_dpoly model; z1:=dp_lc polold;
  4949. repold:=bas_rep model;
  4950. fa:=bas_dpoly basel; z:= dp_lc fa;
  4951. if !*bcsimp then % modify z and z1
  4952. if (gcd:=bc_inv z) then
  4953. << z1:=bc_prod(z1,gcd); z:=bc_fi 1 >>
  4954. else
  4955. << gcd:=bc_gcd(z,z1);
  4956. z:=car bc_divmod(z,gcd);
  4957. z1:=car bc_divmod(z1,gcd)
  4958. >>;
  4959. mo:=mo_diff(dp_lmon polold,dp_lmon fa);
  4960. polnew:=dp_diff(dp_times_bc(z,polold),
  4961. dp_times_bcmo(z1,mo,fa));
  4962. repnew:=dp_diff(dp_times_bc(z,repold),
  4963. dp_times_bcmo(z1,mo,bas_rep basel));
  4964. if cali_trace() > 79 then
  4965. << prin2 "---> "; dp_print polnew >>
  4966. else if cali_trace() > 0 then prin2 ".";
  4967. if cali_trace() > 89 then
  4968. << prin2 " uses "; dp_print fa >>;
  4969. return bas_make1(bas_nr model,polnew,repnew);
  4970. end;
  4971. symbolic procedure red!=subst2(model,basel);
  4972. % Only for binomials without representation parts.
  4973. begin scalar m,b,u,r;
  4974. if cali_trace()>0 then prin2 ".";
  4975. m:=bas_dpoly model; b:=bas_dpoly basel;
  4976. if (length b neq 2) or bas_rep model then
  4977. rederr"switch off binomial";
  4978. u:=mo_qrem(dp_lmon m,dp_lmon b);
  4979. r:=list dp_term(dp_lc m,
  4980. mo_sum(mo_power(dp_lmon cdr b,car u),cdr u));
  4981. return bas_make(bas_nr model,dp_sum(r,cdr m));
  4982. end;
  4983. % ---------------- Top reduction ------------------------
  4984. symbolic procedure red_TopRedBE(bas,model);
  4985. % Takes a base element model and returns it top reduced with bounded
  4986. % ecart.
  4987. if (null bas_dpoly model) or (null bas) then model
  4988. else begin
  4989. scalar v,q;
  4990. if cali_trace()>79 then
  4991. << write" reduce "; dp_print bas_dpoly model >>;
  4992. while (q:=bas_dpoly model) and
  4993. (v:=red_divtestBE(bas,dp_lmon q,bas_dpecart model)) do
  4994. model:=red_subst(model,v);
  4995. return model;
  4996. end;
  4997. symbolic procedure red_divtestBE(a,b,e);
  4998. % Returns the first f in the base list a, such that lt(f) | b
  4999. % and ec(f)<=e, else nil. b is a monomial.
  5000. if null a then nil
  5001. else if (bas_dpecart(car a) <= e) and
  5002. mo_vdivides!?(dp_lmon bas_dpoly car a,b) then car a
  5003. else red_divtestBE(cdr a,b,e);
  5004. symbolic procedure red_divtest(a,b);
  5005. % Returns the first f in the base list a, such that lt(f) | b else nil.
  5006. % b is a monomial.
  5007. if null a then nil
  5008. else if mo_vdivides!?(dp_lmon bas_dpoly car a,b) then car a
  5009. else red_divtest(cdr a,b);
  5010. symbolic procedure red_TopRed(bas,model);
  5011. % Takes a base element model and returns it top reduced.
  5012. % For noetherian term orders this is the classical top reduction; no
  5013. % additional simplifiers occur. For local term orders it is Mora's
  5014. % reduction by minimal ecart.
  5015. if (null bas_dpoly model) or (null bas) then model
  5016. else begin
  5017. scalar v,q;
  5018. % Make first reduction with bounded ecart.
  5019. model:=red_TopRedBE(bas,model);
  5020. % Now loop into reduction with minimal ecart.
  5021. while (q:=bas_dpoly model) and (v:=red_divtest(bas,dp_lmon q)) do
  5022. << v:=red_subst(model,v);
  5023. if not !*noetherian then bas:=red_update(bas,model);
  5024. model:=red_TopRedBE(bas,v);
  5025. >>;
  5026. return model;
  5027. end;
  5028. % Management of the simplifier list. Has a meaning only in the
  5029. % non noetherian case.
  5030. symbolic procedure red_update(simp,b);
  5031. % Update the simplifier list simp with the base element b.
  5032. begin
  5033. if cali_trace()>59 then
  5034. << terpri(); write "[ec:",bas_dpecart b,"] ->";
  5035. dp_print2 bas_dpoly b
  5036. >>
  5037. else if cali_trace()>0 then write"*";
  5038. return merge(list b,
  5039. for each x in simp join
  5040. if red!=cancelsimp(b,x) then nil else {x},
  5041. function red_better);
  5042. end;
  5043. symbolic procedure red!=cancelsimp(a,b);
  5044. % Test for updating the simplifier list.
  5045. red_better(a,b) and
  5046. mo_vdivides!?(dp_lmon bas_dpoly a,dp_lmon bas_dpoly b);
  5047. % ------------- Total reduction and Tail reduction -----------
  5048. Comment
  5049. For total reduction one has to organize recursive calls of TopRed on
  5050. tails of the current model. Since we do pseudoreduction, we have to
  5051. multiply the prefix terms with the multiplier during recursive calls.
  5052. We do that, hiding the prefix terms on rep part components with
  5053. negative component number. Retrival may be done not recursively, but
  5054. in a single step.
  5055. end Comment;
  5056. symbolic procedure red!=hide p;
  5057. % Hide the terms of the dpoly p. This is involutive !
  5058. for each x in p collect (mo_times_ei(-1,mo_neg car x) . cdr x);
  5059. symbolic procedure red!=hideLt model;
  5060. bas_make1(bas_nr model,cdr p,
  5061. dp_sum(bas_rep model, red!=hide({car p})))
  5062. where p=bas_dpoly model;
  5063. symbolic procedure red!=recover model;
  5064. % The dpoly part of model is empty, but the rep part contains
  5065. % hidden terms.
  5066. begin scalar u,v;
  5067. for each x in bas_rep model do
  5068. if mo_comp car x < 0 then u:=x.u else v:=x.v;
  5069. return bas_make1(bas_nr model, dp_neworder reversip red!=hide u,
  5070. reversip v);
  5071. end;
  5072. symbolic procedure red_TailRedDriver(bas,model,redfctn);
  5073. % Takes a base element model and reduces the tail with the
  5074. % top reduce "redfctn" recursively.
  5075. if (null bas_dpoly model) or (null cdr bas_dpoly model)
  5076. or (null bas) then model
  5077. else begin
  5078. while bas_dpoly model do
  5079. model:=apply2(redfctn,bas,red!=hideLt(model));
  5080. return red!=recover(model);
  5081. end;
  5082. symbolic procedure red_TailRed(bas,model);
  5083. % The tail reduction as we understand it at the moment.
  5084. if !*noetherian then
  5085. red_TailRedDriver(bas,model,function red_TopRed)
  5086. else red_TailRedDriver(bas,model,function red_TopRedBE);
  5087. symbolic procedure red_TotalRed(bas,model);
  5088. % Make a terminating total reduction, i.e. for noetherian term orders
  5089. % the classical one and for local term orders tail reduction with
  5090. % bounded ecart.
  5091. red_TailRed(bas,red_TopRed(bas,model));
  5092. % ---------- Reduction of the straightening parts --------
  5093. symbolic procedure red_Straight(bas);
  5094. % Autoreduce straightening formulae of the base list bas, classical
  5095. % in the noetherian case and with bounded ecart in the local case.
  5096. begin scalar u;
  5097. u:=for each x in bas collect red_TailRed(bas,x);
  5098. if !*bcsimp then u:=bas_simp u;
  5099. return sort(u,function red_better);
  5100. end;
  5101. symbolic procedure red_collect bas;
  5102. % Returns ( bas1 . bas2 ), where bas2 may be reduced with bas1.
  5103. begin scalar bas1,bas2;
  5104. bas1:=listminimize(bas,function (lambda(x,y);
  5105. mo_vdivides!?(dp_lmon bas_dpoly x,dp_lmon bas_dpoly y)));
  5106. bas2:=setdiff(bas,bas1);
  5107. return bas1 . bas2;
  5108. end;
  5109. symbolic procedure red_TopInterreduce m;
  5110. % Reduce rows of the base list m with red_TopRed until it has pairwise
  5111. % incomparable leading terms
  5112. % Compute correct representation parts. Do no tail reduction.
  5113. begin scalar c,w,bas1;
  5114. m:=bas_sort bas_zerodelete m;
  5115. if !*bcsimp then m:=bas_simp m;
  5116. while cdr (c:=red_collect m) do
  5117. << if cali_trace()>69 then
  5118. <<write" interreduce ";terpri();bas_print m>>;
  5119. m:=nil; w:=cdr c; bas1:=car c;
  5120. while w do
  5121. << c:=red_TopRed(bas1,car w);
  5122. if bas_dpoly c then m:=c . m;
  5123. w:=cdr w
  5124. >>;
  5125. if !*bcsimp then m:=bas_simp m;
  5126. m:=merge(bas1,bas_sort m,function red_better);
  5127. >>;
  5128. return m;
  5129. end;
  5130. % ----- Interface to the former syntax --------------
  5131. symbolic procedure red_redpol(bas,model);
  5132. % Returns (reduced model . multiplier)
  5133. begin scalar m;
  5134. m:=red_prepare model;
  5135. return red_extract
  5136. (if !*red_total then red_TotalRed(bas,m) else red_TopRed(bas,m))
  5137. end;
  5138. symbolic procedure red_Interreduce m;
  5139. % Applies to arbitrary term orders.
  5140. begin
  5141. % Top reduction, producing pairwise incomparable leading terms.
  5142. m:=red_TopInterreduce m;
  5143. if !*red_total then m:=red_Straight m; % Tail reduction :
  5144. return m;
  5145. end;
  5146. endmodule; % red
  5147. end;
  5148. module res;
  5149. COMMENT
  5150. ######################
  5151. ### ###
  5152. ### RESOLUTIONS ###
  5153. ### ###
  5154. ######################
  5155. This module contains algorithms on complexes, i.e. chains of modules
  5156. (submodules of free modules represented as im f of certain dpmat's).
  5157. A chain (in particular a resolution) is a list of dpmat's with the
  5158. usual annihilation property of subsequent dpmat's.
  5159. This module contains
  5160. - An algorithm to compute a minimal resolution of a dpmat,
  5161. - the same for a local dpmat.
  5162. - the extraction of the (graded) Betti numbers from a
  5163. resolution.
  5164. This module is just under development.
  5165. END COMMENT;
  5166. % ------------- Minimal resolutions --------------
  5167. symbolic procedure Resolve!*(m,d);
  5168. % Compute a minimal resolution of the dpmat m, i.e. a list of dpmat's
  5169. % (s0 s1 s2 ...), where sk is the k-th syzygy module of m, upto the
  5170. % d'th part.
  5171. (begin scalar a,u;
  5172. if dpmat_cols m=0 then
  5173. << cali!=degrees:=nil; m:=ideal2mat!* m>>
  5174. else cali!=degrees:=dpmat_coldegs m;
  5175. a:=list(m); u:=syzygies!* m;
  5176. while (not dpmat_zero!? u)and(d>1) do
  5177. << m:=u; u:=syzygies!* m; d:=d-1;
  5178. u:=groeb_minimize(m,u); m:=car u; u:=cdr u; a:=m . a;
  5179. >>;
  5180. return reversip (u.a);
  5181. end) where cali!=degrees:=cali!=degrees;
  5182. % ----------------- The Betti numbers -------------
  5183. symbolic procedure bettiNumbers!* c;
  5184. % Returns the list of Betti numbers of the chain c.
  5185. for each x in c collect dpmat_cols x;
  5186. symbolic procedure gradedBettiNumbers!* c;
  5187. % Returns the list of degree lists (according to the ecart) of the
  5188. % generators of the chain c.
  5189. for each x in c collect
  5190. begin scalar i,d; d:=dpmat_coldegs x;
  5191. return
  5192. if d then sort(for each y in d collect mo_ecart cdr y,'leq)
  5193. else for i:=1:dpmat_cols x collect 0;
  5194. end;
  5195. endmodule; % res
  5196. end;
  5197. module ring;
  5198. COMMENT
  5199. ##################
  5200. ## ##
  5201. ## RINGS ##
  5202. ## ##
  5203. ##################
  5204. Informal syntax :
  5205. Ring = ('RING (name list) ((degree list list)) deg_type ecart)
  5206. with deg_type = 'lex or 'revlex.
  5207. The term order is defined at first comparing successively degrees and
  5208. then by the name list lex. or revlex. For details consult the manual.
  5209. (name list) contains a phantom name cali!=mk for the module
  5210. component, see below in module mo.
  5211. The variable cali!=basering contains the actual base ring.
  5212. The ecart is a list of positive integers (the ecart vector for the
  5213. given ring) and has
  5214. length = length names cali!=basering.
  5215. It is used in several places for optimal strategies (noetherina term
  5216. orders ) or to guarantee termination (local term orders).
  5217. All homogenizations are executed with respect to that list.
  5218. END COMMENT;
  5219. symbolic procedure ring_define(n,to1,type,ecart);
  5220. list('ring,'cali!=mk . n, to1, type,ecart);
  5221. symbolic procedure setring!* c;
  5222. begin
  5223. if !*noetherian and not ring_isnoetherian c then
  5224. rederr"term order is not noetherian";
  5225. cali!=basering:=c;
  5226. setkorder ring_all_names c;
  5227. return c;
  5228. end;
  5229. symbolic procedure setecart!* e;
  5230. begin scalar r; r:=cali!=basering;
  5231. if not ring_checkecart(e,ring_names r) then
  5232. typerr(e,"ecart vector")
  5233. else cali!=basering:=
  5234. ring_define(ring_names r,ring_degrees r,ring_tag r,e)
  5235. end;
  5236. symbolic procedure ring_2a c;
  5237. makelist {makelist ring_names c,
  5238. makelist for each x in ring_degrees c collect makelist x,
  5239. ring_tag c, makelist ring_ecart c};
  5240. symbolic procedure ring_from_a u;
  5241. begin scalar vars,tord,c,r,tag,ecart;
  5242. if not eqcar(u,'list) then typerr(u,"ring") else u:=cdr u;
  5243. vars:=reval car u; tord:=reval cadr u; tag:=reval caddr u;
  5244. if length u=4 then ecart:=reval cadddr u;
  5245. if not(tag memq '(lex revlex)) then typerr(tag,"term order tag");
  5246. if not eqcar(vars,'list) then typerr(vars,"variable list")
  5247. else vars:=cdr vars;
  5248. if tord={'list} then c:=nil
  5249. else if not (c:=ring!=testtord(vars,tord)) then
  5250. typerr(tord,"term order degrees");
  5251. if null ecart then
  5252. if (null tord)or not ring_checkecart(car tord,vars) then
  5253. ecart:=for each x in vars collect 1
  5254. else ecart:=car tord
  5255. else if not ring_checkecart(cdr ecart,vars) then
  5256. typerr(ecart,"ecart list")
  5257. else ecart:=cdr ecart;
  5258. r:=ring_define(vars,c,tag,ecart);
  5259. if !*noetherian and not(ring_isnoetherian r) then
  5260. rederr"Term order is non noetherian";
  5261. return r
  5262. end;
  5263. symbolic procedure ring!=testtord(vars,u);
  5264. % Test the non empty term order degrees for consistency and return
  5265. % the symbolic equivalent of u.
  5266. if (ring!=lengthtest(cdr u,length vars +1)
  5267. and ring!=contenttest cdr u)
  5268. then for each x in cdr u collect cdr x
  5269. else nil;
  5270. symbolic procedure ring!=lengthtest(m,v);
  5271. % Test, whether m is a list of (algebraic) lists of the length v.
  5272. if null m then t
  5273. else eqcar(car m,'list)
  5274. and (length car m = v)
  5275. and ring!=lengthtest(cdr m,v);
  5276. symbolic procedure ring!=contenttest m;
  5277. % Test, whether m is a list of (algebraic) number lists.
  5278. if null m then t
  5279. else numberlistp cdar m and ring!=contenttest cdr m;
  5280. symbolic procedure ring_names r; % User names only
  5281. cdadr r;
  5282. symbolic procedure ring_all_names r; cadr r; % All names
  5283. symbolic procedure ring_degrees r; caddr r;
  5284. symbolic procedure ring_tag r; cadddr r;
  5285. symbolic procedure ring_ecart r; nth(r,5);
  5286. % --- Test the term order for the chain condition ------
  5287. symbolic procedure ring!=trans d;
  5288. % Transpose the degree matrix.
  5289. if (null d)or(null car d) then nil
  5290. else (for each x in d collect car x) .
  5291. ring!=trans(for each x in d collect cdr x);
  5292. symbolic procedure ring!=testlex d;
  5293. if null d then t
  5294. else ring!=testlex1(car d) and ring!=testlex(cdr d);
  5295. symbolic procedure ring!=testlex1 d;
  5296. if null d then t
  5297. else if car d=0 then ring!=testlex1(cdr d)
  5298. else (car d>0);
  5299. symbolic procedure ring!=testrevlex d;
  5300. if null d then t
  5301. else ring!=testrevlex1(car d) and ring!=testrevlex(cdr d);
  5302. symbolic procedure ring!=testrevlex1 d;
  5303. if null d then nil
  5304. else if car d=0 then ring!=testrevlex1(cdr d)
  5305. else (car d>0);
  5306. symbolic procedure ring_isnoetherian r;
  5307. % Test, whether the term order of the ring r satisfies the chain
  5308. % condition.
  5309. if ring_tag r ='revlex then
  5310. ring!=testrevlex ring!=trans ring_degrees r
  5311. else ring!=testlex ring!=trans ring_degrees r;
  5312. symbolic procedure ring!=degpos d;
  5313. if null d then t
  5314. else (car d>0) and ring!=degpos cdr d;
  5315. symbolic procedure ring_checkecart(e,vars);
  5316. (length e=length vars) and ring!=degpos e;
  5317. % ---- Test noetherianity switching noetherian on :
  5318. put('noetherian,'simpfg,'((t (ring!=test))));
  5319. symbolic procedure ring!=test;
  5320. if not ring_isnoetherian cali!=basering then
  5321. << !*noetherian:=nil;
  5322. rederr"Current term order is not noetherian"
  5323. >>;
  5324. % ---- Different term orders -------------
  5325. symbolic operator eliminationorder;
  5326. symbolic procedure eliminationorder(v1,v2);
  5327. % Elimination order : v1 = all variables; v2 = variables to eliminate.
  5328. if !*mode='algebraic then
  5329. makelist for each x in
  5330. eliminationorder!*(cdr reval v1,cdr reval v2)
  5331. collect makelist x
  5332. else eliminationorder!*(v1,v2);
  5333. symbolic operator degreeorder;
  5334. symbolic procedure degreeorder(vars);
  5335. if !*mode='algebraic then
  5336. makelist for each x in degreeorder!*(cdr reval vars) collect
  5337. makelist x
  5338. else degreeorder!*(vars);
  5339. symbolic operator localorder;
  5340. symbolic procedure localorder(vars);
  5341. if !*mode='algebraic then
  5342. makelist for each x in localorder!*(cdr reval vars) collect
  5343. makelist x
  5344. else localorder!*(vars);
  5345. symbolic operator blockorder;
  5346. symbolic procedure blockorder(v1,v2);
  5347. if !*mode='algebraic then
  5348. makelist for each x in
  5349. blockorder!*(cdr reval v1,cdr reval v2)
  5350. collect makelist x
  5351. else blockorder!*(v1,v2);
  5352. symbolic procedure blockorder!*(vars,l);
  5353. % l is a list of integers, that sum up to |vars|.
  5354. % Returns the degree vector for the corresponding block order.
  5355. if neq(for each x in l sum x,length vars) then
  5356. rederr"block lengths sum doesn't match variable number"
  5357. else begin scalar u; integer pre,post;
  5358. pre:=0; post:=length vars;
  5359. for each x in l do
  5360. << u:=(append(append(for i:=1:pre collect 0,for i:=1:x collect 1),
  5361. for i:=1:post-x collect 0)) . u;
  5362. pre:=pre+x; post:=post-x
  5363. >>;
  5364. return reversip u;
  5365. end;
  5366. symbolic procedure eliminationorder!*(v1,v2);
  5367. % Elimination order : v1 = all variables
  5368. % v2 = variables to eliminate.
  5369. { for each x in v1 collect
  5370. if x member v2 then 1 else 0,
  5371. for each x in v1 collect
  5372. if x member v2 then 0 else 1};
  5373. symbolic procedure degreeorder!*(vars);
  5374. {for each x in vars collect 1};
  5375. symbolic procedure localorder!*(vars);
  5376. {for each x in vars collect -1};
  5377. % ---------- Ring constructors -----------------
  5378. symbolic procedure ring_rlp(r,u);
  5379. % u is a subset of ring_names r. Returns the ring r with the block order
  5380. % "first degrevlex on u, then the order on r"
  5381. ring_define(ring_names r,
  5382. (for each x in ring_names r collect if x member u then 1 else 0)
  5383. . append(reverse for each x in u collect
  5384. for each y in ring_names r collect if x=y then -1 else 0,
  5385. ring_degrees r), ring_tag r, ring_ecart r);
  5386. symbolic procedure ring_lp(r,u);
  5387. % u is a subset of ring_names r. Returns the ring r with the block order
  5388. % "first lex on u, then the order on r"
  5389. ring_define(ring_names r,
  5390. append(for each x in u collect for each y in ring_names r collect
  5391. if x=y then 1 else 0, ring_degrees r),
  5392. ring_tag r, ring_ecart r);
  5393. symbolic procedure ring_sum(a,b);
  5394. % Returns the direct sum of two base rings with degree matrix at
  5395. % first b then a and ecart=appended ecart lists.
  5396. begin scalar vars,zeroa,zerob,degs,ecart;
  5397. if not disjoint(ring_names a,ring_names b) then
  5398. rederr"RINGSUM only for disjoint variable sets";
  5399. vars:=append(ring_names a,ring_names b);
  5400. ecart:=append(ring_ecart a,ring_ecart b);
  5401. zeroa:=for each x in ring_names a collect 0;
  5402. zerob:=for each x in ring_names b collect 0;
  5403. degs:=append(
  5404. for each x in ring_degrees b collect append(zeroa,x),
  5405. for each x in ring_degrees a collect append(x,zerob));
  5406. return ring_define(vars, degs, ring_tag a,ecart);
  5407. end;
  5408. % --------- First initialization :
  5409. setring!* ring_define('(t x y z),'((1 1 1 1)),'revlex,'(1 1 1 1));
  5410. !*noetherian:=t;
  5411. % -------- End of first initialization ----------------
  5412. endmodule; % ring
  5413. end;
  5414. module scripts;
  5415. COMMENT
  5416. ######################
  5417. ## ##
  5418. ## ADVANCED ##
  5419. ## APPLICATIONS ##
  5420. ## ##
  5421. ######################
  5422. This module contains several additional advanced applications of
  5423. standard basis computations, inspired partly by the scripts
  5424. distributed with the commutative algebra package MACAULAY
  5425. (Bayer/Stillman/Eisenbud).
  5426. The following topics are currently covered :
  5427. - [BGK]'s heuristic variable optimization
  5428. - certain stuff on maps (preimage, ratpreimage)
  5429. - ideals of points (in affine and proj. spaces)
  5430. - ideals of (affine and proj.) monomial curves
  5431. - General Rees rings, associated graded rings, and related
  5432. topics (analytic spread, symmetric algebra)
  5433. - several short scripts (minimal generators, symbolic powers
  5434. of primes, singular locus)
  5435. END COMMENT;
  5436. %---------- [BGK]'s heuristic variable optimization ----------
  5437. symbolic operator varopt;
  5438. symbolic procedure varopt m;
  5439. if !*mode='algebraic then makelist varopt!* dpmat_from_a m
  5440. else varopt!* m;
  5441. symbolic procedure varopt!* m;
  5442. % Find a heuristically optimal variable order.
  5443. begin scalar c; c:=mo_zero();
  5444. for each x in dpmat_list m do
  5445. for each y in bas_dpoly x do c:=mo_lcm(c,car y);
  5446. return
  5447. for each x in
  5448. sort(mo_2list c,function(lambda(x,y); cdr x>cdr y)) collect
  5449. car x;
  5450. end;
  5451. % ----- Certain stuff on maps -------------
  5452. % A ring map is represented as a list
  5453. % {preimage_ring, image_ring, subst_list},
  5454. % where subst_list is a substitution list {v1=ex1,v2=ex2,...} in
  5455. % algebraic prefix form, i.e. looks like (list (equal var image) ...)
  5456. symbolic operator preimage;
  5457. symbolic procedure preimage(m,map);
  5458. % Compute the preimage of an ideal m under a (polynomial) ring map.
  5459. if !*mode='algebraic then
  5460. begin map:=cdr reval map;
  5461. return preimage!*(reval m,
  5462. {ring_from_a first map, ring_from_a second map, third map});
  5463. end
  5464. else preimage!*(m,map);
  5465. symbolic procedure preimage!*(m,map);
  5466. % m and the result are given and returned in algebraic prefix form.
  5467. if not !*noetherian then
  5468. rederr"PREIMAGE only for noetherian term orders"
  5469. else begin scalar u,oldring,newring,oldnames;
  5470. if not eqcar(m,'list) then rederr"PREIMAGE only for ideals";
  5471. oldring:=first map; newring:=second map;
  5472. oldnames:=ring_names oldring;
  5473. setring!* ring_sum(newring,oldring);
  5474. u:=bas_renumber for each x in cdr third map collect
  5475. << if not member(second x,oldnames) then
  5476. typerr(second x,"var. name");
  5477. bas_make(0,dp_diff(dp_from_a second x,dp_from_a third x))
  5478. >>;
  5479. m:=matsum!* {dpmat_from_a m,dpmat_make(length u,0,u,nil,nil)};
  5480. m:=dpmat_2a eliminate!*(m,ring_names newring);
  5481. setring!* oldring;
  5482. return m;
  5483. end;
  5484. symbolic operator ratpreimage;
  5485. symbolic procedure ratpreimage(m,map);
  5486. % Compute the preimage of an ideal m under a rational ring map.
  5487. if !*mode='algebraic then
  5488. begin map:=cdr reval map;
  5489. return ratpreimage!*(reval m,
  5490. {ring_from_a first map, ring_from_a second map, third map});
  5491. end
  5492. else ratpreimage!*(m,map);
  5493. symbolic procedure ratpreimage!*(m,map);
  5494. % m and the result are given and returned in algebraic prefix form.
  5495. if not !*noetherian then
  5496. rederr"RATPREIMAGE only for noetherian term orders"
  5497. else begin scalar u,oldring,newnames,oldnames,f,g,v,g0;
  5498. if not eqcar(m,'list) then rederr"RATPREIMAGE only for ideals";
  5499. oldring:=first map; v:=gensym();
  5500. newnames:=v . ring_names second map;
  5501. oldnames:=ring_names oldring; u:=append(oldnames,newnames);
  5502. setring!* ring_define(u,nil,'lex,for each x in u collect 1);
  5503. g0:=dp_fi 1;
  5504. u:=bas_renumber for each x in cdr third map collect
  5505. << if not member(second x,oldnames) then
  5506. typerr(second x,"var. name");
  5507. f:=simp third x; g:=dp_from_a prepf denr f;
  5508. f:=dp_from_a prepf numr f; g0:=dp_prod(g,g0);
  5509. bas_make(0,dp_diff(dp_prod(g,dp_from_a second x),f))
  5510. >>;
  5511. u:=bas_make(0,dp_diff(dp_prod(g0,dp_from_a v),dp_fi 1)) . u;
  5512. m:=matsum!* {dpmat_from_a m,dpmat_make(length u,0,u,nil,nil)};
  5513. m:=dpmat_2a eliminate!*(m,newnames);
  5514. setring!* oldring;
  5515. return m;
  5516. end;
  5517. % ---- The ideals of affine resp. proj. points. The old stuff, but the
  5518. % ---- algebraic interface now uses the linear algebra approach.
  5519. symbolic procedure affine_points1!* m;
  5520. begin scalar names;
  5521. if length(names:=ring_names cali!=basering) neq length cadr m then
  5522. typerr(m,"coordinate matrix");
  5523. m:=for each x in cdr m collect
  5524. 'list . for each y in pair(names,x) collect
  5525. {'plus,car y,{'minus,reval cdr y}};
  5526. m:=for each x in m collect dpmat_from_a x;
  5527. m:=matintersect!* m;
  5528. return m;
  5529. end;
  5530. symbolic procedure scripts!=ideal u;
  5531. 'list . for each x in cali_choose(u,2) collect
  5532. {'plus,{'times, car first x,cdr second x},
  5533. {'minus,{'times, car second x,cdr first x}}};
  5534. symbolic procedure proj_points1!* m;
  5535. begin scalar names;
  5536. if length(names:=ring_names cali!=basering) neq length cadr m then
  5537. typerr(m,"coordinate matrix");
  5538. m:=for each x in cdr m collect scripts!=ideal pair(names,x);
  5539. m:=for each x in m collect interreduce!* dpmat_from_a x;
  5540. m:=matintersect!* m;
  5541. return m;
  5542. end;
  5543. % ----- Affine and proj. monomial curves ------------
  5544. symbolic operator affine_monomial_curve;
  5545. symbolic procedure affine_monomial_curve(l,R);
  5546. % l is a list of integers, R contains length l ring var. names.
  5547. % Returns the generators of the monomial curve (t^i : i\in l) in R.
  5548. if !*mode='algebraic then
  5549. dpmat_2a affine_monomial_curve!*(cdr reval l,cdr reval R)
  5550. else affine_monomial_curve!*(l,R);
  5551. symbolic procedure affine_monomial_curve!*(l,R);
  5552. if not numberlistp l then typerr(l,"number list")
  5553. else if length l neq length R then
  5554. rederr"number of variables doesn't match"
  5555. else begin scalar u,t0,v;
  5556. v:=list gensym();
  5557. r:=ring_define(r,{l},'revlex,l);
  5558. setring!* ring_sum(r,ring_define(v,degreeorder!* v,'lex,'(1)));
  5559. t0:=dp_from_a car v;
  5560. u:=bas_renumber for each x in pair(l,ring_names r) collect
  5561. bas_make(0,dp_diff(dp_from_a cdr x,dp_power(t0,car x)));
  5562. u:=dpmat_make(length u,0,u,nil,nil);
  5563. u:=(eliminate!*(u,v) where cali!=monset=ring_names cali!=basering);
  5564. setring!* r;
  5565. return dpmat_neworder(u,dpmat_gbtag u);
  5566. end;
  5567. symbolic operator proj_monomial_curve;
  5568. symbolic procedure proj_monomial_curve(l,R);
  5569. % l is a list of integers, R contains length l ring var. names.
  5570. % Returns the generators of the monomial curve
  5571. % (s^(d-i)*t^i : i\in l) in R where d = max { x : x \in l}
  5572. if !*mode='algebraic then
  5573. dpmat_2a proj_monomial_curve!*(cdr reval l,cdr reval R)
  5574. else proj_monomial_curve!*(l,R);
  5575. symbolic procedure proj_monomial_curve!*(l,R);
  5576. if not numberlistp l then typerr(l,"number list")
  5577. else if length l neq length R then
  5578. rederr"number of variables doesn't match"
  5579. else begin scalar u,t0,t1,v,d;
  5580. t0:=gensym(); t1:=gensym(); v:={t0,t1};
  5581. d:=listexpand(function max2,l);
  5582. r:=ring_define(r,degreeorder!* r,'revlex,for each x in r collect 1);
  5583. setring!* ring_sum(r,ring_define(v,degreeorder!* v,'lex,'(1 1)));
  5584. t0:=dp_from_a t0; t1:=dp_from_a t1;
  5585. u:=bas_renumber for each x in pair(l,ring_names r) collect
  5586. bas_make(0,dp_diff(dp_from_a cdr x,
  5587. dp_prod(dp_power(t0,car x),dp_power(t1,d-car x))));
  5588. u:=dpmat_make(length u,0,u,nil,nil);
  5589. u:=(eliminate!*(u,v) where cali!=monset=ring_names cali!=basering);
  5590. setring!* r;
  5591. return dpmat_neworder(u,dpmat_gbtag u);
  5592. end;
  5593. % -- General Rees rings, associated graded rings, and related topics --
  5594. symbolic operator blowup;
  5595. symbolic procedure blowup(m,n,vars);
  5596. % vars is a list of var. names for the ring R
  5597. % of the same length as dpmat_list n.
  5598. % Returns an ideal J such that (S+R)/J == S/M [ N.t ]
  5599. % ( with S = the current ring )
  5600. % is the blow up ring of the ideal N over S/M.
  5601. % (S+R) is the new current ring.
  5602. if !*mode='algebraic then
  5603. dpmat_2a blowup!*(dpmat_from_a reval m,dpmat_from_a reval n,
  5604. cdr reval vars)
  5605. else blowup!*(M,N,vars);
  5606. symbolic procedure blowup!*(M,N,vars);
  5607. if (dpmat_cols m > 0)or(dpmat_cols n > 0) then
  5608. rederr"BLOWUP defined only for ideals"
  5609. else if not !*noetherian then
  5610. rederr"BLOWUP only for noetherian term orders"
  5611. else begin scalar u,s,t0,v,r1;
  5612. if length vars neq dpmat_rows n then
  5613. rederr {"ring must have",dpmat_rows n,"variables"};
  5614. u:=for each x in dpmat_rowdegrees n collect mo_ecart cdr x;
  5615. r1:=ring_define(vars,list u,'revlex,u);
  5616. s:=ring_sum(cali!=basering,r1); v:=list(gensym());
  5617. setring!* ring_sum(s,ring_define(v,degreeorder!* v,'lex,'(1)));
  5618. t0:=dp_from_a car v;
  5619. n:=for each x in
  5620. pair(vars,for each y in dpmat_list n collect bas_dpoly y)
  5621. collect dp_diff(dp_from_a car x,
  5622. dp_prod(dp_neworder cdr x,t0));
  5623. m:=bas_renumber append(bas_neworder dpmat_list m,
  5624. for each x in n collect bas_make(0,x));
  5625. m:=(eliminate!*(interreduce!* dpmat_make(length m,0,m,nil,nil),v)
  5626. where cali!=monset=nil);
  5627. setring!* s;
  5628. return dpmat_neworder(m,dpmat_gbtag m);
  5629. end;
  5630. symbolic operator assgrad;
  5631. symbolic procedure assgrad(m,n,vars);
  5632. % vars is a list of var. names for the ring T
  5633. % of the same length as dpmat_list n.
  5634. % Returns an ideal J such that (S+T)/J == (R/N + N/N^2 + ... )
  5635. % ( with R=S/M and S the current ring )
  5636. % is the associated graded ring of the ideal N over R.
  5637. % (S+T) is the new current ring.
  5638. if !*mode='algebraic then
  5639. dpmat_2a assgrad!*(dpmat_from_a reval m,dpmat_from_a reval n,
  5640. cdr reval vars)
  5641. else assgrad!*(M,N,vars);
  5642. symbolic procedure assgrad!*(M,N,vars);
  5643. if (dpmat_cols m > 0)or(dpmat_cols n > 0) then
  5644. rederr"ASSGRAD defined only for ideals"
  5645. else begin scalar u;
  5646. u:=blowup!*(m,n,vars);
  5647. return matsum!* {u,dpmat_neworder(n,nil)};
  5648. end;
  5649. symbolic operator analytic_spread;
  5650. symbolic procedure analytic_spread m;
  5651. % Returns the analytic spread of the ideal m.
  5652. if !*mode='algebraic then analytic_spread!* dpmat_from_a reval m
  5653. else analytic_spread!* m;
  5654. symbolic procedure analytic_spread!* m;
  5655. if (dpmat_cols m>0) then rederr"ANALYTIC SPREAD only for ideals"
  5656. else (begin scalar r,m1,vars;
  5657. r:=ring_names cali!=basering;
  5658. vars:=for each x in dpmat_list m collect gensym();
  5659. m1:=blowup!*(dpmat_from_dpoly nil,m,vars);
  5660. return dim!* gbasis!* matsum!*{m1,dpmat_from_a('list . r)};
  5661. end) where cali!=basering=cali!=basering;
  5662. symbolic operator sym;
  5663. symbolic procedure sym(M,vars);
  5664. % vars is a list of var. names for the ring R
  5665. % of the same length as dpmat_list M.
  5666. % Returns an ideal J such that (S+R)/J == Sym(M)
  5667. % ( with S = the current ring )
  5668. % is the symmetric algebra of M over S.
  5669. % (S+R) is the new current ring.
  5670. if !*mode='algebraic then
  5671. dpmat_2a sym!*(dpmat_from_a M,cdr reval vars)
  5672. else sym!*(m,vars);
  5673. symbolic procedure sym!*(m,vars);
  5674. % The symmetric algebra of the dpmat m.
  5675. if not !*noetherian then
  5676. rederr"SYM only for noetherian term orders"
  5677. else begin scalar n,u,r1;
  5678. if length vars neq dpmat_rows m then
  5679. rederr {"ring must have",dpmat_rows m,"variables"};
  5680. cali!=degrees:=dpmat_coldegs m;
  5681. u:=for each x in dpmat_rowdegrees m collect mo_ecart cdr x;
  5682. r1:=ring_define(vars,list u,'revlex,u); n:=syzygies!* m;
  5683. setring!* ring_sum(cali!=basering,r1);
  5684. return mat2list!* interreduce!*
  5685. dpmat_mult(dpmat_neworder(n,nil),
  5686. ideal2mat!* dpmat_from_a('list . vars));
  5687. end;
  5688. % ----- Several short scripts ----------
  5689. % ------ Minimal generators of an ideal or module.
  5690. symbolic operator minimal_generators;
  5691. symbolic procedure minimal_generators m;
  5692. if !*mode='algebraic then
  5693. dpmat_2a minimal_generators!* dpmat_from_a reval m
  5694. else minimal_generators!* m;
  5695. symbolic procedure minimal_generators!* m;
  5696. car groeb_minimize(m,syzygies!* m);
  5697. % ------- Symbolic powers of prime (or unmixed) ideals
  5698. symbolic operator symbolic_power;
  5699. symbolic procedure symbolic_power(m,d);
  5700. if !*mode='algebraic then
  5701. dpmat_2a symbolic_power!*(dpmat_from_a m,reval d)
  5702. else symbolic_power!*(m,d);
  5703. symbolic procedure symbolic_power!*(m,d);
  5704. eqhull!* idealpower!*(m,d);
  5705. % ---- non zero divisor property -----------
  5706. put('nzdp,'psopfn,'scripts!=nzdp);
  5707. symbolic procedure scripts!=nzdp m;
  5708. if length m neq 2 then rederr"Syntax : nzdp(dpoly,dpmat)"
  5709. else begin scalar f,b;
  5710. f:=reval car m; intf_get second m;
  5711. if null(b:=get(second m,'gbasis)) then
  5712. put(second m,'gbasis,b:=gbasis!* get(second m,'basis));
  5713. return if nzdp!*(dp_from_a f,b) then 'yes else 'no;
  5714. end;
  5715. symbolic procedure nzdp!*(f,m);
  5716. % Test dpoly f for a non zero divisor on coker m. m must be a gbasis.
  5717. submodulep!*(matqquot!*(m,f),m);
  5718. endmodule; % scripts
  5719. end;
  5720. module triang;
  5721. COMMENT
  5722. ##########################################
  5723. ## ##
  5724. ## Solving zerodimensional systems ##
  5725. ## Triangular systems ##
  5726. ## ##
  5727. ##########################################
  5728. Zerosolve returns lists of dpmats in prefix form, that consist of
  5729. triangular systems in the sense of Lazard, provided the input is
  5730. radical. For the corresponding definitions and concepts see
  5731. [Lazard] D. Lazard: Solving zero dimensional algebraic systems.
  5732. J. Symb. Comp. 13 (1992), 117 - 131.
  5733. and
  5734. [EFGB] H.-G. Graebe: Triangular systems and factorized Groebner
  5735. bases. Report Nr. 7 (1995), Inst. f. Informatik,
  5736. Univ. Leipzig.
  5737. The triangularization of zerodim. ideal bases is done by Moeller's
  5738. approach, see
  5739. [Moeller] H.-M. Moeller : On decomposing systems of polynomial
  5740. equations with finitely many solutions.
  5741. J. AAECC 4 (1993), 217 - 230.
  5742. We present three implementations :
  5743. -- the pure lex gb (zerosolve)
  5744. -- the "slow turn to pure lex" (zerosolve1)
  5745. and
  5746. -- the mix with [FGLM] (zerosolve2)
  5747. END COMMENT;
  5748. symbolic procedure triang!=trsort(a,b);
  5749. mo_dlexcomp(dp_lmon a,dp_lmon b);
  5750. symbolic procedure triang!=makedpmat x;
  5751. makelist for each p in x collect dp_2a p;
  5752. % =================================================================
  5753. % The pure lex approach.
  5754. symbolic operator zerosolve;
  5755. symbolic procedure zerosolve m;
  5756. if !*mode='algebraic then makelist zerosolve!* dpmat_from_a m
  5757. else zerosolve!* m;
  5758. symbolic procedure zerosolve!* m;
  5759. % Solve a zerodimensional dpmat ideal m, first groebfactor it and then
  5760. % triangularize it. Returns a list of dpmats in prefix form.
  5761. if (dpmat_cols m>0) or (dim!* m>0) then
  5762. rederr"ZEROSOLVE only for zerodimensional ideals"
  5763. else if not !*noetherian or ring_degrees cali!=basering then
  5764. rederr"ZEROSOLVE only for pure lex. term orders"
  5765. else for each x in groebfactor!*(m,nil) join triang_triang car x;
  5766. symbolic procedure triang_triang m;
  5767. % m must be a zerodim. ideal gbasis (recommended to be radical)
  5768. % wrt. a pure lex term order.
  5769. % Returns a list l of dpmats in triangular form.
  5770. if (dpmat_cols m>0) or (dim!* m>0) then
  5771. rederr"Triangularization only for zerodimensional ideals"
  5772. else if not !*noetherian or ring_degrees cali!=basering then
  5773. rederr"Triangularization only for pure lex. term orders"
  5774. else for each x in triang!=triang(m,ring_names cali!=basering) collect
  5775. triang!=makedpmat x;
  5776. symbolic procedure triang!=triang(A,vars);
  5777. % triang!=triang(A,vars)={f1.x for x in triang!=triang(B,cdr vars)}
  5778. % \union triang!=triang(A:<B>,vars)
  5779. % where A={f1,...,fr}, B={f2~,...fr~}, see [Moeller].
  5780. % Returns a list of polynomial lists.
  5781. if dpmat_unitideal!? A then nil
  5782. else begin scalar x,f1,m1,m2,B;
  5783. x:=car vars;
  5784. m1:=sort(for each x in dpmat_list A collect bas_dpoly x,
  5785. function triang!=trsort);
  5786. if length m1 = length vars then return {m1};
  5787. f1:=car m1;
  5788. m2:=for each y in cdr m1 collect bas_make(1,dp_xlt(y,x));
  5789. B:=interreduce!* dpmat_make(length m2,0,m2,nil,nil);
  5790. return append(
  5791. for each u in triang!=triang(B,cdr vars) collect (f1 . u),
  5792. triang!=triang(matstabquot!*(A,B),vars));
  5793. end;
  5794. % =================================================================
  5795. % Triangularization wrt. an arbitrary term order
  5796. symbolic operator zerosolve1;
  5797. symbolic procedure zerosolve1 m;
  5798. if !*mode='algebraic then makelist zerosolve1!* dpmat_from_a m
  5799. else zerosolve1!* m;
  5800. symbolic procedure zerosolve1!* m;
  5801. for each x in groebfactor!*(m,nil) join triang_triang1 car x;
  5802. symbolic procedure triang_triang1 m;
  5803. % m must be a zerodim. ideal gbasis (recommended to be radical)
  5804. % Returns a list l of dpmats in triangular form.
  5805. if (dpmat_cols m>0) or (dim!* m>0) then
  5806. rederr"Triangularization only for zerodimensional ideals"
  5807. else if not !*noetherian then
  5808. rederr"Triangularization only for noetherian term orders"
  5809. else for each x in triang!=triang1(m,ring_names cali!=basering) collect
  5810. triang!=makedpmat x;
  5811. symbolic procedure triang!=triang1(A,vars);
  5812. % triang!=triang(A,vars)={f1.x for x in triang!=triang1(B,cdr vars)}
  5813. % \union triang!=triang1(A:<B>,vars)
  5814. % where A={f1,...,fr}, B={f2~,...fr~}, see [Moeller].
  5815. % Returns a list of polynomial lists.
  5816. if dpmat_unitideal!? A then nil
  5817. else if length vars = 1 then {{bas_dpoly first dpmat_list A}}
  5818. else (begin scalar u,x,f1,m1,m2,B,vars1,res;
  5819. x:=car vars; vars1:=ring_names cali!=basering;
  5820. setring!* ring_define(vars1,eliminationorder!*(vars1,{x}),
  5821. 'revlex,ring_ecart cali!=basering);
  5822. a:=groebfactor!*(dpmat_neworder(a,nil),nil);
  5823. % Constraints in dimension zero may be skipped :
  5824. a:=for each x in a collect car x;
  5825. for each u in a do
  5826. << m1:=sort(for each x in dpmat_list u collect bas_dpoly x,
  5827. function triang!=trsort);
  5828. f1:=car m1;
  5829. m2:=for each y in cdr m1 collect bas_make(1,dp_xlt(y,x));
  5830. B:=interreduce!* dpmat_make(length m2,0,m2,nil,nil);
  5831. res:=nconc(append(
  5832. for each v in triang!=triang1(B,cdr vars) collect (f1 . v),
  5833. triang!=triang1a(matstabquot!*(u,B),vars)),res);
  5834. >>;
  5835. return res;
  5836. end) where cali!=basering=cali!=basering;
  5837. symbolic procedure triang!=triang1a(A,vars);
  5838. % triang!=triang(A,vars)={f1.x for x in triang!=triang1(B,cdr vars)}
  5839. % \union triang!=triang1(A:<B>,vars)
  5840. % where A is already a gr basis wrt. the elimination order.
  5841. % Returns a list of polynomial lists.
  5842. if dpmat_unitideal!? A then nil
  5843. else if length vars = 1 then {{bas_dpoly first dpmat_list A}}
  5844. else begin scalar u,x,f1,m1,m2,B;
  5845. x:=car vars;
  5846. m1:=sort(for each x in dpmat_list a collect bas_dpoly x,
  5847. function triang!=trsort);
  5848. f1:=car m1;
  5849. m2:=for each y in cdr m1 collect bas_make(1,dp_xlt(y,x));
  5850. B:=interreduce!* dpmat_make(length m2,0,m2,nil,nil);
  5851. return append(
  5852. for each u in triang!=triang1(B,cdr vars) collect (f1 . u),
  5853. triang!=triang1a(matstabquot!*(A,B),vars));
  5854. end;
  5855. % =================================================================
  5856. % Triangularization wrt. an arbitrary term order and FGLM approach.
  5857. symbolic operator zerosolve2;
  5858. symbolic procedure zerosolve2 m;
  5859. if !*mode='algebraic then makelist zerosolve2!* dpmat_from_a m
  5860. else zerosolve2!* m;
  5861. symbolic procedure zerosolve2!* m;
  5862. % Solve a zerodimensional dpmat ideal m, first groebfactoring it and
  5863. % secondly triangularizing it.
  5864. for each x in groebfactor!*(m,nil) join triang_triang2 car x;
  5865. symbolic procedure triang_triang2 m;
  5866. % m must be a zerodim. ideal gbasis (recommended to be radical)
  5867. % Returns a list l of dpmats in triangular form.
  5868. if (dpmat_cols m>0) or (dim!* m>0) then
  5869. rederr"Triangularization only for zerodimensional ideals"
  5870. else if not !*noetherian then
  5871. rederr"Triangularization only for noetherian term orders"
  5872. else for each x in triang!=triang2(m,ring_names cali!=basering)
  5873. collect triang!=makedpmat x;
  5874. symbolic procedure triang!=triang2(A,vars);
  5875. % triang!=triang(A,vars)={f1.x for x in triang!=triang2(B,cdr vars)}
  5876. % \union triang!=triang2(A:<B>,vars)
  5877. % where A={f1,...,fr}, B={f2~,...fr~}, see [Moeller].
  5878. % Returns a list of polynomial lists.
  5879. if dpmat_unitideal!? A then nil
  5880. else if length vars = 1 then {{bas_dpoly first dpmat_list A}}
  5881. else (begin scalar u,x,f1,m1,m2,B,vars1,vars2,extravars,res,c1;
  5882. x:=car vars; vars1:=ring_names cali!=basering;
  5883. extravars:=dpmat_from_a('list . (vars2:=setdiff(vars1,vars)));
  5884. % We need this to make A truely zerodimensional.
  5885. c1:=ring_define(vars1,eliminationorder!*(vars1,{x}),
  5886. 'revlex,ring_ecart cali!=basering);
  5887. a:=matsum!* {extravars,a};
  5888. u:=change_termorder!*(a,c1);
  5889. a:=groebfactor!*(dpmat_sieve(u,vars2,nil),nil);
  5890. % Constraints in dimension zero may be skipped :
  5891. a:=for each x in a collect car x;
  5892. for each u in a do
  5893. << m1:=sort(for each x in dpmat_list u collect bas_dpoly x,
  5894. function triang!=trsort);
  5895. f1:=car m1;
  5896. m2:=for each y in cdr m1 collect bas_make(1,dp_xlt(y,x));
  5897. B:=interreduce!* dpmat_make(length m2,0,m2,nil,nil);
  5898. res:=nconc(append(
  5899. for each v in triang!=triang2(B,cdr vars) collect (f1 . v),
  5900. triang!=triang2a(matstabquot!*(u,B),vars)),res);
  5901. >>;
  5902. return res;
  5903. end) where cali!=basering=cali!=basering;
  5904. symbolic procedure triang!=triang2a(A,vars);
  5905. % triang!=triang(A,vars)={f1.x for x in triang!=triang2(B,cdr vars)}
  5906. % \union triang!=triang2(A:<B>,vars)
  5907. % where A is already a gr basis wrt. the elimination order.
  5908. % Returns a list of polynomial lists.
  5909. if dpmat_unitideal!? A then nil
  5910. else if length vars = 1 then {{bas_dpoly first dpmat_list A}}
  5911. else begin scalar u,x,f1,m1,m2,B;
  5912. x:=car vars;
  5913. m1:=sort(for each x in dpmat_list a collect bas_dpoly x,
  5914. function triang!=trsort);
  5915. f1:=car m1;
  5916. m2:=for each y in cdr m1 collect bas_make(1,dp_xlt(y,x));
  5917. B:=interreduce!* dpmat_make(length m2,0,m2,nil,nil);
  5918. return append(
  5919. for each u in triang!=triang2(B,cdr vars) collect (f1 . u),
  5920. triang!=triang2a(matstabquot!*(A,B),vars));
  5921. end;
  5922. endmodule; % triang
  5923. end;
  5924.