prime.red 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735
  1. module prime; % corrected version | 15.6.1995
  2. COMMENT
  3. ####################################
  4. # #
  5. # PRIME DECOMPOSITION, RADICALS, #
  6. # AND RELATED PROBLEMS #
  7. # #
  8. ####################################
  9. This module contains algorithms
  10. - for zerodimensional ideals :
  11. - to test whether it is radical
  12. - to compute its radical
  13. - for a primality test
  14. - for zerodimensional ideals and modules :
  15. - to compute its primes
  16. - to compute its primary decomposition
  17. - for arbitrary ideals :
  18. - for a primality test
  19. - to compute its radical
  20. - to test whether it is radical
  21. - for arbitrary ideals and modules :
  22. - to compute its isolated primes
  23. - to compute its primary decomposition and
  24. the associated primes
  25. - a shortcut for the primary decomposition
  26. computation for unmixed modules
  27. The algorithms follow
  28. Seidenberg : Trans. AMS 197 (1974), 273 - 313.
  29. Kredel : in Proc. EUROCAL'87, Lecture Notes in Comp. Sci. 378
  30. (1986), 270 - 281.
  31. Gianni, Trager, Zacharias :
  32. J. Symb. Comp. 6 (1988), 149 - 167.
  33. The primary decomposition now proceeds as follows:
  34. 1) compute the isolated primes
  35. 2) compute by ideal separation quasi-primary components
  36. 3) for each of them split off embedded components
  37. 4) apply the decomposition recursively to them
  38. 5) Decide in a last (global) step unnecessary components among
  39. them
  40. See Gr\"abe : Factorized Gr\"obner bases and primary
  41. decomposition. To appear
  42. The switch factorprimes switches between invokation of the Groebner
  43. factorizer (on/ the default) and algorithms, that use only univariate
  44. factorization as described in [GTZ] (off).
  45. END COMMENT;
  46. switch factorprimes; % (on) see primes
  47. !*factorprimes:=t; % Invoke the Groebner factorizer first.
  48. % ------ The radical of a zerodimensional ideal -----------
  49. symbolic procedure prime!=mksqrfree(pol,x);
  50. % Make the univariate dpoly p(x) squarefree.
  51. begin scalar p;
  52. p:=numr simp dp_2a pol;
  53. return dp_from_a prepf car qremf(p,gcdf!*(p,numr difff(p,x)))
  54. end;
  55. put('zeroradical,'psopfn,'prime!=evzero);
  56. symbolic procedure prime!=evzero m;
  57. begin scalar c;
  58. intf_test m; intf_get(m:=car m);
  59. if not (c:=get(m,'gbasis)) then
  60. put(m,'gbasis,c:=gbasis!* get(m,'basis));
  61. return dpmat_2a zeroradical!* c;
  62. end;
  63. symbolic procedure zeroradical!* m;
  64. % Returns the radical of the zerodim. ideal m. m must be a gbasis.
  65. if dpmat_cols m>0 or not dimzerop!* m then
  66. rederr"ZERORADICAL only for zerodimensional ideals"
  67. else if dpmat_unitideal!? m then m
  68. else begin scalar u;
  69. u:=for each x in ring_names cali!=basering collect
  70. bas_make(0,prime!=mksqrfree(odim_up(x,m),x));
  71. u:=dpmat_make(length u,0,bas_renumber u,nil,nil);
  72. return gbasis!* matsum!* {m,u};
  73. end;
  74. put('iszeroradical,'psopfn,'prime!=eviszero);
  75. symbolic procedure prime!=eviszero m;
  76. begin scalar c;
  77. intf_test m; intf_get(m:=car m);
  78. if not (c:=get(m,'gbasis)) then
  79. put(m,'gbasis,c:=gbasis!* get(m,'basis));
  80. return if iszeroradical!* c then 'yes else 'no;
  81. end;
  82. symbolic procedure iszeroradical!* m;
  83. % Test whether the zerodim. ideal m is radical. m must be a gbasis.
  84. if dpmat_cols m>0 or not dimzerop!* m then
  85. rederr"ISZERORADICAL only for zerodimensional ideals"
  86. else if dpmat_unitideal!? m then t
  87. else begin scalar isradical;
  88. isradical:=t;
  89. for each x in ring_names cali!=basering do
  90. isradical:=isradical and
  91. null matop_pseudomod(prime!=mksqrfree(odim_up(x,m),x),m);
  92. return isradical;
  93. end;
  94. % ---- The primes of a zerodimensional ideal or module ------
  95. symbolic operator zeroprimes;
  96. symbolic procedure zeroprimes m;
  97. if !*mode='algebraic then
  98. makelist for each x in zeroprimes!* dpmat_from_a reval m
  99. collect dpmat_2a x
  100. else zeroprimes!* m;
  101. symbolic procedure zeroprimes!* m;
  102. % The primes of the zerodimensional ideal Ann F/M.
  103. % The unit ideal has no primes.
  104. listminimize(for each x in
  105. if !*factorprimes then groebf_zeroprimes1(annihilator2!* m,nil)
  106. else prime_zeroprimes1 gbasis!* annihilator2!* m
  107. join prime!=zeroprimes2 x, function submodulep!*);
  108. symbolic procedure prime_iszeroprime m;
  109. % Test a zerodimensiomal ideal to be prime. m must be a gbasis.
  110. if dpmat_cols m>0 or not dimzerop!* m then
  111. rederr "iszeroprime only for zerodimensional ideals"
  112. else if dpmat_unitideal!? m then rederr"the ideal is the unit ideal"
  113. else prime!=iszeroprime1 m and prime!=iszeroprime2 m;
  114. symbolic procedure prime_zeroprimes1 m;
  115. % A first approximation to the isolated primes in dim=0 : Factor all
  116. % univariate polynomials in m.
  117. % m must be a gbasis. Returns a reduced list of gbases.
  118. if dpmat_cols m>0 then rederr"ZEROPRIMES only for ideals"
  119. else if dpmat_unitideal!? m then nil
  120. else if not dimzerop!* m then
  121. rederr"ZEROPRIMES only for zerodimensional ideals"
  122. else begin scalar l;
  123. l:={m};
  124. for each x in ring_names cali!=basering do
  125. l:=for each y in l join
  126. if not member(x,for each v in dpmat_list y join
  127. {mo_linear dp_lmon bas_dpoly v}) then
  128. (begin scalar u,p;
  129. u:=dp_factor (p:=odim_up(x,y));
  130. if (length u=1) and equal(car u,p) then return {y}
  131. else return for each z in u join
  132. if not dpmat_unitideal!?(p:=gbasis!* matsum!*
  133. {y,dpmat_from_dpoly z}) then {p};
  134. end)
  135. else {y};
  136. return l;
  137. end;
  138. symbolic procedure prime!=iszeroprime1 m;
  139. % A first non primality test.
  140. if dpmat_cols m>0 then rederr"ISZEROPRIME only for ideals"
  141. else if dpmat_unitideal!? m then nil
  142. else if not dimzerop!* m then
  143. rederr"ISZEROPRIME only for zerodimensional ideals"
  144. else begin scalar b; b:=t;
  145. for each x in ring_names cali!=basering do
  146. b:=b and
  147. begin scalar u,p;
  148. u:=dp_factor (p:=odim_up(x,m));
  149. if (length u=1) and equal(car u,p) then return t
  150. else return nil
  151. end;
  152. return b;
  153. end;
  154. symbolic procedure prime_gpchange(vars,v,m);
  155. % Change to general position with respect to v. Only for pure lex.
  156. % term order and radical ideal m.
  157. if null vars or dpmat_unitideal!? m then m
  158. else begin scalar s,x,a;
  159. s:=0; x:=mo_from_a car vars;
  160. a:=list (v.prepf addf(!*k2f v,!*k2f car vars));
  161. % the substitution rule v -> v + x .
  162. while not member(x,moid_from_bas dpmat_list m)
  163. % i.e. m has a leading term equal to x
  164. and ((s:=s+1) < 10)
  165. % to avoid too much loops.
  166. do m:=gbasis!* dpmat_sub(a,m);
  167. if s=10 then rederr" change to general position failed";
  168. return prime_gpchange(cdr vars,v,m);
  169. end;
  170. symbolic procedure prime!=zeroprimes2 m;
  171. % Decompose the radical zerodimensional dmpat ideal m using a general
  172. % position argument. Returns a reduced list of gbases.
  173. (begin scalar c,v,vars,u,d,r;
  174. c:=cali!=basering; vars:=ring_names c; v:=gensym();
  175. u:=setdiff(vars,for each x in moid_from_bas dpmat_list m
  176. join {mo_linear x});
  177. if (length u)=1 then return prime!=zeroprimes3(m,first u);
  178. if ring_tag c='revlex then % for proper ring_sum redefine it.
  179. r:=ring_define(vars,ring_degrees c,'lex,ring_ecart c)
  180. else r:=c;
  181. setring!* ring_sum(r,ring_define(list v,nil,'lex,'(1)));
  182. cali!=degrees:=nil;
  183. m:=gbasis!* matsum!*
  184. {dpmat_neworder(m,nil), dpmat_from_dpoly dp_from_a v};
  185. u:=setdiff(v.vars,for each x in moid_from_bas dpmat_list m
  186. join {mo_linear x});
  187. if not dpmat_unitideal!? m then
  188. << m:=prime_gpchange(u,v,m);
  189. u:=for each x in prime!=zeroprimes3(m,v) join
  190. if not dpmat_unitideal!? x and
  191. not dpmat_unitideal!?(d:=eliminate!*(x,{v})) then {d}
  192. % To recognize (1) even if x is not a gbasis.
  193. >>
  194. else u:=nil;
  195. setring!* c;
  196. return for each x in u collect gbasis!* dpmat_neworder(x,nil);
  197. end)
  198. where cali!=degrees:=cali!=degrees,
  199. cali!=basering:=cali!=basering;
  200. symbolic procedure prime!=zeroprimes3(m,v);
  201. % m is in general position with univariate polynomial in v.
  202. begin scalar u,p;
  203. u:=dpmat_list m;
  204. while u and not equal(mo_support dp_lmon (p:=bas_dpoly car u),
  205. list v) do u:=cdr u;
  206. if null u then rederr"univariate polynomial not found";
  207. p:=for each x in cdr ((fctrf numr simp dp_2a p) where !*factor=t)
  208. collect dpmat_from_dpoly dp_from_a prepf car x;
  209. return for each x in p collect matsum!* {m,x};
  210. end;
  211. symbolic procedure prime!=iszeroprime2 m;
  212. % Test the radical zerodimensional dmpat ideal m to be prime using a
  213. % general position argument.
  214. (begin scalar c,v,vars,u,r;
  215. c:=cali!=basering; vars:=ring_names c; v:=gensym();
  216. if ring_tag c='revlex then % for proper ring_sum redefine it.
  217. r:=ring_define(vars,ring_degrees c,'lex,ring_ecart c)
  218. else r:=c;
  219. setring!* ring_sum(r,ring_define(list v,nil,'lex,'(1)));
  220. cali!=degrees:=nil;
  221. m:=matsum!* {dpmat_neworder(m,nil), dpmat_from_dpoly dp_from_a v};
  222. m:=prime_gpchange(vars,v,gbasis!* m);
  223. u:=prime!=iszeroprime3(m,v);
  224. setring!* c; return u;
  225. end)
  226. where cali!=degrees:=cali!=degrees,
  227. cali!=basering:=cali!=basering;
  228. symbolic procedure prime!=iszeroprime3(m,v);
  229. begin scalar u,p;
  230. u:=dpmat_list m;
  231. while u and not equal(mo_support dp_lmon (p:=bas_dpoly car u),
  232. list v) do u:=cdr u;
  233. if null u then rederr"univariate polynomial not found";
  234. if (length(u:=cdr ((fctrf numr simp dp_2a p) where !*factor=t))>1)
  235. or (cdar u>1) then return nil
  236. else return t
  237. end;
  238. % --------- Primality test for an arbitrary ideal. ---------
  239. put('isprime,'psopfn,'prime!=isprime);
  240. symbolic procedure prime!=isprime m;
  241. begin scalar c;
  242. intf_test m; intf_get(m:=car m);
  243. if not (c:=get(m,'gbasis)) then
  244. put(m,'gbasis,c:=gbasis!* get(m,'basis));
  245. return if isprime!* c then 'yes else 'no;
  246. end;
  247. symbolic procedure isprime!* m;
  248. % Test an dpmat ideal m to be prime. m must be a gbasis.
  249. if dpmat_cols m>0 then rederr"prime test only for ideals"
  250. else (begin scalar vars,u,v,c1,c2,m1,m2,lc;
  251. v:=moid_goodindepvarset m; cali!=degrees:=nil;
  252. if null v then return prime_iszeroprime m;
  253. vars:=ring_names(c1:=cali!=basering);
  254. % Change to dimension zero.
  255. u:=setdiff(ring_names c1,v);
  256. setring!* ring_rlp(c1,u);
  257. m1:=dpmat_2a gbasis!* dpmat_neworder(m,nil);
  258. setring!*(c2:= ring_define(u,degreeorder!* u,'revlex,
  259. for each x in u collect 1));
  260. m1:=groeb_mingb dpmat_from_a m1;
  261. if dpmat_unitideal!?(m1) then
  262. << setring!* c1; rederr"Input must be a gbasis" >>;
  263. lc:=bc_2a prime!=quot m1; setring!* c1;
  264. % Test recontraction of m1 to be equal to m.
  265. m2:=gbasis!* matqquot!*(m,dp_from_a lc);
  266. if not submodulep!*(m2,m) then return nil;
  267. % Test the zerodimensional ideal m1 to be prime
  268. setring!* c2; u:=prime_iszeroprime m1; setring!* c1;
  269. return u;
  270. end)
  271. where cali!=degrees:=cali!=degrees,
  272. cali!=basering:=cali!=basering;
  273. symbolic operator isolatedprimes;
  274. symbolic procedure isolatedprimes m;
  275. if !*mode='algebraic then
  276. makelist for each x in isolatedprimes!* dpmat_from_a reval m
  277. collect dpmat_2a x
  278. else isolatedprimes!* m;
  279. symbolic procedure isolatedprimes!* m;
  280. % Returns the isolated primes of the dpmat m as a dpmat list.
  281. if !*factorprimes then
  282. listminimize(
  283. for each x in groebfactor!*(annihilator2!* m,nil) join
  284. prime!=factorisoprimes car x,
  285. function submodulep!*)
  286. else prime!=isoprimes gbasis!* annihilator2!* m;
  287. symbolic procedure prime!=isoprimes m;
  288. % m is a gbasis and an ideal.
  289. if dpmat_zero!? m then nil else
  290. (begin scalar u,c,v,vars,m1,m2,l,p;
  291. if null(v:=odim_parameter m) then return
  292. for each x in prime_zeroprimes1 m join prime!=zeroprimes2 x;
  293. vars:=ring_names(c:=cali!=basering); cali!=degrees:=nil;
  294. u:=delete(v,vars);
  295. setring!* ring_rlp(c,u);
  296. m1:=dpmat_2a gbasis!* dpmat_neworder(m,nil);
  297. setring!* ring_define(u,degreeorder!* u,
  298. 'revlex,for each x in u collect 1);
  299. p:=bc_2a prime!=quot(m1:=groeb_mingb dpmat_from_a m1);
  300. l:=for each x in prime!=isoprimes m1 collect
  301. (dpmat_2a x . bc_2a prime!=quot x);
  302. setring!* c;
  303. l:=for each x in l collect
  304. gbasis!* matqquot!*(dpmat_from_a car x,dp_from_a cdr x);
  305. if dp_unit!?(p:=dp_from_a p) or
  306. submodulep!*(matqquot!*(m,p),m) or
  307. dpmat_unitideal!?(m2:=gbasis!* matsum!* {m,dpmat_from_dpoly p})
  308. then return l
  309. else return
  310. listminimize(append(l,prime!=isoprimes m2),
  311. function submodulep!*);
  312. end)
  313. where cali!=degrees:=cali!=degrees,
  314. cali!=basering:=cali!=basering;
  315. symbolic procedure prime!=factorisoprimes m;
  316. % m is a gbasis and an ideal.
  317. if dpmat_zero!? m then nil else
  318. (begin scalar u,c,v,vars,m1,m2,l,p;
  319. if null(v:=odim_parameter m) then
  320. return for each x in groebf_zeroprimes1(m,nil) join
  321. prime!=zeroprimes2 x;
  322. vars:=ring_names(c:=cali!=basering); cali!=degrees:=nil;
  323. u:=delete(v,vars);
  324. setring!* ring_rlp(c,u);
  325. m1:=dpmat_2a gbasis!* dpmat_neworder(m,nil);
  326. setring!* ring_define(u,degreeorder!* u,
  327. 'revlex,for each x in u collect 1);
  328. p:=bc_2a prime!=quot(m1:=groeb_mingb dpmat_from_a m1);
  329. l:=for each x in prime!=factorisoprimes m1 collect
  330. (dpmat_2a x . bc_2a prime!=quot x);
  331. setring!* c;
  332. l:=listgroebfactor!* for each x in l collect
  333. matqquot!*(dpmat_from_a car x,dp_from_a cdr x);
  334. if dp_unit!?(p:=dp_from_a p) or
  335. submodulep!*(matqquot!*(m,p),m) or
  336. null (m2:=groebfactor!*(matsum!* {m,dpmat_from_dpoly p},nil))
  337. then return l
  338. else return
  339. listminimize(append(l,for each x in m2 join
  340. prime!=factorisoprimes car x), function submodulep!*);
  341. end)
  342. where cali!=degrees:=cali!=degrees,
  343. cali!=basering:=cali!=basering;
  344. symbolic procedure prime!=quot m;
  345. % The lcm of the leading coefficients of m.
  346. begin scalar p,u;
  347. u:=for each x in dpmat_list m collect dp_lc bas_dpoly x;
  348. if null u then return bc_fi 1;
  349. p:=car u; for each x in cdr u do p:=bc_lcm(p,x);
  350. return p
  351. end;
  352. % ------------------- The radical ---------------------
  353. symbolic operator radical;
  354. symbolic procedure radical m;
  355. % Returns the radical of the dpmat ideal m.
  356. if !*mode='algebraic then
  357. dpmat_2a radical!* gbasis!* dpmat_from_a reval m
  358. else radical!* m;
  359. symbolic procedure radical!* m;
  360. % m must be a gbasis.
  361. if dpmat_cols m>0 then rederr"RADICAL only for ideals"
  362. else (begin scalar u,c,v,vars,m1,l,p,p1;
  363. if null(v:=odim_parameter m) then return zeroradical!* m;
  364. vars:=ring_names (c:=cali!=basering);
  365. cali!=degrees:=nil; u:=delete(v,vars);
  366. setring!* ring_rlp(c,u);
  367. m1:=dpmat_2a gbasis!* dpmat_neworder(m,nil);
  368. setring!* ring_define(u,degreeorder!* u,
  369. 'revlex,for each x in u collect 1);
  370. p:=bc_2a prime!=quot(m1:=groeb_mingb dpmat_from_a m1);
  371. l:=radical!* m1; p1:=bc_2a prime!=quot l;
  372. l:=dpmat_2a l; setring!* c;
  373. l:=gbasis!* matqquot!*(dpmat_from_a l,dp_from_a p1);
  374. if dp_unit!?(p:=dp_from_a p) or
  375. submodulep!*(matqquot!*(m,p),m) then return l
  376. else << m1:=radical!* gbasis!* matsum!* {m,dpmat_from_dpoly p};
  377. if submodulep!*(m1,l) then l:=m1
  378. else if not submodulep!*(l,m1) then
  379. l:= matintersect!* {l,m1};
  380. >>;
  381. return l;
  382. end)
  383. where cali!=degrees:=cali!=degrees,
  384. cali!=basering:=cali!=basering;
  385. % ------------------- The unmixed radical ---------------------
  386. symbolic operator unmixedradical;
  387. symbolic procedure unmixedradical m;
  388. % Returns the radical of the dpmat ideal m.
  389. if !*mode='algebraic then
  390. dpmat_2a unmixedradical!* gbasis!* dpmat_from_a reval m
  391. else unmixedradical!* m;
  392. symbolic procedure unmixedradical!* m;
  393. % m must be a gbasis.
  394. if dpmat_cols m>0 then rederr"UNMIXEDRADICAL only for ideals"
  395. else (begin scalar u,c,d,v,vars,m1,l,p,p1;
  396. if null(v:=moid_goodindepvarset m) then return zeroradical!* m;
  397. vars:=ring_names (c:=cali!=basering);
  398. d:=length v; u:=setdiff(vars,v);
  399. setring!* ring_rlp(c,u);
  400. m1:=dpmat_2a gbasis!* dpmat_neworder(m,nil);
  401. setring!* ring_define(u,degreeorder!* u,'revlex,
  402. for each x in u collect 1);
  403. p:=bc_2a prime!=quot(m1:=groeb_mingb dpmat_from_a m1);
  404. l:=zeroradical!* m1; p1:=bc_2a prime!=quot l;
  405. l:=dpmat_2a l; setring!* c;
  406. l:=matqquot!*(dpmat_from_a l,dp_from_a p1);
  407. if dp_unit!?(p:=dp_from_a p) then return l
  408. else << m1:=gbasis!* matsum!* {m,dpmat_from_dpoly p};
  409. if dim!* m1=d then
  410. l:= matintersect!* {l,unmixedradical!* m1};
  411. >>;
  412. return l;
  413. end)
  414. where cali!=degrees:=cali!=degrees,
  415. cali!=basering:=cali!=basering;
  416. % ------------------- The equidimensional hull---------------------
  417. symbolic operator eqhull;
  418. symbolic procedure eqhull m;
  419. % Returns the radical of the dpmat ideal m.
  420. if !*mode='algebraic then
  421. dpmat_2a eqhull!* gbasis!* dpmat_from_a reval m
  422. else eqhull!* m;
  423. symbolic procedure eqhull!* m;
  424. % m must be a gbasis.
  425. begin scalar d;
  426. if (d:=dim!* m)=0 then return m
  427. else return prime!=eqhull(m,d)
  428. end;
  429. symbolic procedure prime!=eqhull(m,d);
  430. % d(>0) is the dimension of the dpmat m.
  431. (begin scalar u,c,v,vars,m1,l,p;
  432. v:=moid_goodindepvarset m;
  433. if length v neq d then
  434. rederr "EQHULL found a component of wrong dimension";
  435. vars:=ring_names(c:=cali!=basering);
  436. cali!=degrees:=nil; u:=setdiff(ring_names c,v);
  437. setring!* ring_rlp(c,u);
  438. m1:=dpmat_2a gbasis!* dpmat_neworder(m,nil);
  439. setring!* ring_define(u,degreeorder!* u,'revlex,
  440. for each x in u collect 1);
  441. p:=bc_2a prime!=quot(m1:=groeb_mingb dpmat_from_a m1);
  442. setring!* c; cali!=degrees:=dpmat_coldegs m;
  443. if submodulep!*(l:=matqquot!*(m,dp_from_a p),m) then return m;
  444. m1:=gbasis!* matstabquot!*(m,annihilator2!* l);
  445. if dim!* m1=d then return matintersect!* {l,prime!=eqhull(m1,d)}
  446. else return l;
  447. end)
  448. where cali!=degrees:=cali!=degrees,
  449. cali!=basering:=cali!=basering;
  450. % ---------- Primary Decomposition Algorithms ------------
  451. Comment
  452. by [GTZ]'s approach:
  453. - Compute successively a list {(Q_i,p_i)} of pairs
  454. (primary module, associated prime ideal)
  455. such that
  456. Q = \intersection{Q_i}
  457. - figure out the superfluous components
  458. (Note, that different to our former opinion (v. 2.2.) it is not
  459. sufficient to extract the elements from that list, that are minimal
  460. wrt. inclusion for the primary component. There may be components,
  461. containing none of these minimal primaries, but containing their
  462. intersection !!)
  463. Primary decompositions return a list of {Q,P} pairs with prime
  464. ideal P and corresponding primary component Q.
  465. end comment;
  466. % - The primary decomposition of a zerodimensional ideal or module -
  467. symbolic procedure prime_separate l;
  468. % l is a list of (gbases of) prime ideals.
  469. % Returns a list of (p . f) with p \in l and dpoly f \in all q \in l
  470. % except p.
  471. for each x in l collect (x . prime!=polynomial(x,delete(x,l)));
  472. symbolic procedure prime!=polynomial(x,l);
  473. % Returns a dpoly f inside all q \in l and outside x.
  474. if null l then dp_fi 1
  475. else begin scalar u,p,q;
  476. p:=prime!=polynomial(x,cdr l);
  477. if null matop_pseudomod(p,car l) then return p;
  478. u:=dpmat_list car l;
  479. while u and null matop_pseudomod(q:=bas_dpoly car u,x) do u:=cdr u;
  480. if null u then
  481. rederr"prime ideal separation failed"
  482. else return dp_prod(p,q);
  483. end;
  484. symbolic operator zeroprimarydecomposition;
  485. symbolic procedure zeroprimarydecomposition m;
  486. % Returns a list of {Q,p} with p a prime ideal and Q a p-primary
  487. % component of m. For m=S^c the list is empty.
  488. if !*mode='algebraic then
  489. makelist for each x in
  490. zeroprimarydecomposition!* dpmat_from_a reval m
  491. collect makelist {dpmat_2a first x,dpmat_2a second x}
  492. else zeroprimarydecomposition!* m;
  493. symbolic procedure zeroprimarydecomposition!* m;
  494. % The symbolic counterpart, returns a list of {Q,p}. m is not
  495. % assumed to be a gbasis.
  496. if not dimzerop!* m then rederr
  497. "zeroprimarydecomposition only for zerodimensional ideals or modules"
  498. else for each f in prime_separate
  499. (for each y in zeroprimes!* m collect gbasis!* y)
  500. collect {matqquot!*(m,cdr f),car f};
  501. % -- Primary decomposition for modules without embedded components ---
  502. symbolic operator easyprimarydecomposition;
  503. symbolic procedure easyprimarydecomposition m;
  504. if !*mode='algebraic then
  505. makelist for each x in
  506. easyprimarydecomposition!* dpmat_from_a reval m
  507. collect makelist {dpmat_2a first x,dpmat_2a second x}
  508. else easyprimarydecomposition!* m;
  509. symbolic procedure easyprimarydecomposition!* m;
  510. % Primary decomposition for a module without embedded components.
  511. begin scalar u; u:=isolatedprimes!* m;
  512. return if null u then nil
  513. else if length u=1 then {{m,car u}}
  514. else for each f in
  515. prime_separate(for each y in u collect gbasis!* y)
  516. collect {matqquot!*(m,cdr f),car f};
  517. end;
  518. % ---- General primary decomposition ----------
  519. symbolic operator primarydecomposition;
  520. symbolic procedure primarydecomposition m;
  521. if !*mode='algebraic then
  522. makelist for each x in
  523. primarydecomposition!* gbasis!* dpmat_from_a reval m
  524. collect makelist {dpmat_2a first x,dpmat_2a second x}
  525. else primarydecomposition!* m;
  526. symbolic procedure primarydecomposition!* m;
  527. % m must be a gbasis. The [GTZ] approach.
  528. if dpmat_cols m=0 then
  529. for each x in prime!=decompose1 ideal2mat!* m collect
  530. {mat2list!* first x,second x}
  531. else prime!=decompose1 m;
  532. % --------------- Implementation of the [GTZ] approach
  533. symbolic procedure prime!=decompose1 m;
  534. % The method as in the final version of the paper: Dropping dimension
  535. % by one in each step.
  536. (begin scalar u,c,v,vars,m1,l,l1,p,q;
  537. if null(v:=odim_parameter m) then
  538. return zeroprimarydecomposition!* m;
  539. vars:=ring_names (c:=cali!=basering);
  540. cali!=degrees:=nil; u:=delete(v,vars);
  541. setring!* ring_rlp(c,u);
  542. m1:=dpmat_2a gbasis!* dpmat_neworder(m,nil);
  543. setring!* ring_define(u,degreeorder!* u,
  544. 'revlex,for each x in u collect 1);
  545. p:=bc_2a prime!=quot(m1:=groeb_mingb dpmat_from_a m1);
  546. l:=for each x in prime!=decompose1 m1 collect
  547. {(dpmat_2a first x . bc_2a prime!=quot first x),
  548. (dpmat_2a second x . bc_2a prime!=quot second x)};
  549. setring!* c;
  550. l:=for each x in l collect
  551. << cali!=degrees:=dpmat_coldegs m;
  552. {gbasis!* matqquot!*(dpmat_from_a car first x,
  553. dp_from_a cdr first x),
  554. gbasis!* matqquot!*(dpmat_from_a car second x,
  555. dp_from_a cdr second x)}
  556. >>;
  557. if dp_unit!?(p:=dp_from_a p) or
  558. submodulep!*(m1:=matqquot!*(m,p),m) then return l
  559. else
  560. << q:=p; v:=1;
  561. while not submodulep!*(m1:=dpmat_times_dpoly(p,m1),m)
  562. and (v<15) do << q:=dp_prod(p,q); v:=v+1 >>;
  563. if (v=15) then
  564. rederr"Power detection in prime!=decompose1 failed";
  565. l1:=prime!=decompose1 gbasis!* matsum!*
  566. {m, dpmat_times_dpoly(q,
  567. dpmat_unit(dpmat_cols m,dpmat_coldegs m))};
  568. Comment
  569. At this moment M = M:<p>\intersection (M,q*F), q=p^n, and
  570. - l is the list of primary comp., lifted from the first part
  571. (they are lifted from a localization and have p as non
  572. zero divisor)
  573. - l1 is the list of primary comp. of the second part
  574. (which have p as zero divisor and should be tested
  575. against M, whether they are indeed necessary)
  576. end comment;
  577. p:=append(for each x in l collect second x,
  578. for each x in l1 collect second x);
  579. l:=append(l,for each x in l1 join
  580. if prime!=necessary(second x,m,p) then {x});
  581. >>;
  582. return l;
  583. end)
  584. where cali!=degrees:=cali!=degrees,
  585. cali!=basering:=cali!=basering;
  586. symbolic procedure prime!=decompose2 m;
  587. % The method as in [BKW] : Reducing directly to dimension zero. This
  588. % is usually a quite bad guess.
  589. (begin scalar u,c,v,vars,m1,l,l1,p,q;
  590. v:=moid_goodindepvarset m;
  591. if null v then return zeroprimarydecomposition!* m;
  592. vars:=ring_names (c:=cali!=basering);
  593. cali!=degrees:=nil; u:=setdiff(vars,v);
  594. setring!* ring_rlp(c,u);
  595. m1:=dpmat_2a gbasis!* dpmat_neworder(m,nil);
  596. setring!* ring_define(u,degreeorder!* u,
  597. 'revlex,for each x in u collect 1);
  598. p:=bc_2a prime!=quot(m1:=groeb_mingb dpmat_from_a m1);
  599. l:=for each x in zeroprimarydecomposition!* m1 collect
  600. {(dpmat_2a first x . bc_2a prime!=quot first x),
  601. (dpmat_2a second x . bc_2a prime!=quot second x)};
  602. setring!* c;
  603. l:=for each x in l collect
  604. << cali!=degrees:=dpmat_coldegs m;
  605. {gbasis!* matqquot!*(dpmat_from_a car first x,
  606. dp_from_a cdr first x),
  607. gbasis!* matqquot!*(dpmat_from_a car second x,
  608. dp_from_a cdr second x)}
  609. >>;
  610. if dp_unit!?(p:=dp_from_a p) or
  611. submodulep!*(m1:=matqquot!*(m,p),m) then return l
  612. else
  613. << q:=p; v:=1;
  614. while not submodulep!*(m1:=dpmat_times_dpoly(p,m1),m)
  615. and (v<15) do << q:=dp_prod(p,q); v:=v+1 >>;
  616. if (v=15) then
  617. rederr"Power detection in prime!=decompose2 failed";
  618. l1:=prime!=decompose2 gbasis!* matsum!*
  619. {m, dpmat_times_dpoly(q,
  620. dpmat_unit(dpmat_cols m,dpmat_coldegs m))};
  621. p:=append(for each x in l collect second x,
  622. for each x in l1 collect second x);
  623. l:=append(l,for each x in l1 join
  624. if prime!=necessary(second x,m,p) then {x});
  625. >>;
  626. return l;
  627. end)
  628. where cali!=degrees:=cali!=degrees,
  629. cali!=basering:=cali!=basering;
  630. symbolic procedure prime!=necessary(P,m,l);
  631. % P a prime to be testet, M the original module, l the list of
  632. % (possibly) associated primes of M, including P.
  633. % Returns true <=> P is an embedded prime.
  634. begin scalar l1,unit;
  635. l1:=for each u in l join if (u=p) or submodulep!*(u,p) then {t};
  636. if null l1 then
  637. rederr"prime!=necessary: supplied prime's list incorrect";
  638. if length l1 = 1 then % P is an isolated prime.
  639. return t;
  640. unit:=dpmat_unit(dpmat_cols m,cali!=degrees);
  641. % Unit matrix for reference.
  642. l1:=for each u in l join if not submodulep!*(u,p) then {u};
  643. % L_1 = Primes not contained in P.
  644. l:=delete(p,setdiff(l,l1)); % L = Primes contained in P.
  645. m:=matqquot!*(m,prime!=polynomial(p,l1));
  646. % Ass M is now contained in L \union (P).
  647. return not submodulep!*(matstabquot!*(m,p),m);
  648. end;
  649. endmodule; % prime
  650. end;