mo.red 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349
  1. module mo;
  2. COMMENT
  3. ##################
  4. ## ##
  5. ## MONOMIALS ##
  6. ## ##
  7. ##################
  8. Monomials are of the form x^a*e_i with a multipower x^a and a module
  9. component e_i. They belong either to the base ring R (i=0) or to a
  10. free module R^c (c >= i > 0).
  11. All computations are performed with respect to a "current module"
  12. over a "current ring" (=cali!=basering).
  13. To each module component e_i of the current module we assign a
  14. "column degree", i.e. a monomial representing a certain multidegree
  15. of the basis vector e_i. See the module dpmat for more details.
  16. The column degrees of the current module are stored in the assoc.
  17. list cali!=degrees.
  18. Informal syntax :
  19. <monomial> ::= (<exponential part> . <degree part>)
  20. < .. part> ::= list of integer
  21. Here exponent lists may have varying length since trailing zeroes are
  22. assumed to be omitted. The zero component of <exp. part> contains the
  23. module component. It correspond to the phantom var. name cali!=mk.
  24. END COMMENT;
  25. % ----------- manipulations of the degree part --------------------
  26. symbolic procedure mo!=sprod(a,b);
  27. % Scalar product of integer lists a and b .
  28. if not a or not b then 0
  29. else (car a)#*(car b) #+ mo!=sprod(cdr a,cdr b);
  30. symbolic procedure mo!=deglist(a);
  31. % a is an exponent list. Returns the degree list of a.
  32. if null a then
  33. for each x in ring_degrees cali!=basering collect 0
  34. else (mo!=sum(
  35. for each x in ring_degrees cali!=basering collect
  36. mo!=sprod(cdr a,x),
  37. if b then cddr b else nil)
  38. where b = assoc(car a,cali!=degrees));
  39. symbolic procedure mo_neworder m;
  40. % Deletes trailing zeroes and returns m with new degree part.
  41. (m1 . mo!=deglist m1) where m1 =mo!=shorten car m;
  42. symbolic procedure mo_degneworder l;
  43. % New degree parts in the degree list l.
  44. for each x in l collect car x . mo_neworder cdr x;
  45. symbolic procedure mo!=shorten m;
  46. begin scalar m1;
  47. m1:=reverse m;
  48. while m1 and eqn(car m1,0) do m1:=cdr m1;
  49. return reversip m1;
  50. end;
  51. % ------------- comparisions of monomials -----------------
  52. symbolic procedure mo_zero; nil . mo!=deglist nil;
  53. % Returns the unit monomial x^0.
  54. symbolic procedure mo_zero!? u; mo!=zero car u;
  55. symbolic procedure mo!=zero u;
  56. null u or car u = 0 and mo!=zero cdr u;
  57. symbolic procedure mo_equal!?(m1,m2);
  58. % Test whether m1 = m2.
  59. equal(mo!=shorten car m1,mo!=shorten car m2);
  60. symbolic procedure mo_divides!?(m1,m2);
  61. % m1,m2:monomial. true :<=> m1 divides m2
  62. mo!=modiv1(car m1,car m2);
  63. symbolic procedure mo!=modiv1(e1,e2);
  64. if not e1 then t else if not e2 then nil
  65. else leq(car e1,car e2) and mo!=modiv1(cdr e1, cdr e2);
  66. symbolic procedure mo_compare(m1,m2);
  67. % compare (m1,m2) . m1 < m2 => -1 | m1 = m2 => 0 | m1 > m2 => +1
  68. begin scalar x;
  69. x:=mo!=degcomp(cdr m1,cdr m2);
  70. if x=0 then
  71. x:=if equal(ring_tag cali!=basering,'revlex) then
  72. mo!=revlexcomp(car m1, car m2)
  73. else mo!=lexcomp(car m1,car m2);
  74. return x;
  75. end;
  76. symbolic procedure mo_dlexcomp(a,b); mo!=lexcomp(car a,car b)=1;
  77. % Descending lexicographic order, first by mo_comp.
  78. symbolic procedure mo!=degcomp(d1,d2);
  79. if null d1 then 0
  80. else if car d1 = car d2 then mo!=degcomp(cdr d1,cdr d2)
  81. else if car d1 #< car d2 then -1
  82. else 1;
  83. symbolic procedure mo!=revlexcomp(e1,e2);
  84. if length e1 #> length e2 then -1
  85. else if length e2 #> length e1 then 1
  86. else - mo!=degcomp(reverse e1,reverse e2);
  87. symbolic procedure mo!=lexcomp(e1,e2);
  88. if null e1 then
  89. if null e2 then 0 else mo!=lexcomp('(0),e2)
  90. else if null e2 then mo!=lexcomp(e1,'(0))
  91. else if car e1 = car e2 then mo!=lexcomp(cdr e1,cdr e2)
  92. else if car e1 #> car e2 then 1
  93. else -1;
  94. % ---------- manipulation of the module component --------
  95. symbolic procedure mo_comp v;
  96. % Retuns the module component of v.
  97. if null car v then 0 else caar v;
  98. symbolic procedure mo_from_ei i;
  99. % Make e_i.
  100. if i=0 then mo_zero() else (x . mo!=deglist x) where x =list(i);
  101. symbolic procedure mo_vdivides!?(v1,v2);
  102. % Equal module component and v1 divides v2.
  103. eqn(mo_comp v1,mo_comp v2) and mo_divides!?(v1,v2);
  104. symbolic procedure mo_deletecomp v;
  105. % Delete component part.
  106. if null car v then v
  107. else if null cdar v then (nil . mo!=deglist nil)
  108. else ((x . mo!=deglist x) where x=cons(0,cdar v));
  109. symbolic procedure mo_times_ei(i,m);
  110. % Returns m * e_i or n*e_{i+k}, if m=n*e_k.
  111. (x . mo!=deglist x)
  112. where x=if null car m then list(i) else cons(i #+ caar m,cdar m);
  113. symbolic procedure mo_deg m; cdr m;
  114. % Returns the degree part of m.
  115. symbolic procedure mo_getdegree(v,l);
  116. % Compute the (virtual) degree of the monomial v with respect to the
  117. % assoc. list l of column degrees.
  118. mo_deletecomp(if a then mo_sum(v,cdr a) else v)
  119. where a =assoc(mo_comp(v),l);
  120. % --------------- monomial arithmetics -----------------------
  121. symbolic procedure mo_lcm (m1,m2);
  122. % Monomial least common multiple.
  123. begin scalar x,e1,e2;
  124. e1:=car m1; e2:=car m2;
  125. while e1 and e2 do
  126. <<x := (if car e1 #> car e2 then car e1 else car e2) . x;
  127. e1 := cdr e1; e2 := cdr e2>>;
  128. x:=append(reversip x,if e1 then e1 else e2);
  129. return (mo!=shorten x) . (mo!=deglist x);
  130. end;
  131. symbolic procedure mo_gcd (m1,m2);
  132. % Monomial greatest common divisor.
  133. begin scalar x,e1,e2;
  134. e1:=car m1; e2:=car m2;
  135. while e1 and e2 do
  136. <<x := (if car e1 #< car e2 then car e1 else car e2) . x;
  137. e1 := cdr e1; e2 := cdr e2>>;
  138. x:=reversip x; return (mo!=shorten x) . (mo!=deglist x);
  139. end;
  140. symbolic procedure mo_neg v;
  141. % Return v^-1.
  142. (for each x in car v collect -x).(for each x in cdr v collect -x);
  143. symbolic procedure mo_sum(m1,m2);
  144. % Monomial product.
  145. ((mo!=shorten x) . (mo!=deglist x))
  146. where x =mo!=sum(car m1,car m2);
  147. symbolic procedure mo!=sum(e1,e2);
  148. begin scalar x;
  149. while e1 and e2 do
  150. <<x := (car e1 #+ car e2) . x; e1 := cdr e1; e2 := cdr e2>>;
  151. return append(reversip x,if e1 then e1 else e2);
  152. end;
  153. symbolic procedure mo_diff (m1,m2); mo_sum(m1,mo_neg m2);
  154. symbolic procedure mo_qrem(m,n);
  155. % m,n monomials. Returns (q . r) with m=n^q*r.
  156. begin scalar m1,n1,q,q1;
  157. q:=-1; m1:=cdar m; n1:=cdar n;
  158. while m1 and n1 and (q neq 0) do
  159. << if car n1 > 0 then
  160. << q1:=car m1 / car n1;
  161. if (q=-1) or (q>q1) then q:=q1;
  162. >>;
  163. n1:=cdr n1; m1:=cdr m1;
  164. >>;
  165. if n1 or (q=-1) then q:=0;
  166. return q . mo_diff(m,mo_power(n,q));
  167. end;
  168. symbolic procedure mo_power(mo,n);
  169. % Monomial power mo^n.
  170. (for each x in car mo collect n #* x) .
  171. (for each x in cdr mo collect n #* x);
  172. symbolic procedure mo!=pair(a,b);
  173. if null a or null b then nil
  174. else (car a . car b) . mo!=pair(cdr a,cdr b);
  175. symbolic procedure mo_2list m;
  176. % Returns a list (var name . exp) for the monomial m.
  177. begin scalar k; k:=car m;
  178. return for each x in
  179. mo!=pair(ring_names cali!=basering, if k then cdr k else nil)
  180. join if cdr x neq 0 then {x};
  181. end;
  182. symbolic procedure mo_varexp(var,m);
  183. % Returns the exponent of var:var. name in the monomial m.
  184. if not member(var,ring_names cali!=basering) then
  185. typerr(var,"variable name")
  186. else begin scalar c;
  187. c:=assoc(var,mo_2list m);
  188. return if c then cdr c else 0
  189. end;
  190. symbolic procedure mo_inc(m,x,j);
  191. % Return monomial m with power of var. x increased by j.
  192. begin scalar n,v;
  193. if not member(x,v:=ring_all_names cali!=basering) then
  194. typerr(x,"dpoly variable");
  195. m:=car m;
  196. while x neq car v do
  197. << if m then <<n:=car m . n; m:=cdr m>> else n:=0 . n;
  198. v:=cdr v;
  199. >>;
  200. if m then
  201. << n:=(car m #+ j).n; if m:=cdr m then n:=nconc(reverse m,n) >>
  202. else n:=j . n;
  203. while n and (car n = 0) do n:=cdr n;
  204. n:=reversip n;
  205. return n . mo!=deglist n
  206. end;
  207. symbolic procedure mo_linear m;
  208. % Test whether the monomial m is linear and return the corresponding
  209. % variable or nil.
  210. (if (length u=1 and cdar u=1) then caar u else nil)
  211. where u=mo_2list m;
  212. symbolic procedure mo_ecart m;
  213. % Returns the ecart of the monomial m.
  214. if null car m then 0
  215. else mo!=sprod(cdar (if a then mo_sum(cdr a,m) else m),
  216. ring_ecart cali!=basering)
  217. where a:=atsoc(mo_comp m,cali!=degrees);
  218. symbolic procedure mo_radical m;
  219. % Returns the radical of the monomial m.
  220. (x . mo!=deglist x)
  221. where x = for each y in car m collect if y=0 then 0 else 1;
  222. symbolic procedure mo_seed(m,s);
  223. % Set var's outside the list s equal to one.
  224. begin scalar m1,x,v;
  225. if not subsetp(s,v:=ring_all_names cali!=basering) then
  226. typerr(s,"dpoly name's list");
  227. m1:=car m;
  228. while m1 and v do
  229. << x:=cons(if member(car v,s) then car m1 else 0,x);
  230. m1:=cdr m1; v:=cdr v
  231. >>;
  232. while x and eqn(car x,0) do x:=cdr x;
  233. x:=reversip x;
  234. return x . mo!=deglist x;
  235. end;
  236. symbolic procedure mo_wconvert(m,w);
  237. % Conversion of monomials for weighted Hilbert series.
  238. % w is a list of (integer) weight lists.
  239. ( x . mo!=deglist x) where
  240. x = mo!=shorten(0 . for each x in w collect
  241. (if car m then mo!=sprod(cdar m,x) else 0));
  242. % ---------------- monomial interface ---------------
  243. symbolic procedure mo_from_a u;
  244. % Convert a kernel to a monomial.
  245. if not(u member ring_all_names cali!=basering) then
  246. typerr(u,"dpoly variable")
  247. else begin scalar x,y;
  248. y:=mo!=shorten
  249. for each x in ring_all_names cali!=basering collect
  250. if x equal u then 1 else 0;
  251. return y . mo!=deglist y;
  252. end;
  253. symbolic procedure mo_2a e;
  254. % Convert a monomial to part of algebraic prefix form of a dpoly.
  255. mo!=expvec2a1(car e,ring_all_names cali!=basering);
  256. symbolic procedure mo!=expvec2a1(u,v);
  257. if null u then nil
  258. else if car u = 0 then mo!=expvec2a1(cdr u,cdr v)
  259. else if car u = 1 then car v . mo!=expvec2a1(cdr u,cdr v)
  260. else list('expt,car v,car u) . mo!=expvec2a1(cdr u,cdr v);
  261. symbolic procedure mo_prin(e,v);
  262. % Print monomial e in infix form. V is a boolean variable which is
  263. % true if an element in a product has preceded this one
  264. mo!=dpevlpri1(car e,ring_all_names cali!=basering,v);
  265. symbolic procedure mo!=dpevlpri1(e,u,v);
  266. if null e then nil
  267. else if car e = 0 then mo!=dpevlpri1(cdr e,cdr u,v)
  268. else <<if v then print_lf "*";
  269. print_lf car u;
  270. if car e #> 1 then <<print_lf "^"; print_lf car e>>;
  271. mo!=dpevlpri1(cdr e,cdr u,t)>>;
  272. symbolic procedure mo_support m;
  273. % Returns the support of the monomial m as a list of var. names
  274. % in the correct order.
  275. begin scalar u;
  276. for each x in ring_names cali!=basering do
  277. if mo_divides!?(mo_from_a x,m) then u:=x . u;
  278. return reversip u;
  279. end;
  280. endmodule; % mo
  281. end;