ncdip.red 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. module ncdip; % Non-commutative distributive polynomials.
  2. % Author: H. Melenk, ZIB Berlin, J. Apel, University of Leipzig.
  3. symbolic procedure ncdsetup!* u;
  4. % U is a list of algebraic arguments:
  5. % 1. list of variables,
  6. % 2. list of commutator relations in explicit form x*y=y*x + r
  7. % where ord(r) < ord(x*y) .
  8. % All variable pairs whitch do not occur here are considered
  9. % communtative.
  10. begin scalar x,y,w,vars,lh,z,lv,r,q;
  11. vars := for each x in cdr listeval(car u,nil)
  12. collect reval x;
  13. ncdipcircular!*:=nil;
  14. if null vdpsortmode!* then vdpsortmode!*:= 'lex;
  15. vdpinit2 (ncdipvars!*:=vars);
  16. lv:=length vars;
  17. ncdipbase!*:=mkvect lv;
  18. ncdiptable!*:=mkvect lv;
  19. for i:=1:lv do putv(ncdiptable!*,i,mkvect lv);
  20. q:=cdr listeval(cadr u,nil);
  21. while q do
  22. <<r:=car q;q:=cdr q;
  23. if (eqcar(r,'equal) or eqcar(r,'replaceby)) and
  24. eqcar(lh:=cadr r,'times) and
  25. null cdddr r and
  26. (w:=member(y:=caddr lh,vars)) and
  27. member(x:=cadr lh,w)
  28. then
  29. << % does any variable other than x or y appear in the rhs?
  30. if smember(x,q) or smember(y,q) then ncdipcircular!*:=t;
  31. for each v in vars do
  32. if v neq x and v neq y and smember(v,caddr r) then
  33. ncdipcircular!*:=t;
  34. % establish the commutator in DIP form.
  35. w:=ncdipndx(x,vars,1).ncdipndx(y,vars,1);
  36. r:=a2dip(z:=reval caddr r);
  37. if evcomp(dipevlmon r,dipevlmon a2dip {'times,x,y})<0 then
  38. typerr({'equal,{'times,x,y},z},
  39. "commutator under current term order");
  40. getv(ncdipbase!*,car w):= sort(cdr w.getv(ncdipbase!*,car w),'lessp);
  41. getv(getv(ncdiptable!*,car w),cdr w):= {'(1 . 1).r}>>
  42. else typerr(r,"commutator ")>>end;
  43. symbolic procedure ncdipndx(x,vars,n);
  44. if null vars then 0 else if x=car vars then n else ncdipndx(x,cdr vars,n #+ 1);
  45. %------------ noncom multiply ----------------------------
  46. symbolic procedure vdp!-nc!-m!*p(bc,ev,p);
  47. % multiply polynomial p left by monomial (bc,ev).
  48. begin scalar r,s;
  49. r:=dip2vdp dip!-nc!-m!*p(bc,ev,vdppoly p);
  50. if !*gsugar then
  51. <<s:=gsugar p; for each e in ev do s:=s+e;r:=gsetsugar(r,s)>>;
  52. return r end;
  53. symbolic procedure vdp!-nc!-prod(u,v);
  54. % non-commutative product of two distributive polynomials.
  55. begin scalar r;
  56. r:=dip2vdp dip!-nc!-prod(vdppoly u,vdppoly v);
  57. if !*gsugar then r:=gsetsugar(r,gsugar u + gsugar v);
  58. return r end;
  59. symbolic procedure dip!-nc!-prod(u,v);
  60. % We distribute first over the shorter of the two factors.
  61. if length u < length v then dip!-nc!-prod!-distleft(u,v)
  62. else dip!-nc!-prod!-distright(u,v);
  63. symbolic procedure dip!-nc!-prod!-distleft(u,v);
  64. if dipzero!? u then u else
  65. dipsum(dip!-nc!-m!*p!-distleft(diplbc u,dipevlmon u,v),
  66. dip!-nc!-prod!-distleft(dipmred u,v));
  67. symbolic procedure dip!-nc!-m!*p!-distleft(bc,ev,p);
  68. if dipzero!? p then nil else
  69. begin scalar lev,lbc,q;
  70. lev:=dipevlmon p;lbc:=diplbc p;
  71. p:=dip!-nc!-m!*p!-distleft(bc,ev,dipmred p);
  72. q:=dip!-nc!-ev!-prod(bc,ev,lbc,lev);
  73. return dipsum(p,q)end;
  74. symbolic procedure dip!-nc!-prod!-distright(u,v);
  75. if dipzero!? v then v else
  76. dipsum(dip!-nc!-m!*p!-distright(u,diplbc v,dipevlmon v),
  77. dip!-nc!-prod!-distright(u,dipmred v));
  78. symbolic procedure dip!-nc!-m!*p!-distright(p,bc,ev);
  79. if dipzero!? p then nil else
  80. begin scalar lev,lbc,q;
  81. lev:=dipevlmon p;lbc:=diplbc p;
  82. p:=dip!-nc!-m!*p!-distright(dipmred p,bc,ev);
  83. q:=dip!-nc!-ev!-prod(lbc,lev,bc,ev);
  84. return dipsum(p,q)end;
  85. symbolic procedure dip!-nc!-ev!-prod(bc1,ev1,bc2,ev2);
  86. % compute (bc1*ev1) * (bc2*ev2). Result is a dip.
  87. dip!-nc!-ev!-prod1(ev1,1,dipfmon(bcprod(bc1,bc2),ev2));
  88. symbolic procedure dip!-nc!-ev!-prod1(ev,n,r);
  89. % loop over ev and n (counter). NOTE: ev must be processed from right to left!
  90. if null ev then r else
  91. dip!-nc!-ev!-prod2(car ev,n,dip!-nc!-ev!-prod1(cdr ev,n#+1,r));
  92. symbolic procedure dip!-nc!-ev!-prod2(j,n,r);
  93. % muliply x_n^j * r
  94. if j=0 or dipzero!? r then r else
  95. begin scalar ev,bc,r0,w,s,evl,evr;integer i;
  96. ev:=dipevlmon r;bc:=diplbc r;
  97. r:=dip!-nc!-ev!-prod2(j,n,dipmred r);
  98. % collect the variables in ev which do not commute with x_n;
  99. w:=getv(ncdipbase!*,n);
  100. while w and nth(ev,car w)=0 do w:=cdr w;
  101. % no commutator?
  102. if null w then
  103. <<r0:=dipfmon(bc,dipevadd1var(j,n,ev));return dipsum(r0,r)>>;
  104. % We handle now the leftmost commutator and
  105. % push the rest of the problem down to the recursion:
  106. % split the monmial into parts left and
  107. % right of the noncom variable and multiply these.
  108. w:=car w;s:=nth(ev,w);
  109. % Split the ev into left and right part.
  110. i:=0;for each e in ev do <<i:=i#+1;if i<w then<<evl:=e.evl;evr:=0 .evr>>
  111. else if i=w then <<evl:=0 .evl;evr:=0 .evr>>
  112. else <<evl:=0 .evl;evr:=e .evr>> >>;
  113. evl:=reversip evl;evr:=reversip evr;
  114. r0:=dip!-nc!-get!-commutator(n,j,w,s);
  115. % multiply by left exponent
  116. r0:=if ncdipcircular!* then
  117. <<r0:=dip!-nc!-prod(dipfmon(a2bc 1,evl),r0);
  118. r0:=dip!-nc!-prod(r0,dipfmon(bc,evr))>> else
  119. <<r0:=dipprod(dipfmon(a2bc 1,evl),r0);
  120. r0:=dipprod(r0,dipfmon(bc,evr))>>;
  121. done:return dipsum(r0,r)end;
  122. symbolic procedure dip!-nc!-get!-commutator(n1,e1,n2,e2);
  123. % Compute the commutator for y^e1*x^e2 where y is
  124. % the n1-th variable and x is the n2-th variable.
  125. % The commutators for power products are computed
  126. % recursively when needed. They are stored in a data base.
  127. % I assume here that the commutator for (1,1) has been
  128. % put into the data base before. We update the table
  129. % in place by nconc-ing new pairs to its end.
  130. begin scalar w,r,p;
  131. w:=getv(getv(ncdiptable!*,n1),n2);p:=e1.e2;
  132. if (r:=assoc(p,w)) then return cdr r;
  133. % compute new commutator recursively:
  134. % first e1 downwards, then e2
  135. r:=if e1>1 then
  136. % compute y^e1*x^e2 as y*(y^(e1-1)*x^e2)
  137. dip!-nc!-ev!-prod2(1,n1,dip!-nc!-get!-commutator(n1,e1#-1,n2,e2))
  138. else
  139. % compute y*x^e2 as (y*x^(e2-1))*x
  140. dip!-nc!-prod(dip!-nc!-get!-commutator(n1,1,n2,e2#-1),dipfvarindex n2);
  141. nconc(w,{(p.r)});
  142. return r end;
  143. symbolic procedure dipfvarindex n;
  144. % Make a dip from a single variable index.
  145. a2dip nth(dipvars!*,n);
  146. symbolic procedure dipevadd1var(e,n,ev);
  147. % add e into the nth position of ev.
  148. if null ev or n<1 then ev else
  149. if n=1 then (car ev #+ e).cdr ev else car ev.dipevadd1var(e,n#-1,cdr ev);
  150. % ------------ conversion algebraic => nc dip --------------
  151. symbolic procedure a2ncdip a;
  152. if atom a then a2dip a else
  153. if car a = 'difference then
  154. a2ncdip{'plus,cadr a,{'times,-1,caddr a}} else
  155. if car a = 'minus then
  156. a2ncdip{'times,-1,cadr a} else
  157. if car a='expt and fixp caddr a then
  158. a2ncdip('times.for i:=1:caddr a collect cadr a) else
  159. if car a='plus then
  160. begin scalar r;
  161. r:=a2ncdip cadr a;
  162. for each w in cddr a do r:=dipsum(r,a2ncdip w);
  163. return r end else
  164. if car a='times then
  165. begin scalar r;
  166. r:=a2ncdip cadr a;
  167. for each w in cddr a do r:=dip!-nc!-prod(r,a2ncdip w);
  168. return r end else
  169. if car a='!*sq then a2ncdip prepsq cadr a else a2dip a;
  170. symbolic procedure a2ncvdp a;dip2vdp a2ncdip a;
  171. endmodule;;end;