nullsp.red 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. module nullsp; % Compute the nullspace (basis vectors) of a matrix.
  2. % Author: Herbert Melenk <melenk@sc.zib-berlin.de>.
  3. % Algorithm: Rational Gaussian elimination with standard qutotients.
  4. put('nullspace,'psopfn,'nullspace!-eval);
  5. symbolic procedure nullspace!-eval u;
  6. % interface for the nullspace calculation.
  7. begin scalar v,n,matinput;
  8. v := reval car u;
  9. if eqcar(v,'MAT) then
  10. <<matinput:=t; v := cdr v>>
  11. else if eqcar(v,'LIST) then
  12. v := for each row in cdr v collect
  13. if not eqcar(row,'LIST) then typerr ("matrix",u) else
  14. <<row := cdr row;
  15. if null n then n := length row else
  16. if n neq length row
  17. then rerror(matrix,15,"lists not in matrix shape");
  18. row>> else rerror(matrix,16,"Not a matrix");
  19. v := nullspace!-alg v;
  20. return 'list . for each vect in v collect
  21. if matinput then 'MAT . for each x in vect collect list x
  22. else 'LIST . vect;
  23. end;
  24. symbolic procedure nullspace!-alg(m);
  25. % "M" is a Matrix, encoded as list of lists(=rows) of algebraic
  26. % expressions.
  27. % Result is the basis of the kernel of M in the same encoding.
  28. begin scalar mp,vars,rvars,r,res,oldorder; integer n;
  29. n := length car m;
  30. vars := for i:=1:n collect gensym();
  31. rvars := reverse vars;
  32. oldorder := setkorder rvars;
  33. mp := for each row in m collect
  34. <<r := nil ./ 1;
  35. for each col in pair(vars,row) do
  36. r := addsq(r,simp list('times,car col,cdr col));
  37. r>>;
  38. res := nullspace!-elim(mp,rvars);
  39. setkorder oldorder;
  40. return reverse for each q in res collect
  41. for each x in vars collect
  42. cdr atsoc(x,q);
  43. end;
  44. symbolic procedure nullspace!-elim(m,vars);
  45. % "M" is a matrix encoded as list of linear polnomials (sq's) in
  46. % the variables "vars". The current korder cooresponds to vars.
  47. % Result is a basis for the null space of the matrix, encoded
  48. % as list of vectors, where each vector is an alist over vars.
  49. % A rational Gaussian elimination is performed and unit vectors
  50. % are substituted for the remaining unrestricted variables.
  51. begin scalar c,s,x,w,arbvars,depvars,row,res,break;
  52. while vars and not break do
  53. <<for each p in m do
  54. if domainp numr p then if numr p then break:=t %unsolvable
  55. else m:=delete(p,m);
  56. if not break then
  57. <<x:=car vars; vars:=cdr vars; row:=nil;
  58. % select row with x as leading variable.
  59. for each p in m do
  60. if null row and mvar numr p = x then row:=p;
  61. % if none, then x is a free variable.
  62. if null row then arbvars:=x.arbvars else
  63. <<m:=delete(row,m);
  64. c:=multsq(negf denr row ./1, 1 ./ lc numr row);
  65. row := multsq(row,c);
  66. % collect formula for x,
  67. depvars := (x . (red numr row ./ denr row)) . depvars;
  68. % and perform elimination with this row.
  69. m:=for each p in m collect
  70. <<if mvar numr p=x then
  71. <<p:=addsq(p, multsq(row,lc numr p ./ denr p));
  72. % Simplification for non-numeric coefficients.
  73. if not domainp (w:=numr p) and not domainp lc w then
  74. p:=subs2!* p>>;
  75. p>>;
  76. >>;
  77. >>;
  78. >>;
  79. if break then return nil;
  80. % Construct solutions by assigning unit vectors to the
  81. % free variables and perform backsubstitution.
  82. for each x in arbvars do
  83. << s := for each y in arbvars collect
  84. (y . if y=x then 1 else 0);
  85. c := 1;
  86. for each y in depvars do
  87. << s := (car y . prepsq (w:=subsq(cdr y,s))) . s;
  88. c := lcm!*(c,denr w)
  89. >>;
  90. if not(c=1) then <<c:=prepf c;
  91. s:=for each q in s collect car q.reval{'times,cdr q,c}>>;
  92. res := s . res;
  93. >>;
  94. return res;
  95. end;
  96. endmodule;
  97. end;