跳转到内容

模組:Complex Number/Matrix

本页使用了标题或全文手工转换
维基百科,自由的百科全书

这是本页的一个历史版本,由A2569875留言 | 贡献2022年4月15日 (五) 05:31 逆矩阵编辑。这可能和当前版本存在着巨大的差异。

local p = {}
local comp_lib = require("Module:Complex_Number")
local cmath = comp_lib.cmath.init()
local toCnumber = cmath.constructor
p.cmath = cmath
p.toCnumber = toCnumber
function p._isNaN(x)
	return (not (x==x)) and  (x~=x)
end

function p._determinant(matrix, n)
	local det = 0;
	local submatrix={}
	if n == 2 then return ((matrix[1][1] * matrix[2][2]) - (matrix[2][1] * matrix[1][2]));
	else 
		for x = 1,n do
			local subi = 1;
			for i = 2,n do
				local subj = 1;
				local res_row = {}
				for j = 1,n do
					--if (j == x) continue;
					if j ~= x then
						--submatrix[subi][subj] = matrix[i][j];
						res_row[subj] = matrix[i][j]
						subj=subj+1
					end
				end
				submatrix[subi] = p.mmath.row(unpack(res_row))
				subi=subi+1
			end
			submatrix = p.mmath.matrix(unpack(submatrix)) 
			det = det + (math.pow(-1, (x-1) ) * matrix[1][x] * p._determinant( submatrix, n - 1 ));
		end
   end
   return det;
end

function p._cofactor(matrix, _p, _q)
	local result = {}
	local n = #matrix
    local i, j = 1, 1;
	for i = 2,n do
		local res_row = {}
		for j = 2,n do
			res_row[#res_row + 1] = 0
		end
		result[#result + 1] = p.mmath.row(unpack(res_row))
	end
	result = p.mmath.matrix(unpack(result)) 
    -- Looping for each element of the matrix
	for row = 1,n do
		for col = 1,n do
			--  Copying into temporary matrix only those element
			--  which are not in given row and column
			if row ~= _p and col ~= _q then
				result[i][j] = matrix[row][col]
				j = j + 1
				-- Row is filled, so increase row index and
				-- reset col index
				if j == n then
					j = 1;
					i = i + 1
				end
			end
		end
	end
	return result
end

function p._adjoint(matrix)
	local N = #matrix
	local result = {}
	if N == 1 then
	    --result[0][0] = 1;
	    return p.mmath.matrix(p.mmath.row(1))
	end
	
	for i = 1,N do
		local res_row = {}
		for j = 1,N do
			res_row[#res_row + 1] = 0
		end
		result[#result + 1] = p.mmath.row(unpack(res_row))
	end
	result = p.mmath.matrix(unpack(result)) 
	
	-- temp is used to store cofactors of matrix[][]
	local temp = {}
	local sign = 1
 
	for i=1,N do
		for j=1,N do
			-- Get cofactor of matrix[i][j]
			temp = p._cofactor(matrix, i, j);
			
			-- sign of result[j][i] positive if sum of row
			-- and column indexes is even.
			sign = ((i+j)%2==0)and 1 or -1
			
			-- Interchanging rows and columns to get the
			-- transpose of the cofactor matrix
			result[j][i] = (sign)*(p._determinant(temp, N-1));
		end
	end
	return result
end

function p._inverse(matrix)
	local result = {}
    -- Find determinant of matrix[][]
    local det = p._determinant(matrix, #matrix);
    if det == 0 then
    	error("Singular matrix, can't find its inverse")
    end
 
    -- Find adjoint
    local adj = p._adjoint(matrix)
 
    -- Find Inverse using formula "inverse(matrix) = adj(matrix)/det(matrix)"
	for i = 1,#matrix do
		local res_row = {}
		for j = 1,#matrix do
			res_row[#res_row + 1] = adj[i][j] / det
		end
		result[#result + 1] = p.mmath.row(unpack(res_row))
	end
	result = p.mmath.matrix(unpack(result)) 
    return result
end

--[[
	p.mmath.matrix(p.mmath.row(1,5),p.mmath.row(7,9))
	p.mmath.matrix(p.mmath.row(1, 2, 3), p.mmath.row(5, 7, 6), p.mmath.row(7, 9, 8))

	p.determinant(p.mmath.matrix(p.mmath.row(1,5),p.mmath.row(7,9)))
	p.determinant(p.mmath.matrix(p.mmath.row(1, 2, 3), p.mmath.row(5, 7, 6), p.mmath.row(7, 9, 8)))
	p.determinant(p.mmath.matrix(p.mmath.row(1, 2, 3, 0), p.mmath.row(5, 7, 6, 2), p.mmath.row(7, 9, 8, 1), p.mmath.row(2, 1, 3, 9)))
	p._inverse(p.mmath.matrix(p.mmath.row(1, 2, 3, 0), p.mmath.row(5, 7, 6, 2), p.mmath.row(7, 9, 8, 1), p.mmath.row(2, 1, 3, 9)))
]]
p.mmath={
	rows = function(mat)
		return #mat
	end,
	cols = function(mat)
		return #(mat[1]or{})
	end,
	mathform = function(mat)
		for i = 1,#mat do mat[i].mathform = true end
		mat.mathform = true
		return mat
	end,
	transpose = function(mat)
		local res_mat = {}
		for i = 1,p.mmath.cols(mat) do
			local res_row = {}
			for j = 1,p.mmath.rows(mat) do
				res_row[#res_row + 1] = mat[j][i]
			end
			res_mat[#res_mat + 1] = p.mmath.row(unpack(res_row))
			res_mat[#res_mat].mathform = mat.mathform
		end
		local result_mat = p.mmath.matrix(unpack(res_mat)) 
		result_mat.mathform = mat.mathform
		return result_mat
	end,
	determinant = function(matrix)
		return p._determinant(matrix, #matrix)
	end,
	identity = function(num)
		local size = tonumber(tostring(num)) or 1
		local res_mat = {}
		for i = 1,size do
			local res_row = {}
			for j = 1,size do
				res_row[#res_row + 1] = (i==j)and 1 or 0
			end
			res_mat[#res_mat + 1] = p.mmath.row(unpack(res_row))
		end
		return p.mmath.matrix(unpack(res_mat)) 
	end,
	diag = function(...)
		local diag_items = {...}
		local size = #diag_items
		local res_mat = {}
		for i = 1,size do
			local res_row = {}
			for j = 1,size do
				res_row[#res_row + 1] = (i==j)and diag_items[i] or 0
			end
			res_mat[#res_mat + 1] = p.mmath.row(unpack(res_row))
		end
		return p.mmath.matrix(unpack(res_mat)) 
	end,
	matrixMeta = {
		__add = function (op1, op2)
			local result_obj = {}
			local all_count = math.max(#op1, #op2)
			for i = 1,all_count do result_obj[i] = (op1[i]or p.mmath.row(0))+(op2[i]or p.mmath.row(0))end

			local result_mat = p.mmath.matrix(unpack(result_obj)) 
			result_mat.mathform = op1.mathform or op2.mathform
			return result_mat
		end,
		__sub = function (op1, op2)
			local result_obj = {}
			local all_count = math.max(#op1, #op2)
			for i = 1,all_count do result_obj[i] = (op1[i]or p.mmath.row(0))-(op2[i]or p.mmath.row(0))end
			local result_mat = p.mmath.matrix(unpack(result_obj)) 
			result_mat.mathform = op1.mathform or op2.mathform
			return result_mat
		end,
		__mul = function (op1, op2)
			local scalar_flag = false
			local can_mul = true
			if type(op2)==type({})then
				if type(op2.objType)==type("string") then
					if op2.objType~='matrix' then can_mul = false end
				else
					scalar_flag = true
				end
			else
				scalar_flag = true
			end
			if not can_mul then error( "Can not multiply" ) end
			local res_mat = {}
			if scalar_flag then
				for i = 1,#op1 do
					local ri = op1[i]
					local res_row = {}
					for j = 1,#ri do
						res_row[#res_row + 1] = op2 * (ri[j] or 0)
					end
					res_mat[#res_mat + 1] = p.mmath.row(unpack(res_row))
					res_mat[#res_mat].mathform = op1.mathform or op2.mathform
				end
			else
				local _m = p.mmath.rows(op1)
				local _n = p.mmath.cols(op1)
				local _p = p.mmath.cols(op2)
				if _n ~= p.mmath.rows(op2) then error( "dimension mismatch" ) end

				for _i = 1,_m do 
					local res_row = {}
					for _j = 1,_p do
						local sum = 0
						for _r = 1,_n do 
							sum = sum + (op1[_i][_r]or 0) * (op2[_r][_j]or 0)
						end
						res_row[#res_row + 1] = sum
					end
					res_mat[#res_mat + 1] = p.mmath.row(unpack(res_row))
					res_mat[#res_mat].mathform = op1.mathform or op2.mathform
				end
			end
			local result_mat = p.mmath.matrix(unpack(res_mat)) 
			result_mat.mathform = op1.mathform or op2.mathform
			return result_mat
		end,
		__tostring = function (this)
			local ret = ''
			for i = 1,#this do 
				ret = ret..(ret==''and''or(this.mathform and' \\\\\n'or','))..tostring(this[i])
			end
			if this.mathform then return'\\begin{bmatrix}'..ret..'\\end{bmatrix}'
			else return'{'..ret..'}'end
		end,
	},
	rowMeta = {
		__add = function (op1, op2)
			local result_obj = {}
			local all_count = math.max(#op1, #op2)
			for i = 1,all_count do result_obj[i] = (op1[i]or 0)+(op2[i]or 0)end
			return p.mmath.row(unpack(result_obj)) 
		end,
		__sub = function (op1, op2)
			local result_obj = {}
			local all_count = math.max(#op1, #op2)
			for i = 1,all_count do result_obj[i] = (op1[i]or 0)-(op2[i]or 0)end
			return p.mmath.row(unpack(result_obj)) 
		end,
		__mul = function (op1, op2)
			local result_obj = {}
			local all_count = math.max(#op1, #op2)
			for i = 1,all_count do result_obj[i] = (op1[i]or 0)*(op2[i]or 0)end
			return p.mmath.row(unpack(result_obj)) 
		end,
		__div = function (op1, op2)
			local result_obj = {}
			local all_count = math.max(#op1, #op2)
			for i = 1,all_count do result_obj[i] = (op1[i]or 0)/(op2[i]or 0)end
			return p.mmath.row(unpack(result_obj)) 
		end,
		__mod = function (op1, op2)
			local result_obj = {}
			local all_count = math.max(#op1, #op2)
			for i = 1,all_count do result_obj[i] = (op1[i]or 0)%(op2[i]or 0)end
			return p.mmath.row(unpack(result_obj)) 
		end,
		__unm = function (this)
			local result_obj = {}
			for i = 1,#this do result_obj[i] = -this[i]end
			return p.mmath.row(unpack(result_obj)) 
		end,
		__eq = function (op1, op2)
			local flag = true
			local all_count = math.max(#op1, #op2)
			for i = 1,all_count do flag = flag and ((op1[i]or 0)==(op2[i]or 0))end
			return flag
		end,
		__tostring = function (this)
			local ret = ''
			for i = 1,#this do 
				local to_text = tostring(this[i])
				if this.mathform then to_text='{'..to_text..'}'end
				ret = ret..(ret==''and''or(this.mathform and' & 'or','))..to_text
			end
			if this.mathform then return ret
			else return'{'..ret..'}'end
		end,
	},
	row = function(...)
		local row_obj = {...}
		setmetatable(row_obj,p.mmath.rowMeta)
		row_obj.objType = 'row'
		row_obj.numberType = "matrix"
		row_obj.mathform = false
		return row_obj
	end,
	matrix = function(...)
		local col_obj = {...}
		setmetatable(col_obj,p.mmath.matrixMeta)
		col_obj.objType = 'matrix'
		col_obj.numberType = "matrix"
		col_obj.mathform = false
		return col_obj
	end,
	toMatrix = function(input_data)

			if type(input_data.objType)==type('objType') then
				return input_data
			else
				return toCnumber(input_data)
			end

		
	end,
	init = function()
		p.mmath.e = cmath.e
		p.mmath.pi = cmath.pi
		p.mmath["π"] = cmath["π"] 
		p.mmath["°"] = cmath["°"]
		p.mmath.nan = cmath.nan
		p.mmath.i = cmath.i
		
		p.mmath.numberType = comp_lib._numberType
		p.mmath.constructor = p.mmath.toMatrix
		return p.mmath
	end
}
return p