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

时间:2015-08-12 06:01:05

标签: python

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

首先我设置了增强矩阵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 个答案:

答案 0 :(得分:17)

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

假设有以下矩阵要解决:

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
  • 注意整数和浮动分割之间的区别
  • 打印语句可以帮助您调试问题。