首页 文章

在python中使用旋转进行高斯消除

提问于
浏览
-4

我正在尝试编写一个函数来解决线性系统使用高斯消除与旋转 . 我不允许使用任何模块 . 有人可以帮帮我吗?我不知道我做错了什么 . 提前致谢 :) :) :)

首先我设置了增强矩阵M,然后我进行了旋转和行操作,最后我进行了后置替换

def linearsolver(A,b):   
  n = len(A) 
  M = A 

  i = 0 
  for x in M:
   x.append(b[i]) 
   i += 1 

  for k in range(n):   
   for i in range(k,n): 
     if abs(M[i][k]) > abs(M[k][k]):  
        M[k], M[i] = M[i],M[k]  
     else: 
        pass  

   for j in range(k+1,n):
       q = M[j][k] / M[k][k] 
       for m in range(k, n+1):         
          M[j][m] +=  q * M[k][m]

  x = [0 for i in range(n)]

  x[n] =float(M[n][n+1])/M[n][n]
  for i in range (n-1,-1,-1): 
    z = 0 
    for j in range(i+1,n):
        z = z  + float(M[i][j])*x[j] 
    x[i] = float(M[i][n+1] - z)/M[i][i]
  print x

1 回答

  • 12

    让它变得有教育意义,因为它显然是你的功课,并解释代码中的错误,不是吗?也许你可以在这个过程中学到一些东西 .

    假设有以下矩阵要解决:

    A = [[3, 2, -4], [2, 3, 3], [5, -3, 1]]
    b = [3, 15, 14]
    

    你的初始代码:

    def linearsolver(A,b):   
      n = len(A) 
      M = A 
    
      i = 0 
      for x in M:
       x.append(b[i]) 
       i += 1 
    
      for k in range(n):   
       for i in range(k,n): 
         if abs(M[i][k]) > abs(M[k][k]):  
            M[k], M[i] = M[i],M[k]  
         else: 
            pass  
    
       for j in range(k+1,n):
           q = M[j][k] / M[k][k] 
           for m in range(k, n+1):         
              M[j][m] +=  q * M[k][m]
    
      x = [0 for i in range(n)]
    
      x[n] =float(M[n][n+1])/M[n][n]
      for i in range (n-1,-1,-1): 
        z = 0 
        for j in range(i+1,n):
            z = z  + float(M[i][j])*x[j] 
        x[i] = float(M[i][n+1] - z)/M[i][i]
      print x
    

    首先你得到一个错误,关于索引超出范围或某事

    Traceback (most recent call last):
      File "solver.py", line 32, in <module>
        print linearsolver([[3, 2, -4], [2, 3, 3], [5, -3, 1]], [3, 15, 14])
      File "solver.py", line 24, in linearsolver
        x[n] =float(M[n][n+1])/M[n][n]
    IndexError: list index out of range
    

    你怎么调试这个?打印当前的计算状态:

    x = [0 for i in range(n)]
    
      print "n = ", n
      print "x = ", x
      for row in M:
        print row
    
      x[n] =float(M[n][n+1])/M[n][n]
    

    你会得到输出:

    n =  3
    x =  [0, 0, 0]
    [5, -3, 1, 14]
    [2, 3, 3, 15]
    [3, 2, -4, 3]
    Traceback (most recent call last):
      File "solver.py", line 37, in <module>
        print linearsolver([[3, 2, -4], [2, 3, 3], [5, -3, 1]], [3, 15, 14])
      File "solver.py", line 29, in linearsolver
        x[n] =float(M[n][n+1])/M[n][n]
    IndexError: list index out of range
    

    如果算正确,则尝试写入 x[3] 并访问 M[3][4]M[3][3] . 但是,python从0开始计数,这意味着最后一个元素比预期的小-1 . 最后一个元素是 x[2]M[2][3] . 这可以通过对所有索引应用-1来解决:

    x[n-1] =float(M[n-1][n])/M[n-1][n-1]
    

    跑吧......

    n =  3
    x =  [0, 0, 0]
    [5, -3, 1, 14]
    [2, 3, 3, 15]
    [3, 2, -4, 3]
    Traceback (most recent call last):
      File "solver.py", line 37, in <module>
        print linearsolver([[3, 2, -4], [2, 3, 3], [5, -3, 1]], [3, 15, 14])
      File "solver.py", line 34, in linearsolver
        x[i] = float(M[i][n+1] - z)/M[i][i]
    IndexError: list index out of range
    

    该死的,另一个追溯!但是,我们正在取得进展,现在它在更高的线上!当你仔细观察它时,再次使用 n+1 . 最初 An 行和 n 列 . 因为您将 b 附加到矩阵,所以有 n+1 列 . 由于从0开始索引,最后一个元素是总列数的-1: n+1-1 = n 我们修复它并且有代码:

    def linearsolver(A,b):
      n = len(A)
      M = A
    
      i = 0
      for x in M:
       x.append(b[i])
       i += 1
    
      for k in range(n):
       for i in range(k,n):
         if abs(M[i][k]) > abs(M[k][k]):
            M[k], M[i] = M[i],M[k]
         else:
            pass
    
       for j in range(k+1,n):
           q = M[j][k] / M[k][k]·
           for m in range(k, n+1):
              M[j][m] +=  q * M[k][m]
    
      x = [0 for i in range(n)]
    
      print "n = ", n
      print "x = ", x
      for row in M:
        print row
    
      x[n-1] =float(M[n-1][n])/M[n-1][n-1]
      for i in range (n-1,-1,-1):·
        z = 0·
        for j in range(i+1,n):
            z = z  + float(M[i][j])*x[j]·
        x[i] = float(M[i][n] - z)/M[i][i]
      print x
    

    当我们运行它时,我们得到结果!!! 1!

    n =  3
    x =  [0, 0, 0]
    [5, -3, 1, 14]
    [2, 3, 3, 15]
    [3, 2, -4, 3]
    [6.4, 5.75, -0.75]
    

    只需检查它是否有效:

    3 * 6.4 + 2 * 5.75 - 4 * -0.75 = 33.7 (not 3)
    2 * 6.4 + 3 * 5.75 + 3 * -0.75 = 27.8 (not 15)
    5 * 6.4 - 3 * 5.75 + 1 * -0.75 = 14.0 (correct)
    

    嗯......我们的矩阵没有解决,但至少我们有一行正确解决了 . 该算法要求最后一步具有特定格式的矩阵,其中大多数行以0开头 . 但事实并非如你所见 . 让我们在计算时添加额外的打印来显示矩阵:

    def linearsolver(A,b):
      n = len(A)
      M = A
    
      i = 0
      for x in M:
       x.append(b[i])
       i += 1
    
      for k in range(n):
       print "Iteration ", k
       for i in range(k,n):
         if abs(M[i][k]) > abs(M[k][k]):
            M[k], M[i] = M[i],M[k]
         else:
            pass
    
       # Show the matrix after swapping rows
       for row in M:
         print row
       print
    
       for j in range(k+1,n):
           q = M[j][k] / M[k][k]
           for m in range(k, n+1):
              M[j][m] +=  q * M[k][m]
    
       # Show matrix after multiplying rows
       for row in M:
         print row
       print
    
      x = [0 for i in range(n)]
    
      print "n = ", n
      print "x = ", x
      for row in M:
        print row
    
      x[n-1] =float(M[n-1][n])/M[n-1][n-1]
      for i in range (n-1,-1,-1):
        z = 0
        for j in range(i+1,n):
            z = z  + float(M[i][j])*x[j]
        x[i] = float(M[i][n] - z)/M[i][i]
      print x
    

    并运行它:

    Iteration  0
    [5, -3, 1, 14]
    [2, 3, 3, 15]
    [3, 2, -4, 3]
    
    [5, -3, 1, 14]
    [2, 3, 3, 15]
    [3, 2, -4, 3]
    
    Iteration  1
    [5, -3, 1, 14]
    [2, 3, 3, 15]
    [3, 2, -4, 3]
    
    [5, -3, 1, 14]
    [2, 3, 3, 15]
    [3, 2, -4, 3]
    
    Iteration  2
    [5, -3, 1, 14]
    [2, 3, 3, 15]
    [3, 2, -4, 3]
    
    [5, -3, 1, 14]
    [2, 3, 3, 15]
    [3, 2, -4, 3]
    
    n =  3
    x =  [0, 0, 0]
    [5, -3, 1, 14]
    [2, 3, 3, 15]
    [3, 2, -4, 3]
    [6.4, 5.75, -0.75]
    

    如您所见,行乘法根本没有发生!让我们检查一下状态:

    for j in range(k+1,n):
           q = M[j][k] / M[k][k]·
           print "j=", j, "q=", q
           print "M[j][k]=", M[j][k], "M[k][k]=", M[k][k]
           for m in range(k, n+1):
              M[j][m] +=  q * M[k][m]
    

    对于迭代0,我们得到:

    Iteration  0
    [5, -3, 1, 14]
    [2, 3, 3, 15]
    [3, 2, -4, 3]
    
    j= 1 q= 0
    M[j][k]= 2 M[k][k]= 5
    j= 2 q= 0
    M[j][k]= 3 M[k][k]= 5
    [5, -3, 1, 14]
    [2, 3, 3, 15]
    [3, 2, -4, 3]
    

    等一下, q 不应该是0!它应该是0.4和0.6!发生这种情况是因为两个数字都是整数而python提供的结果是整数而不是浮点数 . 要解决此问题,请将其更改为 float()

    for j in range(k+1,n):
           q = float(M[j][k]) / M[k][k]·
           print "j=", j, "q=", q
           print "M[j][k]=", M[j][k], "M[k][k]=", M[k][k]
           for m in range(k, n+1):
              M[j][m] +=  q * M[k][m]
    

    现在我们得到结果:

    Iteration  0
    [5, -3, 1, 14]
    [2, 3, 3, 15]
    [3, 2, -4, 3]
    
    j= 1 q= 0.4
    M[j][k]= 2 M[k][k]= 5
    j= 2 q= 0.6
    M[j][k]= 3 M[k][k]= 5
    [5, -3, 1, 14]
    [4.0, 1.7999999999999998, 3.4, 20.6]
    [6.0, 0.20000000000000018, -3.4, 11.4]
    

    虽然它有不同的输出,但我们在第一列中缺少零 . 为什么?代替2,有4而不是0,代替3,有6而不是0.我知道!你应该减去而不是添加乘法行:

    Iteration  0
    [5, -3, 1, 14]
    [2, 3, 3, 15]
    [3, 2, -4, 3]
    
    j= 1 q= 0.4
    M[j][k]= 2 M[k][k]= 5
    j= 2 q= 0.6
    M[j][k]= 3 M[k][k]= 5
    [5, -3, 1, 14]
    [0.0, 4.2, 2.6, 9.399999999999999]
    [0.0, 3.8, -4.6, -5.4]
    
    Iteration  1
    [5, -3, 1, 14]
    [0.0, 4.2, 2.6, 9.399999999999999]
    [0.0, 3.8, -4.6, -5.4]
    
    j= 2 q= 0.904761904762
    M[j][k]= 3.8 M[k][k]= 4.2
    [5, -3, 1, 14]
    [0.0, 4.2, 2.6, 9.399999999999999]
    [0.0, 0.0, -6.952380952380952, -13.904761904761903]
    
    Iteration  2
    [5, -3, 1, 14]
    [0.0, 4.2, 2.6, 9.399999999999999]
    [0.0, 0.0, -6.952380952380952, -13.904761904761903]
    
    [5, -3, 1, 14]
    [0.0, 4.2, 2.6, 9.399999999999999]
    [0.0, 0.0, -6.952380952380952, -13.904761904761903]
    
    n =  3
    x =  [0, 0, 0]
    [5, -3, 1, 14]
    [0.0, 4.2, 2.6, 9.399999999999999]
    [0.0, 0.0, -6.952380952380952, -13.904761904761903]
    [2.9999999999999996, 0.9999999999999996, 2.0]
    

    你能在大多数行的开头看到那些0.0吗?让我们现在检查证明:

    3 * 2.9999999999999996 + 2 * 0.9999999999999996 - 4 * 2.0 = 2.9999999999999964 (almost 3)
    2 * 2.9999999999999996 + 3 * 0.9999999999999996 + 3 * 2.0 = 14.999999999999998 (almost 15)
    5 * 2.9999999999999996 - 3 * 0.9999999999999996 + 1 * 2.0 = 14.0 (correct)
    

    计算机存在浮点数问题,但算法使我们得到了正确的解决方案[3,1,2]

    删除帮助程序打印后,有代码:

    def linearsolver(A,b):
      n = len(A)
      M = A
    
      i = 0
      for x in M:
       x.append(b[i])
       i += 1
    
      for k in range(n):
       for i in range(k,n):
         if abs(M[i][k]) > abs(M[k][k]):
            M[k], M[i] = M[i],M[k]
         else:
            pass
    
       for j in range(k+1,n):
           q = float(M[j][k]) / M[k][k]
           for m in range(k, n+1):
              M[j][m] -=  q * M[k][m]
    
      x = [0 for i in range(n)]
    
      x[n-1] =float(M[n-1][n])/M[n-1][n-1]
      for i in range (n-1,-1,-1):
        z = 0
        for j in range(i+1,n):
            z = z  + float(M[i][j])*x[j]
        x[i] = float(M[i][n] - z)/M[i][i]
      print x
    

    要带走的东西:

    • Python从0开始计算索引,这意味着最后一个索引是n-1

    • 注意整数和浮点除法之间的区别

    • Print语句可以帮助您调试问题 .

相关问题