线性代数学习三,将矩阵变为行最简形,标准形以及计算矩阵的秩
线性代数学习五,向量的运算与用施密特正交化方法从线性无关组导出正交向量

线性代数学习四,矩阵的运算和求逆

太阳神上 posted @ 2008年8月23日 07:47 in Algorithm with tags Matrix operation inverse , 2341 阅读

矩阵的运算是通过Lua的metatable来完成的,用起来和C++的操作符重载一样方便,而矩阵的求逆就是通过求伴随矩阵再除以其行列式的值而得。即

A^{-1}=\frac{1}{|A|}A^{*}

在实现过程中遇到了一些麻烦,有一个是我的对于伴随矩阵的理解有问题,原来伴随矩阵不仅仅要每个元素由其代数余子式代替,还得转置一下。

 

  1. #!/usr/bin/env lua
  2.  
  3. require 'determinant'
  4.  
  5. function Matrix(data,row,column)
  6.         local size=table.maxn(data)
  7.         assert(size==row*column)
  8.  
  9.         local matrix={}
  10.         matrix.data=data
  11.         matrix.row=row
  12.         matrix.column=column
  13.  
  14.         matrix.at=function(this,row,column)
  15.                 return this.data[(row-1)*this.column+column]
  16.         end
  17.  
  18.         matrix.set=function(this,row,column,num)
  19.                 this.data[(row-1)*this.column+column]=num
  20.         end
  21.  
  22.         matrix.swaprow=function(this,r1,r2)
  23.                 local temp
  24.                 for i=1,this.column do
  25.                         temp=this:at(r1,i)
  26.                         this:set(r1,i,this:at(r2,i))
  27.                         this:set(r2,i,temp)
  28.                 end
  29.         end
  30.  
  31.         matrix.simplifycolumn=function(this,column,layer)
  32.                 if this:at(layer,column) == 0 then
  33.                         for i=layer+1,this.row do
  34.                                 if this:at(i,column) ~= 0 then
  35.                                         this:swaprow(i,layer)
  36.                                         break
  37.                                 end
  38.                         end
  39.                 end
  40.  
  41.                 if this:at(layer,column) == 0 then
  42.                         return layer
  43.                 end
  44.  
  45.                 for i=1,this.row do
  46.                         if i~= layer then
  47.                                 local tomultiply=-this:at(i,column)/this:at(layer,column)
  48.                                 for j=1,this.column do
  49.                                         this:set(i,j,this:at(layer,j)*tomultiply+this:at(i,j))
  50.                                 end
  51.                         end
  52.                 end
  53.  
  54.                 return layer+1
  55.         end
  56.  
  57.         matrix.swapcolumn=function(this,c1,c2)
  58.                 local temp
  59.                 for i=1,this.row do
  60.                         temp=this:at(i,c1)
  61.                         this:set(i,c1,this:at(i,c2))
  62.                         this:set(i,c2,temp)
  63.                 end
  64.         end
  65.  
  66.         matrix.simplifyrow=function(this,row,layer)
  67.                 if this:at(row,layer) == 0 then
  68.                         for i=layer+1,this.column do
  69.                                 if this:at(row,i) ~= 0 then
  70.                                         this:swapcolumn(i,layer)
  71.                                         break
  72.                                 end
  73.                         end
  74.                 end
  75.                
  76.                 if this:at(row,layer) == 0 then
  77.                         return layer
  78.                 end
  79.  
  80.                 for i=1,this.column do
  81.                         if i ~= layer then
  82.                                 local tomultiply=-this:at(row,i)/this:at(row,layer)
  83.                                 for j=1,this.row do
  84.                                         this:set(j,i,this:at(j,layer)*tomultiply+this:at(j,i))
  85.                                 end
  86.                         end
  87.                 end
  88.  
  89.                 return layer+1
  90.         end
  91.  
  92.         -- Make the matrix to reduced form
  93.         matrix.reduce=function(this)
  94.                 local layer=1
  95.                 for i=1,this.column do
  96.                         layer=this:simplifycolumn(i,layer)
  97.                         if layer>this.row then
  98.                                 break
  99.                         end
  100.                 end
  101.                
  102.                
  103.                 for i=1,this.row do
  104.                         local tomultiply=nil
  105.                         for j=1,this.column do
  106.                                 if tomultiply then
  107.                                         this:set(i,j,this:at(i,j)*tomultiply)
  108.                                 elseif this:at(i,j)~= 0 then
  109.                                         tomultiply=1/this:at(i,j)
  110.                                         this:set(i,j,1)
  111.                                 end
  112.                         end
  113.                 end     
  114.         end
  115.  
  116.         -- Make the matrix to canonical form
  117.         matrix.canonicalize=function(this)
  118.                 this:reduce()
  119.                 local layer=1
  120.                 for i=1,this.row do
  121.                         layer=this:simplifyrow(i,layer)
  122.                         if layer>this.column then
  123.                                 break
  124.                         end
  125.                 end     
  126.         end
  127.  
  128.         -- Get the rank of the matrix
  129.         -- Matrix should be reduced before.
  130.         matrix.rank=function(this)
  131.                 local rank=0
  132.                 for i=1,this.row do
  133.                         for j=1,this.column do
  134.                                 if this:at(i,j) ~= 0 then
  135.                                         rank=rank+1
  136.                                         break
  137.                                 end
  138.                         end
  139.                 end
  140.  
  141.                 return rank
  142.         end
  143.  
  144.         matrix.print=function(this)
  145.                 for i=1,this.row do
  146.                         for j=1,this.column do
  147.                                 io.write(this:at(i,j),'\t')
  148.                         end
  149.                         io.write('\n')
  150.                 end
  151.         end
  152.  
  153.         -- Get the transposed matrix
  154.         matrix.transpose=function(this)
  155.                 local data={}
  156.  
  157.                 for i=1,this.column do
  158.                         for j=1,this.row do
  159.                                 table.insert(data,this:at(j,i))
  160.                         end
  161.                 end
  162.  
  163.                 return Matrix(data,this.column,this.row)
  164.         end
  165.  
  166.         matrix.cofactor=function(this,row,column)
  167.                 local data={}
  168.  
  169.                 for i=1,this.row do
  170.                         for j=1,this.column do
  171.                                 if i~=row and j~=column then
  172.                                         table.insert(data,this:at(i,j))
  173.                                 end
  174.                         end
  175.                 end
  176.  
  177.                 if (row+column)%2==0 then
  178.                         return Determinant(data):eval()
  179.                 else
  180.                         return -Determinant(data):eval()
  181.                 end
  182.         end
  183.  
  184.         -- Get the adjoint matrix of this matrix
  185.         matrix.adjoint=function(this)
  186.                 local data={}
  187.                 for i=1,this.row do
  188.                         for j=1,this.column do
  189.                                 table.insert(data,this:cofactor(i,j))
  190.                         end
  191.                 end
  192.  
  193.                 return Matrix(data,this.row,this.column):transpose()
  194.         end
  195.  
  196.         -- Get the inverse matrix of this matrix
  197.         -- If this matrix is not invertible, nil is returned
  198.         matrix.inverse=function(this)
  199.                 -- Only array can be invertible
  200.                 if this.row ~= this.column then
  201.                         return nil
  202.                 end
  203.  
  204.                 local det=Determinant(this.data):eval();
  205.                 if det==0 then
  206.                         return nil
  207.                 end
  208.                
  209.                 return (1/det)*this:adjoint()
  210.         end
  211.  
  212.         if MatrixCalc then
  213.                 setmetatable(matrix,MatrixCalc)
  214.         end
  215.  
  216.         return matrix
  217. end
  218.  
  219. -- The matrix calculation metatable
  220. MatrixCalc={}
  221.  
  222. MatrixCalc.__add=function(a,b)
  223.         assert(a.row==b.row and a.column==b.column)
  224.         local data={}
  225.  
  226.         for i=1,a.row*a.column do
  227.                 table.insert(data,a.data[i]+b.data[i])
  228.         end
  229.  
  230.         return Matrix(data,a.row,a.column)
  231. end
  232.  
  233. MatrixCalc.__sub=function(a,b)
  234.         assert(a.row==b.row and a.column==b.column)
  235.         local data={}
  236.  
  237.         for i=1,a.row*a.column do
  238.                 table.insert(data,a.data[i]-b.data[i])
  239.         end
  240.  
  241.         return Matrix(data,a.row,a.column)
  242. end
  243.  
  244. MatrixCalc.__unm=function(a)
  245.         local data={}
  246.  
  247.         for i=1,a.row*a.column do
  248.                 table.insert(data,-a.data[i])
  249.         end
  250.  
  251.         return Matrix(data,a.row,a.column)
  252. end
  253.  
  254. MatrixCalc.__mul=function(a,b)
  255.         if tonumber(a) then
  256.                 -- a is a number
  257.                 local data={}
  258.                 for i=1,b.row*b.column do
  259.                         table.insert(data,a*b.data[i])
  260.                 end
  261.                 return Matrix(data,b.row,b.column)
  262.         else
  263.                 -- a is a matrix
  264.                 assert(a.column==b.row)
  265.                
  266.                 local data={}
  267.                 for i=1,a.row do
  268.                         for j=1,b.column do
  269.                                 local value=0
  270.                                 for m=1,a.column do
  271.                                         value=value+a:at(i,m)*b:at(m,j)
  272.                                 end
  273.                                 table.insert(data,value)
  274.                         end
  275.                 end
  276.  
  277.                 return Matrix(data,a.row,b.column)
  278.         end
  279. end
  280.  
  281. MatrixCalc.__eq=function(a,b)
  282.         if a.row~=b.row or a.row~=b.column then
  283.                 return false
  284.         end
  285.  
  286.         for i=1,a.row*a.column do
  287.                 if a.data[i]~=b.data[i] then
  288.                         return false
  289.                 end
  290.         end
  291.  
  292.         return true
  293. end

登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter