Lua中的矩阵(数组) - 交换行并应用行操作

我有这段代码

--[[

Lua中的高斯消元

--]]

-- 打印矩阵
function printmatrix(m)
   for r=1,#m do
      for c=1,#m[r] do
         io.write(m[r][c])
         if c < #m[r] then io.write(", ") end
      end
      print() -- 打印新行
   end
end

-- 以CSV格式读取矩阵
function readcsv()
   local m = {}
   while true do
      local line = io.read("l") -- 读取行,不包括行尾字符
      if line==nil or line=="" then break end -- 空行或错误输入导致矩阵结束
      local row, index = {}, 0
      -- 下一行比较棘手,并在行中处理所有条目
      for w in string.gmatch(line,"([^,]*),?") do
     local v = tonumber(w) -- 将条目转换为数字
     index = index+1
     if v==nil then
        row[index] = 0 -- 如果无法读取数字,则默认值为0
     else
        row[index] = v -- 如果数字有效
     end
      end
      m[ #m+1 ] = row
   end
   return m
end

-- 确定m的大小并检查其是否为矩形
function dim(m)
   local rows = #m -- 行数
   local cols = 0  -- 列数
   if rows > 0 then cols = #m[1] end
   -- 检查矩阵是否为矩形
   for i=2,rows do
      if cols ~= #m[i] then error("not rectangular!") end
   end
   return rows, cols
end

-- 如果m [r] [c]为零,则交换行r与一些行i>r(如果可能),以使m [r] [c]非零
function swap(m,r,c)
   local nrows, ncols = dim(m)
   if r<=0 or r>nrows or c<=0 or c>ncols then error("position out of range") end
   if m[r][c] ~= 0 then
      -- 没有要做的事情
      return
   end
   -- 找到一个合适的行
   local i=r+1
   while i <= nrows do
      if m[i][c] ~= 0 then break end
      i = i+1
   end
   if i <= nrows then
      -- 交换i,r行
      -- DO IT!
   end
end

-- 如果m [r] [c]不为零,则应用行操作,使每个m [i] [c] == 0对于i>r
function clear(m,r,c)
   local nrows, ncols = dim(m)
   if r<=0 or r>nrows or c<=0 or c>ncols then error("position out of range") end
   if m[r][c] == 0 then
      -- 没有要做的事情
      return
   end
   for i=r+1,nrows do
      local f = m[i][c] / m[r][c] do
      -- 应用行_i = row_i - f*row_r
      -- DO IT!**
   end
   end
end

-- 将高斯消元应用于m,以将其变成梯形形式
function echelon(m)
   local nrows, ncols = dim(m)
   local r,c = 1,1 -- 当前位置
   while r<=nrows and c<=ncols do
      -- 尝试在此位置获取非零值
      swap(m,r,c)
      if m[r][c] == 0 then
     -- 无法,所以向右移动
     c = c+1
      else
     clear(m,r,c)
     -- 完成,所以对角线移动
     r = r+1
     c = c+1
      end
   end
end

m = readcsv()
print("original:")
printmatrix(m)
echelon(m)
print("梯形形式:")
printmatrix(m)

我希望有人能够澄清如何编写代码(Lua中的` -DO IT! '处),我对此还很陌生,谢谢

为了提供一些背景,我只是在尝试高斯消元,以在计算梯形形式这种特定方法时使我的工作更快 - 对于我来说,首个非零元素为1并不那么重要

它应该返回这样

original:
1, 3, 5, 7
2, 1, -1, 0
3, 4, 4, 7
5, 5, 3, 7
梯形形式:
1, 3, 5, 7
0, -5, -11, -14
0, 0, 0, 0
0, 0, 0, 0
点赞
用户6632736
用户6632736
--[[
高斯消元在 Lua 中的实现
--]]

-- 打印矩阵
local function printmatrix(m)
    for _, row in ipairs(m) do
        io.write(table.concat(row, ', ') .. '\n')
    end
end

-- 以 CSV 格式读取矩阵
local function readcsv(file)
    io.input(file)
    local m = {columns = 0, rectangular = true}
    for line in io.lines() do
        local row = {}
        -- 下一行为该行中所有条目,需要较为繁琐地遍历
        for w in line:gmatch'[^,]+' do
            row[#row + 1] = tonumber(w) or 0
        end
        m[#m + 1] = row
        -- 更新矩阵尺寸
        m.rectangular = m.rectangular and (#row == m.columns or #m == 1)
        m.columns = #row > m.columns and #row or m.columns
    end
    return m
end

-- 如果 m[r][c] 为零,则交换第 r 行和第 i 行(其中 r < i),使 m[r][c] 不为零(如果可能的话)
local function swap(m, r, c)
    local nrows, ncols = #m, m.columns
    if r <= 0 or r > nrows or c <= 0 or c > ncols then error 'Position out of range' end
    if m[r][c] ~= 0 then
        -- 不需要操作
        return
    end
    -- 找到一个合适的行
    local i = r + 1
    while i <= nrows and m[i][c] == 0 do
        i = i + 1
    end
    if i <= nrows then
        m[r], m[i] = m[i], m[r]
    end
end

-- 如果 m[r][c] 不为零,则应用行操作,使得对于 i > r,每个 m[i][c] 都等于 0
local function clear(m, r, c)
    local nrows, ncols = #m, m.columns
    if r <= 0 or r > nrows or c <= 0 or c > ncols then error 'Position out of range' end
    if m[r][c] == 0 then
        -- 不需要操作
        return
    end
    for i = r + 1, nrows do
        local f = m[i][c] / m[r][c]
        for j = 1, #m[i] do
            m[i][j] = m[i][j] - f * m[r][j]
        end
    end
end

-- 使用高斯消元将矩阵 m 转换为梯形矩阵
function echelon(m)
    local nrows, ncols = #m, m.columns
    local r, c = 1, 1 -- 当前位置
    while r <= nrows and c <= ncols do
        -- 尝试在此位置获取一个非零值
        swap(m, r, c)
        if m[r][c] == 0 then
            -- 不能获取,则向右移
            c = c + 1
        else
            clear(m, r, c)
            -- 完成,斜向移动
            r = r + 1
            c = c + 1
        end
    end
end

local m = readcsv(arg[1])
print 'Original:'
printmatrix(m)
if m.rectangular then
    echelon(m)
    print 'Echelon form:'
    printmatrix(m)
else
    error 'Matrix not rectangular!'
end

t.scv:

1,3,5,7
2,1,-1,0
3,4,4,7
5,5,3,7

lua t.lua t.csv:

Original:
1, 3, 5, 7
2, 1, -1, 0
3, 4, 4, 7
5, 5, 3, 7
Echelon form:
1, 3, 5, 7
0, -5, -11, -14
0, 0, 0, 0
0, 0, 0, 0

你也可以使用标准输入(lua t.lua;输入数值,以 Ctrl + D 终止)。

  1. 如果想要交换 Lua 中的任意变量,只需要使用 a, b = b, a
  2. 我使用了一个简单的方法来实现你的第二个 doit (应用行操作:for j = 1, #m [i] do m [i] [j] = m [i] [j] - f * m [r] [j] end)。
  3. 我让你的代码变得更加简洁优雅。我还简化了解析 CSV 行所使用的正则表达式。
  4. 我还在矩阵输入时计算了其尺寸和矩形性。
2020-10-31 13:44:12