cali.red 190 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665
  1. % Author H.-G. Graebe | Univ. Leipzig
  2. % graebe@informatik.uni-leipzig.d400.de
  3. module cali;
  4. terpri(); write "CALI 2.1. Last update 22/10/93"; terpri();
  5. COMMENT
  6. #########################
  7. #### ####
  8. #### HEADER MODULE ####
  9. #### ####
  10. #########################
  11. This is the header module of the package CALI, a package for
  12. computational commutative algebra.
  13. Author : H.-G. Graebe
  14. Univ. Leipzig
  15. FB Mathematik/Informatik
  16. Augustusplatz 10 - 11
  17. D - 04109 Leipzig
  18. Germany
  19. email : graebe@informatik.uni-leipzig.d400.de
  20. Version : 2.1, finished at Oct. 22, 1993.
  21. See cali.chg for change's documentation.
  22. Please send all comments, bugs, hints, wishes, criticisms etc. to the
  23. above email address.
  24. Abstract :
  25. This package contains algorithms for computations in commutative
  26. algebra closely related to the Groebner algorithm for ideals and
  27. modules. There are facilities for local computations, using a modern
  28. implementation of Mora's standard basis algorithm, that works for
  29. arbitrary term orders. This reflects the full analogy between modules
  30. over local rings and homogeneous (in fact H-local) modules over
  31. polynomial rings.
  32. CALI extends also the restricted term order facilities of the
  33. groebner package, defining term orders by degree vector lists, and
  34. the rigid implementation of the sugar idea, by a more flexible ecart
  35. vector, in particular useful for local computations.
  36. The package was designed mainly as a symbolic mode programming
  37. environment extending the build-in facilities of REDUCE for the
  38. computational approach to problems arising naturally in commutative
  39. algebra. An algebraic mode interface allows to access (in a more
  40. rigid frame) all important features implemented symbolically.
  41. As main topics CALI contains facilities for
  42. -- defining rings, ideals and modules,
  43. -- computing Groebner bases and local standard bases,
  44. -- computing syzygies, resolutions and (graded) Betti numbers,
  45. -- computing Hilbert series, multiplicities, independent sets,
  46. dimensions.
  47. -- computing normal forms and representations,
  48. -- computing sums, products, intersections, elimination ideals etc.
  49. -- primality tests, radicals, unmixed parts, primary decompositions
  50. etc. of ideals and modules,
  51. -- scripts for advanced applications of Groebner bases (blowup,
  52. associated graded ring, analytic spread,
  53. symmetric algebra, monomial curves etc.)
  54. Reduce version required :
  55. The program was tested under v. 3.4.1., but should work as well under
  56. v. 3.3.
  57. Relevant publications :
  58. See the bibliography in the manual.
  59. Key words :
  60. Groebner algorithm for ideals and modules, local standard bases,
  61. normal forms, Hilbert series, independent sets, free resolution,
  62. constructive commutative algebra, primality test, radical,
  63. unmixed part, primary decomposition, blowup, associated graded ring,
  64. analytic spread, symmetric algebra, monomial curves, sets of points.
  65. END COMMENT;
  66. comment
  67. create!-package( '(
  68. cali % This header module.
  69. bcsf % Base coeff. arithmetics.
  70. ring % Base ring and monomial arithmetics.
  71. mo % Monomial arithmetic.
  72. dpoly % Distr. polynomial (and vector) arithmetics.
  73. bas % Polynomial lists.
  74. dpmat % dpmat's arithmetic.
  75. red % Normal form algorithms and related topics.
  76. groeb % Groebner algorithm and related topics.
  77. mora % Modifications for local computations.
  78. matop % Module operations on dpmats.
  79. quot % Different quotients.
  80. moid % Lead. term ideal algorithms.
  81. res % Resolutions.
  82. intf % Interface to algebraic mode.
  83. odim % Alg. for zerodimensional ideals and
  84. % modules.
  85. prime % Primality test, radical, and primary
  86. % decomposition.
  87. ),nil);
  88. load!-package 'matrix;
  89. fluid '(
  90. cali!=rules % see bcsf
  91. cali!=basering % see rings
  92. cali!=degrees % see mons in rings
  93. cali!=trace % see red, groeb, mora
  94. cali!=monset % see groeb
  95. );
  96. % Default :
  97. switch
  98. hardzerotest, % (off) see bcsf, try simp for each zerotest.
  99. red_total, % (on) see red, do total reductions.
  100. binomial, % (off) see red, do multireductions
  101. % for binomial ideals.
  102. bcsimp, % (on) see red, cancel coefficient's gcd.
  103. lazy, % (off) see mora, apply the lazy strategy.
  104. noetherian, % (on) see interf, test term orders and
  105. % choose non local algorithms.
  106. factorunits, % (off) see mora, try to remove units from
  107. % polynomials by factorization.
  108. detectunits; % (off) see mora, detect generators of the form
  109. % monomial * unit.
  110. % The first initialization : No tracing.
  111. cali!=trace:=0;
  112. % ---- Some useful things, probably implemented also elsewhere
  113. % ---- in the system.
  114. symbolic procedure first x; car x;
  115. symbolic procedure second x; cadr x;
  116. symbolic procedure third x; caddr x;
  117. symbolic procedure strcat l;
  118. % Concatenate the items in the list l to a string.
  119. begin scalar u;
  120. u:=for each x in l join explode x;
  121. while memq('!!,u) do u:=delete('!!,u);
  122. while memq('!",u) do u:=delete('!",u);
  123. return compress append(append('(!"),u),'(!"));
  124. end;
  125. symbolic procedure numberlistp l;
  126. % l is a list of numbers.
  127. if null l then t
  128. else fixp car l and numberlistp cdr l;
  129. symbolic procedure merge(l1,l2,fn);
  130. % Returns the (physical) merge of the two sorted lists l1 and l2.
  131. if null l1 then l2
  132. else if null l2 then l1
  133. else if apply2(fn,car l1,car l2) then rplacd(l1,merge(cdr l1,l2,fn))
  134. else rplacd(l2,merge(l1,cdr l2,fn));
  135. symbolic procedure listexpand(fn,l); eval expand(l,fn);
  136. symbolic procedure listtest(a,b,f);
  137. % Return the first u in a s.th. f(u,b) or nil.
  138. if null a then nil
  139. else if apply2(f,car a,b) then
  140. if car a=nil then t else car a
  141. else listtest(cdr a,b,f);
  142. symbolic procedure listminimize(a,f);
  143. % Returns a minimal list b such that for all v in a ex. u in b such
  144. % that f(u,v).
  145. if null a then nil else reverse cali!=min(nil,a,f);
  146. symbolic procedure cali!=min(b,a,f);
  147. if null a then b
  148. else if listtest(b,car a,f) or listtest(cdr a,car a,f) then
  149. cali!=min(b,cdr a,f)
  150. else cali!=min(car a . b,cdr a,f);
  151. symbolic procedure disjoint(a,b);
  152. if null a then t else not member(car a,b) and disjoint(cdr a,b);
  153. symbolic procedure print_lf u;
  154. % Line feed after about 70 characters.
  155. <<if posn()>69 then <<terpri();terpri()>>; prin2 u>>;
  156. symbolic procedure cali_choose(m,k);
  157. % Returns the list of k-subsets of m.
  158. if (length m < k) then nil
  159. else if k=1 then for each x in m collect list x
  160. else nconc(
  161. for each x in cali_choose(cdr m,k-1) collect (car m . x),
  162. cali_choose(cdr m,k));
  163. endmodule; % cali - The header module
  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. cali!=rules:=m;
  190. return getrules();
  191. end;
  192. symbolic operator getrules;
  193. symbolic procedure getrules();
  194. makelist for each x in cali!=rules collect
  195. list('replaceby,prepf car x,prepf cdr x);
  196. symbolic procedure bc!=simp u;
  197. if cali!=rules then
  198. begin scalar r,c; integer i; i:=0;
  199. r:=cali!=rules;
  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:=cali!=rules;
  206. >>;
  207. >>;
  208. if (i<1000) then return u
  209. else rederr"recursion depth of bc!=simp to high"
  210. end
  211. else u;
  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. module ring;
  249. COMMENT
  250. ##################
  251. ## ##
  252. ## RINGS ##
  253. ## ##
  254. ##################
  255. Informal syntax :
  256. Ring = ('RING (name list) ((degree list list)) deg_type ecart)
  257. with deg_type = 'lex or 'revlex.
  258. The term order is defined at first comparing successively degrees and
  259. then by the name list lex. or revlex. For details consult the manual.
  260. (name list) contains a phantom name cali!=mk for the module
  261. component, see below in module mons.
  262. The variable cali!=basering contains the actual base ring.
  263. The ecart is a list of positive integers (the ecart vector for the
  264. given ring) and has
  265. length = length names cali!=basering.
  266. It is used in several places for optimal strategies (groeb) or to
  267. guarantee termination (mora).
  268. All homogenizations are executed with respect to that list.
  269. END COMMENT;
  270. symbolic procedure ring_define(n,to,type,ecart);
  271. list('ring,'cali!=mk . n, to, type,ecart);
  272. symbolic procedure setring!* c;
  273. begin
  274. if !*noetherian and not ring_isnoetherian c then
  275. rederr"term order is not noetherian";
  276. cali!=basering:=c;
  277. setkorder ring_all_names c;
  278. return c;
  279. end;
  280. symbolic procedure setecart!* e;
  281. begin scalar r; r:=cali!=basering;
  282. if not ring_checkecart(e,ring_names r) then
  283. typerr(e,"ecart vector")
  284. else cali!=basering:=
  285. ring_define(ring_names r,ring_degrees r,ring_tag r,e)
  286. end;
  287. symbolic procedure ring_2a c;
  288. makelist {makelist ring_names c,
  289. makelist for each x in ring_degrees c collect makelist x,
  290. ring_tag c, makelist ring_ecart c};
  291. symbolic procedure ring_from_a u;
  292. begin scalar vars,tord,c,r,tag,ecart;
  293. if not eqcar(u,'list) then typerr(u,"ring") else u:=cdr u;
  294. vars:=reval car u; tord:=reval cadr u; tag:=reval caddr u;
  295. if length u=4 then ecart:=reval cadddr u;
  296. if not(tag memq '(lex revlex)) then typerr(tag,"term order tag");
  297. if not eqcar(vars,'list) then typerr(vars,"variable list")
  298. else vars:=cdr vars;
  299. if tord={'list} then c:=nil
  300. else if not (c:=ring!=testtord(vars,tord)) then
  301. typerr(tord,"term order degrees");
  302. if null ecart then
  303. if (null tord)or not ring_checkecart(car tord,vars) then
  304. ecart:=for each x in vars collect 1
  305. else ecart:=car tord
  306. else if not ring_checkecart(cdr ecart,vars) then
  307. typerr(ecart,"ecart list")
  308. else ecart:=cdr ecart;
  309. r:=ring_define(vars,c,tag,ecart);
  310. if !*noetherian and not(ring_isnoetherian r) then
  311. rederr"Term order is non noetherian";
  312. return r
  313. end;
  314. symbolic procedure ring!=testtord(vars,u);
  315. % Test the non empty term order degrees for consistency and return
  316. % the symbolic equivalent of u.
  317. if (ring!=lengthtest(cdr u,length vars +1)
  318. and ring!=contenttest cdr u)
  319. then for each x in cdr u collect cdr x
  320. else nil;
  321. symbolic procedure ring!=lengthtest(m,v);
  322. % Test, whether m is a list of (algebraic) lists of the length v.
  323. if null m then t
  324. else eqcar(car m,'list)
  325. and (length car m = v)
  326. and ring!=lengthtest(cdr m,v);
  327. symbolic procedure ring!=contenttest m;
  328. % Test, whether m is a list of (algebraic) number lists.
  329. if null m then t
  330. else numberlistp cdar m and ring!=contenttest cdr m;
  331. symbolic procedure ring_names r; % User names only
  332. cdadr r;
  333. symbolic procedure ring_all_names r; cadr r; % All names
  334. symbolic procedure ring_degrees r; caddr r;
  335. symbolic procedure ring_tag r; cadddr r;
  336. symbolic procedure ring_ecart r; nth(r,5);
  337. % --- Test the term order for the chain condition ------
  338. symbolic procedure ring!=trans d;
  339. % Transpose the degree matrix.
  340. if (null d)or(null car d) then nil
  341. else (for each x in d collect car x) .
  342. ring!=trans(for each x in d collect cdr x);
  343. symbolic procedure ring!=testlex d;
  344. if null d then t
  345. else ring!=testlex1(car d) and ring!=testlex(cdr d);
  346. symbolic procedure ring!=testlex1 d;
  347. if null d then t
  348. else if car d=0 then ring!=testlex1(cdr d)
  349. else (car d>0);
  350. symbolic procedure ring!=testrevlex d;
  351. if null d then t
  352. else ring!=testrevlex1(car d) and ring!=testrevlex(cdr d);
  353. symbolic procedure ring!=testrevlex1 d;
  354. if null d then nil
  355. else if car d=0 then ring!=testrevlex1(cdr d)
  356. else (car d>0);
  357. symbolic procedure ring_isnoetherian r;
  358. % Test, whether the term order of the ring r satisfies the chain
  359. % condition.
  360. if ring_tag r ='revlex then
  361. ring!=testrevlex ring!=trans ring_degrees r
  362. else ring!=testlex ring!=trans ring_degrees r;
  363. symbolic procedure ring!=degpos d;
  364. if null d then t
  365. else (car d>0) and ring!=degpos cdr d;
  366. symbolic procedure ring_checkecart(e,vars);
  367. (length e=length vars) and ring!=degpos e;
  368. % ---- Test noetherianity switching noetherian on :
  369. put('noetherian,'simpfg,'((t (ring!=test))));
  370. symbolic procedure ring!=test;
  371. if not ring_isnoetherian cali!=basering then
  372. << !*noetherian:=nil;
  373. rederr"Current term order is not noetherian"
  374. >>;
  375. % ---- Different term orders in algebraic mode -------------
  376. algebraic procedure eliminationorder(v1,v2);
  377. % Elimination order : v1 = all variables
  378. % v2 = variables to eliminate.
  379. { for each x in v1 collect
  380. if x member v2 then 1 else 0,
  381. for each x in v1 collect
  382. if x member v2 then 0 else 1};
  383. algebraic procedure degreeorder(vars);
  384. {for each x in vars collect 1};
  385. algebraic procedure localorder(vars);
  386. {for each x in vars collect -1};
  387. % ---- Different term orders in symbolic mode -------------
  388. symbolic procedure eliminationorder!*(v1,v2);
  389. % Elimination order : v1 = all variables
  390. % v2 = variables to eliminate.
  391. { for each x in v1 collect
  392. if x member v2 then 1 else 0,
  393. for each x in v1 collect
  394. if x member v2 then 0 else 1};
  395. symbolic procedure degreeorder!*(vars);
  396. {for each x in vars collect 1};
  397. symbolic procedure localorder!*(vars);
  398. {for each x in vars collect -1};
  399. symbolic procedure ring_rlp(r,u);
  400. % u is a subset of ring_names r. Returns the block order
  401. % "first degrevlex on u, then the order on r"
  402. (for each x in ring_names r collect if x member u then 1 else 0)
  403. . append(for each x in u collect for each y in ring_names r collect
  404. if x=y then -1 else 0, ring_degrees r);
  405. % ---------- Ring constructors -----------------
  406. symbolic procedure ring_sum(a,b);
  407. % Returns the direct sum of two base rings with degree matrix at
  408. % first b then a and ecart=appended ecart lists.
  409. begin scalar vars,zeroa,zerob,degs,ecart;
  410. if not disjoint(ring_names a,ring_names b) then
  411. rederr"RINGSUM only for disjoint variable sets";
  412. vars:=append(ring_names a,ring_names b);
  413. ecart:=append(ring_ecart a,ring_ecart b);
  414. zeroa:=for each x in ring_names a collect 0;
  415. zerob:=for each x in ring_names b collect 0;
  416. degs:=append(
  417. for each x in ring_degrees b collect append(zeroa,x),
  418. for each x in ring_degrees a collect append(x,zerob));
  419. return ring_define(vars, degs, ring_tag a,ecart);
  420. end;
  421. % --------- First initialization :
  422. setring!* ring_define('(t x y z),'((1 1 1 1)),'revlex,'(1 1 1 1));
  423. !*noetherian:=t;
  424. % -------- End of first initialization ----------------
  425. endmodule; % ring
  426. module mo;
  427. COMMENT
  428. ##################
  429. ## ##
  430. ## MONOMIALS ##
  431. ## ##
  432. ##################
  433. Monomials are of the form x^a*e_i with a multipower x^a and a module
  434. component e_i. They belong either to the base ring R (i=0) or to a
  435. free module R^c (c >= i > 0).
  436. All computations are performed with respect to a "current module"
  437. over a "current ring" (=cali!=basering).
  438. To each module component e_i of the current module we assign a
  439. "column degree", i.e. a monomial representing a certain multidegree
  440. of the basis vector e_i. See the module dpmat for more details.
  441. The column degrees of the current module are stored in the assoc.
  442. list cali!=degrees.
  443. Informal syntax :
  444. <monomial> ::= (<exponential part> . <degree part>)
  445. < .. part> ::= list of integer
  446. Here exponent lists may have varying length since trailing zeroes are
  447. assumed to be omitted. The zero component of <exp. part> contains the
  448. module component. It correspond to the phantom var. name cali!=mk.
  449. END COMMENT;
  450. % ----------- manipulations of the degree part --------------------
  451. symbolic procedure mo!=sprod(a,b);
  452. % Scalar product of integer lists a and b .
  453. if not a or not b then 0
  454. else (car a)#*(car b) #+ mo!=sprod(cdr a,cdr b);
  455. symbolic procedure mo!=deglist(a);
  456. % a is an exponent list. Returns the degree list of a.
  457. if null a then
  458. for each x in ring_degrees cali!=basering collect 0
  459. else (mo!=sum(
  460. for each x in ring_degrees cali!=basering collect
  461. mo!=sprod(cdr a,x),
  462. if b then cddr b else nil)
  463. where b = assoc(car a,cali!=degrees));
  464. symbolic procedure mo_neworder m;
  465. % Deletes trailing zeroes and returns m with new degree part.
  466. (m1 . mo!=deglist m1) where m1 =mo!=shorten car m;
  467. symbolic procedure mo_degneworder l;
  468. % New degree parts in the degree list l.
  469. for each x in l collect car x . mo_neworder cdr x;
  470. symbolic procedure mo!=shorten m;
  471. begin scalar m1;
  472. m1:=reverse m;
  473. while m1 and eqn(car m1,0) do m1:=cdr m1;
  474. return reversip m1;
  475. end;
  476. % ------------- comparisions of monomials -----------------
  477. symbolic procedure mo_zero; nil . mo!=deglist nil;
  478. % Returns the unit monomial x^0.
  479. symbolic procedure mo_zero!? u; mo!=zero car u;
  480. symbolic procedure mo!=zero u;
  481. null u or car u = 0 and mo!=zero cdr u;
  482. symbolic procedure mo_equal!?(m1,m2);
  483. % Test whether m1 = m2.
  484. equal(mo!=shorten car m1,mo!=shorten car m2);
  485. symbolic procedure mo_divides!?(m1,m2);
  486. % m1,m2:monomial. true :<=> m1 divides m2
  487. mo!=modiv1(car m1,car m2);
  488. symbolic procedure mo!=modiv1(e1,e2);
  489. if not e1 then t else if not e2 then nil
  490. else leq(car e1,car e2) and mo!=modiv1(cdr e1, cdr e2);
  491. symbolic procedure mo_compare(m1,m2);
  492. % compare (m1,m2) . m1 < m2 => -1 | m1 = m2 => 0 | m1 > m2 => +1
  493. begin scalar a,x;
  494. x:=mo!=degcomp(cdr m1,cdr m2);
  495. if x eq 0 then
  496. x:=if equal(ring_tag cali!=basering,'revlex) then
  497. mo!=revlexcomp(car m1, car m2)
  498. else mo!=lexcomp(car m1,car m2);
  499. return x;
  500. end;
  501. symbolic procedure mo_dlexcomp(a,b); mo!=lexcomp(car a,car b)=1;
  502. % Descending lexicographic order, first by mo_comp.
  503. symbolic procedure mo!=degcomp(d1,d2);
  504. if null d1 then 0
  505. else if car d1 = car d2 then mo!=degcomp(cdr d1,cdr d2)
  506. else if car d1 #< car d2 then -1
  507. else 1;
  508. symbolic procedure mo!=revlexcomp(e1,e2);
  509. if null e1 then
  510. if null e2 then 0 else mo!=revlexcomp('(0),e2)
  511. else if null e2 then mo!=revlexcomp(e1,'(0))
  512. else if car e1 = car e2 then mo!=revlexcomp(cdr e1,cdr e2)
  513. else if car e1 #< car e2 then 1
  514. else -1;
  515. symbolic procedure mo!=lexcomp(e1,e2);
  516. if null e1 then
  517. if null e2 then 0 else mo!=lexcomp('(0),e2)
  518. else if null e2 then mo!=lexcomp(e1,'(0))
  519. else if car e1 = car e2 then mo!=lexcomp(cdr e1,cdr e2)
  520. else if car e1 #> car e2 then 1
  521. else -1;
  522. % ---------- manipulation of the module component --------
  523. symbolic procedure mo_comp v;
  524. % Retuns the module component of v.
  525. if null car v then 0 else caar v;
  526. symbolic procedure mo_from_ei i;
  527. % Make e_i.
  528. if i=0 then mo_zero() else (x . mo!=deglist x) where x =list(i);
  529. symbolic procedure mo_vdivides!?(v1,v2);
  530. % Equal module component and v1 divides v2.
  531. eqn(mo_comp v1,mo_comp v2) and mo_divides!?(v1,v2);
  532. symbolic procedure mo_deletecomp v;
  533. % Delete component part.
  534. if null car v then v
  535. else if null cdar v then (nil . mo!=deglist nil)
  536. else ((x . mo!=deglist x) where x=cons(0,cdar v));
  537. symbolic procedure mo_times_ei(i,m);
  538. % Returns m * e_i or n*e_{i+k}, if m=n*e_k.
  539. (x . mo!=deglist x)
  540. where x=if null car m then list(i) else cons(i #+ caar m,cdar m);
  541. symbolic procedure mo_degree m; cdr m;
  542. % Returns the degree part of m.
  543. symbolic procedure mo_getdegree(v,l);
  544. % Compute the (virtual) degree of the monomial v with respect to the
  545. % assoc. list l of column degrees.
  546. mo_deletecomp(if a then mo_sum(v,cdr a) else v)
  547. where a =assoc(mo_comp(v),l);
  548. % --------------- monomial arithmetics -----------------------
  549. symbolic procedure mo_lcm (m1,m2);
  550. % Monomial least common multiple.
  551. begin scalar x,e1,e2;
  552. e1:=car m1; e2:=car m2;
  553. while e1 and e2 do
  554. <<x := (if car e1 #> car e2 then car e1 else car e2) . x;
  555. e1 := cdr e1; e2 := cdr e2>>;
  556. x:=append(reversip x,if e1 then e1 else e2);
  557. return (mo!=shorten x) . (mo!=deglist x);
  558. end;
  559. symbolic procedure mo_gcd (m1,m2);
  560. % Monomial greatest common divisor.
  561. begin scalar x,e1,e2;
  562. e1:=car m1; e2:=car m2;
  563. while e1 and e2 do
  564. <<x := (if car e1 #< car e2 then car e1 else car e2) . x;
  565. e1 := cdr e1; e2 := cdr e2>>;
  566. x:=reversip x; return (mo!=shorten x) . (mo!=deglist x);
  567. end;
  568. symbolic procedure mo_neg v;
  569. % Return v^-1.
  570. (for each x in car v collect -x).(for each x in cdr v collect -x);
  571. symbolic procedure mo_sum(m1,m2);
  572. % Monomial product.
  573. ((mo!=shorten x) . (mo!=deglist x))
  574. where x =mo!=sum(car m1,car m2);
  575. symbolic procedure mo!=sum(e1,e2);
  576. begin scalar x;
  577. while e1 and e2 do
  578. <<x := (car e1 #+ car e2) . x; e1 := cdr e1; e2 := cdr e2>>;
  579. return append(reversip x,if e1 then e1 else e2);
  580. end;
  581. symbolic procedure mo_diff (m1,m2); mo_sum(m1,mo_neg m2);
  582. symbolic procedure mo_qrem(m,n);
  583. % m,n monomials. Returns (q . r) with m=n^q*r.
  584. begin scalar m1,n1,q,q1;
  585. q:=-1; m1:=cdar m; n1:=cdar n;
  586. while m1 and n1 and (q neq 0) do
  587. << if car n1 > 0 then
  588. << q1:=car m1 / car n1;
  589. if (q=-1) or (q>q1) then q:=q1;
  590. >>;
  591. n1:=cdr n1; m1:=cdr m1;
  592. >>;
  593. if n1 or (q=-1) then q:=0;
  594. return q . mo_diff(m,mo_power(n,q));
  595. end;
  596. symbolic procedure mo_power(mo,n);
  597. % Monomial power mo^n.
  598. (for each x in car mo collect n #* x) .
  599. (for each x in cdr mo collect n #* x);
  600. symbolic procedure mo!=pair(a,b);
  601. if null a or null b then nil
  602. else (car a . car b) . mo!=pair(cdr a,cdr b);
  603. symbolic procedure mo_2list m;
  604. % Returns a list (var name . exp) for the monomial m.
  605. begin scalar k; k:=car m;
  606. return
  607. mo!=pair(ring_names cali!=basering, if k then cdr k else nil);
  608. end;
  609. symbolic procedure mo_varexp(var,m);
  610. % Returns the exponent of var:var. name in the monomial m.
  611. if not member(var,ring_names cali!=basering) then
  612. typerr(var,"variable name")
  613. else begin scalar c;
  614. c:=assoc(var,mo_2list m);
  615. return if c then cdr c else 0
  616. end;
  617. symbolic procedure mo_inc(m,x,j);
  618. % Return monomial m with power of var. x increased by j.
  619. begin scalar n,v;
  620. if not member(x,v:=ring_all_names cali!=basering) then
  621. typerr(x,"dpoly variable");
  622. m:=car m;
  623. while x neq car v do
  624. << if m then <<n:=car m . n; m:=cdr m>> else n:=0 . n;
  625. v:=cdr v;
  626. >>;
  627. if m then
  628. << n:=(car m #+ j).n; if m:=cdr m then n:=nconc(reverse m,n) >>
  629. else n:=j . n;
  630. while n and (car n = 0) do n:=cdr n;
  631. n:=reversip n;
  632. return n . mo!=deglist n
  633. end;
  634. symbolic procedure mo_linear m;
  635. % Test whether the monomial m is linear.
  636. (length u=1 and cdar u=1) where u=mo_2list m;
  637. symbolic procedure mo_ecart m;
  638. % Returns the ecart of the monomial m.
  639. if null car m then 0
  640. else mo!=sprod(cdar m,ring_ecart cali!=basering);
  641. symbolic procedure mo_radical m;
  642. % Returns the radical of the monomial m.
  643. (x . mo!=deglist x)
  644. where x = for each y in car m collect if y=0 then 0 else 1;
  645. symbolic procedure mo_seed(m,s);
  646. % Set var's outside the list s equal to one.
  647. begin scalar m1,i,x,v;
  648. if not subsetp(s,v:=ring_all_names cali!=basering) then
  649. typerr(s,"dpoly name's list");
  650. m1:=car m;
  651. while m1 and v do
  652. << x:=cons(if member(car v,s) then car m1 else 0,x);
  653. m1:=cdr m1; v:=cdr v
  654. >>;
  655. while x and eqn(car x,0) do x:=cdr x;
  656. x:=reversip x;
  657. return x . mo!=deglist x;
  658. end;
  659. symbolic procedure mo_convert m;
  660. ( x . mo!=deglist x ) where x =mo!=shorten list(0,mo_ecart m);
  661. % ---------------- monomial interface ---------------
  662. symbolic procedure mo_from_a u;
  663. % Convert a kernel to a monomial.
  664. if not(u member ring_all_names cali!=basering) then
  665. typerr(u,"dpoly variable")
  666. else begin scalar x,y;
  667. y:=mo!=shorten
  668. for each x in ring_all_names cali!=basering collect
  669. if x equal u then 1 else 0;
  670. return y . mo!=deglist y;
  671. end;
  672. symbolic procedure mo_2a e;
  673. % Convert a monomial to part of algebraic prefix form of a dpoly.
  674. mo!=expvec2a1(car e,ring_all_names cali!=basering);
  675. symbolic procedure mo!=expvec2a1(u,v);
  676. if null u then nil
  677. else if car u = 0 then mo!=expvec2a1(cdr u,cdr v)
  678. else if car u = 1 then car v . mo!=expvec2a1(cdr u,cdr v)
  679. else list('expt,car v,car u) . mo!=expvec2a1(cdr u,cdr v);
  680. symbolic procedure mo_prin(e,v);
  681. % Print monomial e in infix form. V is a boolean variable which is
  682. % true if an element in a product has preceded this one
  683. mo!=dpevlpri1(car e,ring_all_names cali!=basering,v);
  684. symbolic procedure mo!=dpevlpri1(e,u,v);
  685. if null e then nil
  686. else if car e = 0 then mo!=dpevlpri1(cdr e,cdr u,v)
  687. else <<if v then print_lf "*";
  688. print_lf car u;
  689. if car e #> 1 then <<print_lf "^"; print_lf car e>>;
  690. mo!=dpevlpri1(cdr e,cdr u,t)>>;
  691. symbolic procedure mo_support m;
  692. % Returns the support of the monomial m as a list of var. names
  693. % in the correct order.
  694. begin scalar u;
  695. for each x in ring_names cali!=basering do
  696. if mo_divides!?(mo_from_a x,m) then u:=x . u;
  697. return reversip u;
  698. end;
  699. endmodule; % mo
  700. module dpoly;
  701. COMMENT
  702. ##################
  703. ## ##
  704. ## POLYNOMIALS ##
  705. ## ##
  706. ##################
  707. Polynomial vectors and polynomials are handled in a unique way using
  708. the module component of monomials to store the vector component. If
  709. the component is 0, we have a polynomial, otherwise a vector. They
  710. are represented in a distributive form (dpoly for short).
  711. Informal syntax of (vector) polynomials :
  712. <dpoly> ::= list of <term>s
  713. <term> ::= ( <monomial> . <base coefficient> )
  714. END COMMENT;
  715. % ----------- constructors and selectors -------------------
  716. symbolic procedure dp_lc p;
  717. % Leading base coefficient of the dpoly p.
  718. cdar p;
  719. symbolic procedure dp_lmon p;
  720. % Leading monomial of the dpoly p.
  721. caar p;
  722. symbolic procedure dp_term (a,e);
  723. % Constitutes a term from a:base coeff. and e:monomial.
  724. (e . a);
  725. symbolic procedure dp_from_ei n;
  726. % Returns e_i as dpoly.
  727. list dp_term(bc_fi 1,mo_from_ei n);
  728. symbolic procedure dp_fi n;
  729. % dpoly from integer
  730. list dp_term(bc_fi n,mo_zero());
  731. symbolic procedure dp_fbc c;
  732. % Converts the base coefficient c into a dpoly.
  733. list dp_term(c,mo_zero());
  734. % ------------ dpoly arithmetics ---------------------------
  735. symbolic procedure dp!=comp(i,v);
  736. if null v then nil
  737. else if eqn(mo_comp dp_lmon v,i) then car v . dp!=comp(i,cdr v)
  738. else dp!=comp(i,cdr v);
  739. symbolic procedure dp_comp(i,v);
  740. % Returns the (polynomial) component i of the vector v.
  741. for each x in dp!=comp(i,v) collect (mo_deletecomp car x) . cdr x;
  742. symbolic procedure dp!=mocompare (t1,t2);
  743. % true <=> term t1 is smaller than term t2 in the current term order.
  744. eqn(mo_compare (car t1, car t2),1);
  745. symbolic procedure dp_neworder p;
  746. % Returns reordered dpoly p after change of the term order.
  747. sort(for each x in p collect (mo_neworder car x) . cdr x,
  748. function dp!=mocompare);
  749. symbolic procedure dp_neg p;
  750. % Returns - p for the dpoly p.
  751. for each x in p collect (car x . bc_neg cdr x);
  752. symbolic procedure dp_times_mo (mo,p);
  753. % Returns p * x^mo for the dpoly p and the monomial mo.
  754. for each x in p collect (mo_sum(mo,car x) . cdr x);
  755. symbolic procedure dp_times_bc (bc,p);
  756. % Returns p * bc for the dpoly p and the base coeff. bc.
  757. for each x in p collect (car x . bc_prod(bc,cdr x));
  758. symbolic procedure dp_times_bcmo (bc,mo,p);
  759. % Returns p * bc * x^mo for the dpoly p, the monomial mo and the base
  760. % coeff. bc.
  761. for each x in p collect (mo_sum(mo,car x) . bc_prod(bc,cdr x));
  762. symbolic procedure dp_times_ei(i,p);
  763. % Returns p * e_i for the dpoly p.
  764. dp_neworder for each x in p collect (mo_times_ei(i,car x) . cdr x);
  765. symbolic procedure dp_project(p,k);
  766. % Delete all terms x^a*e_i with i>k.
  767. for each x in p join if mo_comp car x <= k then {x};
  768. symbolic procedure dp_content p;
  769. % Returns the leading coefficient, if invertible, or the content of
  770. % p.
  771. if null p then bc_fi 0
  772. else begin scalar w;
  773. w:=dp_lc p; p:=cdr p;
  774. while p and not bc_inv w do
  775. << w:=bc_gcd(w,dp_lc p); p:=cdr p >>;
  776. return w
  777. end;
  778. symbolic procedure dp_mondelete(p,s);
  779. % Returns (p.m) with common monomial factor m with support in the
  780. % var. list s deleted.
  781. if null p or null s then (p . mo_zero()) else
  782. begin scalar cmf;
  783. cmf:=dp!=cmf(p,s);
  784. if mo_zero!? cmf then return (p . cmf)
  785. else return
  786. cons(for each x in p collect mo_diff(car x,cmf) . cdr x,cmf)
  787. end;
  788. symbolic procedure dp!=cmf(p,s);
  789. begin scalar a;
  790. a:=mo_seed(dp_lmon p,s); p:=cdr p;
  791. while p and (not mo_zero!? a) do
  792. << a:=mo_gcd(a,mo_seed(dp_lmon p,s)); p:=cdr p >>;
  793. return a
  794. end;
  795. symbolic procedure dp_unit!? p;
  796. % Tests whether lt p of the dpoly p is a unit.
  797. % This means : p is a unit, if the t.o. is noetherian
  798. % or : p is a local unit, if the t.o. is a tangentcone order.
  799. p and (mo_zero!? dp_lmon p);
  800. symbolic procedure dp_simp pol;
  801. % Returns (pol_new . z) with
  802. % pol_new having leading coefficient 1 or
  803. % dp_content pol canceled out
  804. % and pol_old = z * dpoly_new .
  805. if null pol then pol . bc_fi 1
  806. else begin scalar z,z1;
  807. if (z:=bc_inv (z1:=dp_lc pol)) then
  808. return dp_times_bc(z,pol) . z1;
  809. % -- now we assume that base coefficients are a gcd domain ----
  810. z:=dp_content pol;
  811. if bc_minus!? z1 then z:=bc_neg z;
  812. pol:=for each x in pol collect
  813. car x . car bc_divmod(cdr x,z);
  814. return pol . z;
  815. end;
  816. symbolic procedure dp_prod(p1,p2);
  817. % Returns p1 * p2 for the dpolys p1 and p2.
  818. if length p1 <= length p2 then dp!=prod(p1,p2)
  819. else dp!=prod(p2,p1);
  820. symbolic procedure dp!=prod(p1,p2);
  821. if null p1 or null p2 then nil
  822. else
  823. begin scalar v;
  824. for each x in p1 do
  825. v:=dp_sum( dp_times_bcmo(cdr x,car x, p2 ),v);
  826. return v;
  827. end;
  828. symbolic procedure dp_sum(p1,p2);
  829. % Returns p1 + p2 for the dpolys p1 and p2.
  830. if null p1 then p2
  831. else if null p2 then p1
  832. else begin scalar sl,al;
  833. sl := mo_compare(dp_lmon p1, dp_lmon p2);
  834. if sl = 1 then return car p1 . dp_sum(cdr p1, p2);
  835. if sl = -1 then return car p2 . dp_sum(p1, cdr p2);
  836. al := bc_sum(dp_lc p1, dp_lc p2);
  837. if bc_zero!? al then return dp_sum(cdr p1, cdr p2)
  838. else return dp_term(al,dp_lmon p1) . dp_sum(cdr p1, cdr p2)
  839. end;
  840. symbolic procedure dp_diff(p1,p2);
  841. % Returns p1 - p2 for the dpolys p1 and p2.
  842. dp_sum(p1, dp_neg p2);
  843. symbolic procedure dp_power(p,n);
  844. % Returns p^n for the dpoly p.
  845. if (not fixp n) or (n < 0) then typerr(n," exponent")
  846. else if n=0 then dp_fi 1
  847. else if n=1 then p
  848. else if null cdr p then dp!=power1(p,n)
  849. else dp!=power(p,n);
  850. symbolic procedure dp!=power1(p,n); % For monomials.
  851. list dp_term(bc_power(dp_lc p,n),mo_power(dp_lmon p,n));
  852. symbolic procedure dp!=power(p,n);
  853. if n=1 then p
  854. else if evenp n then dp!=power(dp_prod(p,p),n/2)
  855. else dp_prod(p,dp!=power(dp_prod(p,p),n/2));
  856. symbolic procedure dp_tcpart p;
  857. % Return the homogeneous degree part of p of highest degree.
  858. if null p then nil
  859. else begin scalar d,u; d:=car mo_degree caar p;
  860. while p and (d=car mo_degree caar p) do
  861. << u:=car p . u; p:=cdr p >>;
  862. return reversip u;
  863. end;
  864. symbolic procedure dp_deletecomp p;
  865. % delete the component part from all terms.
  866. dp_neworder for each x in p collect mo_deletecomp car x . cdr x;
  867. % ------ Converting prefix forms into dpolys ------------------
  868. symbolic procedure dp_from_a u;
  869. % Converts the algebraic (prefix) form u into a dpoly.
  870. if atom u then dp!=a2dpatom u
  871. else if not atom car u or not idp car u
  872. then typerr(car u,"dpoly operator")
  873. else (if x='dp!=fnpow then dp!=fnpow(dp_from_a cadr u,caddr u)
  874. else if x then
  875. apply(x,list for each y in cdr u collect dp_from_a y)
  876. else dp!=a2dpatom u)
  877. where x = get(car u,'dp!=fn);
  878. symbolic procedure dp!=a2dpatom u;
  879. % Converts the atom (or kernel) u into a dpoly.
  880. if u=0 then nil
  881. else if numberp u or not member(u, ring_all_names cali!=basering)
  882. then list dp_term(bc_from_a u,mo_zero())
  883. else list dp_term(bc_fi 1,mo_from_a u);
  884. symbolic procedure dp!=fnsum u;
  885. % U is a list of dpoly expressions. The result is the dpoly
  886. % representation for the sum. Analogously for the other symbolic
  887. % procedures below.
  888. (<<for each y in cdr u do x := dp_sum(x,y); x>>) where x = car u;
  889. put('plus,'dp!=fn,'dp!=fnsum);
  890. put('plus2,'dp!=fn,'dp!=fnsum);
  891. symbolic procedure dp!=fnprod u;
  892. (<<for each y in cdr u do x := dp_prod(x,y); x>>) where x = car u;
  893. put('times,'dp!=fn,'dp!=fnprod);
  894. put('times2,'dp!=fn,'dp!=fnprod);
  895. symbolic procedure dp!=fndif u; dp_diff(car u, cadr u);
  896. put('difference,'dp!=fn,'dp!=fndif);
  897. symbolic procedure dp!=fnpow(u,n); dp_power(u,n);
  898. put('expt,'dp!=fn,'dp!=fnpow);
  899. symbolic procedure dp!=fnneg u;
  900. ( if null v then v else dp_term(bc_neg dp_lc v,dp_lmon v) . cdr v)
  901. where v = car u;
  902. put('minus,'dp!=fn,'dp!=fnneg);
  903. symbolic procedure dp!=fnquot u;
  904. if null cadr u or not null cdadr u
  905. or not mo_zero!? dp_lmon cadr u
  906. then typerr(dp_2a cadr u,"distributive polynomial denominator")
  907. else dp!=fnquot1(car u,dp_lc cadr u);
  908. symbolic procedure dp!=fnquot1(u,v);
  909. if null u then u
  910. else dp_term(bc_quot(dp_lc u,v), dp_lmon u) .
  911. dp!=fnquot1(cdr u,v);
  912. put('quotient,'dp!=fn,'dp!=fnquot);
  913. % -------- Converting dpolys into prefix forms -------------
  914. % ------ Authors: R. Gebauer, A. C. Hearn, H. Kredel -------
  915. symbolic procedure dp_2a u;
  916. % Returns the prefix equivalent of the dpoly u.
  917. if null u then 0 else dp!=replus dp!=2a u;
  918. symbolic procedure dp!=2a u;
  919. if null u then nil
  920. else ((if bc_minus!? x then
  921. list('minus,dp!=retimes(bc_2a bc_neg x . y))
  922. else dp!=retimes(bc_2a x . y))
  923. where x = dp_lc u, y = mo_2a dp_lmon u)
  924. . dp!=2a cdr u;
  925. symbolic procedure dp!=replus u;
  926. if atom u then u else if null cdr u then car u else 'plus . u;
  927. symbolic procedure dp!=retimes u;
  928. % U is a list of prefix expressions the first of which is a number.
  929. % The result is the prefix representation for their product.
  930. if car u = 1 then if cdr u then dp!=retimes cdr u else 1
  931. else if null cdr u then car u
  932. else 'times . u;
  933. % ----------- Printing routines for dpolys --------------
  934. % ---- Authors: R. Gebauer, A. C. Hearn, H. Kredel ------
  935. symbolic procedure dp_print u;
  936. % Prints a distributive polynomial in infix form.
  937. << terpri(); dp_print1(u,nil); terpri(); terpri() >>;
  938. symbolic procedure dp_print1(u,v);
  939. % Prints a dpoly in infix form.
  940. % U is a distributive form. V is a flag which is true if a term
  941. % has preceded current form.
  942. if null u then if null v then print_lf 0 else nil
  943. else begin scalar bool,w;
  944. w := dp_lc u;
  945. if bc_minus!? w then <<bool := t; w := bc_neg w>>;
  946. if bool then print_lf " - " else if v then print_lf " + ";
  947. ( if not bc_one!? w or mo_zero!? x then
  948. << bc_prin w; mo_prin(x,t)>>
  949. else mo_prin(x,nil))
  950. where x = dp_lmon u;
  951. dp_print1(cdr u,t)
  952. end;
  953. % -------------- Auxiliary dpoly operations -------------------
  954. symbolic procedure dp_ecart p;
  955. % Returns the ecart of the dpoly p.
  956. if null p then 0 else (dp!=ecart p) - (mo_ecart dp_lmon p);
  957. symbolic procedure dp!=ecart p;
  958. if null p then 0
  959. else max2(mo_ecart dp_lmon p,dp!=ecart cdr p);
  960. symbolic procedure dp_df(pol,var);
  961. % Returns the derivative of the dpoly pol by the variable var.
  962. dp!=df(pol,var,mo_from_a var);
  963. symbolic procedure dp!=df(f,var,mo);
  964. if null f then nil
  965. else begin scalar x;
  966. x:=mo_varexp(var,dp_lmon f);
  967. if x > 0 then return
  968. dp_sum(list dp_term(bc_prod(dp_lc f,bc_fi x),
  969. mo_diff(dp_lmon f,mo)),
  970. dp!=df(cdr f,var,mo))
  971. else return dp!=df(cdr f,var,mo)
  972. end;
  973. symbolic procedure dp_jac(f,l);
  974. % Make the jacobian vector (df/dx_i) with respect to the variable
  975. % list l.
  976. begin integer i; scalar w; i:=0;
  977. while l do
  978. << i:=i+1; w:=dp_sum(w,dp_times_ei(i,dp_df(f,car l)));
  979. l:=cdr l
  980. >>;
  981. return w;
  982. end;
  983. symbolic procedure dp_homogenize(p,x);
  984. % Homogenize (according to mo_ecart) the dpoly p using the variable x.
  985. if null p then p
  986. else begin integer maxdeg;
  987. maxdeg:=0;
  988. for each y in p do maxdeg:=max2(maxdeg,mo_ecart car y);
  989. return dp_compact dp_neworder for each y in p collect
  990. mo_inc(car y,x,maxdeg-mo_ecart car y) . cdr y;
  991. end;
  992. symbolic procedure dp_seed(p,s);
  993. % Returns the dpoly p with all vars outside the list s set equal to 1.
  994. if null p then p
  995. else dp_compact dp_neworder
  996. for each x in p collect mo_seed(car x,s).cdr x;
  997. symbolic procedure dp_compact p;
  998. % Collect equal terms in the sorted dpoly p.
  999. if null p then p else dp_sum(list car p,dp_compact cdr p);
  1000. symbolic procedure dp_convert pol;
  1001. % Create univariate polynomial.
  1002. if null pol then nil
  1003. else dp_sum(list dp_term(dp_lc pol,mo_convert dp_lmon pol),
  1004. dp_convert cdr pol);
  1005. % -- dpoly operations based on computation with ideal bases.
  1006. symbolic procedure dp_pseudodivmod(g,f);
  1007. % Returns a dpoly list {q,r,z} such that z * g = q * f + r and
  1008. % z is a dpoly unit. Computes redpol({[f.e_1]},[g.0]).
  1009. % g, f and r must belong to the same free module.
  1010. begin scalar u;
  1011. f:=list bas_make1(1,f,dp_from_ei 1);
  1012. g:=bas_make(0,g);
  1013. u:=if !*noetherian then red_redpol(f,g) else mora_redpol(f,g);
  1014. return {dp_neg dp_deletecomp bas_rep car u,bas_dpoly car u,cdr u};
  1015. end;
  1016. symbolic procedure dpgcd!*(u,v);
  1017. % Compute the gcd of two polynomials by the syzygies' method :
  1018. % 0 = u*u1 + v*v1 => gcd = u/v1 = -v/u1 .
  1019. if dp_unit!? u or dp_unit!? v then dp_fi 1
  1020. else begin scalar g,w;
  1021. w:=bas_dpoly first dpmat_list
  1022. syzygies!* dpmat_make(2,0,{bas_make(1,u),bas_make(2,v)},nil);
  1023. return car dp_pseudodivmod(u,dp_comp(2,w));
  1024. end;
  1025. symbolic operator dpgcd;
  1026. symbolic procedure dpgcd(u,v);
  1027. if !*mode='symbolic then rederr"only for algebraic mode"
  1028. else dp_2a dpgcd!*(dp_from_a u,dp_from_a v);
  1029. endmodule; % dpoly
  1030. module bas;
  1031. COMMENT
  1032. #######################
  1033. #### ####
  1034. #### IDEAL BASES ####
  1035. #### ####
  1036. #######################
  1037. Ideal bases are lists of vector polynomials (with additional
  1038. information), constituting the rows of a dpmat (see below). In a
  1039. rep. part there can be stored vectors representing each base element
  1040. according to a fixed basis. Usually rep=nil.
  1041. Informal syntax :
  1042. <bas> ::= list of base elements
  1043. <base element> ::= list(nr dpoly length ecart rep)
  1044. END COMMENT;
  1045. % -------- Reference operators for the base element b ---------
  1046. symbolic procedure bas_dpoly b; cadr b;
  1047. symbolic procedure bas_dplen b; caddr b;
  1048. symbolic procedure bas_nr b; car b;
  1049. symbolic procedure bas_dpecart b; cadddr b;
  1050. symbolic procedure bas_rep b; nth(b,5);
  1051. % ----- Elementary constructors for the base element be --------
  1052. symbolic procedure bas_newnumber(nr,be);
  1053. % Returns be with new number part.
  1054. nr . cdr be;
  1055. symbolic procedure bas_make(nr,pol);
  1056. % Make base element with rep=nil.
  1057. list(nr,pol, length pol,dp_ecart pol,nil);
  1058. symbolic procedure bas_make1(nr,pol,rep);
  1059. % Make base element with prescribed rep.
  1060. list(nr,pol, length pol,dp_ecart pol,rep);
  1061. symbolic procedure bas_getelement(i,bas);
  1062. % Returns the base element with number i from bas (or nil).
  1063. if null bas then list(i,nil,0,0,nil)
  1064. else if eqn(i,bas_nr car bas) then car bas
  1065. else bas_getelement(i,cdr bas);
  1066. % ---------- Operations on base lists ---------------
  1067. symbolic procedure bas_sort b;
  1068. % Sort the base list b.
  1069. sort(b,function red_better);
  1070. symbolic procedure bas_print u;
  1071. % Prints a list of distributive polynomials using dp_print.
  1072. begin terpri();
  1073. if null u then print 'empty
  1074. else for each v in u do
  1075. << write bas_nr v, " --> ";
  1076. dp_print1(bas_dpoly v,nil); terpri();terpri() >>;
  1077. end;
  1078. symbolic procedure bas_renumber u;
  1079. % Renumber base list u.
  1080. if null u then nil
  1081. else begin scalar i; i:=0;
  1082. return for each x in u collect <<i:=i+1; bas_newnumber(i,x) >>
  1083. end;
  1084. symbolic procedure bas_setrelations u;
  1085. % Set in the base list u the relation part rep of base element nr. i
  1086. % to e_i (provided i>0).
  1087. for each x in u do
  1088. if bas_nr x > 0 then rplaca(cddddr x, dp_from_ei bas_nr x);
  1089. symbolic procedure bas_removerelations u;
  1090. % Remove relation parts.
  1091. for each x in u do rplaca(cddddr x, nil);
  1092. symbolic procedure bas_getrelations u;
  1093. % Returns the relations of the base list u as a separate base list.
  1094. begin scalar w;
  1095. for each x in u do w:=bas_make(bas_nr x,bas_rep x) . w;
  1096. return reversip w;
  1097. end;
  1098. symbolic procedure bas_from_a u;
  1099. % Converts the algebraic (prefix) form u to a base list clearing
  1100. % denominators. Only for lists.
  1101. bas_renumber for each v in cdr u collect
  1102. bas_make(0,dp_from_a prepf numr simp v);
  1103. symbolic procedure bas_2a u;
  1104. % Converts the base list u to its algebraic prefix form.
  1105. append('(list),for each x in u collect dp_2a bas_dpoly x);
  1106. symbolic procedure bas_neworder u;
  1107. % Returns reordered base list u (e.g. after change of term order).
  1108. for each x in u collect
  1109. bas_make1(bas_nr x,dp_neworder bas_dpoly x,
  1110. dp_neworder bas_rep x);
  1111. symbolic procedure bas_zerodelete u;
  1112. % Returns base list u with zero elements deleted but not renumbered.
  1113. if null u then nil
  1114. else if null bas_dpoly car u then bas_zerodelete cdr u
  1115. else car u.bas_zerodelete cdr u;
  1116. symbolic procedure bas_simpelement b;
  1117. % Returns (b_new . z) with
  1118. % bas_dpoly b_new having leading coefficient 1 or
  1119. % gcd(dp_content bas_poly,dp_content bas_rep) canceled out
  1120. % and dpoly_old = z * dpoly_new , rep_old= z * rep_new.
  1121. if null bas_dpoly b then b . bc_fi 1
  1122. else begin scalar z,z1,pol,rep;
  1123. if (z:=bc_inv (z1:=dp_lc bas_dpoly b)) then
  1124. return bas_make1(bas_nr b,
  1125. dp_times_bc(z,bas_dpoly b),
  1126. dp_times_bc(z,bas_rep b))
  1127. . z1;
  1128. % -- now we assume that base coefficients are a gcd domain ----
  1129. z:=bc_gcd(dp_content bas_dpoly b,dp_content bas_rep b);
  1130. if bc_minus!? z1 then z:=bc_neg z;
  1131. pol:=for each x in bas_dpoly b collect
  1132. car x . car bc_divmod(cdr x,z);
  1133. rep:=for each x in bas_rep b collect
  1134. car x . car bc_divmod(cdr x,z);
  1135. return bas_make1(bas_nr b,pol,rep) . z;
  1136. end;
  1137. symbolic procedure bas_simp u;
  1138. % Applies bas_simpelement to each dpoly in the base list u.
  1139. for each x in u collect car bas_simpelement x;
  1140. symbolic procedure bas_zero!? b;
  1141. % Test whether all base elements are zero.
  1142. null b or (null bas_dpoly car b and bas_zero!? cdr b);
  1143. symbolic procedure bas_sieve(bas,vars);
  1144. % Sieve out all base elements from the base list bas with leading
  1145. % term containing a variable from the list of var. names vars and
  1146. % renumber the result.
  1147. begin scalar u,m; m:=mo_zero();
  1148. for each x in vars do
  1149. if member(x,ring_names cali!=basering) then
  1150. m:=mo_sum(m,mo_from_a x)
  1151. else typerr(x,"variable name");
  1152. return bas_renumber for each x in bas_zerodelete bas join
  1153. if mo_zero!? mo_gcd(m,dp_lmon bas_dpoly x) then {x};
  1154. end;
  1155. symbolic procedure bas_homogenize(b,var);
  1156. % Homogenize the base list b using the var. name var.
  1157. for each x in b collect
  1158. bas_make1(bas_nr x,dp_homogenize(bas_dpoly x,var),
  1159. dp_homogenize(bas_rep x,var));
  1160. symbolic procedure bas_dehomogenize(b,var);
  1161. % Set the var. name var in the base list b equal to one.
  1162. begin scalar u,v;
  1163. if not member(var,v:=ring_all_names cali!=basering) then
  1164. typerr(var,"dpoly variable");
  1165. u:=setdiff(v,list var);
  1166. return for each x in b collect
  1167. bas_make1(bas_nr x,dp_seed(bas_dpoly x,u),
  1168. dp_seed(bas_rep x,u));
  1169. end;
  1170. endmodule; % bas
  1171. module dpmat;
  1172. COMMENT
  1173. #####################
  1174. ### ###
  1175. ### MATRICES ###
  1176. ### ###
  1177. #####################
  1178. This module introduces special dpoly matrices with its own matrix
  1179. syntax.
  1180. Informal syntax :
  1181. <matrix> ::= list('DPMAT,#rows,#cols,baslist,column_degrees)
  1182. Dpmat's are the central data structure exploited in the modules of
  1183. this package. Each such matrix describes a map
  1184. f : R^rows --> R^cols,
  1185. that gives rise for the definition of two modules,
  1186. im f = the submodule of R^cols generated by the rows
  1187. of the matrix
  1188. and coker f = R^cols/im f.
  1189. Conceptually dpmat's are identified with im f.
  1190. END COMMENT;
  1191. % ------------- Reference operators ----------------
  1192. symbolic procedure dpmat_rows m; cadr m;
  1193. symbolic procedure dpmat_cols m; caddr m;
  1194. symbolic procedure dpmat_list m; cadddr m;
  1195. symbolic procedure dpmat_coldegs m; nth(m,5);
  1196. % ------------- Elementary operations --------------
  1197. symbolic procedure dpmat_rowdegrees m;
  1198. % Returns the row degrees of the dpmat m as an assoc. list.
  1199. (for each x in dpmat_list m join
  1200. if bas_nr x > 0 then
  1201. {(bas_nr x).(mo_getdegree(dp_lmon bas_dpoly x,l))})
  1202. where l=dpmat_coldegs m;
  1203. symbolic procedure dpmat_make(r,c,bas,degs);
  1204. list('dpmat,r,c,bas,degs);
  1205. symbolic procedure dpmat_element(r,c,mmat);
  1206. % Returns mmat[r,c].
  1207. dp_neworder
  1208. dp_comp(c, bas_dpoly bas_getelement(r,dpmat_list mmat));
  1209. symbolic procedure dpmat_print m; mathprint dpmat_2a m;
  1210. symbolic procedure getleadterms!* m;
  1211. % Returns the dpmat with the leading terms of m.
  1212. (begin scalar b;
  1213. b:=for each x in dpmat_list m collect
  1214. bas_make(bas_nr x,list(car bas_dpoly x));
  1215. return dpmat_make(dpmat_rows m,dpmat_cols m,b,cali!=degrees);
  1216. end) where cali!=degrees:=dpmat_coldegs m;
  1217. % -------- Symbolic mode file transfer --------------
  1218. symbolic procedure savemat!*(m,name);
  1219. % Save the dpmat m under the name <name>.
  1220. begin scalar nat,c;
  1221. if not (stringp name or idp name) then typerr(name,"file name");
  1222. if not eqcar(m,'dpmat) then typerr(m,"dpmat");
  1223. nat:=!*nat; !*nat:=nil;
  1224. write"Saving as ",name;
  1225. out name$
  1226. write"algebraic(setring "$
  1227. % mathprint prints lists without terminator, but matrices with
  1228. % terminator.
  1229. mathprint ring_2a cali!=basering$ write")$"$
  1230. write"algebraic(<<basis :="$ dpmat_print m$
  1231. if dpmat_cols m=0 then write"$"$ write">>)$"$
  1232. if (c:=dpmat_coldegs m) then
  1233. << write"algebraic(degrees:="$
  1234. mathprint moid_2a for each x in c collect cdr x$ write")$"$
  1235. >>;
  1236. write"end$"$ terpri()$
  1237. shut name; terpri(); !*nat:=nat;
  1238. end;
  1239. symbolic procedure initmat!* name;
  1240. % Initialize a dpmat from <name>.
  1241. if not (stringp name or idp name) then typerr(name,"file name")
  1242. else begin scalar m,c,d; integer i;
  1243. write"Initializing ",name; terpri();
  1244. in name$ m:=reval 'basis; cali!=degrees:=nil;
  1245. if eqcar(m,'list) then
  1246. << m:=bas_from_a m; m:=dpmat_make(length m,0,m,nil)>>
  1247. else if eqcar(m,'mat) then
  1248. << c:=moid_from_a reval 'degrees; i:=0;
  1249. cali!=degrees:=for each x in c collect <<i:=i+1; i . x >>;
  1250. m:=dpmat_from_a m;
  1251. >>
  1252. else typerr(m,"basis or matrix");
  1253. dpmat_print m;
  1254. return m;
  1255. end;
  1256. % ---- Algebraic mode file transfer ---------
  1257. symbolic operator savemat;
  1258. symbolic procedure savemat(m,name);
  1259. if !*mode='symbolic then rederr"only for algebraic mode"
  1260. else savemat!*(dpmat_from_a m,name);
  1261. symbolic operator initmat;
  1262. symbolic procedure initmat name;
  1263. if !*mode='symbolic then rederr"only for algebraic mode"
  1264. else dpmat_2a initmat!* name;
  1265. % --------------- Arithmetics for dpmat's ----------------------
  1266. symbolic procedure dpmat!=dpsubst(a,b);
  1267. % Substitute in the dpoly a each e_i by b_i from the base list b.
  1268. begin scalar v;
  1269. for each x in b do
  1270. v:=dp_sum(v,dp_prod(dp_comp(bas_nr x,a),bas_dpoly x));
  1271. return v;
  1272. end;
  1273. symbolic procedure dpmat_mult(a,b);
  1274. % Returns a * b.
  1275. if not eqn(dpmat_cols a,dpmat_rows b) then
  1276. rerror('dpmat,1," matrices don't match for MATMULT")
  1277. else dpmat_make( dpmat_rows a, dpmat_cols b,
  1278. for each x in dpmat_list a collect
  1279. bas_make(bas_nr x,
  1280. dpmat!=dpsubst(bas_dpoly x,dpmat_list b)),
  1281. cali!=degrees)
  1282. where cali!=degrees:=dpmat_coldegs b;
  1283. symbolic procedure dpmat_times_dpoly(f,m);
  1284. % Returns f * m for the dpoly f and the dpmat m.
  1285. dpmat_make(dpmat_rows m,dpmat_cols m,
  1286. for each x in dpmat_list m collect
  1287. bas_make1(bas_nr x, dp_prod(f,bas_dpoly x),
  1288. dp_prod(f,bas_rep x)),
  1289. cali!=degrees) where cali!=degrees:=dpmat_coldegs m;
  1290. symbolic procedure dpmat_neg a;
  1291. % Returns - a.
  1292. dpmat_make(
  1293. dpmat_rows a,
  1294. dpmat_cols a,
  1295. for each x in dpmat_list a collect
  1296. bas_make1(bas_nr x,dp_neg bas_dpoly x, dp_neg bas_rep x),
  1297. cali!=degrees) where cali!=degrees:=dpmat_coldegs a;
  1298. symbolic procedure dpmat_diff(a,b);
  1299. % Returns a - b.
  1300. dpmat_sum(a,dpmat_neg b);
  1301. symbolic procedure dpmat_sum(a,b);
  1302. % Returns a + b.
  1303. if not (eqn(dpmat_rows a,dpmat_rows b)
  1304. and eqn(dpmat_cols a, dpmat_cols b)
  1305. and equal(dpmat_coldegs a,dpmat_coldegs b)) then
  1306. rerror('dpmat,2,"matrices don't match for MATSUM")
  1307. else (begin scalar u,v,w;
  1308. u:=dpmat_list a; v:=dpmat_list b;
  1309. w:=for i:=1:dpmat_rows a collect
  1310. (bas_make1(i,dp_sum(bas_dpoly x,bas_dpoly y),
  1311. dp_sum(bas_rep x,bas_rep y))
  1312. where y= bas_getelement(i,v),
  1313. x= bas_getelement(i,u));
  1314. return dpmat_make(dpmat_rows a,dpmat_cols a,w,cali!=degrees);
  1315. end) where cali!=degrees:=dpmat_coldegs a;
  1316. symbolic procedure dpmat_from_dpoly p;
  1317. dpmat_make(1,0,list bas_make(1,p),nil);
  1318. symbolic procedure dpmat_unit(n,degs);
  1319. % Returns the unit dpmat of size n.
  1320. dpmat_make(n,n, for i:=1:n collect bas_make(i,dp_from_ei i),degs);
  1321. symbolic procedure dpmat_transpose m;
  1322. % Returns transposed m with consistent column degrees.
  1323. if (dpmat_cols m = 0) then dpmat!=transpose ideal2mat!* m
  1324. else dpmat!=transpose m;
  1325. symbolic procedure dpmat!=transpose m;
  1326. (begin scalar b,p,q;
  1327. cali!=degrees:=
  1328. for each x in dpmat_rowdegrees m collect
  1329. (car x).(mo_neg cdr x);
  1330. for i:=1:dpmat_cols m do
  1331. << p:=nil;
  1332. for j:=1:dpmat_rows m do
  1333. << q:=dpmat_element(j,i,m);
  1334. if q then p:=dp_sum(p,dp_times_ei(j,q))
  1335. >>;
  1336. if p then b:=bas_make(i,p) . b;
  1337. >>;
  1338. return dpmat_make(dpmat_cols m,dpmat_rows m,reverse b,
  1339. cali!=degrees);
  1340. end) where cali!=degrees:=cali!=degrees;
  1341. symbolic procedure ideal2mat!* u;
  1342. % Returns u as column vector if dpmat_cols u = 0.
  1343. if dpmat_cols u neq 0 then
  1344. rerror('dpmat,4,"IDEAL2MAT only for ideal bases")
  1345. else dpmat_make(dpmat_rows u,1,
  1346. for each x in dpmat_list u collect
  1347. bas_make(bas_nr x,dp_times_ei(1,bas_dpoly x)),
  1348. nil) where cali!=degrees:=nil;
  1349. symbolic procedure dpmat_renumber old;
  1350. % Renumber dpmat_list old.
  1351. % Returns (new . change) with new = change * old.
  1352. if null dpmat_list old then (old . dpmat_unit(dpmat_rows old,nil))
  1353. else (begin scalar i,u,v,w;
  1354. cali!=degrees:=dpmat_rowdegrees old;
  1355. i:=0; u:=dpmat_list old;
  1356. while u do
  1357. <<i:=i+1; v:=bas_newnumber(i,car u) . v;
  1358. w:=bas_make(i,dp_from_ei bas_nr car u) . w ; u:=cdr u>>;
  1359. return dpmat_make(i,dpmat_cols old,
  1360. reverse v,dpmat_coldegs old) .
  1361. dpmat_make(i,dpmat_rows old,reverse w,cali!=degrees);
  1362. end) where cali!=degrees:=cali!=degrees;
  1363. symbolic procedure mathomogenize!*(m,var);
  1364. % Returns m with homogenized rows using the var. name var.
  1365. dpmat_make(dpmat_rows m, dpmat_cols m,
  1366. bas_homogenize(dpmat_list m,var), cali!=degrees)
  1367. where cali!=degrees:=dpmat_coldegs m;
  1368. symbolic operator mathomogenize;
  1369. symbolic procedure mathomogenize(m,v);
  1370. % Returns the homogenized matrix of m with respect to the variable v.
  1371. if !*mode='symbolic then rederr"only for algebraic mode"
  1372. else dpmat_2a mathomogenize!*(dpmat_from_a reval m,v);
  1373. symbolic procedure matdehomogenize!*(m,var);
  1374. % Returns m with var. name var set equal to one.
  1375. dpmat_make(dpmat_rows m, dpmat_cols m,
  1376. bas_dehomogenize(dpmat_list m,var), cali!=degrees)
  1377. where cali!=degrees:=dpmat_coldegs m;
  1378. symbolic procedure dpmat_sieve(m,vars);
  1379. % Apply bas_sieve to dpmat_list m.
  1380. dpmat_make(length x,dpmat_cols m,x,cali!=degrees)
  1381. where x=bas_sieve(dpmat_list m,vars)
  1382. where cali!=degrees:=dpmat_coldegs m;
  1383. symbolic procedure dpmat_neworder m;
  1384. % Apply bas_neworder to dpmat_list m with current cali!=degrees.
  1385. dpmat_make(dpmat_rows m,dpmat_cols m,
  1386. bas_neworder dpmat_list m,cali!=degrees);
  1387. symbolic procedure dpmat_zero!? m;
  1388. % Test whether m is a zero dpmat.
  1389. bas_zero!? dpmat_list m;
  1390. procedure dpmat_project(m,k);
  1391. % Project the dpmat m onto its first k components.
  1392. dpmat_make(dpmat_rows m,k,
  1393. for each x in dpmat_list m collect
  1394. bas_make(bas_nr x,dp_project(bas_dpoly x,k)),
  1395. dpmat_coldegs m);
  1396. % ---------- Interface to algebraic mode
  1397. symbolic procedure dpmat_2a m;
  1398. % Convert the dpmat m to a matrix (c>0) or a polynomial list (c=0) in
  1399. % algebraic (pseudo)prefix form.
  1400. if dpmat_cols m=0 then bas_2a dpmat_list m
  1401. else 'mat .
  1402. if dpmat_rows m=0 then list for j:=1:dpmat_cols m collect 0
  1403. else for i:=1:dpmat_rows m collect
  1404. for j:=1:dpmat_cols m collect
  1405. dp_2a dpmat_element(i,j,m);
  1406. symbolic procedure dpmat_from_a m;
  1407. % Convert an algebraic polynomial list or matrix expression into a
  1408. % dpmat with respect to the current setting of cali!=degrees.
  1409. if eqcar(m,'mat) then
  1410. begin integer i; scalar u,p; m:=cdr m;
  1411. for each x in m do
  1412. << i:=1; p:=nil;
  1413. for each y in x do
  1414. << p:=dp_sum(p,dp_times_ei(i,dp_from_a reval y)); i:=i+1 >>;
  1415. u:=bas_make(0,p).u
  1416. >>;
  1417. return dpmat_make(length m,length car m,
  1418. bas_renumber reversip u, cali!=degrees);
  1419. end
  1420. else if eqcar(m,'list) then
  1421. ((begin scalar x; x:=bas_from_a reval m;
  1422. return dpmat_make(length x,0,x,nil)
  1423. end) where cali!=degrees:=nil)
  1424. else typerr(m,"polynomial list or matrix");
  1425. % ---- Substitution in dpmats --------------
  1426. symbolic procedure dpmat_sub(a,m);
  1427. % a=list of (var . alg. prefix form) to be substituted into the dpmat
  1428. % m.
  1429. dpmat_from_a subeval1(a,dpmat_2a m)
  1430. where cali!=degrees:=dpmat_coldegs m;
  1431. % ------------- Determinant ------------------------
  1432. symbolic procedure dpmat_det m;
  1433. % Returns the determinant of the dpmat m.
  1434. if dpmat_rows m neq dpmat_cols m then rederr "non-square matrix"
  1435. else dp_from_a prepf numr detq matsm dpmat_2a m;
  1436. endmodule; % dpmat
  1437. module red;
  1438. COMMENT
  1439. #################
  1440. ## ##
  1441. ## NORMAL FORM ##
  1442. ## ALGORITHMS ##
  1443. ## ##
  1444. #################
  1445. This module contains normal form algorithms for base elements. All
  1446. reductions executed on the dpoly part, are repeated on the rep part,
  1447. hence tracing them up for further use. In several places they are
  1448. managed as
  1449. <model>::=(dpoly part).(rep part).
  1450. The output trace intensity can be managed with the global parameter
  1451. cali!=trace that has the following meaning :
  1452. cali!=trace >= 0 no trace
  1453. 10 '.' for each substitution
  1454. 70 trace interreduce!*
  1455. 80 trace redpol
  1456. 90 show substituents
  1457. The reduction strategy is first matching in the simplifier (base)
  1458. list. It can be changed overloading red_better, the relation
  1459. according to what base lists are sorted. Standard is minimal ecart,
  1460. breaking ties with minimal length (since such a strategy is good for
  1461. both the classical and the local case).
  1462. The module "mora" contains additional and special procedures for the
  1463. local case. The local case can be activated by "off noetherian".
  1464. Switches :
  1465. red_total : t compute total normal forms
  1466. nil reduce only until lt is standard
  1467. bcsimp : t apply bas_simp
  1468. binomial : t Allow multireduction. Only for
  1469. binomial ideals without
  1470. representation part.
  1471. END COMMENT;
  1472. % Standard is :
  1473. !*red_total:=t;
  1474. !*bcsimp:=t;
  1475. !*binomial:=nil;
  1476. symbolic procedure red_better(a,b);
  1477. % Base list sort criterion. Simplifier lists are sorted such that the
  1478. % best substituent comes first.
  1479. if bas_dpecart a < bas_dpecart b then t
  1480. else if bas_dpecart a > bas_dpecart b then nil
  1481. else bas_dplen a < bas_dplen b;
  1482. symbolic procedure red_subst(model,basel);
  1483. % model and basel = base elements
  1484. % Returns (model1 . z) with model1 a base element
  1485. % and base coeff. z
  1486. % such that
  1487. %
  1488. % pol_new := z * pol_old - z1 * mo * f_a
  1489. % rep_new := z * rep_old - z1 * mo * rep_a
  1490. %
  1491. % with appropriate base coeff. z and z1 and monomial mo.
  1492. if !*binomial then red!=subst2(model,basel)
  1493. else red!=subst1(model,basel);
  1494. symbolic procedure red!=subst1(model,basel);
  1495. begin scalar polold,polnew,repold,repnew,gcd,mo,fa,z,z1;
  1496. polold:=bas_dpoly model; z1:=dp_lc polold;
  1497. repold:=bas_rep model;
  1498. fa:=bas_dpoly basel; z:= dp_lc fa;
  1499. if !*bcsimp then % modify z and z1
  1500. if (gcd:=bc_inv z) then
  1501. << z1:=bc_prod(z1,gcd); z:=bc_fi 1 >>
  1502. else
  1503. << gcd:=bc_gcd(z,z1);
  1504. z:=car bc_divmod(z,gcd);
  1505. z1:=car bc_divmod(z1,gcd)
  1506. >>;
  1507. mo:=mo_diff(dp_lmon polold,dp_lmon fa);
  1508. polnew:=dp_diff(dp_times_bc(z,polold),
  1509. dp_times_bcmo(z1,mo,fa));
  1510. repnew:=dp_diff(dp_times_bc(z,repold),
  1511. dp_times_bcmo(z1,mo,bas_rep basel));
  1512. if cali!=trace > 79 then
  1513. << prin2 "---> "; dp_print polnew >>
  1514. else if cali!=trace > 0 then prin2 ".";
  1515. if cali!=trace > 89 then
  1516. << prin2 " uses "; dp_print fa >>;
  1517. return bas_make1(bas_nr model,polnew,repnew) . z;
  1518. end;
  1519. symbolic procedure red!=subst2(model,basel);
  1520. % Only for binomials without representation parts.
  1521. begin scalar m,b,u,r;
  1522. if cali!=trace>0 then prin2 ".";
  1523. m:=bas_dpoly model; b:=bas_dpoly basel;
  1524. if (length b neq 2) or bas_rep model then
  1525. rederr"switch off binomial";
  1526. u:=mo_qrem(dp_lmon m,dp_lmon b);
  1527. r:=list dp_term(dp_lc m,
  1528. mo_sum(mo_power(dp_lmon cdr b,car u),cdr u));
  1529. return bas_make(bas_nr model,dp_sum(r,cdr m)) . bc_fi 1;
  1530. end;
  1531. symbolic procedure red_redpol(bas,model);
  1532. % Takes model = a base element and bas = a base list.
  1533. % Returns (model1 . z) with model1 a base element (nr,pol1,rep1) and
  1534. % pol1 = z * pol + \sum c_a f_a
  1535. % rep1 = z * rep + \sum c_a rep_a.
  1536. % No extra simplification is done since otherwise z should be
  1537. % divided. z is a polynomial unit, i.e. of degree 0.
  1538. if (null bas_dpoly model) or (null bas) then model . dp_fi 1
  1539. else begin
  1540. scalar z,v,pol1,rep1,pol,rep,z1,q;
  1541. z:=bc_fi 1;
  1542. if cali!=trace>79 then
  1543. << write" reduce "; dp_print bas_dpoly model >>;
  1544. while (q:=bas_dpoly model) and (v:=red_divtest(bas,dp_lmon q)) do
  1545. << v:=red_subst(model,v); model:=car v;
  1546. z:=bc_prod(z,cdr v)
  1547. >>;
  1548. % Now we've got a model with standard leading term.
  1549. if !*red_total and bas_dpoly model
  1550. and (v:=cdr bas_dpoly model) then
  1551. % If pol = q + rem and
  1552. % (z*q+)rem1 = z*(q+)rem + \sum e_a*f_a then
  1553. % rep1 = z*rep + \sum e_a*rep_a
  1554. % is the correct representation of z*q+rem1.
  1555. << pol:=bas_dpoly model; % Uses only lt:=lt(pol) below
  1556. v:=bas_make1(bas_nr model,v,bas_rep model);
  1557. % v = cdr pol
  1558. v:=red_redpol(bas,v); % is now (model1 . z1)
  1559. z1:=cdr v; z:=bc_prod(z,dp_lc z1);
  1560. pol1:=bas_dpoly car v; rep:=bas_rep car v;
  1561. pol:=dp_term(bc_prod(dp_lc z1,dp_lc pol), dp_lmon pol)
  1562. . pol1; % pol := z1 * lt + pol1
  1563. model:=bas_make1(bas_nr model,pol,rep);
  1564. >>;
  1565. return model . dp_fbc z;
  1566. end;
  1567. % ----- Interface to symbolic mode computations with dpmat's --
  1568. symbolic procedure red!=sort(a,b);
  1569. % This term order must refine the division order.
  1570. eqn(mo_compare(dp_lmon bas_dpoly a,dp_lmon bas_dpoly b),1);
  1571. symbolic procedure red_straight bas;
  1572. % Autoreduce straightening formulae of the base list bas. Applicable
  1573. % only to noetherian term orders.
  1574. begin scalar u;
  1575. u:=red!=redstraight1 sort(bas,function red!=sort);
  1576. if !*bcsimp then u:=bas_simp u;
  1577. return sort(u,function red_better);
  1578. end;
  1579. symbolic procedure red!=redstraight1 bas;
  1580. if null bas then nil
  1581. else (car red_redpol(cdr bas,car bas)) . red!=redstraight1 cdr bas;
  1582. symbolic procedure red_divtest(a,b);
  1583. % Returns the first f in the base list a, such that lt(f) | b else nil.
  1584. % b is a monomial.
  1585. if null a then nil
  1586. else if mo_vdivides!?(dp_lmon bas_dpoly car a,b) then car a
  1587. else red_divtest(cdr a,b);
  1588. symbolic procedure red_collect bas;
  1589. % Returns ( bas1 . bas2 ), where bas2 may be reduced with bas1.
  1590. begin scalar bas1,bas2;
  1591. bas1:=listminimize(bas,function (lambda(x,y);
  1592. mo_vdivides!?(dp_lmon bas_dpoly x,dp_lmon bas_dpoly y)));
  1593. bas2:=setdiff(bas,bas1);
  1594. return bas1 . bas2;
  1595. end;
  1596. symbolic procedure red_interreduce m;
  1597. % Reduce rows of the base list m until it has pairwise incomparable
  1598. % leading terms. If red_total is on then do also autoreduction.
  1599. % Compute correct representation parts.
  1600. begin scalar c,w,bas1,pol,rep;
  1601. m:=bas_sort bas_zerodelete m;
  1602. if !*bcsimp then m:=bas_simp m;
  1603. while cdr (c:=red_collect m) do
  1604. << if cali!=trace>69 then
  1605. <<write" interreduce ";terpri();bas_print m>>;
  1606. m:=nil; w:=cdr c; bas1:=car c;
  1607. while w do
  1608. << c:=car red_redpol(bas1,car w);
  1609. if bas_dpoly c then m:=c . m;
  1610. w:=cdr w
  1611. >>;
  1612. if !*bcsimp then m:=bas_simp m;
  1613. m:=merge(bas1,bas_sort m,function red_better);
  1614. >>;
  1615. if !*red_total then m:=red_straight m;
  1616. return m;
  1617. end;
  1618. endmodule; % red
  1619. module groeb;
  1620. COMMENT
  1621. ##############################
  1622. ## ##
  1623. ## GROEBNER PACKAGE ##
  1624. ## ##
  1625. ##############################
  1626. The trace intensity can be managed with cali!=trace by the following
  1627. rules :
  1628. cali!=trace >= 0 no trace
  1629. 2 show actual step
  1630. 10 show input and output
  1631. 20 show new base elements
  1632. 30 show pairs
  1633. 40 show actual pairlist
  1634. 50 show S-polynomials
  1635. Pair lists have the following informal syntax :
  1636. <spairlist>::= list of spairs
  1637. < spair > ::= (komp groeb!=weight lcm p_i p_j)
  1638. with lcm = lcm(lt(bas_dpoly p_i),lt(bas_dpoly p_j)).
  1639. The pair selection strategy is by first matching in the pair list.
  1640. It can be changed overloading groeb!=better, the relation according to
  1641. what pair lists are sorted. Standard is the sugar strategy.
  1642. cali!=monset :
  1643. One can manage a list of variables, that are allowed to be canceled
  1644. out, if they appear as common factors in a dpoly. This is possible if
  1645. these variables are non zero divisors (e.g. for prime ideals) and
  1646. affects "pure" Groebner basis computation only.
  1647. END COMMENT;
  1648. % ---------- Global variables ------------------------------
  1649. % Standard :
  1650. symbolic procedure groeb_stbasis(bas,comp_mgb,comp_ch,comp_syz);
  1651. % Returns { mgb , change , syz } with
  1652. % dpmat mgb = (if comp_mgb=true the minimal)
  1653. % Groebner basis of the dpmat bas.
  1654. % dpmat change defined by mgb = change * bas
  1655. % if comp_ch = true.
  1656. % dpmat syz = (not interreduced) syzygy matrix of the dpmat bas
  1657. % if comp_syz = true.
  1658. if dpmat_zero!? bas then
  1659. {bas,dpmat_unit(dpmat_rows bas,nil),
  1660. dpmat_unit(dpmat_rows bas,nil)}
  1661. else (begin scalar u,syz,change,syz1,mon_set;
  1662. if comp_ch or comp_syz then mon_set:=nil else mon_set:=cali!=monset;
  1663. if comp_syz then % syzygies for zero base elements.
  1664. << u:=setdiff(for i:=1:dpmat_rows bas collect i,
  1665. for each x in dpmat_list bas collect bas_nr x);
  1666. syz1:=for each x in u collect bas_make(0,dp_from_ei x);
  1667. >>;
  1668. u:=groeb_innerstbasis(bas,comp_ch,comp_syz,mon_set); syz:=cadr u;
  1669. if comp_mgb then
  1670. << u:=groeb_mingb car u;
  1671. if !*red_total then
  1672. u:=dpmat_make(dpmat_rows u,dpmat_cols u,
  1673. red_straight dpmat_list u,
  1674. cali!=degrees);
  1675. >>
  1676. else u:=car u;
  1677. cali!=degrees:=dpmat_rowdegrees bas;
  1678. if comp_ch then
  1679. change:=dpmat_make(dpmat_rows u,dpmat_rows bas,
  1680. bas_neworder bas_getrelations dpmat_list u,
  1681. cali!=degrees);
  1682. bas_removerelations dpmat_list u;
  1683. if comp_syz then
  1684. << syz:=nconc(syz,syz1);
  1685. syz:= dpmat_make(length syz,dpmat_rows bas,
  1686. bas_neworder bas_renumber syz,cali!=degrees);
  1687. >>;
  1688. cali!=degrees:=dpmat_coldegs u;
  1689. return {u,change,syz}
  1690. end) where cali!=degrees:=dpmat_coldegs bas;
  1691. symbolic procedure groeb_innerstbasis(bas,comp_ch,comp_syz,mon_set1);
  1692. % Returns ( gb . syz . trace ) with change on the relations part of
  1693. % gb, where
  1694. % dpmat gb is the Groebner basis
  1695. % base list syz is the dpmat_list of the syzygy matrix of bas
  1696. % spairlist trace is the Groebner trace.
  1697. begin integer i;
  1698. scalar u,q,gb,syz,p,pl,pol,rep,trace,nr, return_by_unit, Ccrit;
  1699. % -------- Initialization
  1700. gb:=bas_sort dpmat_list bas;
  1701. if comp_ch or comp_syz then bas_setrelations gb;
  1702. Ccrit:=(not comp_syz) and (dpmat_cols bas<2);
  1703. % -- don't reduce main syzygies
  1704. nr:=dpmat_rows bas; % the number of the last base element inserted
  1705. if cali!=trace > 0 then
  1706. <<terpri(); write" Computing Groebner basis ";terpri()>>;
  1707. if cali!=trace > 5 then
  1708. << terpri(); write" Compute Groebner basis of"; bas_print gb >>;
  1709. pl:=groeb_makepairlist(gb,Ccrit);
  1710. if cali!=trace > 30 then groeb_printpairlist pl;
  1711. if cali!=trace > 5 then
  1712. <<terpri(); write" New base elements :";terpri() >>;
  1713. % -------- working out pair list
  1714. while pl and not return_by_unit do
  1715. << % ------- Choose a pair
  1716. p:=car pl; pl:=cdr pl;
  1717. % ------ compute S-polynomial (which is a modelement)
  1718. if cali!=trace > 10 then groeb_printpair(p,pl);
  1719. pol:=groeb_spol p;
  1720. if cali!=trace > 70 then
  1721. << terpri(); write" S.-pol : ";
  1722. dp_print1(bas_dpoly pol,nil)
  1723. >>;
  1724. pol:=car red_redpol(gb,pol);
  1725. if cali!=trace > 70 then
  1726. << terpri(); write" Reduced S.-pol. : ";
  1727. dp_print1(bas_dpoly pol,nil)
  1728. >>;
  1729. if !*bcsimp then pol:=car bas_simpelement pol;
  1730. if bas_dpoly pol then
  1731. % --- the S-polynomial doesn't reduce to zero
  1732. << nr:=nr+1;
  1733. pol:=bas_newnumber(nr,pol);
  1734. if mon_set1 then
  1735. pol:=bas_make(nr,
  1736. car dp_mondelete(bas_dpoly pol,mon_set1));
  1737. % --- update the tracelist
  1738. q:=bas_dpoly pol;
  1739. trace:=list(groeb!=i p,groeb!=j p,nr,dp_lmon q) . trace;
  1740. if cali!=trace > 20 then
  1741. << terpri(); write nr,". ---> ";
  1742. dp_print1(q,nil); terpri()
  1743. >>;
  1744. if Ccrit and (dp_unit!? q) then return_by_unit:=t;
  1745. % ----- updating pairlist
  1746. if not return_by_unit then
  1747. << pl:=groeb_updatePL(pl,gb,pol,Ccrit);
  1748. if cali!=trace > 30 then
  1749. << terpri(); groeb_printpairlist pl >>;
  1750. >>;
  1751. gb:=merge(list pol,gb,function red_better);
  1752. % --- updating gb
  1753. >>
  1754. else % ------ S-polynomial reduces to zero
  1755. if comp_syz then
  1756. syz:=car bas_simpelement(bas_make(0,bas_rep pol)) . syz
  1757. >>;
  1758. % -------- updating the result
  1759. if return_by_unit then return
  1760. % --- no syzygies are to be computed
  1761. dpmat_make(1,dpmat_cols bas,list(bas_newnumber(nr,pol)),
  1762. cali!=degrees) . nil . reversip trace;
  1763. gb:=dpmat_make(length gb,dpmat_cols bas,gb,cali!=degrees);
  1764. return gb . syz . reversip trace
  1765. end;
  1766. % ---------- Critical pair criteria -----------------------
  1767. symbolic procedure groeb!=critA(p);
  1768. if null p then nil
  1769. else reversip groeb!=critA1(nil,p);
  1770. symbolic procedure groeb!=critA1(b,a);
  1771. if null a then b
  1772. else if groeb!=testA1(b,car a) or groeb!=testA2(cdr a,car a) then
  1773. groeb!=critA1(b,cdr a)
  1774. else groeb!=critA1(car a . b,cdr a);
  1775. symbolic procedure groeb!=testA1(u,b);
  1776. % Test, whether komp(a)=komp(b) and lcm(a) | lcm(b) for some a in u.
  1777. if null u then nil
  1778. else ((caar u=car b) and mo_divides!?(nth(car u,3),nth(b,3)))
  1779. or groeb!=testA1(cdr u,b);
  1780. symbolic procedure groeb!=testA2(u,b);
  1781. % Test, whether komp(b)=komp(a) and lcm(a) |<> lcm(b) for some a in u.
  1782. if null u then nil
  1783. else ((caar u=car b) and mo_divides!?(nth(car u,3),nth(b,3))
  1784. and not mo_equal!?(nth(car u,3),nth(b,3)))
  1785. or groeb!=testA2(cdr u,b);
  1786. symbolic procedure groeb!=critB(e,p);
  1787. % Delete pairs from p, for which testB is false.
  1788. for each x in p join if not groeb!=testB(e,x) then {x};
  1789. symbolic procedure groeb!=testB(e,a);
  1790. % e=lt(f_k). Test, whether for a=pair (i j)
  1791. % komp(a)=komp(e) and Syz(i,j,k)=[ 1 * * ].
  1792. (mo_comp e=car a)
  1793. and mo_divides!?(e,nth(a,3))
  1794. and (not mo_equal!?(mo_lcm(dp_lmon bas_dpoly nth(a,5),e),
  1795. nth(a,3)))
  1796. and (not mo_equal!?(mo_lcm(dp_lmon bas_dpoly nth(a,4),e),
  1797. nth(a,3)));
  1798. symbolic procedure groeb!=critC(p);
  1799. % Delete main syzygies.
  1800. for each x in p join if not groeb!=testC1 x then {x};
  1801. symbolic procedure groeb!=testC1 el;
  1802. mo_equal!?(
  1803. mo_sum(dp_lmon bas_dpoly nth(el,5),
  1804. dp_lmon bas_dpoly nth(el,4)),
  1805. nth(el,3));
  1806. symbolic procedure groeb_updatePL(p,gb,be,Ccrit);
  1807. % Update the pairlist p with the new base element be and the old ones
  1808. % in the base list gb. Discard pairs where both base elements have
  1809. % number part 0.
  1810. begin scalar p1,k,a,n; n:=(bas_nr be neq 0);
  1811. a:=dp_lmon bas_dpoly be; k:=mo_comp a;
  1812. for each b in gb do
  1813. if (k=mo_comp dp_lmon bas_dpoly b)
  1814. and(n or (bas_nr b neq 0)) then
  1815. p1:=groeb!=newpair(k,b,be).p1;
  1816. p1:=groeb!=critA(sort(p1,function groeb!=better));
  1817. if Ccrit then p1:=groeb!=critC p1;
  1818. return
  1819. merge(p1,
  1820. groeb!=critB(a,p), function groeb!=better);
  1821. end;
  1822. symbolic procedure groeb_makepairlist(gb,Ccrit);
  1823. begin scalar newgb,p;
  1824. while gb do
  1825. << p:=groeb_updatePL(p,newgb,car gb,Ccrit);
  1826. newgb:=car gb . newgb;
  1827. gb:=cdr gb
  1828. >>;
  1829. return p;
  1830. end;
  1831. % -------------- S-pair list constructions --------------------
  1832. symbolic procedure groeb!=i p; bas_nr nth(p,4);
  1833. symbolic procedure groeb!=j p; bas_nr nth(p,5);
  1834. symbolic procedure groeb!=better(a,b);
  1835. % True if the Spair a is better than the Spair b.
  1836. if (cadr a < cadr b) then t
  1837. else if (cadr a = cadr b) then mo_compare(nth(a,3),nth(b,3))<=0
  1838. else nil;
  1839. symbolic procedure groeb!=weight(lcm,p1,p2);
  1840. mo_ecart(lcm) + min2(bas_dpecart p1,bas_dpecart p2);
  1841. symbolic procedure groeb!=newpair(k,p1,p2);
  1842. % Make an spair from base elements with common component number k.
  1843. list(k,groeb!=weight(lcm,p1,p2),lcm, p1,p2)
  1844. where lcm =mo_lcm(dp_lmon bas_dpoly p1,dp_lmon bas_dpoly p2);
  1845. symbolic procedure groeb_printpairlist p;
  1846. begin
  1847. for each x in p do
  1848. << write groeb!=i x,".",groeb!=j x; print_lf " | " >>;
  1849. terpri();
  1850. end;
  1851. symbolic procedure groeb_printpair(pp,p);
  1852. begin terpri();
  1853. write"Investigate (",groeb!=i pp,".",groeb!=j pp,") ",
  1854. "Pair list has length ",length p; terpri()
  1855. end;
  1856. % ------------- S-polynomial constructions -----------------
  1857. symbolic procedure groeb_spol pp;
  1858. % Make an S-polynomial from the spair pp, i.e. return
  1859. % a base element with
  1860. % dpoly = ( zi*mi*(red) pi - zj*mj*(red) pj )
  1861. % rep = (zi*mi*rep_i - zj*mj*rep_j),
  1862. %
  1863. % where mi=lcm/lm(pi), mj=lcm/lm(pj)
  1864. % and zi and zj are appropriate scalars.
  1865. %
  1866. begin scalar pi,pj,ri,rj,zi,zj,lcm,mi,mj,a,b;
  1867. a:=nth(pp,4); b:=nth(pp,5); lcm:=nth(pp,3);
  1868. pi:=bas_dpoly a; pj:=bas_dpoly b; ri:=bas_rep a; rj:=bas_rep b;
  1869. mi:=mo_diff(lcm,dp_lmon pi); mj:=mo_diff(lcm,dp_lmon pj);
  1870. zi:=dp_lc pj; zj:=bc_neg dp_lc pi;
  1871. a:=dp_sum(dp_times_bcmo(zi,mi, cdr pi),
  1872. dp_times_bcmo(zj,mj, cdr pj));
  1873. b:=dp_sum(dp_times_bcmo(zi,mi, ri),
  1874. dp_times_bcmo(zj,mj, rj));
  1875. a:=bas_make1(0,a,b);
  1876. return if !*bcsimp then car bas_simpelement a else a;
  1877. end;
  1878. symbolic procedure groeb_mingb gb;
  1879. % Returns the min. Groebner basis dpmat mgb of the dpmat gb
  1880. % discarding base elements with bas_nr<=0.
  1881. begin scalar u;
  1882. u:=for each x in car red_collect dpmat_list gb join
  1883. if bas_nr x>0 then {x};
  1884. % Choosing base elements with minimal leading terms only.
  1885. return dpmat_make(length u,dpmat_cols gb,bas_renumber u,
  1886. dpmat_coldegs gb);
  1887. end;
  1888. % ------- Minimizing a basis using its syszgies ---------
  1889. symbolic procedure groeb!=delete(l,bas);
  1890. % Delete base elements from the base list bas with number in the
  1891. % integer list l.
  1892. begin scalar b;
  1893. while bas do
  1894. << if not memq(bas_nr car bas,l) then b:=car bas . b;
  1895. bas:= cdr bas
  1896. >>;
  1897. return reverse b
  1898. end;
  1899. symbolic procedure groeb_minimize(bas,syz);
  1900. % Minimize the dpmat pair bas,syz deleting superfluous base elements
  1901. % from bas using syzygies from syz containing unit entries.
  1902. (begin scalar drows, dcols, s,s1,i,j,p,q,y;
  1903. cali!=degrees:=dpmat_coldegs syz;
  1904. s1:=dpmat_list syz; j:=0;
  1905. while j < dpmat_rows syz do
  1906. << j:=j+1;
  1907. if (q:=bas_dpoly bas_getelement(j,s1)) then
  1908. << i:=0;
  1909. while leq(i,dpmat_cols syz) and
  1910. (memq(i,dcols) or not dp_unit!?(p:=dp_comp(i,q)))
  1911. do i:=i+1;
  1912. if leq(i,dpmat_cols syz) then
  1913. << drows:=j . drows;
  1914. dcols:=i . dcols;
  1915. s1:=for each x in s1 collect
  1916. if memq(bas_nr x,drows) then x
  1917. else (bas_make(bas_nr x,
  1918. dp_diff(dp_prod(y,p),dp_prod(q,dp_comp(i,y))))
  1919. where y:=bas_dpoly x);
  1920. >>
  1921. >>
  1922. >>;
  1923. % --- s1 becomes the new syzygy part, s the new base part.
  1924. s1:=bas_renumber bas_simp groeb!=delete(drows,s1);
  1925. s1:=dpmat_make(length s1,dpmat_cols syz,s1,cali!=degrees);
  1926. % The new syzygy matrix of the old basis.
  1927. s:=dpmat_renumber
  1928. dpmat_make(dpmat_rows bas,dpmat_cols bas,
  1929. groeb!=delete(dcols,dpmat_list bas),
  1930. dpmat_coldegs bas);
  1931. s1:=dpmat_mult(s1,dpmat_transpose cdr s);
  1932. % The new syzygy matrix of the new basis, but not yet in the
  1933. % right form since cali!=degrees is empty.
  1934. s:=car s; % The new basis.
  1935. cali!=degrees:=dpmat_rowdegrees s;
  1936. s1:=interreduce!* dpmat_make(dpmat_rows s1,dpmat_cols s1,
  1937. bas_neworder dpmat_list s1,cali!=degrees);
  1938. return s.s1;
  1939. end) where cali!=degrees:=cali!=degrees;
  1940. % ---- Groebner algorithm with factorization and constraint lists.
  1941. symbolic procedure groeb!=problemsort(a,b); nth(a,4)<=nth(b,4);
  1942. % Sorted by ascending easydim to force depth first search.
  1943. symbolic operator groebfactor;
  1944. symbolic procedure groebfactor m;
  1945. if !*mode='symbolic then rederr"only for algebraic mode"
  1946. else makelist
  1947. for each x in groebfactor!*(dpmat_from_a m,dp_fi 1) collect
  1948. dpmat_2a x;
  1949. symbolic procedure groebfactor!*(bas,poly);
  1950. % Returns a list l of mgb's such that
  1951. % V(bas) \intersect D(poly) =
  1952. % \union { V(b) : b \in l } \intersect D(poly)
  1953. % Data structure : problem = (dpmat,constraint list,pair list,easydim)
  1954. % result = dpmat . constraint list
  1955. if dpmat_cols bas > 0 then
  1956. rederr "GROEBFACTORIZE only for ideal bases"
  1957. else if null !*noetherian then
  1958. rederr "GROEBFACTORIZE only for noetherian term orders"
  1959. else if dpmat_zero!? bas then list(bas)
  1960. else begin integer nr; scalar gbs,pl,u,res;
  1961. % -------- Initialization
  1962. if cali!=trace > 5 then
  1963. << write"Compute Groebner basis of"; dpmat_print bas;
  1964. write" Preprocessing basis ... ";terpri()
  1965. >>;
  1966. poly:=if dp_unit!? poly then nil else {poly};
  1967. gbs:=for each x in groeb!=preprocess(nil,bas,poly) collect
  1968. list(car x,cdr x,
  1969. groeb_makepairlist(dpmat_list car x,t),
  1970. easydim!* car x);
  1971. gbs:=sort(gbs,function groeb!=problemsort);
  1972. while gbs do
  1973. << if cali!=trace>10 then
  1974. print for each x in gbs collect nth(x,4);
  1975. u:=groeb!=slave car gbs; gbs:=cdr gbs;
  1976. if u then
  1977. if second u then % a result
  1978. << u:=car second u;
  1979. if cali!=trace > 5 then
  1980. << write"partial result :"; terpri();
  1981. dpmat_print car u ;
  1982. prin2"constraints : ";
  1983. for each x in cdr u do dp_print x;
  1984. >>;
  1985. if not groeb!=redtest(res,car u) then
  1986. res:=u . groeb!=sieve(res,car u);
  1987. >>
  1988. else % a new problem list
  1989. << u:=first u;
  1990. for each x in u do
  1991. if not groeb!=redtest(res,car x) then
  1992. gbs:=groeb!=update(gbs,x);
  1993. if cali!=trace>20 then
  1994. << terpri(); write length gbs," remaining branches. ",
  1995. length res," partial results"; terpri()
  1996. >>;
  1997. >>
  1998. else % branch discarded
  1999. if cali!=trace>20 then print"Branch discarded";
  2000. >>;
  2001. return for each x in res collect car x;
  2002. end;
  2003. symbolic procedure groeb!=redtest(a,c);
  2004. % Ex. u \in a : car u \submodule c
  2005. listtest(a,c,function(lambda(x,y); submodulep!*(car x,y)));
  2006. symbolic procedure groeb!=sieve(a,c);
  2007. % Remove u \in a with c \submodule car u.
  2008. for each x in a join if not submodulep!*(c,car x) then {x};
  2009. symbolic procedure groeb!=update(gbs,P);
  2010. % Update problem list gbs with a new problem P=(p,c_p,pl_p,dim_p) .
  2011. begin scalar u,con;
  2012. if (u:=groeb!=redtest(gbs,car p)) then
  2013. cdr u:=intersection(second u,second p) . cddr u
  2014. else
  2015. << con:=second p;
  2016. gbs:=for each x in gbs join
  2017. if submodulep!*(car p,car x) then
  2018. << con:=intersection(con,second x); >>
  2019. else {x};
  2020. gbs:=merge(gbs,{{ first p, con, third p, nth(p,4) }},
  2021. function groeb!=problemsort);
  2022. >>;
  2023. return gbs;
  2024. end;
  2025. symbolic procedure groeb!=test(con,m);
  2026. if null con then t
  2027. else begin scalar p; p:=car con;
  2028. for each x in cdr con do p:=dp_prod(p,x);
  2029. return bas_dpoly car red_redpol(m,bas_make(0,p));
  2030. end;
  2031. symbolic procedure groeb!=preprocess(a1,b,con);
  2032. % Returns a list of (dpmat . constraint) factoring elements of the
  2033. % dpmat b. a1 is a list of essential results (dpmat . constraint)
  2034. % already computed.
  2035. % Data structure : problem = dpmat . constraint list
  2036. begin scalar a,c,d,back,u,v,p;
  2037. b:=list(b.con);
  2038. if cali!=trace>20 then prin2"preprocessing started";
  2039. while b do
  2040. << if cali!=trace>20 then
  2041. << terpri(); write length a," ready. ";
  2042. write length b," left."; terpri()
  2043. >>;
  2044. c:=car b; b:=cdr b;
  2045. if not (null groeb!=test(con:=cdr c,dpmat_list car c)
  2046. or groeb!=redtest(a1,car c)
  2047. or groeb!=redtest(a,car c)) then
  2048. << d:=dpmat_list car c; back:=nil;
  2049. while d and not back do
  2050. << u:=((fctrf numr simp dp_2a bas_dpoly car d)
  2051. where !*factor=t);
  2052. if (length u>2) or (cdadr u>1) then
  2053. << back:=t; v:=nil;
  2054. for each y in cdr u do
  2055. << p:=dp_from_a prepf car y; v:=(p.con).v;
  2056. if not member(p,con) then con:=p . con;
  2057. >>;
  2058. b:=append(for each y in v collect
  2059. matsum!* {car c,
  2060. dpmat_make(1,0, list bas_make(1,car y),nil)}
  2061. . cdr y,
  2062. b);
  2063. >>
  2064. else d:=cdr d
  2065. >>;
  2066. if not back then
  2067. << if cali!=trace>20 then
  2068. << terpri(); write"Subproblem :"; dpmat_print car c >>;
  2069. a:=c . groeb!=sieve(a,car c)
  2070. >>
  2071. >>
  2072. >>;
  2073. if cali!=trace>20 then prin2"preprocessing finished...";
  2074. return a;
  2075. end;
  2076. symbolic procedure groeb!=slave c;
  2077. begin integer i; scalar be,back,p,u,v,a,b,gb,pl,nr,pol,con;
  2078. back:=nil;
  2079. gb:=dpmat_list first c; con:=second c; pl:=third c; nr:=length gb;
  2080. while pl and not back do
  2081. << p:=car pl; pl:=cdr pl;
  2082. if cali!=trace > 10 then groeb_printpair(p,pl);
  2083. pol:=groeb_spol p;
  2084. if cali!=trace > 70 then
  2085. << terpri(); write"S.-pol : "; dp_print1(bas_dpoly pol,nil) >>;
  2086. pol:=bas_dpoly car red_redpol(gb,pol);
  2087. if cali!=trace > 70 then
  2088. << terpri(); write"Reduced S.-pol. : "; dp_print1(pol,nil) >>;
  2089. if pol then
  2090. << if !*bcsimp then pol:=car dp_simp pol;
  2091. if dp_unit!? pol then
  2092. << if cali!=trace>20 then print "unit ideal";
  2093. back:=t
  2094. >>
  2095. else
  2096. << % -- factorize pol
  2097. u:=((fctrf numr simp dp_2a pol) where !*factor=t);
  2098. nr:=nr+1;
  2099. if length cdr u=1 then % only one factor
  2100. << pol:=dp_from_a prepf caadr u;
  2101. be:=bas_make(nr,pol);
  2102. u:=be.gb;
  2103. if null groeb!=test(con,u) then
  2104. << back:=t;
  2105. if cali!=trace>20 then print" zero constraint";
  2106. >>
  2107. else
  2108. << if cali!=trace>20 then
  2109. << terpri(); write nr,". "; dp_print1( pol,nil) >>;
  2110. pl:=groeb_updatePL(pl,gb,be,t);
  2111. if cali!=trace > 30 then
  2112. << terpri(); groeb_printpairlist pl >>;
  2113. gb:=merge(list be,gb,function red_better);
  2114. >>
  2115. >>
  2116. else % more than one factor
  2117. << for each x in cdr u do
  2118. << pol:=dp_from_a prepf car x;
  2119. be:=bas_make(nr,pol);
  2120. a:=be.gb;
  2121. if groeb!=test(con,a) then
  2122. << if cali!=trace>20 then
  2123. << terpri(); write nr; write". ";
  2124. dp_print1( pol,nil)
  2125. >>;
  2126. p:=groeb_updatePL(append(pl,nil),gb,be,t);
  2127. if cali!=trace > 30 then
  2128. << terpri(); groeb_printpairlist p >>;
  2129. b:=merge(list be,append(gb,nil),
  2130. function red_better);
  2131. b:=dpmat_make(length b,0,b,nil);
  2132. v:={b,con,p}.v;
  2133. >>
  2134. else if cali!=trace>20 then print" zero constraint";
  2135. if not member(pol,con) then con:=pol . con;
  2136. >>;
  2137. if null v then
  2138. << if cali!=trace>20 then print "Branch canceled";
  2139. back:=t
  2140. >>
  2141. else if length v=1 then
  2142. << c:=car v; gb:=dpmat_list first c; con:=second c;
  2143. pl:=third c; v:=nil;
  2144. >>
  2145. else
  2146. << back:=t;
  2147. if cali!=trace>20 then
  2148. << write" Branching into ",length v," parts ";
  2149. terpri();
  2150. >>;
  2151. >>;
  2152. >>;
  2153. >>;
  2154. >>;
  2155. >>;
  2156. if not back then % pl exhausted => new partial result.
  2157. << u:=groeb_mingb dpmat_make(length gb,0,gb,nil);
  2158. if !*red_total then
  2159. % interreduce and try factorization once more.
  2160. << u:=groeb!=preprocess(nil,
  2161. dpmat_make(dpmat_rows u,0,
  2162. red_straight dpmat_list u,nil),con);
  2163. if length u>1 then
  2164. << v:=for each x in u collect
  2165. {car x,cdr x,groeb_makepairlist(dpmat_list car x,t)};
  2166. back:=t
  2167. >>
  2168. else u:=car u;
  2169. >>
  2170. >>;
  2171. if back then return
  2172. {for each x in v collect
  2173. {first x,second x,third x,easydim!* first x},
  2174. nil}
  2175. else if u then return {nil,list u}
  2176. else return nil;
  2177. end;
  2178. endmodule; % groeb
  2179. module mora;
  2180. COMMENT
  2181. ######################
  2182. ## ##
  2183. ## STANDARD BASIS ##
  2184. ## ALGORITHMS ##
  2185. ## ##
  2186. ######################
  2187. This module contains the modifications to the modules red and groeb
  2188. necessary for non noetherian term orders. Consult the comments given
  2189. there for the meaning of several parameters, switches etc.
  2190. We make use of encoupled ecart vectors, hence all algorithms work for
  2191. arbitrary term orders (even for pure rev.-lex.).
  2192. "on lazy" turns on the lazy strategy of the tangent cone algorithm
  2193. (the default). Otherwise we use Lazard's approach with
  2194. homogenization.
  2195. The following options effect the computation only if no
  2196. representation part has to be computed :
  2197. "on factorunits" tries to remove unit factors (i.e. with deg lt(f)=0)
  2198. from polynomials by factorization.
  2199. "on detectunits" deletes unit factors only from polynomials of the
  2200. form monomial * unit.
  2201. END COMMENT;
  2202. % The default :
  2203. !*lazy:=t;
  2204. % ---------------- Special tools for local algebra -----------
  2205. symbolic procedure mora!=factorunits p;
  2206. if null p then nil
  2207. else mora!=delprod
  2208. for each y in cdr (fctrf numr simp dp_2a p where !*factor=t)
  2209. collect (dp_from_a prepf car y . cdr y);
  2210. symbolic procedure mora!=delprod u;
  2211. begin scalar p; p:=dp_fi 1;
  2212. for each x in u do
  2213. if not dp_unit!? car x then p:=dp_prod(p,dp_power(car x,cdr x));
  2214. return p
  2215. end;
  2216. symbolic procedure mora!=detectunits p;
  2217. if null p then nil
  2218. else if listtest(cdr p,dp_lmon p,
  2219. function(lambda(x,y);not mo_vdivides!?(y,car x))) then p
  2220. else list dp_term(bc_fi 1,dp_lmon p);
  2221. symbolic procedure mora_factorunits b;
  2222. bas_make(bas_nr b,mora!=factorunits bas_dpoly b);
  2223. symbolic procedure mora_detectunits b;
  2224. bas_make(bas_nr b,mora!=detectunits bas_dpoly b);
  2225. symbolic procedure mora!=postprocess(pol,r0,monset);
  2226. % r0 <=> pol has dprows = 0.
  2227. begin
  2228. if !*bcsimp then pol:=car bas_simpelement pol;
  2229. if !*factorunits and r0 then pol:=mora_factorunits pol
  2230. else if !*detectunits then pol:=mora_detectunits pol;
  2231. if monset then
  2232. pol:=bas_make(bas_nr pol,
  2233. car dp_mondelete(bas_dpoly pol,monset));
  2234. return pol
  2235. end;
  2236. symbolic procedure mora_remo(b,m1,m2);
  2237. for each x in b collect mora!=remo(x,m1,m2);
  2238. symbolic procedure mora!=remo(b,m1,m2);
  2239. % Remove monomials in the base element b (without bas_rep) belonging
  2240. % to the moideal m1 or less than m2 (highest corner), if m2<>nil.
  2241. % The latter works only for ideals.
  2242. if m1 or m2 then
  2243. bas_make(bas_nr b,mora!=remo1(bas_dpoly b,m1,m2))
  2244. else b;
  2245. symbolic procedure mora!=remo1(p,m1,m2);
  2246. for each x in p join
  2247. if mora!=remotest(car x,m1,m2) then nil else list x;
  2248. symbolic procedure mora!=remotest(m,m1,m2);
  2249. (if m2 then (mo_compare(m,m2)=-1) else nil) or moid_member(m,m1);
  2250. % ---------- Reduction specials -------------------
  2251. symbolic procedure mora!=better(a,b); bas_dplen a<bas_dplen b;
  2252. % A hook for its own reduction strategy.
  2253. symbolic procedure mora!=test(a,b);
  2254. % Test for updating the simplifier list.
  2255. mora!=better(a,b) and
  2256. mo_vdivides!?(dp_lmon bas_dpoly a,dp_lmon bas_dpoly b);
  2257. symbolic procedure mora!=update(simp,b);
  2258. % Update the simplifier list simp with the base element b.
  2259. begin if cali!=trace>79 then
  2260. << terpri();
  2261. write(bas_dpecart b," +++> "); dp_print1(bas_dpoly b,nil);
  2262. >>;
  2263. return merge(list b,
  2264. for each x in simp join
  2265. if mora!=test(b,x) then nil else {x},
  2266. function mora!=better);
  2267. end;
  2268. symbolic procedure mora!=divtest(u,m);
  2269. % Returns the first f in the base list u, such that lt(f) | lt(m)
  2270. % and ec(f) <= ec(m) else nil. m is a base element.
  2271. listtest(u,m,function(lambda(x,y);
  2272. (bas_dpecart x leq bas_dpecart y) and
  2273. mo_vdivides!?(dp_lmon bas_dpoly x,dp_lmon bas_dpoly y)));
  2274. symbolic procedure mora!=divtest1(u,m);
  2275. red_divtest(u,dp_lmon bas_dpoly m);
  2276. symbolic procedure mora_redpol(bas,model);
  2277. % Analogous to redpol in the module red, but the unit z may be a true
  2278. % polynomial (with degree 0 leading term):
  2279. % Returns (model1 . z) with model1 = (pol1 , rep1) and
  2280. % pol1 = z * pol + \sum c_a f_a
  2281. % rep1 = z * rep + \sum c_a rep_a
  2282. % No extra simplification are allowed since otherwise z should be
  2283. % divided !!
  2284. % The rep-component 0 is used for managing the polynomial unit z.
  2285. if (null bas_dpoly model) or (null bas) then model . dp_fi 1
  2286. else begin
  2287. scalar ec,z,v1,v2;
  2288. % Prepare rep for collecting the unit.
  2289. model:=bas_make1(bas_nr model,bas_dpoly model,
  2290. dp_sum(bas_rep model,dp_fi 1));
  2291. if cali!=trace>79 then
  2292. << write" reduce "; dp_print1(bas_dpoly model,nil); terpri() >>;
  2293. while (bas_dpoly model) and
  2294. ((v1:=mora!=divtest(bas,model)) or
  2295. (v2:=mora!=divtest1(bas,model))) do
  2296. if v1 then model:=car red_subst(model,v1)
  2297. else
  2298. << v2:=red_subst(model,v2); bas:=mora!=update(bas,model);
  2299. model:=car v2;
  2300. >>;
  2301. % ---- lt(pol) now irreducible ----
  2302. z:=dp_comp(0,bas_rep model);
  2303. return bas_make1(bas_nr model, bas_dpoly model,
  2304. dp_diff(bas_rep model,z)) . z;
  2305. end;
  2306. symbolic procedure mora!=splitup m;
  2307. % Split up the base list m into two lists : m1 is a moideal, m2 the
  2308. % remainder, totally reduced with respect to m1. Returns m1 . m2.
  2309. % Applies only without rep. part.
  2310. begin scalar m1,m2,u;
  2311. for each x in m do
  2312. if length bas_dpoly x=1 then m1:=dp_lmon bas_dpoly x.m1
  2313. else m2:=x.m2;
  2314. if m1 then
  2315. << u:=mora!=splitup for each x in m2 collect
  2316. mora!=remo(x,m1,nil); % recursively
  2317. m2:=cdr u; m1:=moid_sum(car u,m1);
  2318. >>;
  2319. return m1 . sort(bas_zerodelete m2,function mora!=better);
  2320. end;
  2321. symbolic procedure mora_interreduce m;
  2322. % Reduce rows of the base list m until it has pairwise incomparable
  2323. % leading terms. Compute correct representation parts. !*factorunit
  2324. % should be nil for vector lists.
  2325. begin scalar c,m1,m1a,u,v,w,bas1,pol,rep,norep;
  2326. m:=sort(bas_zerodelete m, function mora!=better);
  2327. if null m then return m
  2328. else norep:=null bas_rep first m;
  2329. if !*bcsimp then m:=bas_simp m;
  2330. if norep then
  2331. << if !*factorunits then
  2332. m:=for each x in m collect mora_factorunits x
  2333. else if !*detectunits then
  2334. m:=for each x in m collect mora_detectunits x;
  2335. u:=mora!=splitup m; m1:=car u; m:=cdr u
  2336. >>;
  2337. while cdr (c:=red_collect m) do
  2338. << if cali!=trace>69 then
  2339. <<write" interreduce ";terpri();bas_print m>>;
  2340. w:=cdr c; bas1:=car c; m:=nil;
  2341. while w do
  2342. << c:=mora!=remo(car mora_redpol(bas1, car w),m1,nil);
  2343. if bas_dpoly c then m:=c . m; w:=cdr w
  2344. >>;
  2345. if !*bcsimp then m:=bas_simp m;
  2346. if norep then
  2347. << if !*factorunits then
  2348. m:=for each x in m collect mora_factorunits x
  2349. else if !*detectunits then
  2350. m:=for each x in m collect mora_detectunits x;
  2351. u:=mora!=splitup m;
  2352. if (m1a:=car u) then % remo bas1 with respect to m1a.
  2353. << v:=mora!=splitup mora_remo(bas1,m1a,nil);
  2354. m1:=moid_sum(m1,moid_sum(m1a,car v));
  2355. bas1:=cdr v; m:=cdr u
  2356. >>;
  2357. >>;
  2358. m:=merge(bas1,sort(m,function mora!=better),
  2359. function mora!=better);
  2360. >>;
  2361. if m1 then
  2362. << m1:=for each x in m1 collect
  2363. bas_make(0,list dp_term(bc_fi 1,x));
  2364. m:=merge(sort(m1,function mora!=better),m,
  2365. function mora!=better)
  2366. >>;
  2367. return m;
  2368. end;
  2369. % ---------- Standard basis algorithms ---------------
  2370. symbolic procedure mora_stbasis(bas,comp_mgb,comp_ch,comp_syz);
  2371. % Returns {mgb,change,syz} with
  2372. % dpmat mgb = if comp_mgb=true the minimal standard basis of
  2373. % the dpmat bas else its simplifier list.
  2374. % dpmat change defined by mgb = change * bas
  2375. % if comp_ch = true,
  2376. % dpmat syz = (non interreduced) syzygy matrix of bas
  2377. % if comp_syz = true.
  2378. if dpmat_zero!? bas then
  2379. {bas,dpmat_unit(dpmat_rows bas,nil),dpmat_unit(dpmat_rows bas,nil)}
  2380. else begin scalar u,syz,change,syz1,mon_set;
  2381. cali!=degrees:=dpmat_coldegs bas;
  2382. if comp_ch or comp_syz then mon_set:=nil else mon_set:=cali!=monset;
  2383. if comp_syz then % syzygies for zero base elements.
  2384. << u:=setdiff(for i:=1:dpmat_rows bas collect i,
  2385. for each x in dpmat_list bas collect bas_nr x);
  2386. syz1:=for each x in u collect bas_make(0,dp_from_ei x);
  2387. >>;
  2388. u:=if !*lazy then mora!=lazystbasis(bas,comp_ch,comp_syz,mon_set)
  2389. else mora!=homstbasis(bas,comp_ch,comp_syz,mon_set);
  2390. syz:=cadr u;
  2391. if comp_mgb then u:=groeb_mingb car u else u:=car u;
  2392. cali!=degrees:=dpmat_rowdegrees bas;
  2393. if comp_ch then
  2394. change:=dpmat_make(dpmat_rows u,dpmat_rows bas,
  2395. bas_neworder bas_getrelations dpmat_list u, cali!=degrees);
  2396. bas_removerelations dpmat_list u;
  2397. if comp_syz then
  2398. << syz:=nconc(syz,syz1);
  2399. syz:=dpmat_make(length syz,dpmat_rows bas,
  2400. bas_neworder bas_renumber syz,cali!=degrees);
  2401. >>;
  2402. cali!=degrees:=dpmat_coldegs u;
  2403. return {u,change,syz}
  2404. end;
  2405. % --------- StBasis with global simplifier list. The relict. ---------
  2406. symbolic procedure mora!=simpstbasis(bas,comp_ch,comp_syz,mon_set1);
  2407. % Returns bas . syz . trace with change matrix on rep-part of bas.
  2408. if dpmat_rows bas=0 then bas . dpmat_unit(0,nil) . nil
  2409. else begin integer i,nr,ec;
  2410. scalar syz,m1,simp,u,v1,v2,q,gb,p,pl,pol,rep,trace,Ccrit,
  2411. return_by_unit,norep;
  2412. % -------- Initialization
  2413. gb:=append(dpmat_list bas,nil); % make a copy of bas
  2414. if comp_ch or comp_syz then bas_setrelations gb
  2415. else norep:=t;
  2416. if norep then
  2417. << u:=mora!=splitup gb; m1:=car u; simp:=cdr u >>
  2418. else simp:=append(gb,nil);
  2419. simp:=sort(listminimize(simp,function mora!=test),
  2420. function mora!=better);
  2421. Ccrit:=(not comp_syz) and (dpmat_cols bas=0);
  2422. % -- don't reduce main syzygies
  2423. nr:=dpmat_rows bas;
  2424. if cali!=trace > 0 then
  2425. << terpri(); write" Computing SimpStBasis ";terpri() >>;
  2426. if cali!=trace > 5 then
  2427. << terpri(); write" Compute SimpStBasis of"; bas_print gb >>;
  2428. pl:=groeb_makepairlist(gb,Ccrit);
  2429. if cali!=trace > 30 then groeb_printpairlist pl;
  2430. if cali!=trace > 5 then
  2431. << terpri(); write" New base elements :";terpri() >>;
  2432. % -------- working out pair list
  2433. while pl and not return_by_unit do
  2434. << p:=car pl; pl:=cdr pl;
  2435. % ------ compute S-polynomial (which is a modelement)
  2436. if cali!=trace > 10 then groeb_printpair(p,pl);
  2437. pol:=groeb_spol p;
  2438. if cali!=trace > 70 then
  2439. << terpri(); write" S.-pol : ";
  2440. dp_print1(bas_dpoly pol,nil)
  2441. >>;
  2442. % ---- reduce S-Polynomial ----------------
  2443. if norep and m1 then pol:=mora!=remo(pol,m1,nil);
  2444. while bas_dpoly pol and
  2445. ((v1:=mora!=divtest(simp,pol)) or
  2446. (v2:=mora!=divtest1(simp,pol))) do
  2447. << if v1 then u:=car red_subst(pol,v1)
  2448. else
  2449. << u:=car red_subst(pol,v2);
  2450. simp:=mora!=update(simp,pol)
  2451. >>;
  2452. if norep and m1 then pol:=mora!=remo(u,m1,nil)
  2453. else pol:=u;
  2454. >>;
  2455. if cali!=trace > 70 then
  2456. << terpri(); write" Reduced S.-pol. : ";
  2457. dp_print1(bas_dpoly pol,nil)
  2458. >>;
  2459. if bas_dpoly pol then
  2460. % --- the S-polynomial doesn't reduce to zero
  2461. << if norep then pol:=mora!=postprocess(pol,ccrit,mon_set1);
  2462. nr:=nr+1;
  2463. pol:=bas_newnumber(nr,pol);
  2464. % --- update the tracelist
  2465. trace:=
  2466. list(groeb!=i p,groeb!=j p,nr,dp_lmon bas_dpoly pol) .
  2467. trace;
  2468. if norep and (length bas_dpoly pol=1) then
  2469. << p:=dp_lmon bas_dpoly pol;
  2470. u:=mora!=splitup mora_remo(simp,list p,nil);
  2471. m1:=moid_sum(m1,p . car u);
  2472. simp:=sort(listminimize(cdr u,function mora!=test),
  2473. function mora!=better)
  2474. >>
  2475. else simp:=mora!=update(simp,pol);
  2476. if cali!=trace > 20 then
  2477. << terpri(); write nr,". ---> ";
  2478. dp_print1(bas_dpoly pol,nil); terpri()
  2479. >>;
  2480. if Ccrit and (dp_unit!? bas_dpoly pol) then
  2481. return_by_unit:=t;
  2482. if not return_by_unit then
  2483. << % ----- updating pairlist
  2484. pl:=groeb_updatePL(pl,gb,pol,Ccrit);
  2485. if cali!=trace > 30 then
  2486. << terpri(); groeb_printpairlist pl >>;
  2487. >>;
  2488. gb:=pol.gb;
  2489. >>
  2490. else % ------ S-polynomial reduces to zero
  2491. if comp_syz then
  2492. syz:=bas_simpelement bas_make(0,bas_rep pol).syz;
  2493. >>;
  2494. % -------- updating the result
  2495. if m1 then simp:=bas_renumber
  2496. append(simp, for each x in m1 collect
  2497. bas_make(0,list dp_term(bc_fi 1,x)));
  2498. if cali!=trace>0 then
  2499. write " Simplifier list has length ",length simp;
  2500. if return_by_unit then return
  2501. dpmat_make(1,dpmat_cols bas,list(bas_newnumber(1,pol)),
  2502. cali!=degrees) . nil . reversip trace
  2503. else return
  2504. dpmat_make(length simp,dpmat_cols bas,simp,cali!=degrees)
  2505. . syz . reversip trace;
  2506. end;
  2507. % ------- StBasis with the lazy strategy. The default. -----------
  2508. symbolic procedure mora!=queuesort(a,b);
  2509. % Sort criterion for the queue.
  2510. mo_compare(dp_lmon bas_dpoly a,dp_lmon bas_dpoly b)=1;
  2511. symbolic procedure mora!=nextspol(pl,queue);
  2512. % True <=> take first pl next.
  2513. if null queue then t
  2514. else if null pl then nil
  2515. else mo_compare(nth(car pl,3),dp_lmon bas_dpoly car queue)=1;
  2516. symbolic procedure mora!=lazystbasis(bas,comp_ch,comp_syz,mon_set1);
  2517. % Returns ( gb . syz . nil) as above but using the local standard
  2518. % base algorithm with lazy strategy. (nil, since tracing doesn't make
  2519. % sense.
  2520. if dpmat_rows bas=0 then bas . dpmat_unit(0,nil) . nil
  2521. else begin integer i,nr,ec;
  2522. scalar syz,Ccrit,m1,queue,simp,u,v1,v2,q,gb,p,pl,pol,rep,
  2523. return_by_unit,norep;
  2524. % -------- Initialization
  2525. gb:=append(dpmat_list bas,nil); % make a copy of bas
  2526. if comp_ch or comp_syz then bas_setrelations gb
  2527. else norep:=t;
  2528. if norep then
  2529. << u:=mora!=splitup gb; m1:=car u; simp:=cdr u >>
  2530. else simp:=append(gb,nil);
  2531. simp:=sort(listminimize(simp,function mora!=test),
  2532. function mora!=better);
  2533. Ccrit:=(not comp_syz) and (dpmat_cols bas=0);
  2534. % -- don't reduce main syzygies
  2535. nr:=dpmat_rows bas;
  2536. if cali!=trace > 0 then
  2537. <<terpri(); write" Computing LazyStBasis ";terpri()>>;
  2538. if cali!=trace > 5 then
  2539. << terpri(); write" Compute LazyStBasis of"; bas_print gb >>;
  2540. pl:=groeb_makepairlist(gb,Ccrit);
  2541. if cali!=trace > 30 then groeb_printpairlist pl;
  2542. if cali!=trace > 5 then
  2543. <<terpri(); write" New base elements :";terpri() >>;
  2544. % -------- working out pair list
  2545. while (pl or queue) and not return_by_unit do
  2546. if mora!=nextspol(pl,queue) then
  2547. << p:=car pl; pl:=cdr pl;
  2548. if cali!=trace > 10 then groeb_printpair(p,pl);
  2549. pol:=groeb_spol p;
  2550. if bas_dpoly pol then % back into the queue
  2551. << if norep then
  2552. pol:=mora!=postprocess(pol,ccrit,mon_set1);
  2553. if Ccrit and dp_unit!? bas_dpoly pol then
  2554. return_by_unit:=t
  2555. else queue:=merge(list pol, queue,
  2556. function mora!=queuesort)
  2557. >>
  2558. else % pol reduced to zero.
  2559. if comp_syz then
  2560. syz:=bas_simpelement bas_make(0,bas_rep pol).syz;
  2561. if cali!=trace > 70 then
  2562. << terpri(); write" S.-pol : ";
  2563. dp_print1(bas_dpoly pol,nil)
  2564. >>;
  2565. >>
  2566. else
  2567. << pol:=car queue; queue:=cdr queue;
  2568. if norep and m1 then pol:=mora!=remo(pol,m1,nil);
  2569. if bas_dpoly pol then % try a reduction step
  2570. if ((v1:=mora!=divtest(simp,pol)) or
  2571. (v2:=mora!=divtest1(simp,pol))) then
  2572. << if v1 then u:=car red_subst(pol,v1)
  2573. else
  2574. << u:=car red_subst(pol,v2);
  2575. simp:=mora!=update(simp,pol)
  2576. >>;
  2577. if norep and m1 then pol:=mora!=remo(u,m1,nil)
  2578. else pol:=u;
  2579. if bas_dpoly pol then % back into the queue
  2580. << if norep then
  2581. pol:=mora!=postprocess(pol,ccrit,mon_set1);
  2582. if Ccrit and dp_unit!? bas_dpoly pol then
  2583. return_by_unit:=t
  2584. else queue:=merge(list pol, queue,
  2585. function mora!=queuesort)
  2586. >>
  2587. else % pol reduced to zero.
  2588. if comp_syz then
  2589. syz:=bas_simpelement bas_make(0,bas_rep pol).syz;
  2590. >>
  2591. else % no reduction possible
  2592. << nr:=nr+1; pol:=bas_newnumber(nr,pol);
  2593. if cali!=trace > 20 then
  2594. << terpri(); write nr,". --> ";
  2595. dp_print1(bas_dpoly pol,nil)
  2596. >>;
  2597. pl:=groeb_updatePL(pl,gb,pol,Ccrit);
  2598. if norep and (length bas_dpoly pol=1) then
  2599. << p:=dp_lmon bas_dpoly pol;
  2600. u:=mora!=splitup mora_remo(simp,list p,nil);
  2601. m1:=moid_sum(m1,p . car u);
  2602. simp:=sort(listminimize(cdr u,
  2603. function mora!=test),
  2604. function mora!=better)
  2605. >>
  2606. else simp:=mora!=update(simp,pol);
  2607. gb:=pol.gb;
  2608. >>
  2609. else % ------ S-polynomial reduces to zero
  2610. << if cali!=trace>20 then write " QL = ",length queue;
  2611. if comp_syz then
  2612. syz:=bas_simpelement bas_make(0,bas_rep pol).syz;
  2613. >>
  2614. >>;
  2615. % -------- updating the result
  2616. if m1 then simp:=bas_renumber
  2617. append(simp, for each x in m1 collect
  2618. bas_make(0,list dp_term(bc_fi 1,x)));
  2619. if cali!=trace>0 then
  2620. write " Simplifier list has length ",length simp;
  2621. if return_by_unit then return
  2622. dpmat_make(1,dpmat_cols bas,list(bas_newnumber(1,pol)),
  2623. cali!=degrees). nil . nil
  2624. else return dpmat_make(length simp,dpmat_cols bas,simp,
  2625. cali!=degrees) . syz . nil;
  2626. end;
  2627. % ------ Lazard's approach. Use "off lazy" to activate it. --------
  2628. symbolic procedure mora!=homstbasis(m,comp_ch,comp_syz,mon_set);
  2629. (begin scalar v,c,e,n,to,u;
  2630. c:=cali!=basering; v:=list gensym();
  2631. if not(comp_ch or comp_syz) then mon_set:=append(v,mon_set);
  2632. setring!* ring_sum(c,ring_define(v,nil,'lex,'(1)));
  2633. cali!=degrees:=mo_degneworder dpmat_coldegs m;
  2634. if cali!=trace>0 then print" Homogenize input ";
  2635. u:=groeb_innerstbasis(mathomogenize!*(m,car v),
  2636. comp_ch, comp_syz, mon_set);
  2637. if cali!=trace>0 then print" Dehomogenize output ";
  2638. u:=matdehomogenize!*(car u,car v) . bas_dehomogenize(cadr u,car v);
  2639. setring!* c; cali!=degrees:=dpmat_coldegs m;
  2640. return {dpmat_neworder car u,bas_neworder cdr u};
  2641. end) where cali!=basering:=cali!=basering,
  2642. cali!=degrees:=cali!=degrees;
  2643. endmodule; % mora
  2644. module matop;
  2645. COMMENT
  2646. #############################
  2647. #### ####
  2648. #### MATRIX OPERATIONS ####
  2649. #### ####
  2650. #############################
  2651. This module contains operations on dpmats, that correspond to module
  2652. operations on the corresponding images resp. cokernels.
  2653. END COMMENT;
  2654. procedure matop!=testdpmatlist l;
  2655. % Test l to be a list of dpmats embedded into a common free module.
  2656. if null l then rederr"Empty DPMAT list"
  2657. else begin scalar c,d;
  2658. for each x in l do
  2659. if not eqcar(x,'dpmat) then typerr(x,"DPMAT");
  2660. c:=dpmat_cols car l; d:=dpmat_coldegs car l;
  2661. for each x in cdr l do
  2662. if not (eqn(c,dpmat_cols x) and equal(d,dpmat_coldegs x)) then
  2663. rederr"Matrices don't match in the DPMAT list";
  2664. end;
  2665. procedure matappend!* l;
  2666. % Appends rows of the dpmats in the dpmat list l.
  2667. (begin scalar u,r;
  2668. matop!=testdpmatlist l;
  2669. cali!=degrees:=dpmat_coldegs car l;
  2670. u:=dpmat_list car l; r:=dpmat_rows car l;
  2671. for each y in cdr l do
  2672. << u:=append(u, for each x in dpmat_list y collect
  2673. bas_newnumber(bas_nr x + r,x));
  2674. r:=r + dpmat_rows y;
  2675. >>;
  2676. return dpmat_make(r,dpmat_cols car l,u,cali!=degrees)
  2677. end) where cali!=degrees:=cali!=degrees;
  2678. put('matappend,'psopfn,'matop!=matappend);
  2679. symbolic procedure matop!=matappend l;
  2680. % Append the dpmats in the list l.
  2681. dpmat_2a matappend!* for each x in l collect dpmat_from_a reval x;
  2682. procedure flatten!* m;
  2683. % Returns the ideal of all elements of m.
  2684. if dpmat_cols m = 0 then m
  2685. else (begin scalar x;
  2686. x:=bas_renumber bas_zerodelete
  2687. for i:=1:dpmat_rows m join
  2688. for j:=1:dpmat_cols m collect
  2689. bas_make(0,dpmat_element(i,j,m));
  2690. return dpmat_make(length x,0,x,nil)
  2691. end) where cali!=degrees:=nil;
  2692. procedure matsum!* l;
  2693. % Returns the module sum of the dpmat list l.
  2694. interreduce!* matappend!* l;
  2695. put('matsum,'psopfn,'matop!=matsum);
  2696. put('idealsum,'psopfn,'matop!=matsum);
  2697. symbolic procedure matop!=matsum l;
  2698. % Returns the sum of the ideals/modules in the list l.
  2699. dpmat_2a matsum!* for each x in l collect dpmat_from_a reval x;
  2700. procedure matop!=idealprod2(a,b);
  2701. if (dpmat_cols a > 0) or (dpmat_cols b > 0 ) then
  2702. rederr"IDEALPROD only for ideals"
  2703. else (begin scalar x;
  2704. x:=bas_renumber
  2705. for each a1 in dpmat_list a join
  2706. for each b1 in dpmat_list b collect
  2707. bas_make(0,dp_prod(bas_dpoly a1,bas_dpoly b1));
  2708. return interreduce!* dpmat_make(length x,0,x,nil)
  2709. end) where cali!=degrees:=nil;
  2710. procedure idealprod!* l;
  2711. % Returns the product of the ideals in the dpmat list l.
  2712. if null l then rederr"empty list in IDEALPROD"
  2713. else if length l=1 then car l
  2714. else begin scalar u;
  2715. u:=car l;
  2716. for each x in cdr l do u:=matop!=idealprod2(u,x);
  2717. return u;
  2718. end;
  2719. put('idealprod,'psopfn,'matop!=idealprod);
  2720. symbolic procedure matop!=idealprod l;
  2721. % Returns the product of the ideals in the list l.
  2722. dpmat_2a idealprod!* for each x in l collect dpmat_from_a reval x;
  2723. procedure idealpower!*(a,n);
  2724. if (dpmat_cols a > 0) or (not fixp n) or (n < 0) then
  2725. rederr" Syntax : idealpower(ideal,integer)"
  2726. else if (n=0) then dpmat_from_dpoly dp_fi 1
  2727. else begin scalar w; w:=a;
  2728. for i:=2:n do w:=matop!=idealprod2(w,a);
  2729. return w;
  2730. end;
  2731. symbolic operator idealpower;
  2732. symbolic procedure idealpower(m,l);
  2733. if !*mode='symbolic then rederr"only for algebraic mode"
  2734. else dpmat_2a idealpower!*(dpmat_from_a reval m,l);
  2735. procedure matop!=shiftdegs(d,n);
  2736. % Shift column degrees d n places.
  2737. for each x in d collect ((car x + n) . cdr x);
  2738. procedure directsum!* l;
  2739. % Returns the direct sum of the modules in the dpmat list l.
  2740. if null l then rederr"Empty DPMAT list"
  2741. else (begin scalar r,c,u;
  2742. for each x in l do
  2743. if not eqcar(x,'dpmat) then typerr(x,"DPMAT")
  2744. else if dpmat_cols x=0 then
  2745. rederr"DIRECTSUM only for modules";
  2746. c:=r:=0; % Actual column resp. row index.
  2747. cali!=degrees:=nil;
  2748. for each x in l do
  2749. << cali!=degrees:=append(cali!=degrees,
  2750. matop!=shiftdegs(dpmat_coldegs x,c));
  2751. u:=append(u, for each y in dpmat_list x collect
  2752. bas_make(bas_nr y + r,dp_times_ei(c,bas_dpoly y)));
  2753. r:=r + dpmat_rows x;
  2754. c:=c + dpmat_cols x;
  2755. >>;
  2756. return dpmat_make(r,c,u,cali!=degrees)
  2757. end) where cali!=degrees:=cali!=degrees;
  2758. put('directsum,'psopfn,'matop!=directsum);
  2759. symbolic procedure matop!=directsum l;
  2760. % Returns the direct sum of the modules in the list l.
  2761. dpmat_2a directsum!* for each x in l collect dpmat_from_a reval x;
  2762. symbolic operator deleteunits;
  2763. symbolic procedure deleteunits m;
  2764. if !*mode='symbolic then rederr"only for algebraic mode"
  2765. else if !*noetherian then m
  2766. else dpmat_2a deleteunits!* dpmat_from_a m;
  2767. symbolic procedure deleteunits!* m;
  2768. % Delete units from the base elements of the ideal m.
  2769. if !*noetherian or (dpmat_cols m>0) then m
  2770. else dpmat_make(dpmat_rows m,0,
  2771. for each x in dpmat_list m collect mora_factorunits x,nil);
  2772. symbolic procedure interreduce!* m;
  2773. (begin scalar u,c; c:=dpmat_cols m; m:=dpmat_list m;
  2774. u:=if !*noetherian then red_interreduce m else mora_interreduce m;
  2775. return dpmat_make(length u,c, bas_renumber u,cali!=degrees)
  2776. end) where cali!=degrees:=dpmat_coldegs m;
  2777. symbolic operator interreduce;
  2778. symbolic procedure interreduce m;
  2779. % Interreduce m.
  2780. if !*mode='symbolic then rederr"only for algebraic mode"
  2781. else dpmat_2a interreduce!* dpmat_from_a reval m;
  2782. symbolic procedure gbasis!* m;
  2783. % Produce a minimal Groebner or standard basis of the dpmat m.
  2784. if !*noetherian then car groeb_stbasis(m,t,nil,nil)
  2785. else car mora_stbasis(m,t,nil,nil);
  2786. put('tangentcone,'psopfn,'matop!=tangentcone);
  2787. symbolic procedure matop!=tangentcone m;
  2788. begin scalar c;
  2789. intf_test m; m:=car m; intf_get m;
  2790. if not (c:=get(m,'gbasis)) then rederr"Compute Gbasis first";
  2791. c:=tangentcone!* c;
  2792. return dpmat_2a c;
  2793. end;
  2794. symbolic procedure tangentcone!* m;
  2795. % Returns the tangent cone of m, provided the term order has degrees.
  2796. % m must be a gbasis.
  2797. if null ring_degrees cali!=basering then
  2798. rederr"tangent cone only for degree orders defined"
  2799. else (begin scalar b;
  2800. b:=for each x in dpmat_list m collect
  2801. bas_make(bas_nr x,dp_tcpart bas_dpoly x);
  2802. return dpmat_make(dpmat_rows m,dpmat_cols m,b,cali!=degrees);
  2803. end) where cali!=degrees:=dpmat_coldegs m;
  2804. symbolic procedure syzygies1!* bas;
  2805. % Returns the (not yet interreduced first) syzygy module of the dpmat
  2806. % bas.
  2807. begin
  2808. if cali!=trace > 0 then
  2809. << terpri(); write" Compute syzygies"; terpri() >>;
  2810. if !*noetherian then return third groeb_stbasis(bas,nil,nil,t)
  2811. else return third mora_stbasis(bas,nil,nil,t);
  2812. end;
  2813. symbolic procedure syzygies!* bas;
  2814. % Returns the interreduced syzygy basis.
  2815. interreduce!* syzygies1!* bas;
  2816. symbolic procedure normalform!*(a,b);
  2817. % Returns {a1,r,z} with a1=z*a-r*b where the rows of the dpmat a1 are
  2818. % the normalforms of the rows of the dpmat a with respect to the
  2819. % dpmat b.
  2820. if not(eqn(dpmat_cols a,dpmat_cols b) and
  2821. equal(dpmat_coldegs a,dpmat_coldegs b)) then
  2822. rederr"dpmats don't match for NORMALFORM"
  2823. else (begin scalar a1,z,u,r;
  2824. bas_setrelations dpmat_list b;
  2825. a1:=for each x in dpmat_list a collect
  2826. << u:=if !*noetherian then
  2827. red_redpol(dpmat_list b,x)
  2828. else
  2829. mora_redpol(dpmat_list b,x);
  2830. z:=bas_make(bas_nr x,dp_times_ei(bas_nr x,cdr u)).z;
  2831. car u
  2832. >>;
  2833. r:=bas_getrelations a1; bas_removerelations a1;
  2834. bas_removerelations dpmat_list b; z:=reversip z;
  2835. a1:=dpmat_make(dpmat_rows a,dpmat_cols a,a1,cali!=degrees);
  2836. cali!=degrees:=dpmat_rowdegrees b;
  2837. r:=dpmat_make(dpmat_rows a,dpmat_rows b,bas_neworder r,
  2838. cali!=degrees);
  2839. cali!=degrees:=nil;
  2840. z:=dpmat_make(dpmat_rows a,dpmat_rows a,bas_neworder z,nil);
  2841. return {a1,r,z};
  2842. end) where cali!=degrees:=dpmat_coldegs b;
  2843. symbolic procedure matop_pseudomod(a,b); car mod!*(a,b);
  2844. symbolic procedure mod!*(a,b);
  2845. % Returns the normal form of the dpoly a modulo the dpmat b and the
  2846. % corresponding unit produced during pseudo division.
  2847. (begin scalar a1,z,u,r;
  2848. a:=dp_neworder a; % to be on the safe side.
  2849. u:=if !*noetherian then
  2850. red_redpol(dpmat_list b,bas_make(0,a))
  2851. else
  2852. mora_redpol(dpmat_list b,bas_make(0,a));
  2853. return (bas_dpoly car u) . cdr u;
  2854. end) where cali!=degrees:=dpmat_coldegs b;
  2855. symbolic operator mod;
  2856. symbolic procedure mod(a,b);
  2857. % True normal form as s.q. also for matrices.
  2858. if !*mode='symbolic then rederr"only for algebraic mode"
  2859. else begin scalar u;
  2860. b:=dpmat_from_a reval b; a:=reval a;
  2861. if eqcar(a,'list) then
  2862. if dpmat_cols b>0 then rederr"entries don't match for MOD"
  2863. else a:=makelist for each x in cdr a collect
  2864. << u:=mod!*(dp_from_a x, b);
  2865. {'quotient,dp_2a car u,dp_2a cdr u}
  2866. >>
  2867. else if eqcar(a,'mat) then
  2868. begin a:=dpmat_from_a a;
  2869. if dpmat_cols a neq dpmat_cols b then
  2870. rederr"entries don't match for MOD";
  2871. a:=for each x in dpmat_list a collect mod!*(bas_dpoly x,b);
  2872. a:='mat.
  2873. for each x in a collect
  2874. << u:=dp_2a cdr x;
  2875. for i:=1:dpmat_cols b collect
  2876. {'quotient,dp_2a dp_comp(i,car x),u}
  2877. >>
  2878. end
  2879. else if dpmat_cols b>0 then rederr"entries don't match for MOD"
  2880. else << u:=mod!*(dp_from_a a, b);
  2881. a:={'quotient,dp_2a car u,dp_2a cdr u}
  2882. >>;
  2883. return a;
  2884. end;
  2885. infix mod;
  2886. symbolic operator normalform;
  2887. symbolic procedure normalform(a,b);
  2888. % Compute a normal form of the rows of a with respect to b :
  2889. % first result = third result * a + second result * b.
  2890. if !*mode='symbolic then rederr"only for algebraic mode"
  2891. else begin scalar m;
  2892. m:= normalform!*(dpmat_from_a reval a,dpmat_from_a reval b);
  2893. return {'list,dpmat_2a car m, dpmat_2a cadr m, dpmat_2a caddr m}
  2894. end;
  2895. symbolic procedure eliminate!*(m,vars);
  2896. % Returns a (dpmat) basis of the elimination module of the dpmat m
  2897. % eliminating variables contained in the var. list vars.
  2898. % It sets temporary the standard elimination term order, but doesn't
  2899. % affect the ecart, and computes a Groebner basis of m.
  2900. (begin scalar c,e,bas,v;
  2901. c:=cali!=basering; e:=ring_ecart c;
  2902. v:=ring_names cali!=basering;
  2903. setring!* ring_define(v,eliminationorder!*(v,vars),'revlex,e);
  2904. cali!=degrees:=nil; % No degrees for proper result !!
  2905. bas:=(bas_sieve(dpmat_list
  2906. car groeb_stbasis(dpmat_neworder m,t,nil,nil), vars)
  2907. where !*noetherian=t);
  2908. setring!* c; cali!=degrees:=dpmat_coldegs m;
  2909. return dpmat_make(length bas,dpmat_cols m,bas_neworder bas,
  2910. cali!=degrees);
  2911. end)
  2912. where cali!=degrees:=cali!=degrees,
  2913. cali!=basering:=cali!=basering;
  2914. symbolic operator eliminate;
  2915. symbolic procedure eliminate(m,l);
  2916. % Returns the elimination ideal/module of m with respect to the
  2917. % variables in the list l to be eliminated.
  2918. if !*mode='symbolic then rederr"only for algebraic mode"
  2919. else begin l:=reval l;
  2920. if not eqcar(l,'list) then typerr(l,"variable list");
  2921. m:=dpmat_from_a m; l:=cdr l;
  2922. return dpmat_2a eliminate!*(m,l);
  2923. end;
  2924. symbolic procedure matintersect!* l;
  2925. if null l then rederr"MATINTERSECT with empty list"
  2926. else if length l=1 then car l
  2927. else (begin scalar c,u,v,p,size;
  2928. matop!=testdpmatlist l;
  2929. size:=dpmat_cols car l;
  2930. v:=for each x in l collect gensym();
  2931. c:=cali!=basering;
  2932. setring!* ring_sum(c,
  2933. ring_define(v,degreeorder!* v,'lex,for each x in v collect 1));
  2934. cali!=degrees:=mo_degneworder dpmat_coldegs car l;
  2935. u:=for each x in pair(v,l) collect
  2936. dpmat_times_dpoly(dp_from_a car x,dpmat_neworder cdr x);
  2937. p:=dp_fi 1; for each x in v do p:=dp_diff(p,dp_from_a x);
  2938. if size=0 then p:=dpmat_make(1,0,list bas_make(1,p),cali!=degrees)
  2939. else p:=dpmat_times_dpoly(p,dpmat_unit(size,cali!=degrees));
  2940. p:=gbasis!* matsum!* (p . u);
  2941. p:=dpmat_sieve(p,v);
  2942. setring!* c;
  2943. cali!=degrees:=dpmat_coldegs car l;
  2944. return dpmat_neworder p;
  2945. end)
  2946. where cali!=degrees:=cali!=degrees,
  2947. cali!=basering:=cali!=basering;
  2948. put('matintersect,'psopfn,'matop!=matintersect);
  2949. symbolic procedure matop!=matintersect l;
  2950. % Returns the intersection of the submodules of a fixed free module
  2951. % in the list l.
  2952. dpmat_2a matintersect!* for each x in l collect dpmat_from_a reval x;
  2953. put('idealintersect,'psopfn,'matop!=idealintersect);
  2954. symbolic procedure matop!=idealintersect l;
  2955. rederr "use MATINTERSECT instead";
  2956. % ------- Submodule property and equality test --------------
  2957. put('modequalp,'psopfn,'matop!=equalp);
  2958. % Test, whether a and b are module equal.
  2959. symbolic procedure matop!=equalp u;
  2960. if length u neq 2 then rederr"Syntax : MODEQUALP(dpmat,dpmat) "
  2961. else begin scalar a,b;
  2962. intf_get first u; intf_get second u;
  2963. if null(a:=get(first u,'gbasis)) or
  2964. null(b:=get(second u,'gbasis)) then
  2965. rederr"Compute gbases first";
  2966. if modequalp!*(a,b) then return 'yes else return 'no
  2967. end;
  2968. symbolic procedure modequalp!*(a,b);
  2969. submodulep!*(a,b) and submodulep!*(b,a);
  2970. put('submodulep,'psopfn,'matop!=submodulep);
  2971. % Test, whether a is a submodule of b.
  2972. symbolic procedure matop!=submodulep u;
  2973. if length u neq 2 then rederr"Syntax : SUBMODULEP(dpmat,dpmat)"
  2974. else begin scalar a,b;
  2975. intf_get second u;
  2976. if null(b:=get(second u,'gbasis)) then
  2977. rederr"Compute second gbasis first";
  2978. a:=dpmat_from_a reval first u;
  2979. if submodulep!*(a,b) then return 'yes else return 'no
  2980. end;
  2981. symbolic procedure submodulep!*(a,b);
  2982. if not(dpmat_cols a=dpmat_cols b
  2983. and equal(dpmat_coldegs a,dpmat_coldegs b)) then
  2984. rederr"incompatible modules in SUBMODULEP"
  2985. else (begin
  2986. a:=for each x in dpmat_list a collect bas_dpoly x;
  2987. return not listtest(a,b,function matop_pseudomod)
  2988. end) where cali!=degrees:=dpmat_coldegs a;
  2989. endmodule; % matop
  2990. module quot;
  2991. COMMENT
  2992. #################
  2993. # #
  2994. # QUOTIENTS #
  2995. # #
  2996. #################
  2997. This module contains algorithms for different kinds of quotients of
  2998. ideals and modules.
  2999. END COMMENT;
  3000. % -------- Quotient of a module by a polynomial -----------
  3001. % Returns m : (f) for a polynomial f.
  3002. symbolic operator matquot;
  3003. symbolic procedure matquot(m,f);
  3004. if !*mode='symbolic then rederr"only for algebraic mode"
  3005. else dpmat_2a matquot!*(dpmat_from_a reval m,dp_from_a reval f);
  3006. symbolic procedure matquot!*(m,f);
  3007. if dp_unit!? f then m
  3008. else if dpmat_cols m=0 then flatten!* quot!=quot(ideal2mat!* m,f)
  3009. else quot!=quot(m,f);
  3010. symbolic procedure quot!=quot(m,f);
  3011. begin scalar a,b;
  3012. a:=matintersect!* {m,
  3013. dpmat_times_dpoly(f,dpmat_unit(dpmat_cols m,dpmat_coldegs m))};
  3014. b:=for each x in dpmat_list a collect
  3015. bas_make(bas_nr x,car dp_pseudodivmod(bas_dpoly x,f));
  3016. return dpmat_make(dpmat_rows a,dpmat_cols a,b,dpmat_coldegs m);
  3017. end;
  3018. % -------- Quotient of a module by an ideal -----------
  3019. % Returns m:n as a module.
  3020. symbolic operator idealquotient;
  3021. symbolic procedure idealquotient(m,n);
  3022. if !*mode='symbolic then rederr"only for algebraic mode"
  3023. else dpmat_2a idealquotient2!*(dpmat_from_a reval m,
  3024. dpmat_from_a reval n);
  3025. % -------- Quotient of a module by another module -----------
  3026. % Returns m:n as an ideal in S. m and n must be submodules of a common
  3027. % free module.
  3028. symbolic operator modulequotient;
  3029. symbolic procedure modulequotient(m,n);
  3030. if !*mode='symbolic then rederr"only for algebraic mode"
  3031. else dpmat_2a modulequotient2!*(dpmat_from_a reval m,
  3032. dpmat_from_a reval n);
  3033. % ---- The annihilator of a module, i.e. Ann coker M := M : F ---
  3034. symbolic operator annihilator;
  3035. symbolic procedure annihilator m;
  3036. if !*mode='symbolic then rederr"only for algebraic mode"
  3037. else dpmat_2a annihilator2!* dpmat_from_a reval m;
  3038. % ---- Quotients as M:N = \intersect { M:f | f \in N } ------
  3039. symbolic procedure idealquotient2!*(m,n);
  3040. if dpmat_cols n>0 then rederr"Syntax : idealquotient(dpmat,ideal)"
  3041. else if dpmat_cols m=0 then modulequotient2!*(m,n)
  3042. else matintersect!* for each x in dpmat_list n collect
  3043. quot!=quot(m,bas_dpoly x);
  3044. symbolic procedure modulequotient2!*(m,n);
  3045. (begin scalar c;
  3046. if not((c:=dpmat_cols m)=dpmat_cols n) then rederr
  3047. "MODULEQUOTIENT only for submodules of a common free module";
  3048. if not equal(dpmat_coldegs m,dpmat_coldegs n) then
  3049. rederr"matrices don't match for MODULEQUOTIENT";
  3050. if (c=0) then << m:=ideal2mat!* m; n:=ideal2mat!* n >>;
  3051. cali!=degrees:=dpmat_coldegs m;
  3052. n:=for each x in dpmat_list n collect matop_pseudomod(bas_dpoly x,m);
  3053. n:=for each x in n join if x then {x};
  3054. return if null n then dpmat_from_dpoly dp_fi 1
  3055. else matintersect!* for each x in n collect quot!=mquot(m,x);
  3056. end) where cali!=degrees:=cali!=degrees;
  3057. symbolic procedure quot!=mquot(m,f);
  3058. begin scalar a,b;
  3059. a:=matintersect!*
  3060. {m,dpmat_make(1,dpmat_cols m,list bas_make(1,f),dpmat_coldegs m)};
  3061. b:=for each x in dpmat_list a collect
  3062. bas_make(bas_nr x,car dp_pseudodivmod(bas_dpoly x,f));
  3063. return dpmat_make(dpmat_rows a,0,b,nil);
  3064. end;
  3065. symbolic procedure annihilator2!* m;
  3066. if dpmat_cols m=0 then m
  3067. else modulequotient2!*(m,dpmat_unit(dpmat_cols m,dpmat_coldegs m));
  3068. % -------- Quotients by the general element method --------
  3069. symbolic procedure idealquotient1!*(m,n);
  3070. if dpmat_cols n>0 then rederr "second parameter must be an ideal"
  3071. else if dpmat_cols m=0 then modulequotient1!*(m,n)
  3072. else (begin scalar u1,u2,f,v,r,m1;
  3073. v:=list gensym(); r:=cali!=basering;
  3074. setring!* ring_sum(r,ring_define(v,degreeorder!* v,'revlex,'(1)));
  3075. cali!=degrees:=mo_degneworder dpmat_coldegs m;
  3076. n:=for each x in dpmat_list n collect dp_neworder x;
  3077. u1:=u2:=dp_from_a car v; f:=car n;
  3078. for each x in n do
  3079. << f:=dp_sum(f,dp_prod(u1,x)); u1:=dp_prod(u1,u2) >>;
  3080. m1:=dpmat_sieve(gbasis!* quot!=quot(dpmat_neworder m,f),v);
  3081. setring!* r; cali!=degrees:=dpmat_coldegs m;
  3082. return dpmat_neworder m1;
  3083. end)
  3084. where cali!=degrees:=cali!=degrees,
  3085. cali!=basering:=cali!=basering;
  3086. symbolic procedure modulequotient1!*(m,n);
  3087. (begin scalar c,u1,u2,f,v,r,m1;
  3088. if not((c:=dpmat_cols m)=dpmat_cols n) then rederr
  3089. "MODULEQUOTIENT only for submodules of a common free module";
  3090. if not equal(dpmat_coldegs m,dpmat_coldegs n) then
  3091. rederr"matrices don't match for MODULEQUOTIENT";
  3092. if (c=0) then << m:=ideal2mat!* m; n:=ideal2mat!* n >>;
  3093. cali!=degrees:=dpmat_coldegs m;
  3094. n:=for each x in dpmat_list n collect matop_pseudomod(bas_dpoly x,m);
  3095. n:=for each x in n join if x then {x};
  3096. if null n then return dpmat_from_dpoly dp_fi 1;
  3097. v:=list gensym(); r:=cali!=basering;
  3098. setring!* ring_sum(r,ring_define(v,degreeorder!* v,'revlex,'(1)));
  3099. cali!=degrees:=mo_degneworder cali!=degrees;
  3100. u1:=u2:=dp_from_a car v; f:=dp_neworder car n;
  3101. for each x in n do
  3102. << f:=dp_sum(f,dp_prod(u1,dp_neworder x));
  3103. u1:=dp_prod(u1,u2)
  3104. >>;
  3105. m1:=dpmat_sieve(gbasis!* quot!=mquot(dpmat_neworder m,f),v);
  3106. setring!* r; cali!=degrees:=dpmat_coldegs m;
  3107. return dpmat_neworder m1;
  3108. end)
  3109. where cali!=degrees:=cali!=degrees,
  3110. cali!=basering:=cali!=basering;
  3111. symbolic procedure annihilator1!* m;
  3112. if dpmat_cols m=0 then m
  3113. else modulequotient1!*(m,dpmat_unit(dpmat_cols m,dpmat_coldegs m));
  3114. % --------------- Stable quotients ------------------------
  3115. symbolic operator matqquot;
  3116. symbolic procedure matqquot(m,f);
  3117. % Stable quotient of dpmat m with respect to a polynomial f, i.e.
  3118. % m : <f> = { v \in F | \exists n : f^n*v \in m }
  3119. if !*mode='symbolic then rederr"only for algebraic mode"
  3120. else dpmat_2a matqquot!*(dpmat_from_a reval m,dp_from_a reval f);
  3121. symbolic procedure matqquot!*(m,f);
  3122. if dp_unit!? f then m
  3123. else if dpmat_cols m=0 then
  3124. flatten!* quot!=stabquot(ideal2mat!* m,{f})
  3125. else quot!=stabquot(m,{f});
  3126. symbolic operator matstabquot;
  3127. symbolic procedure matstabquot(m,f);
  3128. % Stable quotient of dpmat m with respect to an ideal f.
  3129. if !*mode='symbolic then rederr"only for algebraic mode"
  3130. else dpmat_2a
  3131. matstabquot!*(dpmat_from_a reval m,dpmat_from_a reval f);
  3132. symbolic procedure matstabquot!*(m,f);
  3133. if dpmat_cols f > 0 then rederr "stable quotient only by ideals"
  3134. else begin scalar c;
  3135. if (c:=dpmat_cols m)=0 then
  3136. << f:=for each x in dpmat_list f collect
  3137. matop_pseudomod(bas_dpoly x,m);
  3138. f:=for each x in f join if x then {x}
  3139. >>
  3140. else f:=for each x in dpmat_list f collect bas_dpoly x;
  3141. if null f then return
  3142. if c=0 then dpmat_from_dpoly dp_fi 1
  3143. else dpmat_unit(c,dpmat_coldegs m);
  3144. if dp_unit!? car f then return m;
  3145. if c=0 then return flatten!* quot!=stabquot(ideal2mat!* m,f)
  3146. else return quot!=stabquot(m,f);
  3147. end;
  3148. symbolic procedure quot!=stabquot(m,f);
  3149. % m must be a module.
  3150. if dpmat_cols m=0 then rederr"quot_stabquot only for cols>0"
  3151. else (begin scalar m1,p,p1,p2,v,v1,v2,c;
  3152. v1:=gensym(); v2:=gensym(); v:={v1,v2};
  3153. setring!* ring_sum(c:=cali!=basering,
  3154. ring_define(v,degreeorder!* v,'lex,'(1 1)));
  3155. cali!=degrees:=mo_degneworder dpmat_coldegs m;
  3156. p1:=p2:=dp_from_a v1;
  3157. f:=for each x in f collect dp_neworder x;
  3158. p:=car f;
  3159. for each x in cdr f do
  3160. << p:=dp_sum(dp_prod(p1,x),p); p1:=dp_prod(p1,p2) >>;
  3161. p:=dp_diff(dp_fi 1,dp_prod(dp_from_a v2,p));
  3162. % p = 1 - v2 * \sum{f_i * v1^i}
  3163. m1:=matsum!* {dpmat_neworder m, dpmat_times_dpoly(p,
  3164. dpmat_unit(dpmat_cols m,cali!=degrees))};
  3165. m1:=dpmat_sieve(gbasis!* m1,v);
  3166. setring!* c; cali!=degrees:=dpmat_coldegs m;
  3167. return dpmat_neworder m1;
  3168. end)
  3169. where cali!=degrees:=cali!=degrees,
  3170. cali!=basering:=cali!=basering;
  3171. endmodule; % quot
  3172. module moid;
  3173. COMMENT
  3174. ##################################
  3175. ## ##
  3176. ## MONOMIAL IDEALS AND ##
  3177. ## HILBERT SERIES COMPUTATION ##
  3178. ## ##
  3179. ##################################
  3180. This module supports computations with leading term ideals. Moideal
  3181. monomials are assumed to be without module component, but there is a
  3182. Hilbert series calculation also for modules. Hilbert series are
  3183. calculated with respect to the ecart vector. To change this overload
  3184. mo_convert
  3185. This module contains :
  3186. - A moideal prime decomposition along Bayer, Stillman (1992).
  3187. - An algorithm to find all strongly independent sets using
  3188. moideal primes (also for modules),
  3189. - An algorithm to compute the dimension (dim M := dim in(M))
  3190. based on strongly independent sets.
  3191. - Two algorithms computing Hilbert series of ideals and
  3192. modules.
  3193. Lit.: Bayer, Stllman : J. Symb. Comp. 14 (1992), 31 - 50.
  3194. Bigatti, Conti, Robbiano, Traverso . to appear
  3195. Monomial ideals have the following informal syntax :
  3196. <moideal> ::= list of monomials
  3197. They may be vmoideals as well, i.e. with module components.
  3198. Moideals are kept ordered with respect to the descending lexicographic
  3199. order, see [BS].
  3200. END COMMENT;
  3201. % ------------- monomial ideal constructors --------------
  3202. symbolic procedure moid_from_bas bas;
  3203. % Returns the list of leading monomials of the base list bas
  3204. % not removing module components.
  3205. for each x in bas_zerodelete bas collect dp_lmon bas_dpoly x;
  3206. symbolic procedure moid_from_dpmat m;
  3207. % Returns the assoc. list of moideals of the columns of the dpmat m.
  3208. (if dpmat_cols m = 0 then list (0 . u)
  3209. else for i:=1:dpmat_cols m collect
  3210. i . for each x in u join if mo_comp(x)=i then {mo_deletecomp x})
  3211. where u=moid_from_bas dpmat_list m;
  3212. symbolic procedure moid_2a m;
  3213. % Convert the moideal m to algebraic mode.
  3214. 'list . for each x in m collect dp_2a list dp_term(bc_fi 1,x);
  3215. symbolic procedure moid_from_a m;
  3216. % Convert a moideal from algebraic mode.
  3217. if not eqcar(m,'list) then typerr(m,"moideal")
  3218. else for each x in cdr m collect dp_lmon dp_from_a x;
  3219. symbolic procedure moid_print m; mathprint moid_2a m;
  3220. % ------- moideal arithmetics ------------------------
  3221. symbolic procedure moid_sum(a,b);
  3222. % (Reduced) sum of two (v)moideals.
  3223. moid_red append(a,b);
  3224. symbolic procedure moid_intersect(a,b);
  3225. % Intersection of two (pure !) moideals.
  3226. begin scalar c;
  3227. while b do
  3228. << c:=nconc(for each x in a collect mo_lcm(x,car b),c);
  3229. b:=cdr b
  3230. >>;
  3231. return moid_red c
  3232. end;
  3233. symbolic procedure moid_sort m;
  3234. % Sorting by descending (pure) lexicographic order, first by mo_comp.
  3235. sort(m,function mo_dlexcomp);
  3236. symbolic procedure moid_red m;
  3237. % Returns a minimal generating set of the (v)moideal m.
  3238. moid!=red moid_sort m;
  3239. symbolic procedure moid!=red m;
  3240. begin scalar v;
  3241. while m do
  3242. << if not moid_member(car m,cdr m) then v:=car m . v;
  3243. m:=cdr m;
  3244. >>;
  3245. return reversip v;
  3246. end;
  3247. symbolic procedure moid_member(mo,m);
  3248. % true <=> c \in m vdivides mo.
  3249. if null m then nil
  3250. else mo_vdivides!?(car m,mo) or moid_member(mo,cdr m);
  3251. symbolic procedure moid_radical u;
  3252. % Returns the radical of the (pure) moideal u.
  3253. moid_red for each x in u collect mo_radical x;
  3254. symbolic procedure moid_quot(m,x);
  3255. % The quotient of the moideal m by the monomial x.
  3256. moid_red for each u in m collect mo_diff(u,mo_gcd(u,x));
  3257. % --------------- moideal prime decomposition --------------
  3258. % Returns the minimal primes of the moideal m as a list of variable
  3259. % lists.
  3260. symbolic procedure moid_primes m;
  3261. begin scalar c,m1,m2;
  3262. m:=listminimize(for each x in m collect mo_support x,
  3263. function subsetp);
  3264. for each x in m do
  3265. if length x=1 then m1:=car x . m1
  3266. else m2:=x . m2;
  3267. return for each x in moid!=primes(m2,ring_names cali!=basering)
  3268. collect append(m1,x);
  3269. end;
  3270. symbolic procedure moid!=primes(m,vars);
  3271. if null m then list nil
  3272. else begin scalar b,c,vars1; b:=t;
  3273. for each x in m do b:=b and intersection(x,vars);
  3274. if not b then return nil;
  3275. return listminimize(
  3276. for each x in intersection(car m,vars) join
  3277. for each y in moid!=primes(moid!=sps(x,cdr m),
  3278. vars:=delete(x,vars)) collect x . y,
  3279. function subsetp);
  3280. end;
  3281. symbolic procedure moid!=sps(x,m);
  3282. for each y in m join if not memq(x,y) then {y};
  3283. % ------------ (Strongly) independent sets -----------------
  3284. symbolic procedure moid_max l;
  3285. if null l then nil
  3286. else car sort(l,function (lambda(x,y);length x >= length y));
  3287. symbolic procedure indepvarsets!* m;
  3288. % Returns the sets of (strongly) independent variables for the
  3289. % dpmat m. m must be a Groebner basis.
  3290. begin scalar u,n;
  3291. u:=listminimize(
  3292. for each x in moid_from_dpmat m join moid_primes cdr x,
  3293. function subsetp);
  3294. n:=ring_names cali!=basering;
  3295. return for each x in u collect setdiff(n,x);
  3296. end;
  3297. % ---------- Dimension and codimension ------------
  3298. symbolic procedure dim!* m;
  3299. % The dpmat m must be a Groebner basis. Computes the dimension of
  3300. % Coker m as the greatest size of a strongly independent set.
  3301. if not eqcar(m,'dpmat) then typerr(m,"DPMAT")
  3302. else length moid_max indepvarsets!* m;
  3303. symbolic procedure codim!* m;
  3304. length ring_names cali!=basering - dim!* m;
  3305. % ---- An easy independent set procedure -------------
  3306. symbolic operator easyindepset;
  3307. symbolic procedure easyindepset m;
  3308. if !*mode='symbolic then rederr"only for algebraic mode"
  3309. else makelist easyindepset!* dpmat_from_a reval m;
  3310. symbolic procedure easyindepset!* m;
  3311. % Returns a maximal with respect to inclusion independent set for the
  3312. % moideal m.
  3313. begin scalar b,c,d;
  3314. m:=for each x in m collect mo_support x;
  3315. b:=c:=ring_names cali!=basering;
  3316. for each x in b do if moid!=ept(d:=delete(x,c),m) then c:=d;
  3317. return setdiff(ring_names cali!=basering,c);
  3318. end;
  3319. symbolic procedure moid!=ept(l,m);
  3320. if null m then t
  3321. else intersection(l,car m) and moid!=ept(l,cdr m);
  3322. symbolic operator easydim;
  3323. symbolic procedure easydim m;
  3324. if !*mode='symbolic then rederr"only for algebraic mode"
  3325. else easydim!* dpmat_from_a reval m;
  3326. symbolic procedure easydim!* m;
  3327. % Returns a lower bound for the dimension. The bound is true for
  3328. % unmixed ideals (e.g. primes). m must be a gbasis.
  3329. if not eqcar(m,'dpmat) then typerr(m,"DPMAT")
  3330. else listexpand(function max2,
  3331. for each x in moid_from_dpmat m collect
  3332. length easyindepset!* cdr x);
  3333. % ---------- The Hilbert series -------------------
  3334. % --- first variant : [BS]
  3335. symbolic procedure moid!=hilb1 m;
  3336. % Compute the univariate Hilbert series of the moideal m by the rule
  3337. % H(m + (M)) = H((M)) - t^ec(m) * H((M):m)
  3338. if null m then dp_fi 1
  3339. else begin scalar m1,m2;
  3340. for each x in m do
  3341. if mo_linear x then m1:=x . m1 else m2:=x . m2;
  3342. if null m2 then return moid!=hilbmon m1
  3343. else if null cdr m2 then return moid!=hilbmon(car m2 . m1)
  3344. else if moid!=powers m2 then return moid!=hilbmon(append(m1,m2))
  3345. else return dp_prod(moid!=hilbmon m1,
  3346. dp_diff(moid!=hilb1 cdr m2,
  3347. dp_times_mo(mo_convert car m2,
  3348. moid!=hilb1 moid_quot(cdr m2,car m2))));
  3349. end;
  3350. symbolic procedure moid!=hilbmon m;
  3351. % Returns the product of the converted dpolys 1 - mo for the
  3352. % monomials mo in m.
  3353. if null m then dp_fi 1
  3354. else begin scalar p;
  3355. m:=for each x in m collect
  3356. dp_sum(dp_fi 1,list dp_term(bc_fi(-1),mo_convert x));
  3357. p:=car m;
  3358. for each x in cdr m do p:=dp_prod(p,x);
  3359. return p;
  3360. end;
  3361. symbolic procedure moid!=powers m;
  3362. % m contains only powers of variables.
  3363. if null m then t
  3364. else (length mo_support car m<2) and moid!=powers cdr m;
  3365. % --- Second variant : by induction on the number of variables.
  3366. symbolic procedure moid!=hilb2 m;
  3367. if null m then dp_fi 1
  3368. else begin scalar m1,m2,x,p;
  3369. for each x in m do
  3370. if mo_linear x then m1:=x . m1 else m2:=x . m2;
  3371. if null m2 then return moid!=hilbmon m1
  3372. else if null cdr m2 then return moid!=hilbmon(car m2 . m1)
  3373. else if moid!=powers m2 then return moid!=hilbmon(append(m1,m2))
  3374. else begin scalar x;
  3375. x:=mo_from_a car mo_support car m2;
  3376. p:=dp_prod(moid!=hilbmon m1,
  3377. dp_sum(moid!=hilb2 moid_red(x . m2),
  3378. dp_times_mo(mo_convert x,
  3379. moid!=hilb2 moid_quot(m2,x))))
  3380. end;
  3381. return p;
  3382. end;
  3383. % -------- Hilbert series from a free resolution --------------
  3384. symbolic procedure hilb3 u;
  3385. % Hilbert series numerator from the resolution u.
  3386. begin scalar sgn,p; sgn:=t;
  3387. for each x in u do
  3388. << if sgn then p:=dp_sum(p,moid!=hilb3 x)
  3389. else p:=dp_diff(p,moid!=hilb3 x);
  3390. sgn:=not sgn;
  3391. >>;
  3392. return p;
  3393. end;
  3394. symbolic procedure moid!=hilb3 u;
  3395. % Convert column degrees of the dpmat u to a generating polynomial.
  3396. (if length c = dpmat_cols u then
  3397. dp_compact for each x in c collect
  3398. dp_term(bc_fi 1,mo_convert cdr x)
  3399. else dp_fi max(1,dpmat_cols u))
  3400. where c:=dpmat_coldegs u;
  3401. % ------- The common interface ----------------
  3402. symbolic procedure hilb(m,fn);
  3403. % Returns the (univariate) Hilbert series numerator of the dpmat m as
  3404. % a dpoly using the internal Hilbert series computation fn for
  3405. % moideals. m must be a Groebner basis.
  3406. if dpmat_cols m = 0 then apply1(fn,moid_from_bas dpmat_list m)
  3407. else (begin scalar w,lt,p,p1; integer i;
  3408. lt:=moid_from_dpmat m;
  3409. for i:=1:dpmat_cols m do
  3410. << p1:=atsoc(i,lt);
  3411. if null p1 then rederr"HILB with wrong leading term list"
  3412. else p1:=apply1(fn,cdr p1);
  3413. w:=atsoc(i,cali!=degrees);
  3414. if w then p1:=dp_times_mo(mo_convert cdr w,p1);
  3415. p:=dp_sum(p,p1);
  3416. >>;
  3417. return p;
  3418. end) where cali!=degrees:=dpmat_coldegs m;
  3419. symbolic procedure hilb1 m; hilb(m,function moid!=hilb1);
  3420. symbolic procedure hilb2 m; hilb(m,function moid!=hilb2);
  3421. symbolic procedure moid!=hilb2hs h;
  3422. % Converts the Hilbert series numerator h into a rational expression
  3423. % with denom = prod ( 1-x^k | k in ecart vector )
  3424. % and cancels common factors. Returns a s.q.
  3425. begin scalar g,x,den,num;
  3426. x:=car ring_names cali!=basering;
  3427. num:=numr simp dp_2a h; % This is the numerator as a s.f.
  3428. den:=1;
  3429. for each n in ring_ecart cali!=basering do
  3430. den:=multf(den,(((x.n).-1).1));
  3431. % This is the denominator as a s.f.
  3432. g:=gcdf!*(num,den);
  3433. return quotf(num,g) ./ quotf(den,g);
  3434. end;
  3435. symbolic procedure hilbseries1 m; moid!=hilb2hs hilb1 m;
  3436. % m must be a Gbasis.
  3437. symbolic procedure hilbseries2 m; moid!=hilb2hs hilb2 m;
  3438. % m must be a Gbasis.
  3439. symbolic procedure hilbseries3 u; moid!=hilb2hs hilb3 u;
  3440. % u must be a resolution.
  3441. % ------------- Multiplicity ---------------------
  3442. symbolic procedure moid_hf2mult n;
  3443. % Get the sum of the coefficients of the s.f. (car n).
  3444. % This is the multiplicity, if n is a HF.
  3445. (prepf absf if numberp f then f
  3446. else car subf(f,list (mvar f . 1))) where f=car n;
  3447. symbolic procedure moid_hf2dim f;
  3448. % Returns the dimension as the pole order at 1 of the HF f.
  3449. if domainp denr f then 0
  3450. else begin scalar g,x,d; integer n;
  3451. f:=denr f; x:=mvar f; n:=0; d:=(((x.1).-1).1);
  3452. while null cdr (g:=qremf(f,d)) do
  3453. << n:=n+1; f:=car g >>;
  3454. return n;
  3455. end;
  3456. symbolic procedure degree!* m; moid_hf2mult hilbseries1 m;
  3457. endmodule; % moid
  3458. module res;
  3459. COMMENT
  3460. ######################
  3461. ### ###
  3462. ### RESOLUTIONS ###
  3463. ### ###
  3464. ######################
  3465. This module contains algorithms on complexes, i.e. chains of modules
  3466. (submodules of free modules represented as im f of certain dpmat's).
  3467. A chain (in particular a resolution) is a list of dpmat's with the
  3468. usual annihilation property of subsequent dpmat's.
  3469. This module contains
  3470. - An algorithm to compute a minimal resolution of a dpmat,
  3471. - the same for a local dpmat, using either the Simp or the
  3472. Lazy strategy,
  3473. - the extraction of the (graded) Betti numbers from a
  3474. resolution.
  3475. This module is just under development.
  3476. END COMMENT;
  3477. % ------------- Minimal resolutions --------------
  3478. symbolic procedure Resolve!*(m,d);
  3479. % Compute a minimal resolution of the dpmat m, i.e. a list of dpmat's
  3480. % (s0 s1 s2 ...), where sk is the k-th syzygy module of m, upto the
  3481. % d'th part.
  3482. (begin scalar a,u;
  3483. if dpmat_cols m=0 then
  3484. << cali!=degrees:=nil; m:=ideal2mat!* m>>
  3485. else cali!=degrees:=dpmat_coldegs m;
  3486. a:=list(m); u:=syzygies!* m;
  3487. while (not dpmat_zero!? u)and(d>1) do
  3488. << m:=u; u:=syzygies!* m; d:=d-1;
  3489. u:=groeb_minimize(m,u); m:=car u; u:=cdr u; a:=m . a;
  3490. >>;
  3491. return reversip (u.a);
  3492. end) where cali!=degrees:=cali!=degrees;
  3493. % ----------------- The Betti numbers -------------
  3494. symbolic procedure bettiNumbers!* c;
  3495. % Returns the list of Betti numbers of the chain c.
  3496. for each x in c collect dpmat_cols x;
  3497. symbolic procedure gradedBettiNumbers!* c;
  3498. % Returns the list of degree lists (according to the ecart) of the
  3499. % generators of the chain c.
  3500. for each x in c collect
  3501. begin scalar i,d; d:=dpmat_coldegs x;
  3502. return
  3503. if d then sort(for each y in d collect mo_ecart cdr y,'leq)
  3504. else for i:=1:dpmat_cols x collect 0;
  3505. end;
  3506. endmodule; % res
  3507. module intf;
  3508. COMMENT
  3509. #####################################
  3510. ### ###
  3511. ### INTERFACE TO ALGEBRAIC MODE ###
  3512. ### ###
  3513. #####################################
  3514. There are two types of procedures :
  3515. The first type takes polynomial lists or polynomial matrices as
  3516. input, converts them into dpmats, computes the result and
  3517. reconverts it to algebraic mode.
  3518. The second type is property driven, i.e. Basis, Gbasis, Syzygies
  3519. etc. are attached via properties to an identifier.
  3520. For them, the 'ring property watches, that cali!=basering hasn't
  3521. changed (including the term order). Otherwise the results must be
  3522. reevaluated using setideal(name,name) or setmodule(name,name) since
  3523. otherwise results may become wrong.
  3524. The switch "noetherian" controls whether the term order satisfies
  3525. the chain condition (default is "on") and chooses either the
  3526. groebner algorithm or the local standard basis algorithm.
  3527. END COMMENT;
  3528. % ----- The properties managed upto now ---------
  3529. fluid '(intf!=properties);
  3530. intf!=properties:='(basis ring gbasis syzygies resolution
  3531. hilbertseries independentsets);
  3532. % --- Some useful common symbolic procedures --------------
  3533. symbolic procedure intf!=clean u;
  3534. % Removes all properties.
  3535. for each x in intf!=properties do remprop(u,x);
  3536. symbolic procedure intf_test m;
  3537. if (length m neq 1)or(not idp car m) then typerr(m,"identifier");
  3538. symbolic procedure intf_get m;
  3539. % Get the 'basis.
  3540. begin scalar c;
  3541. if not (c:=get(m,'basis)) then typerr(m,"dpmat variable");
  3542. if not equal(get(m,'ring),cali!=basering) then
  3543. rederr"invalid base ring";
  3544. cali!=degrees:=dpmat_coldegs c;
  3545. return c;
  3546. end;
  3547. symbolic procedure intf!=set(m,v);
  3548. % Attach the dpmat value v to the variable m.
  3549. << put(m,'ring,cali!=basering);
  3550. put(m,'basis,v);
  3551. if dpmat_cols v = 0 then
  3552. << put(m,'rtype,'list); put(m,'avalue,'list.{dpmat_2a v})>>
  3553. else
  3554. <<put(m,'rtype,'matrix); put(m,'avalue,'matrix.{dpmat_2a v})>>;
  3555. >>;
  3556. % ------ setideal -------------------
  3557. put('setideal,'psopfn,'intf!=setideal);
  3558. symbolic procedure intf!=setideal u;
  3559. % setideal(name,base list)
  3560. begin scalar l;
  3561. if length u neq 2 then rederr "Syntax : setideal(identifier,ideal)";
  3562. if not idp car u then typerr(car u,"ideal name");
  3563. l:=reval cadr u;
  3564. if not eqcar(l,'list) then typerr(l,"ideal basis");
  3565. intf!=clean(car u);
  3566. put(car u,'ring,cali!=basering);
  3567. put(car u,'basis,l:=dpmat_from_a l);
  3568. put(car u,'avalue,'list.{l:=dpmat_2a l});
  3569. put(car u,'rtype,'list);
  3570. return l;
  3571. end;
  3572. % --------------- setmodule -----------------------
  3573. put('setmodule,'psopfn,'intf!=setmodule);
  3574. symbolic procedure intf!=setmodule u;
  3575. % setmodule(name,matrix)
  3576. begin scalar l;
  3577. if length u neq 2 then
  3578. rederr "Syntax : setmodule(identifier,module basis)";
  3579. if not idp car u then typerr(car u,"module name");
  3580. l:=reval cadr u;
  3581. if not eqcar(l,'mat) then typerr(l,"module basis");
  3582. intf!=clean(car u);
  3583. put(car u,'ring,cali!=basering);
  3584. put(car u,'basis,dpmat_from_a l);
  3585. put(car u,'avalue,'matrix.{l});
  3586. put(car u,'rtype,'matrix);
  3587. return l;
  3588. end;
  3589. % ------------ setring ------------------------
  3590. put('setring,'psopfn,'intf!=setring);
  3591. % Setring(vars,term order degrees,tag <,ecart>) sets the internal
  3592. % variable cali!=basering. The term order is at first by the degrees
  3593. % and then by the tag. The tag must be LEX or REVLEX.
  3594. % If ecart is not supplied the ecart is set to the default, i.e. the
  3595. % first degree vector (noetherian degree order) or to (1 1 .. 1).
  3596. % The ring may also be supplied as a list of its arguments as e.g.
  3597. % output by "getring".
  3598. symbolic procedure intf!=setring u;
  3599. begin
  3600. if length u = 1 then u:=cdr reval car u;
  3601. if not memq(length u,'(3 4)) then
  3602. rederr "Syntax : setring(vars,term order,tag[,ecart])";
  3603. setring!* ring_from_a ('list . u);
  3604. return ring_2a cali!=basering;
  3605. end;
  3606. % ----------- getring --------------------
  3607. put('getring,'psopfn,'intf!=getring);
  3608. % Get the base ring of an object as the algebraic list
  3609. % {vars,tord,tag,ecart}.
  3610. symbolic procedure intf!=getring u;
  3611. if null u then ring_2a cali!=basering
  3612. else begin scalar c; c:=get(car u,'ring);
  3613. if null c then typerr(car u,"dpmat variable");
  3614. return ring_2a c;
  3615. end;
  3616. % ------- The algebraic interface -------------
  3617. symbolic operator ideal2mat;
  3618. symbolic procedure ideal2mat m;
  3619. % Convert the list of polynomials m into a matrix column.
  3620. if !*mode='symbolic then rederr"only for algebraic mode"
  3621. else if not eqcar(m,'list) then typerr(m,'list)
  3622. else 'mat . for each x in cdr m collect {x};
  3623. put('flatten,'psopfn,'cali!-flatten);
  3624. symbolic procedure cali!-flatten m;
  3625. % Flatten the matrix in car(m).
  3626. (if !*mode='symbolic then rederr"only for algebraic mode"
  3627. else if not eqcar(m,'mat) then typerr(m,'matrix)
  3628. else 'list . for each x in cdr m join for each y in x collect y)
  3629. where m = reval car m;
  3630. put('setgbasis,'psopfn,'intf!=setgbasis);
  3631. symbolic procedure intf!=setgbasis m;
  3632. % Say that the basis is already a Gbasis.
  3633. begin scalar c;
  3634. intf_test m; m:=car m; c:=intf_get m;
  3635. put(m,'gbasis,c);
  3636. return reval m;
  3637. end;
  3638. symbolic operator setdegrees;
  3639. symbolic procedure setdegrees m;
  3640. % Set a term list as actual column degrees. Execute this before
  3641. % setmodule to supply a module with prescribed column degrees.
  3642. if !*mode='symbolic then rederr"only for algebraic mode"
  3643. else begin scalar i,b;
  3644. b:=moid_from_a reval m; i:=0;
  3645. cali!=degrees:= for each x in b collect <<i:=i+1; i . x>>;
  3646. return moid_2a for each x in cali!=degrees collect cdr x;
  3647. end;
  3648. put('getdegrees,'psopfn,'intf!=getdegrees);
  3649. symbolic procedure intf!=getdegrees m;
  3650. begin
  3651. if m then <<intf_test m; intf_get car m>>;
  3652. return moid_2a for each x in cali!=degrees collect cdr x
  3653. end;
  3654. symbolic operator getecart;
  3655. symbolic procedure getecart;
  3656. if !*mode='symbolic then rederr"only for algebraic mode"
  3657. else makelist ring_ecart cali!=basering;
  3658. put('gbasis,'psopfn,'intf!=gbasis);
  3659. symbolic procedure intf!=gbasis m;
  3660. begin scalar c,c1;
  3661. intf_test m; m:=car m; c1:=intf_get m;
  3662. if (c:=get(m,'gbasis)) then return dpmat_2a c;
  3663. c:=gbasis!* c1;
  3664. put(m,'gbasis,c);
  3665. return dpmat_2a c;
  3666. end;
  3667. symbolic operator setmonset;
  3668. symbolic procedure setmonset m;
  3669. if !*mode='symbolic then rederr"only for algebraic mode"
  3670. else makelist setmonset!* cdr reval m;
  3671. symbolic procedure setmonset!* m;
  3672. if subsetp(m,ring_names cali!=basering) then cali!=monset:=m
  3673. else typerr(m,"monset list");
  3674. symbolic operator getmonset;
  3675. symbolic procedure getmonset(); makelist cali!=monset;
  3676. put('resolve,'psopfn,'intf!=resolve);
  3677. symbolic procedure intf!=resolve m;
  3678. begin scalar c,c1,d;
  3679. intf_test m; if length m=2 then d:=reval cadr m else d:=100;
  3680. m:=car m; c1:=intf_get m;
  3681. if ((c:=get(m,'resolution)) and (car c >= d)) then
  3682. return makelist for each x in cdr c collect dpmat_2a x;
  3683. c:=Resolve!*(c1,d);
  3684. put(m,'resolution,d.c);
  3685. if not get(m,'syzygies) then put(m,'syzygies,cadr c);
  3686. return makelist for each x in c collect dpmat_2a x;
  3687. end;
  3688. put('syzygies,'psopfn,'intf!=syzygies);
  3689. symbolic procedure intf!=syzygies m;
  3690. begin scalar c,c1;
  3691. intf_test m; m:=car m; c1:=intf_get m;
  3692. if (c:=get(m,'syzygies)) then return dpmat_2a c;
  3693. c:=syzygies!* c1;
  3694. put(m,'syzygies,c);
  3695. return dpmat_2a c;
  3696. end;
  3697. put('indepvarsets,'psopfn,'intf!=indepvarsets);
  3698. symbolic procedure intf!=indepvarsets m;
  3699. begin scalar c;
  3700. intf_test m; m:=car m; intf_get m;
  3701. if (c:=get(m,'independentsets)) then
  3702. return makelist for each x in c collect makelist x;
  3703. if not (c:=get(m,'gbasis)) then rederr"Compute Gbasis first";
  3704. c:=indepvarsets!* c;
  3705. put(m,'independentsets,c);
  3706. return makelist for each x in c collect makelist x;
  3707. end;
  3708. put('getleadterms,'psopfn,'intf_getleadterms);
  3709. symbolic procedure intf_getleadterms m;
  3710. begin scalar c;
  3711. intf_test m; m:=car m; intf_get m;
  3712. if not (c:=get(m,'gbasis)) then rederr"Compute Gbasis first";
  3713. c:=getleadterms!* c;
  3714. return dpmat_2a c;
  3715. end;
  3716. put('hilbseries,'psopfn,'intf!=hilbseries);
  3717. symbolic procedure intf!=hilbseries m;
  3718. % Returns the Hilbert series of m.
  3719. begin scalar c;
  3720. intf_test m; m:=car m; intf_get m;
  3721. if (c:=get(m,'hilbertseries)) then return mk!*sq c;
  3722. if not(c:=get(m,'gbasis)) then rederr"Compute Gbasis first"
  3723. else c:=hilbseries1 c;
  3724. put(m,'hilbertseries,c);
  3725. return mk!*sq c;
  3726. end;
  3727. put('degree,'psopfn,'intf_getmult);
  3728. symbolic procedure intf_getmult m;
  3729. % Returns the multiplicity of m.
  3730. begin scalar c;
  3731. intf_test m; m:=car m; intf_get m;
  3732. if (c:=get(m,'hilbertseries)) then return moid_hf2mult c;
  3733. if not(c:=get(m,'gbasis)) then rederr"Compute Gbasis first"
  3734. else c:=hilbseries1 c;
  3735. put(m,'hilbertseries,c);
  3736. return moid_hf2mult c;
  3737. end;
  3738. put('dim,'psopfn,'intf!=dim);
  3739. put('codim,'psopfn,'intf!=codim);
  3740. symbolic procedure intf!=dim m;
  3741. % Returns the dimension of coker m.
  3742. begin scalar c;
  3743. intf_test m; m:=car m; intf_get m;
  3744. if (c:=get(m,'hilbertseries)) then return moid_hf2dim c;
  3745. if (c:=get(m,'independentsets)) then return length moid_max c;
  3746. if not(c:=get(m,'gbasis)) then rederr"Compute Gbasis first"
  3747. else << c:=indepvarsets!* c; put(m,'independentsets,c);
  3748. c:=length moid_max c;
  3749. >>;
  3750. return c;
  3751. end;
  3752. symbolic procedure intf!=codim m;
  3753. % Returns the codimension of coker m.
  3754. length ring_names cali!=basering - intf!=dim m;
  3755. put('BettiNumbers,'psopfn,'intf!=BettiNumbers);
  3756. symbolic procedure intf!=BettiNumbers m;
  3757. begin scalar c;
  3758. intf_test m; m:=car m; intf_get m;
  3759. if (c:=get(m,'resolution)) then return makelist BettiNumbers!* cdr c
  3760. else rederr"Compute a resolution first";
  3761. end;
  3762. put('GradedBettiNumbers,'psopfn,'intf!=GradedBettiNumbers);
  3763. symbolic procedure intf!=GradedBettiNumbers m;
  3764. begin scalar c;
  3765. intf_test m; m:=car m; intf_get m;
  3766. if (c:=get(m,'resolution)) then return
  3767. makelist for each x in GradedBettiNumbers!* cdr c collect makelist x
  3768. else rederr"Compute a resolution first";
  3769. end;
  3770. put('degsfromresolution,'psopfn,'intf!=degsfromresolution);
  3771. symbolic procedure intf!=degsfromresolution m;
  3772. begin scalar c;
  3773. intf_test m; m:=car m;
  3774. if not equal(get(m,'ring),cali!=basering) then
  3775. rederr"invalid base ring";
  3776. if not (c:=get(m,'resolution)) then
  3777. rederr"compute a resolution first";
  3778. return makelist for each x in cdr c collect
  3779. moid_2a for each y in dpmat_coldegs x collect cdr y;
  3780. end;
  3781. symbolic operator sieve;
  3782. symbolic procedure sieve(m,vars);
  3783. % Sieve out all base elements from m containing one of the variables
  3784. % in vars in their leading term.
  3785. if !*mode='symbolic then rederr"only for algebraic mode"
  3786. else dpmat_2a dpmat_sieve(dpmat_from_a reval m,cdr vars);
  3787. endmodule; % intf
  3788. module odim;
  3789. COMMENT
  3790. Applications to zerodimensional ideals and modules.
  3791. END COMMENT;
  3792. % -------------- Test for zero dimension -----------------
  3793. % For a true answer m must be a gbasis.
  3794. put('dimzerop,'psopfn,'odim!=zerop);
  3795. symbolic procedure odim!=zerop m;
  3796. begin scalar c;
  3797. intf_test m; intf_get(m:=car m);
  3798. if not (c:=get(m,'gbasis)) then rederr"Compute Gbasis first";
  3799. if dimzerop!* c then return 'yes else return 'no;
  3800. end;
  3801. symbolic procedure dimzerop!* m; null odim_parameter m;
  3802. symbolic procedure odim_parameter m;
  3803. % Return a parameter of the dpmat m or nil, if it is zerodimensional
  3804. % or (1).
  3805. odim!=parameter moid_from_dpmat m;
  3806. symbolic procedure odim!=parameter m;
  3807. if null m then nil
  3808. else odim!=parameter1 cdar m or odim!=parameter cdr m;
  3809. symbolic procedure odim!=parameter1 m;
  3810. if null m then car reverse ring_names cali!=basering
  3811. else if mo_zero!? car m then nil
  3812. else begin scalar b,u;
  3813. u:=for each x in m join if length(b:=mo_support x)=1 then b;
  3814. b:=reverse ring_names cali!=basering;
  3815. while b and member(car b,u) do b:=cdr b;
  3816. return if b then car b else nil;
  3817. end;
  3818. % --- Get a k-base of F/M as a list of monomials ----
  3819. % m must be a gbasis for the correct result.
  3820. put('getkbase,'psopfn,'odim!=evkbase);
  3821. symbolic procedure odim!=evkbase m;
  3822. begin scalar c;
  3823. intf_test m; intf_get(m:=car m);
  3824. if not (c:=get(m,'gbasis)) then rederr"Compute Gbasis first";
  3825. return moid_2a getkbase!* c;
  3826. end;
  3827. symbolic procedure getkbase!* m;
  3828. if not dimzerop!* m then rederr"dpmat not zerodimensional"
  3829. else for each u in moid_from_dpmat m join
  3830. odim!=kbase(mo_from_ei car u,ring_names cali!=basering,cdr u);
  3831. symbolic procedure odim!=kbase(mo,n,m);
  3832. if moid_member(mo,m) then nil
  3833. else mo . for each x on n join
  3834. odim!=kbase(mo_inc(mo,car x,1),append(x,nil),m);
  3835. % --- Produce an univariate polynomial inside the ideal m ---
  3836. symbolic procedure odim_up(a,m);
  3837. % Returns a univariate polynomial (of smallest possible degree if m
  3838. % is a gbasis) in the variable a inside the zerodimensional ideal m.
  3839. % Uses Buchberger's approach.
  3840. if dpmat_cols m>0 or not dimzerop!* m then
  3841. rederr"univariate polynomials only for zerodimensional ideals"
  3842. else if not member(a,ring_names cali!=basering) then
  3843. typerr(a,"variable name")
  3844. else if null matop_pseudomod(dp_fi 1,m) then dp_fi 1
  3845. else begin scalar b,v,p,l,q,r;
  3846. % l is a list of ( p(a) . NF p(a) ), sorted by lt NF p(a)
  3847. p:=(dp_fi 1 . dp_fi 1); b:=dpmat_list m; v:=mo_from_a a;
  3848. while cdr p do
  3849. << l:=merge(list p,l,function odim!=greater);
  3850. q:=dp_times_mo(v,car p);
  3851. r:=red_redpol(b,bas_make(0,dp_times_mo(v,cdr p)));
  3852. p:=odim!=reduce(dp_prod(cdr r,q) . bas_dpoly car r,l);
  3853. >>;
  3854. return
  3855. if !*bcsimp then car dp_simp car p
  3856. else car p;
  3857. end;
  3858. symbolic procedure odim!=greater(a,b);
  3859. mo_compare(dp_lmon cdr a,dp_lmon cdr b)=1;
  3860. symbolic procedure odim!=reduce(a,l);
  3861. if null cdr a or null l or odim!=greater(a, car l) then a
  3862. else if mo_equal!?(dp_lmon cdr a,dp_lmon cdar l) then
  3863. begin scalar z,z1,z2,b;
  3864. b:=car l; z1:=bc_neg dp_lc cdr a; z2:=dp_lc cdr b;
  3865. if !*bcsimp then
  3866. << if (z:=bc_inv z1) then <<z1:=bc_fi 1; z2:=bc_prod(z2,z)>>
  3867. else
  3868. << z:=bc_gcd(z1,z2);
  3869. z1:=car bc_divmod(z1,z);
  3870. z2:=car bc_divmod(z2,z);
  3871. >>;
  3872. >>;
  3873. a:=dp_sum(dp_times_bc(z2,car a),dp_times_bc(z1,car b)) .
  3874. dp_sum(dp_times_bc(z2,cdr a),dp_times_bc(z1,cdr b));
  3875. return odim!=reduce(a,cdr l)
  3876. end
  3877. else odim!=reduce(a,cdr l);
  3878. endmodule; % odim
  3879. module prime;
  3880. COMMENT
  3881. ####################################
  3882. # #
  3883. # PRIME DECOMPOSITION, RADICALS, #
  3884. # AND RELATED PROBLEMS #
  3885. # #
  3886. ####################################
  3887. This module contains algorithms
  3888. - for zerodimensional ideals :
  3889. - to test whether it is radical
  3890. - to compute its radical
  3891. - for a primality test
  3892. - for zerodimensional ideals and modules :
  3893. - to compute its primes
  3894. - to compute its primary decomposition
  3895. - for arbitrary ideals :
  3896. - for a primality test
  3897. - to compute its radical
  3898. - to test whether it is radical
  3899. - for arbitrary ideals and modules :
  3900. - to compute its isolated primes
  3901. - to compute its primary decomposition and
  3902. the associated primes
  3903. - a shortcut for the primary decomposition
  3904. computation for unmixed modules
  3905. The algorithms follow
  3906. Seidenberg : Trans. AMS 197 (1974), 273 - 313.
  3907. Kredel : in Proc. EUROCAL'87, Lecture Notes in Comp. Sci. 378
  3908. (1986), 270 - 281.
  3909. Gianni, Trager, Zacharias :
  3910. J. Symb. Comp. 6 (1988), 149 - 167.
  3911. with essential modifications for modules as e.g. presented in
  3912. Rutman : J. Symb. Comp. 14 (1992), 483 - 503
  3913. END COMMENT;
  3914. % ------ The radical of a zerodimensional ideal -----------
  3915. symbolic procedure prime!=mksqrfree(pol,x);
  3916. % Make the univariate dpoly p(x) squarefree.
  3917. begin scalar p,q;
  3918. p:=numr simp dp_2a pol;
  3919. q:=numr simp dp_2a dp_df(pol,x);
  3920. return dp_from_a prepf car qremf(p,gcdf!*(p,q))
  3921. end;
  3922. put('zeroradical,'psopfn,'prime!=evzero);
  3923. symbolic procedure prime!=evzero m;
  3924. begin scalar c;
  3925. intf_test m; intf_get(m:=car m);
  3926. if not (c:=get(m,'gbasis)) then rederr"Compute Gbasis first";
  3927. return dpmat_2a zeroradical!* c;
  3928. end;
  3929. symbolic procedure zeroradical!* m;
  3930. % Returns the radical of the zerodim. ideal m. m must be a gbasis.
  3931. if dpmat_cols m>0 or not dimzerop!* m then
  3932. rederr"ZERORADICAL only for zerodimensional ideals"
  3933. else if null matop_pseudomod(dp_fi 1,m) then m
  3934. else begin scalar u;
  3935. u:=for each x in ring_names cali!=basering collect
  3936. bas_make(0,prime!=mksqrfree(odim_up(x,m),x));
  3937. u:=dpmat_make(length u,0,bas_renumber u,nil);
  3938. return gbasis!* matsum!* {m,u};
  3939. end;
  3940. put('iszeroradical,'psopfn,'prime!=eviszero);
  3941. symbolic procedure prime!=eviszero m;
  3942. begin scalar c;
  3943. intf_test m; intf_get(m:=car m);
  3944. if not (c:=get(m,'gbasis)) then rederr"Compute Gbasis first";
  3945. return if iszeroradical!* c then 'yes else 'no;
  3946. end;
  3947. symbolic procedure iszeroradical!* m;
  3948. % Test whether the zerodim. ideal m is radical. m must be a gbasis.
  3949. if dpmat_cols m>0 or not dimzerop!* m then
  3950. rederr"ISZERORADICAL only for zerodimensional ideals"
  3951. else if null matop_pseudomod(dp_fi 1,m) then t
  3952. else begin scalar u,isradical;
  3953. isradical:=t;
  3954. for each x in ring_names cali!=basering do
  3955. isradical:=isradical and
  3956. null matop_pseudomod(prime!=mksqrfree(odim_up(x,m),x),m);
  3957. return isradical;
  3958. end;
  3959. % ---- The primes of a zerodimensional ideal or module ------
  3960. symbolic operator zeroprimes;
  3961. symbolic procedure zeroprimes m;
  3962. if !*mode='symbolic then rederr"only for algebraic mode"
  3963. else makelist for each x in
  3964. zeroprimes!* dpmat_from_a reval m collect dpmat_2a x;
  3965. symbolic procedure zeroprimes!* m;
  3966. % The primes of the zerodimensional ideal Ann F/M.
  3967. % The unit ideal has no primes.
  3968. listminimize(
  3969. for each x in prime!=zeroprimes1 gbasis!* annihilator2!* m
  3970. join prime!=zeroprimes2 x,
  3971. function submodulep!*) ;
  3972. symbolic procedure prime_iszeroprime m;
  3973. % Test a zerodimensiomal ideal to be prime. m must be a gbasis.
  3974. if dpmat_cols m>0 or not dimzerop!* m then
  3975. rederr "iszeroprime only for zerodimensional ideals"
  3976. else if null matop_pseudomod(dp_fi 1,m) then
  3977. rederr"the ideal is the unit ideal"
  3978. else prime!=iszeroprime1 m and prime!=iszeroprime2 m;
  3979. symbolic procedure prime!=zeroprimes1 m;
  3980. % A first approximation to the isolated primes in dim=0.
  3981. if dpmat_cols m>0 then rederr"only for ideals"
  3982. else if null matop_pseudomod(dp_fi 1,m) then nil
  3983. else if not dimzerop!* m then
  3984. rederr"ZEROPRIMES only for zerodimensional ideals or modules"
  3985. else prime!=zeroprimes1a(ring_names cali!=basering,list m);
  3986. symbolic procedure prime!=zeroprimes1a(vars,l);
  3987. % vars=var. names, l=list of dpmats. Find recursively the factors
  3988. % of the univariate polynomial in x=car vars for each u in l and
  3989. % split up with them the elements of l, removing unit ideals.
  3990. if null vars then l
  3991. else begin scalar x,u;
  3992. x:=car vars;
  3993. u:=for each m in prime!=zeroprimes1a(cdr vars,l) join
  3994. for each y in
  3995. cdr ((fctrf numr simp dp_2a odim_up(x,m)) where !*factor=t)
  3996. collect matsum!* {m,
  3997. dpmat_make(1,0,
  3998. list bas_make(1,dp_from_a prepf car y),
  3999. nil)};
  4000. u:=for each x in u collect gbasis!* x;
  4001. return for each x in u join if matop_pseudomod(dp_fi 1,x) then {x};
  4002. end;
  4003. symbolic procedure prime!=iszeroprime1 m;
  4004. % A first non primality test.
  4005. if dpmat_cols m>0 or not dimzerop!* m then
  4006. rederr"iszeroprime only for zerodimensional ideals"
  4007. else prime!=iszeroprime1a(ring_names cali!=basering,m);
  4008. symbolic procedure prime!=iszeroprime1a(vars,m);
  4009. % vars=var. names, l=list of dpmats. Recursively try to factor the
  4010. % univariate polynomial in x=car vars for m
  4011. if null vars then t
  4012. else begin scalar u;
  4013. if (length(u:=cdr ((fctrf numr simp dp_2a odim_up(car vars,m))
  4014. where !*factor=t))>1)
  4015. or (cdar u>1) then return nil
  4016. else return prime!=iszeroprime1a(cdr vars,m);
  4017. end;
  4018. symbolic procedure prime_gpchange(vars,v,m);
  4019. % Change to general position with respect to v. Only for pure lex.
  4020. % term order and radical ideal m.
  4021. if null vars then m
  4022. else if null matop_pseudomod(dp_fi 1,m) then m
  4023. else begin scalar s,x,a;
  4024. s:=0; x:=mo_from_a car vars;
  4025. a:=list (v.prepf addf(!*k2f v,!*k2f car vars));
  4026. % the substitution rule v -> v + x .
  4027. while not member(x,moid_from_bas dpmat_list m)
  4028. % i.e. m has a leading term equal to x
  4029. and ((s:=s+1) < 10)
  4030. % to avoid too much loops.
  4031. do m:=gbasis!* dpmat_sub(a,m);
  4032. if s=10 then rederr" change to general position failed";
  4033. return prime_gpchange(cdr vars,v,m);
  4034. end;
  4035. symbolic procedure prime!=zeroprimes2 m;
  4036. % Decompose the radical zerodimensional dmpat ideal m using a general
  4037. % position argument.
  4038. (begin scalar c,v,vars,u,d,r,vars1;
  4039. c:=cali!=basering; vars:=ring_names c; v:=gensym();
  4040. u:=moid_from_bas dpmat_list m;
  4041. vars1:=for each x in vars join
  4042. if not member(mo_from_a x,u) then {x};
  4043. if (length vars1)=1 then return prime!=zeroprimes3(m,first vars1);
  4044. if ring_tag c='revlex then % for proper ring_sum redefine it.
  4045. r:=ring_define(vars,ring_degrees c,'lex,ring_ecart c)
  4046. else r:=c;
  4047. setring!* ring_sum(r,ring_define(list v,nil,'lex,'(1)));
  4048. cali!=degrees:=nil;
  4049. m:=gbasis!* matsum!* {dpmat_neworder m,
  4050. dpmat_make(1,0,list bas_make(1,dp_from_a v),nil)};
  4051. if matop_pseudomod(dp_fi 1,m) then
  4052. << m:=prime_gpchange(vars1,v,m);
  4053. u:=for each x in prime!=zeroprimes3(m,v) join
  4054. if matop_pseudomod(dp_fi 1,x) and
  4055. matop_pseudomod(dp_fi 1,d:=eliminate!*(x,{v})) then {d}
  4056. % To recognize (1) even if x is not a gbasis.
  4057. >>;
  4058. setring!* c;
  4059. return for each x in u collect interreduce!* dpmat_neworder x;
  4060. end)
  4061. where cali!=degrees:=cali!=degrees,
  4062. cali!=basering:=cali!=basering;
  4063. symbolic procedure prime!=zeroprimes3(m,v);
  4064. % m is in general position with univariate polynomial in v.
  4065. begin scalar u,p;
  4066. u:=dpmat_list m;
  4067. while u and not equal(mo_support dp_lmon (p:=bas_dpoly car u),
  4068. list v) do u:=cdr u;
  4069. if null u then rederr"univariate polynomial not found";
  4070. p:=for each x in cdr ((fctrf numr simp dp_2a p) where !*factor=t)
  4071. collect dpmat_make(1,0,
  4072. list bas_make(1,dp_from_a prepf car x),nil);
  4073. return for each x in p collect matsum!* {m,x};
  4074. end;
  4075. symbolic procedure prime!=iszeroprime2 m;
  4076. % Test the radical zerodimensional dmpat ideal m to be prime using a
  4077. % general position argument.
  4078. (begin scalar c,v,vars,u,r;
  4079. c:=cali!=basering; vars:=ring_names c; v:=gensym();
  4080. if ring_tag c='revlex then % for proper ring_sum redefine it.
  4081. r:=ring_define(vars,ring_degrees c,'lex,ring_ecart c)
  4082. else r:=c;
  4083. setring!* ring_sum(r,ring_define(list v,nil,'lex,'(1)));
  4084. cali!=degrees:=nil;
  4085. m:=matsum!* {dpmat_neworder m,
  4086. dpmat_make(1,0,list bas_make(1,dp_from_a v),nil)};
  4087. m:=prime_gpchange(vars,v,gbasis!* m);
  4088. u:=prime!=iszeroprime3(m,v);
  4089. setring!* c; return u;
  4090. end)
  4091. where cali!=degrees:=cali!=degrees,
  4092. cali!=basering:=cali!=basering;
  4093. symbolic procedure prime!=iszeroprime3(m,v);
  4094. begin scalar u,p;
  4095. u:=dpmat_list m;
  4096. while u and not equal(mo_support dp_lmon (p:=bas_dpoly car u),
  4097. list v) do u:=cdr u;
  4098. if null u then rederr"univariate polynomial not found";
  4099. if (length(u:=cdr ((fctrf numr simp dp_2a p) where !*factor=t))>1)
  4100. or (cdar u>1) then return nil
  4101. else return t
  4102. end;
  4103. % - The primary decomposition of a zerodimensional ideal or module -
  4104. symbolic procedure prime_polynomial l;
  4105. % l is a list of (gbases of) prime ideals.
  4106. % Returns a list of (p . f) with p \in l and dpoly f \in all q \in l
  4107. % except p.
  4108. for each x in l collect (x . prime!=polynomial(x,delete(x,l)));
  4109. symbolic procedure prime!=polynomial(x,l);
  4110. % Returns a dpoly f inside all q \in l and outside x.
  4111. if null l then dp_fi 1
  4112. else begin scalar u,p,q;
  4113. p:=prime!=polynomial(x,cdr l);
  4114. if null matop_pseudomod(p,car l) then return p;
  4115. u:=dpmat_list car l;
  4116. while u and null matop_pseudomod(q:=bas_dpoly car u,x) do u:=cdr u;
  4117. if null u then
  4118. rederr"prime ideal separation failed"
  4119. else return dp_prod(p,q);
  4120. end;
  4121. symbolic operator zeroprimarydecomposition;
  4122. symbolic procedure zeroprimarydecomposition m;
  4123. % Returns a list of {Q,p} with p a prime ideal and Q a p-primary
  4124. % component of m. For m=S^c the list is empty.
  4125. if !*mode='symbolic then rederr"only for algebraic mode"
  4126. else makelist
  4127. for each x in zeroprimarydecomposition!* dpmat_from_a reval m
  4128. collect makelist {dpmat_2a first x,dpmat_2a second x};
  4129. symbolic procedure zeroprimarydecomposition!* m;
  4130. % The symbolic counterpart, returns a list of {Q,p}. m is not
  4131. % assumed to be a gbasis.
  4132. if not dimzerop!* m then rederr
  4133. "zeroprimarydecomposition only for zerodimensional ideals or modules"
  4134. else for each f in prime_polynomial
  4135. (for each y in zeroprimes!* m collect gbasis!* y)
  4136. collect {matqquot!*(m,cdr f),car f};
  4137. % --------- Primality test for an arbitrary ideal. ---------
  4138. put('isprime,'psopfn,'prime!=isprime);
  4139. symbolic procedure prime!=isprime m;
  4140. begin scalar c;
  4141. intf_test m; intf_get(m:=car m);
  4142. if not (c:=get(m,'gbasis)) then rederr"Compute Gbasis first";
  4143. return if isprime!* c then 'yes else 'no;
  4144. end;
  4145. symbolic procedure isprime!* m;
  4146. % Test an dpmat ideal m to be prime. m must be a gbasis.
  4147. if dpmat_cols m>0 then rederr"prime test only for ideals"
  4148. else (begin scalar vars,u,v,c1,c2,m1,m2,lc;
  4149. v:=moid_max indepvarsets!* m; cali!=degrees:=nil;
  4150. if null v then return prime_iszeroprime m;
  4151. vars:=ring_names(c1:=cali!=basering);
  4152. % Change to dimension zero.
  4153. u:=setdiff(ring_names c1,v);
  4154. setring!*
  4155. ring_define(vars,ring_rlp(c1,u),ring_tag c1,ring_ecart c1);
  4156. m1:=dpmat_2a gbasis!* dpmat_neworder m;
  4157. setring!*(c2:= ring_define(u,degreeorder!* u,'revlex,
  4158. for each x in u collect 1));
  4159. m1:=groeb_mingb dpmat_from_a m1;
  4160. if null matop_pseudomod(dp_fi 1,m1) then
  4161. << setring!* c1; rederr"Input must be a gbasis" >>;
  4162. lc:=bc_2a prime!=quot m1; setring!* c1;
  4163. % Test recontraction of m1 to be equal to m.
  4164. m2:=matqquot!*(m,dp_from_a lc);
  4165. if not submodulep!*(m2,m) then return nil;
  4166. % Test the zerodimensional ideal m1 to be prime
  4167. setring!* c2; u:=prime_iszeroprime m1; setring!* c1;
  4168. return u;
  4169. end)
  4170. where cali!=degrees:=cali!=degrees,
  4171. cali!=basering:=cali!=basering;
  4172. symbolic operator isolatedprimes;
  4173. symbolic procedure isolatedprimes m;
  4174. if !*mode='symbolic then rederr"only for algebraic mode"
  4175. else makelist
  4176. for each x in isolatedprimes!* dpmat_from_a reval m collect
  4177. dpmat_2a x;
  4178. symbolic procedure isolatedprimes!* m;
  4179. % Returns the isolated primes of the dpmat m as a dpmat list.
  4180. prime!=isoprimes gbasis!* annihilator2!* m;
  4181. symbolic procedure prime!=isoprimes m;
  4182. % m is a gbasis and an ideal.
  4183. (begin scalar u,c,v,vars,m1,m2,l,p;
  4184. if null(v:=odim_parameter m) then return
  4185. for each x in prime!=zeroprimes1 m join prime!=zeroprimes2 x;
  4186. vars:=ring_names(c:=cali!=basering); cali!=degrees:=nil;
  4187. u:=delete(v,vars);
  4188. setring!* ring_define(vars,ring_rlp(c,u),ring_tag c,ring_ecart c);
  4189. m1:=dpmat_2a gbasis!* dpmat_neworder m;
  4190. setring!* ring_define(u,degreeorder!* u,
  4191. 'revlex,for each x in u collect 1);
  4192. p:=bc_2a prime!=quot(m1:=groeb_mingb dpmat_from_a m1);
  4193. l:=for each x in prime!=isoprimes m1 collect
  4194. (dpmat_2a x . bc_2a prime!=quot x);
  4195. setring!* c;
  4196. l:=for each x in l collect
  4197. matqquot!*(dpmat_from_a car x,dp_from_a cdr x);
  4198. if dp_unit!?(p:=dp_from_a p) or
  4199. submodulep!*(matqquot!*(m,p),m) or
  4200. null matop_pseudomod(dp_fi 1,
  4201. m2:=gbasis!* matsum!* {m,dpmat_from_dpoly p})
  4202. then return l
  4203. else return
  4204. listminimize(append(l,prime!=isoprimes m2),
  4205. function submodulep!*);
  4206. end)
  4207. where cali!=degrees:=cali!=degrees,
  4208. cali!=basering:=cali!=basering;
  4209. symbolic procedure prime!=quot m;
  4210. % The lcm of the leading coefficients of m.
  4211. begin scalar p,u;
  4212. u:=for each x in dpmat_list m collect dp_lc bas_dpoly x;
  4213. if null u then return bc_fi 1;
  4214. p:=car u; for each x in cdr u do p:=bc_lcm(p,x);
  4215. return p
  4216. end;
  4217. % ----------- The radical -------------
  4218. % Returns the radical of the dpmat ideal m.
  4219. symbolic operator radical;
  4220. symbolic procedure radical m;
  4221. if !*mode='symbolic then rederr"only for algebraic mode"
  4222. else dpmat_2a radical!* gbasis!* dpmat_from_a reval m;
  4223. symbolic procedure radical!* m;
  4224. % m must be a gbasis.
  4225. if dpmat_cols m>0 then rederr"RADICAL only for ideals"
  4226. else (begin scalar u,c,v,vars,m1,l,p,p1;
  4227. if null(v:=odim_parameter m) then return zeroradical!* m;
  4228. vars:=ring_names (c:=cali!=basering);
  4229. cali!=degrees:=nil; u:=delete(v,vars);
  4230. setring!* ring_define(vars,ring_rlp(c,u),ring_tag c,ring_ecart c);
  4231. m1:=dpmat_2a gbasis!* dpmat_neworder m;
  4232. setring!* ring_define(u,degreeorder!* u,
  4233. 'revlex,for each x in u collect 1);
  4234. p:=bc_2a prime!=quot(m1:=groeb_mingb dpmat_from_a m1);
  4235. l:=radical!* m1; p1:=bc_2a prime!=quot l;
  4236. l:=dpmat_2a l; setring!* c;
  4237. l:=matqquot!*(dpmat_from_a l,dp_from_a p1);
  4238. if dp_unit!?(p:=dp_from_a p) or
  4239. submodulep!*(matqquot!*(m,p),m) then return l
  4240. else << m1:=radical!* gbasis!* matsum!* {m,dpmat_from_dpoly p};
  4241. if submodulep!*(m1,l) then l:=m1
  4242. else if not submodulep!*(l,m1) then
  4243. l:= matintersect!* {l,m1};
  4244. >>;
  4245. return l;
  4246. end)
  4247. where cali!=degrees:=cali!=degrees,
  4248. cali!=basering:=cali!=basering;
  4249. % -- Primary decomposition for modules without embedded components ---
  4250. symbolic operator easyprimarydecomposition;
  4251. symbolic procedure easyprimarydecomposition m;
  4252. if !*mode='symbolic then rederr"only for algebraic mode"
  4253. else makelist
  4254. for each x in easyprimarydecomposition!* dpmat_from_a reval m
  4255. collect makelist {dpmat_2a first x,dpmat_2a second x};
  4256. symbolic procedure easyprimarydecomposition!* m;
  4257. % Primary decomposition for a module without embedded components.
  4258. begin scalar u; u:=isolatedprimes!* m;
  4259. return if null u then nil
  4260. else if length u=1 then {m,car u}
  4261. else for each f in
  4262. prime_polynomial(for each y in u collect gbasis!* y)
  4263. collect {matqquot!*(m,cdr f),car f};
  4264. end;
  4265. % ---- General primary decomposition ----------
  4266. symbolic operator primarydecomposition;
  4267. symbolic procedure primarydecomposition m;
  4268. if !*mode='symbolic then rederr"only for algebraic mode"
  4269. else makelist
  4270. for each x in primarydecomposition!* gbasis!* dpmat_from_a reval m
  4271. collect makelist {dpmat_2a first x,dpmat_2a second x};
  4272. symbolic procedure primarydecomposition!* m;
  4273. % Returns the primary decomposition of the dpmat (ideal or module) m
  4274. % as a list {Q,p} with a prime ideal p and a p-primary component Q.
  4275. % m must be a gbasis.
  4276. if dpmat_cols m=0 then
  4277. for each x in prime!=decompose1 ideal2mat!* m collect
  4278. {flatten!* first x,second x}
  4279. else prime!=decompose1 m;
  4280. symbolic procedure prime!=decompose1 m;
  4281. (begin scalar u,c,v,vars,m1,l,p,q;
  4282. if null(v:=odim_parameter m) then
  4283. return zeroprimarydecomposition!* m;
  4284. vars:=ring_names (c:=cali!=basering);
  4285. cali!=degrees:=nil; u:=delete(v,vars);
  4286. setring!* ring_define(vars,ring_rlp(c,u),ring_tag c,ring_ecart c);
  4287. m1:=dpmat_2a gbasis!* dpmat_neworder m;
  4288. setring!* ring_define(u,degreeorder!* u,
  4289. 'revlex,for each x in u collect 1);
  4290. p:=bc_2a prime!=quot(m1:=groeb_mingb dpmat_from_a m1);
  4291. l:=for each x in prime!=decompose1 m1 collect
  4292. {(dpmat_2a first x . bc_2a prime!=quot first x),
  4293. (dpmat_2a second x . bc_2a prime!=quot second x)};
  4294. setring!* c;
  4295. l:=for each x in l collect
  4296. << cali!=degrees:=dpmat_coldegs m;
  4297. {gbasis!* matqquot!*(dpmat_from_a car first x,
  4298. dp_from_a cdr first x),
  4299. matqquot!*(dpmat_from_a car second x,dp_from_a cdr second x)}
  4300. >>;
  4301. if dp_unit!?(p:=dp_from_a p) or
  4302. submodulep!*(m1:=matqquot!*(m,p),m) then return l
  4303. else
  4304. << q:=p;
  4305. while not submodulep!*(m1:=dpmat_times_dpoly(p,m1),m) do
  4306. q:=dp_prod(p,q);
  4307. l:=listminimize(
  4308. append(l,prime!=decompose1
  4309. gbasis!* matsum!* {m, dpmat_times_dpoly(q,
  4310. dpmat_unit(dpmat_cols m,dpmat_coldegs m))}),
  4311. function(lambda(x,y);
  4312. submodulep!*(car x,car y)));
  4313. >>;
  4314. return l;
  4315. end)
  4316. where cali!=degrees:=cali!=degrees,
  4317. cali!=basering:=cali!=basering;
  4318. symbolic operator unmixedradical;
  4319. symbolic procedure unmixedradical m;
  4320. % Returns the radical of the dpmat ideal m.
  4321. if !*mode='symbolic then rederr"only for algebraic mode"
  4322. else dpmat_2a unmixedradical!* gbasis!* dpmat_from_a reval m;
  4323. symbolic procedure unmixedradical!* m;
  4324. % m must be a gbasis.
  4325. if dpmat_cols m>0 then rederr"UNMIXEDRADICAL only for ideals"
  4326. else (begin scalar u,c,d,v,vars,m1,l,p,p1;
  4327. if null(v:=moid_max indepvarsets!* m) then
  4328. return zeroradical!* m;
  4329. vars:=ring_names (c:=cali!=basering);
  4330. d:=length v; u:=setdiff(vars,v);
  4331. setring!* ring_define(vars,ring_rlp(c,u),ring_tag c,ring_ecart c);
  4332. m1:=dpmat_2a gbasis!* dpmat_neworder m;
  4333. setring!* ring_define(u,degreeorder!* u,'revlex,
  4334. for each x in u collect 1);
  4335. p:=bc_2a prime!=quot(m1:=groeb_mingb dpmat_from_a m1);
  4336. l:=zeroradical!* m1; p1:=bc_2a prime!=quot l;
  4337. l:=dpmat_2a l; setring!* c;
  4338. l:=matqquot!*(dpmat_from_a l,dp_from_a p1);
  4339. if dp_unit!?(p:=dp_from_a p) then return l
  4340. else << m1:=gbasis!* matsum!* {m,dpmat_from_dpoly p};
  4341. if dim!* m1=d then
  4342. l:= matintersect!* {l,unmixedradical!* m1};
  4343. >>;
  4344. return l;
  4345. end)
  4346. where cali!=degrees:=cali!=degrees,
  4347. cali!=basering:=cali!=basering;
  4348. symbolic operator eqhull;
  4349. symbolic procedure eqhull m;
  4350. % Returns the radical of the dpmat ideal m.
  4351. if !*mode='symbolic then rederr"only for algebraic mode"
  4352. else dpmat_2a eqhull!* gbasis!* dpmat_from_a reval m;
  4353. symbolic procedure eqhull!* m;
  4354. % m must be a gbasis.
  4355. begin scalar d;
  4356. if (d:=dim!* m)=0 then return m
  4357. else return prime!=eqhull(m,d)
  4358. end;
  4359. symbolic procedure prime!=eqhull(m,d);
  4360. % d(>0) is the dimension of the dpmat m.
  4361. (begin scalar u,c,v,vars,m1,l,p;
  4362. v:=moid_max indepvarsets!* m;
  4363. if length v neq d then
  4364. rederr "EQHULL found a component of wrong dimension";
  4365. vars:=ring_names(c:=cali!=basering);
  4366. cali!=degrees:=nil; u:=setdiff(ring_names c,v);
  4367. setring!* ring_define(vars,ring_rlp(c,u),ring_tag c,ring_ecart c);
  4368. m1:=dpmat_2a gbasis!* dpmat_neworder m;
  4369. setring!* ring_define(u,degreeorder!* u,'revlex,
  4370. for each x in u collect 1);
  4371. p:=bc_2a prime!=quot(m1:=groeb_mingb dpmat_from_a m1);
  4372. setring!* c; cali!=degrees:=dpmat_coldegs m;
  4373. if submodulep!*(l:=matqquot!*(m,dp_from_a p),m) then return m;
  4374. m1:=gbasis!* matstabquot!*(m,annihilator2!* l);
  4375. if dim!* m1=d then return matintersect!* {l,prime!=eqhull(m1,d)}
  4376. else return l;
  4377. end)
  4378. where cali!=degrees:=cali!=degrees,
  4379. cali!=basering:=cali!=basering;
  4380. endmodule; % prime
  4381. module scripts;
  4382. COMMENT
  4383. ######################
  4384. ## ##
  4385. ## ADVANCED ##
  4386. ## APPLICATIONS ##
  4387. ## ##
  4388. ######################
  4389. This module contains several additional advanced applications of
  4390. standard basis computations, inspired partly by the scripts
  4391. distributed with the commutative algebra package MACAULAY
  4392. (Bayer/Stillman/Eisenbud).
  4393. The following topics are currently covered :
  4394. - computing the jacobian matrix
  4395. - generating random linear forms
  4396. - generating ideals of minors
  4397. - [BGK]'s heuristic variable optimization
  4398. - certain stuff on maps (preimage, ratpreimage)
  4399. - ideals of points (in affine and proj. spaces)
  4400. - ideals of (affine and proj.) monomial curves
  4401. - General Rees rings, associated graded rings, and related
  4402. topics (analytic spread, symmetric algebra)
  4403. - several short scripts (minimal generators, symbolic powers
  4404. of primes, singular locus)
  4405. END COMMENT;
  4406. % ------ The Jacobian matrix -------------
  4407. symbolic operator matjac;
  4408. symbolic procedure matjac(m,l);
  4409. % Returns the Jacobian matrix from the ideal m
  4410. % (given as an algebraic mode list) with respect to the var. list l.
  4411. if not eqcar(m,'list) then typerr(m,"ideal basis")
  4412. else if not eqcar(l,'list) then typerr(l,"variable list")
  4413. else 'mat . for each x in cdr l collect
  4414. for each y in cdr m collect prepsq difff(numr simp reval y,x);
  4415. % ---------- Random linear forms -------------
  4416. symbolic operator random_linear_form;
  4417. symbolic procedure random_linear_form(vars,bound);
  4418. % Returns a random linear form in algebraic prefix form.
  4419. if not eqcar(vars,'list) then typerr(vars,"variable list")
  4420. else 'plus . for each x in cdr vars collect
  4421. {'times,random(2*bound)-bound,x};
  4422. % ---------- Minors ---------
  4423. symbolic procedure minors!*(m,k);
  4424. % Returns the interreduced ideal of the k-minors of the dpmat m.
  4425. if dpmat_cols m=0 then rederr"MINORS only for matrices"
  4426. else if (dpmat_rows m<k) or (dpmat_cols m<k) then
  4427. dpmat_make(0,0,nil,nil)
  4428. else begin scalar r,c,u;
  4429. r:=cali_choose(for i:=1:dpmat_rows m collect i,k);
  4430. c:=cali_choose(for i:=1:dpmat_cols m collect i,k);
  4431. u:=bas_renumber for each x in r join
  4432. for each y in c collect bas_make(0,scripts!=subdet(m,x,y));
  4433. return interreduce!* dpmat_make(length u,0,u,nil)
  4434. end;
  4435. symbolic procedure scripts!=subdet(m,x,y);
  4436. % Returns the minor of the dpmat m with x as list of row indices and
  4437. % y as list of column indices.
  4438. dp_from_a prepf numr detq matsm ('mat .
  4439. for each a in x collect for each b in y collect
  4440. dp_2a dpmat_element(a,b,m));
  4441. symbolic operator minors;
  4442. symbolic procedure minors(m,b);
  4443. if !*mode='symbolic then rederr"only for algebraic mode"
  4444. else dpmat_2a minors!*(dpmat_from_a reval m,reval b);
  4445. %------- --- [BGK]'s heuristic variable optimization ----------
  4446. symbolic operator varopt;
  4447. symbolic procedure varopt m;
  4448. if !*mode='symbolic then rederr"only for algebraic mode"
  4449. else makelist varopt!* dpmat_from_a m;
  4450. symbolic procedure varopt!* m;
  4451. % Find a heuristically optimal variable order.
  4452. begin scalar c; c:=mo_zero();
  4453. for each x in dpmat_list m do
  4454. for each y in bas_dpoly x do c:=mo_lcm(c,car y);
  4455. return
  4456. for each x in
  4457. sort(mo_2list c,function(lambda(x,y); cdr x>cdr y)) collect
  4458. car x;
  4459. end;
  4460. % ----- Certain stuff on maps -------------
  4461. % A ring map is represented as a list
  4462. % {preimage_ring, image_ring, subst_list},
  4463. % where subst_list is a substitution list {v1=ex1,v2=ex2,...} in
  4464. % algebraic prefix form, i.e. looks like (list (equal var image) ...)
  4465. symbolic operator preimage;
  4466. symbolic procedure preimage(m,map);
  4467. % Compute the preimage of an ideal m under a (polynomial) ring map.
  4468. if !*mode='symbolic then rederr"only for algebraic mode"
  4469. else begin map:=cdr reval map;
  4470. return preimage!*(reval m,
  4471. {ring_from_a first map, ring_from_a second map, third map});
  4472. end;
  4473. symbolic procedure preimage!*(m,map);
  4474. % m and the result are given and returned in algebraic prefix form.
  4475. if not !*noetherian then
  4476. rederr"PREIMAGE only for noetherian term orders"
  4477. else begin scalar u,oldring,newring,oldnames;
  4478. if not eqcar(m,'list) then rederr"PREIMAGE only for ideals";
  4479. oldring:=first map; newring:=second map;
  4480. oldnames:=ring_names oldring;
  4481. setring!* ring_sum(newring,oldring);
  4482. u:=bas_renumber for each x in cdr third map collect
  4483. << if not member(second x,oldnames) then
  4484. typerr(second x,"var. name");
  4485. bas_make(0,dp_diff(dp_from_a second x,dp_from_a third x))
  4486. >>;
  4487. m:=matsum!* {dpmat_from_a m,dpmat_make(length u,0,u,nil)};
  4488. m:=dpmat_2a eliminate!*(m,ring_names newring);
  4489. setring!* oldring;
  4490. return m;
  4491. end;
  4492. symbolic operator ratpreimage;
  4493. symbolic procedure ratpreimage(m,map);
  4494. % Compute the preimage of an ideal m under a rational ring map.
  4495. if !*mode='symbolic then rederr"only for algebraic mode"
  4496. else begin map:=cdr reval map;
  4497. return ratpreimage!*(reval m,
  4498. {ring_from_a first map, ring_from_a second map, third map});
  4499. end;
  4500. symbolic procedure ratpreimage!*(m,map);
  4501. % m and the result are given and returned in algebraic prefix form.
  4502. if not !*noetherian then
  4503. rederr"RATPREIMAGE only for noetherian term orders"
  4504. else begin scalar u,oldring,newnames,oldnames,f,g,v,g0;
  4505. if not eqcar(m,'list) then rederr"RATPREIMAGE only for ideals";
  4506. oldring:=first map; v:=gensym();
  4507. newnames:=v . ring_names second map;
  4508. oldnames:=ring_names oldring; u:=append(oldnames,newnames);
  4509. setring!* ring_define(u,nil,'lex,for each x in u collect 1);
  4510. g0:=dp_fi 1;
  4511. u:=bas_renumber for each x in cdr third map collect
  4512. << if not member(second x,oldnames) then
  4513. typerr(second x,"var. name");
  4514. f:=simp third x; g:=dp_from_a prepf denr f;
  4515. f:=dp_from_a prepf numr f; g0:=dp_prod(g,g0);
  4516. bas_make(0,dp_diff(dp_prod(g,dp_from_a second x),f))
  4517. >>;
  4518. u:=bas_make(0,dp_diff(dp_prod(g0,dp_from_a v),dp_fi 1)) . u;
  4519. m:=matsum!* {dpmat_from_a m,dpmat_make(length u,0,u,nil)};
  4520. m:=dpmat_2a eliminate!*(m,newnames);
  4521. setring!* oldring;
  4522. return m;
  4523. end;
  4524. % ---- The ideals of affine resp. proj. points --------
  4525. symbolic operator affine_points;
  4526. symbolic procedure affine_points m;
  4527. % m is an algebraic matrix, which rows are the coordinates of points
  4528. % in the affine space with Spec = the current ring.
  4529. if !*mode='symbolic then rederr"only for algebraic mode"
  4530. else dpmat_2a affine_points!* reval m;
  4531. symbolic procedure affine_points!* m;
  4532. begin scalar names;
  4533. if length(names:=ring_names cali!=basering) neq length cadr m then
  4534. typerr(m,"coordinate matrix");
  4535. m:=for each x in cdr m collect
  4536. 'list . for each y in pair(names,x) collect
  4537. {'plus,car y,{'minus,reval cdr y}};
  4538. m:=for each x in m collect dpmat_from_a x;
  4539. m:=matintersect!* m;
  4540. return m;
  4541. end;
  4542. symbolic operator proj_points;
  4543. symbolic procedure proj_points m;
  4544. % m is an algebraic matrix, which rows are the coordinates of _points
  4545. % in the projective space with Proj = the current ring.
  4546. if !*mode='symbolic then rederr"only for algebraic mode"
  4547. else dpmat_2a proj_points!* reval m;
  4548. symbolic procedure proj_points!* m;
  4549. begin scalar names,x0,u;
  4550. if length(names:=ring_names cali!=basering) neq length cadr m then
  4551. typerr(m,"coordinate matrix");
  4552. x0:=car names; names:=cdr names;
  4553. m:=for each x in cdr m collect
  4554. 'list .
  4555. << u:=reval car x;
  4556. for each y in pair(names,cdr x) collect
  4557. {'plus,{'times,car y,u},
  4558. {'minus,{'times,reval cdr y,x0}}}
  4559. >>;
  4560. m:=for each x in m collect dpmat_from_a x;
  4561. m:=matintersect!* m;
  4562. return m;
  4563. end;
  4564. % ----- Affine and proj. monomial curves ------------
  4565. symbolic operator affine_monomial_curve;
  4566. symbolic procedure affine_monomial_curve(l,R);
  4567. % l is a list of integers, R contains length l ring var. names.
  4568. % Returns the generators of the monomial curve (t^i : i\in l) in R.
  4569. if !*mode='symbolic then rederr"only for algebraic mode"
  4570. else dpmat_2a affine_monomial_curve!*(cdr reval l,cdr reval R);
  4571. symbolic procedure affine_monomial_curve!*(l,R);
  4572. if not numberlistp l then typerr(l,"number list")
  4573. else if length l neq length R then
  4574. rederr"number of variables doesn't match"
  4575. else begin scalar u,t0,v;
  4576. v:=list gensym();
  4577. r:=ring_define(r,{l},'revlex,l);
  4578. setring!* ring_sum(r,ring_define(v,degreeorder!* v,'lex,'(1)));
  4579. t0:=dp_from_a car v;
  4580. u:=bas_renumber for each x in pair(l,ring_names r) collect
  4581. bas_make(0,dp_diff(dp_from_a cdr x,dp_power(t0,car x)));
  4582. u:=dpmat_make(length u,0,u,nil);
  4583. u:=(eliminate!*(u,v) where cali!=monset=ring_names cali!=basering);
  4584. setring!* r;
  4585. return dpmat_neworder u;
  4586. end;
  4587. symbolic operator proj_monomial_curve;
  4588. symbolic procedure proj_monomial_curve(l,R);
  4589. % l is a list of integers, R contains length l ring var. names.
  4590. % Returns the generators of the monomial curve
  4591. % (s^(d-i)*t^i : i\in l) in R where d = max { x : x \in l}
  4592. if !*mode='symbolic then rederr"only for algebraic mode"
  4593. else dpmat_2a proj_monomial_curve!*(cdr reval l,cdr reval R);
  4594. symbolic procedure proj_monomial_curve!*(l,R);
  4595. if not numberlistp l then typerr(l,"number list")
  4596. else if length l neq length R then
  4597. rederr"number of variables doesn't match"
  4598. else begin scalar u,t0,t1,v,d;
  4599. t0:=gensym(); t1:=gensym(); v:={t0,t1};
  4600. d:=listexpand(function max2,l);
  4601. r:=ring_define(r,degreeorder!* r,'revlex,for each x in r collect 1);
  4602. setring!* ring_sum(r,ring_define(v,degreeorder!* v,'lex,'(1 1)));
  4603. t0:=dp_from_a t0; t1:=dp_from_a t1;
  4604. u:=bas_renumber for each x in pair(l,ring_names r) collect
  4605. bas_make(0,dp_diff(dp_from_a cdr x,
  4606. dp_prod(dp_power(t0,car x),dp_power(t1,d-car x))));
  4607. u:=dpmat_make(length u,0,u,nil);
  4608. u:=(eliminate!*(u,v) where cali!=monset=ring_names cali!=basering);
  4609. setring!* r;
  4610. return dpmat_neworder u;
  4611. end;
  4612. % -- General Rees rings, associated graded rings, and related topics --
  4613. symbolic operator blowup;
  4614. symbolic procedure blowup(m,n,vars);
  4615. % vars is a list of var. names for the ring R
  4616. % of the same length as dpmat_list n.
  4617. % Returns an ideal J such that (S+R)/J == S/M [ N.t ]
  4618. % ( with S = the current ring )
  4619. % is the blow up ring of the ideal N over S/M.
  4620. % (S+R) is the new current ring.
  4621. if !*mode='symbolic then rederr"only for algebraic mode"
  4622. else dpmat_2a blowup!*(dpmat_from_a reval m,dpmat_from_a reval n,
  4623. cdr reval vars);
  4624. symbolic procedure blowup!*(M,N,vars);
  4625. if (dpmat_cols m > 0)or(dpmat_cols n > 0) then
  4626. rederr"BLOWUP defined only for ideals"
  4627. else if not !*noetherian then
  4628. rederr"BLOWUP only for noetherian term orders"
  4629. else begin scalar u,s,t0,v,r1;
  4630. if length vars neq dpmat_rows n then
  4631. rederr {"ring must have",dpmat_rows n,"variables"};
  4632. u:=for each x in dpmat_rowdegrees n collect mo_ecart cdr x;
  4633. r1:=ring_define(vars,list u,'revlex,u);
  4634. s:=ring_sum(cali!=basering,r1); v:=list(gensym());
  4635. setring!* ring_sum(s,ring_define(v,degreeorder!* v,'lex,'(1)));
  4636. t0:=dp_from_a car v;
  4637. n:=for each x in
  4638. pair(vars,for each y in dpmat_list n collect bas_dpoly y)
  4639. collect dp_diff(dp_from_a car x,
  4640. dp_prod(dp_neworder cdr x,t0));
  4641. m:=bas_renumber append(bas_neworder dpmat_list m,
  4642. for each x in n collect bas_make(0,x));
  4643. m:=(eliminate!*(interreduce!* dpmat_make(length m,0,m,nil),v)
  4644. where cali!=monset=nil);
  4645. setring!* s;
  4646. return dpmat_neworder m;
  4647. end;
  4648. symbolic operator assgrad;
  4649. symbolic procedure assgrad(m,n,vars);
  4650. % vars is a list of var. names for the ring T
  4651. % of the same length as dpmat_list n.
  4652. % Returns an ideal J such that (S+T)/J == (R/N + N/N^2 + ... )
  4653. % ( with R=S/M and S the current ring )
  4654. % is the associated graded ring of the ideal N over R.
  4655. % (S+T) is the new current ring.
  4656. if !*mode='symbolic then rederr"only for algebraic mode"
  4657. else dpmat_2a assgrad!*(dpmat_from_a reval m,dpmat_from_a reval n,
  4658. cdr reval vars);
  4659. symbolic procedure assgrad!*(M,N,vars);
  4660. if (dpmat_cols m > 0)or(dpmat_cols n > 0) then
  4661. rederr"ASSGRAD defined only for ideals"
  4662. else begin scalar u;
  4663. u:=blowup!*(m,n,vars);
  4664. return matsum!* {u,dpmat_neworder n};
  4665. end;
  4666. symbolic operator analytic_spread;
  4667. symbolic procedure analytic_spread m;
  4668. % Returns the analytic spread of the ideal m.
  4669. if !*mode='symbolic then rederr"only for algebraic mode"
  4670. else analytic_spread!* dpmat_from_a reval m;
  4671. symbolic procedure analytic_spread!* m;
  4672. if (dpmat_cols m>0) then rederr"ANALYTIC SPREAD only for ideals"
  4673. else (begin scalar r,m1,vars;
  4674. r:=ring_names cali!=basering;
  4675. vars:=for each x in dpmat_list m collect gensym();
  4676. m1:=blowup!*(dpmat_from_dpoly nil,m,vars);
  4677. return dim!* gbasis!* matsum!*{m1,dpmat_from_a('list . r)};
  4678. end) where cali!=basering=cali!=basering;
  4679. symbolic operator sym;
  4680. symbolic procedure sym(M,vars);
  4681. % vars is a list of var. names for the ring R
  4682. % of the same length as dpmat_list M.
  4683. % Returns an ideal J such that (S+R)/J == Sym(M)
  4684. % ( with S = the current ring )
  4685. % is the symmetric algebra of M over S.
  4686. % (S+R) is the new current ring.
  4687. if !*mode='symbolic then rederr"only for algebraic mode"
  4688. else dpmat_2a sym!*(dpmat_from_a M,cdr reval vars);
  4689. symbolic procedure sym!*(m,vars);
  4690. % The symmetric algebra of the dpmat m.
  4691. if not !*noetherian then
  4692. rederr"SYM only for noetherian term orders"
  4693. else begin scalar n,u,s,r1;
  4694. if length vars neq dpmat_rows m then
  4695. rederr {"ring must have",dpmat_rows m,"variables"};
  4696. cali!=degrees:=dpmat_coldegs m;
  4697. u:=for each x in dpmat_rowdegrees m collect mo_ecart cdr x;
  4698. r1:=ring_define(vars,list u,'revlex,u); n:=syzygies!* m;
  4699. setring!* ring_sum(cali!=basering,r1);
  4700. return flatten!* interreduce!*
  4701. dpmat_mult(dpmat_neworder n,
  4702. ideal2mat!* dpmat_from_a('list . vars));
  4703. end;
  4704. % ----- Several short scripts ----------
  4705. % ------ Minimal generators of an ideal or module.
  4706. symbolic operator minimal_generators;
  4707. symbolic procedure minimal_generators m;
  4708. if !*mode='symbolic then rederr"only for algebraic mode"
  4709. else dpmat_2a minimal_generators!* dpmat_from_a reval m;
  4710. symbolic procedure minimal_generators!* m;
  4711. car groeb_minimize(m,syzygies!* m);
  4712. % ------- Symbolic powers of prime (or unmixed) ideals
  4713. symbolic operator symbolic_power;
  4714. symbolic procedure symbolic_power(m,d);
  4715. if !*mode='symbolic then rederr"only for algebraic mode"
  4716. else dpmat_2a symbolic_power!*(dpmat_from_a m,reval d);
  4717. symbolic procedure symbolic_power!*(m,d);
  4718. eqhull!* idealpower!*(m,d);
  4719. % ----- Singular locus -----------
  4720. algebraic procedure singular_locus(m,c);
  4721. matsum(m, minors(matjac(m,first getring()),c));
  4722. endmodule; % scripts
  4723. end;