python - 如何使用 Python 求解具有 16 个未知数的 4 x 4 数组(更新)

标签 python arrays math

我需要求解一个 2 x 2 数组,其中有 4 个未知数

A B
CD

我知道所有水平总和 A+B=11, C+D=7
我知道所有垂直总和 A+C=10, B+D=8
我知道所有对角线和 A+D=15, B+C=3

然后我使用 Python 求解 A、B、C、D

import numpy as np

A = [[1, 1, 1, 1], 
     [1, 0, 0, 1], 
     [1, 0, 1, 0], 
     [0, 0, 1, 1]]
a = [18, 15, 10, 7]
answera = np.linalg.solve(A, a)
print(answera)

答案是[9. 2.1.6.]哪个是正确的

现在我需要求解 4 x 4 数组,其中 16 个未知数

A B C D
E F G H
我JKL
M N O P

我知道水平和A+B+C+D=10,E+F+G+H=26,I+J+K+L=42,M+N+O+P=58
我知道垂直和A+E+I+M=28,B+F+J+N=32,C+G+K+O=36,D+H+L+P=40
我知道对角线和M=13,I+N=23,E+J+O=30,A+F+K+P=34,B+G+L=21,C+H=11,D=4< br/> 另一对角线和A=1,B+E=7,C+F+I=18,D+G+J+M=34,H+K+N=33,L+O=27,P=16< br/> 这意味着我知道 4 个角的值。

我尝试了以下代码,但没有成功

C = [[1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 
     [0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0], 
     [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0],
     [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1],
     [0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
     [0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0],
     [0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0],
     [0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0],
     [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0],
     [0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0],
     [0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0],
     [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1],
     [0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0],
     [0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0],
     [0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0],
     [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]] 

c = [10, 26, 42, 58, 7, 21, 39, 33, 27, 11, 23, 35, 30, 23, 32, 136]
answerc = np.linalg.solve(C, c)
print(answerc)

正确答案应该是[1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16.] 但我收到错误消息

Traceback (most recent call last):
answerc = np.linalg.solve(C, c)
r = gufunc(a, b, signature=signature, extobj=extobj)
 raise LinAlgError("Singular matrix")
numpy.linalg.LinAlgError: Singular matrix

我的方向正确吗?我需要解决 5X5 与 25 个未知数,6X6 与 36 个未知数等等。有没有更简单的方法?

------------------------------------------------------------ ------------------------------------------

按照Rory Daulton先生的解决方案,我可以毫无问题地解决上述1到16 4X4数组,但是当我在另一个带有负数的数组中使用它时,它没有给出预期的答案;

负4X4数组如下

-20   -10    -5    0
-10   -20   -10   -5
-5      0   -10   -20
-10   -20   -10   -5

我的Python代码如下

import numpy as np
G = [[1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],  # horizontal rows
     [0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0], 
     [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0],
     [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1],
     [1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0],  # vertical columns
     [0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0],
     [0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0],
     [0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1],
     [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0],  # forward diagonals
     [0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0],
     [0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0],
     [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1],
     [0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0],
     [0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0],
     [0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
     [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],  # back diagonals
     [0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
     [0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0],
     [0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0],
     [0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0],
     [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0],
     [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
    ]

g = [-35, -45, -35, -45,  # horizontal rows
     -45, -50, -35, -30,  # vertical columns
     -10, -25, -20, -55, -40, -10, 0,  # forward diagonals
     -20, -20, -30, -20, -35, -30, -5,  # back diagonals
    ]

answerg = np.linalg.lstsq(G, g, rcond=None)
print(answerg[0])

输出并不完全是原始数组

[-2.00000000e+01 -1.31250000e+01 -1.87500000e+00  8.88178420e-15
 -6.87500000e+00 -2.00000000e+01 -1.00000000e+01 -8.12500000e+00
 -8.12500000e+00  2.13162821e-14 -1.00000000e+01 -1.68750000e+01
 -1.00000000e+01 -1.68750000e+01 -1.31250000e+01 -5.00000000e+00]

我应该尝试什么?预先感谢您。

最佳答案

简短回答:您的问题有无数种解决方案。因此,这需要对方程进行更复杂的分析。

长答案:您的代码存在多个问题。

首先,您很容易犯错误,因为矩阵的行与您提供的数据不对应。更糟糕的是,你没有任何评论来解释事情。这种不匹配可能会导致错误。您的求和中有 22 条数据,因此请使用它们。您尝试合并一些总和并忽略其他总和(四个角),但您做得不正确,最终得到了一个奇异矩阵。

接下来,您使用linalg.solve。在您的问题中,您的数据项 (22) 多于未知数 (16),因此 solve 是不合适的。 The numpy documentation for solve

a must be square and of full-rank, i.e., all rows (or, equivalently, columns) must be linearly independent; if either is not true, use lstsq for the least-squares best “solution” of the system/equation.

由数据生成的矩阵不是方形的,因此行不是线性独立的,因此您应该使用 lstsq 而不是 solvelstsq 例程提供的信息超出您解决问题所需的信息,因此只需打印结果列表中的第一项即可。

结合这些想法并添加一些注释可以得到以下代码:

import numpy as np

C = [[1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],  # horizontal rows
     [0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0], 
     [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0],
     [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1],
     [1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0],  # vertical columns
     [0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0],
     [0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0],
     [0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1],
     [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0],  # forward diagonals
     [0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0],
     [0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0],
     [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1],
     [0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0],
     [0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0],
     [0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
     [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],  # back diagonals
     [0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
     [0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0],
     [0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0],
     [0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0],
     [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0],
     [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
    ]

c = [10, 26, 42, 58,  # horizontal rows
     28, 32, 36, 40,  # vertical columns
     13, 23, 30, 34, 21, 11, 4,  # forward diagonals
     1, 7, 18, 34, 33, 27, 16,  # back diagonals
    ]

answerc = np.linalg.lstsq(C, c, rcond=None)
print(answerc[0])

打印输出就是您想要的:

[ 1.  2.  3.  4.  5.  6.  7.  8.  9. 10. 11. 12. 13. 14. 15. 16.]
<小时/>

但是,说实话,并不能保证这是一个答案——只是它是一个“最接近”的答案。另外,如果这是一个答案,可能还有其他答案。事实上,进一步分析表明还有其他答案可以满足您的所有条件。

sympy模块可以生成矩阵的行简化梯形形式,可以用来对所有答案做更深入的分析。然而,常数将成为矩阵的一部分,而不是用作单独的数组。这是 sympy 尝试解决您的问题的代码:

import sympy

C = [[1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10],  # horizontal rows
     [0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 26], 
     [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 42],
     [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 58],
     [1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 28],  # vertical columns
     [0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 32],
     [0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 36],
     [0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 40],
     [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 13],  # forward diagonals
     [0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 23],
     [0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 30],
     [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 34],
     [0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 21],
     [0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 11],
     [0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  4],
     [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  1],  # back diagonals
     [0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  7],
     [0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 18],
     [0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 34],
     [0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 33],
     [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 27],
     [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 16],
    ]

print(sympy.Matrix(C).rref())

打印输出为

(Matrix([
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0,   1],
[0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, -13],
[0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  1, 0,  18],
[0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0,   4],
[0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,  1, 0,  20],
[0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0,   6],
[0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,  0, 0,   7],
[0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, -1, 0,  -7],
[0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, -1, 0,  -6],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,  0, 0,  10],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,  0, 0,  11],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,  1, 0,  27],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,  0, 0,  13],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,  1, 0,  29],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 1,  16],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0,   0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0,   0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0,   0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0,   0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0,   0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0,   0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0,   0]]), (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 15))

如果您知道如何分析这一点,您会发现您的问题有无限多个答案。如果您将第 15 个单元格中的数字设置为 15+x,那么上面的矩阵显示所有限制的答案是

 1     2+x   3-x   4
 5-x   6     7     8+x
 9+x  10    11    12-x
13    14-x  15+x  16

numpy 的 solve 函数仅在只有一种解决方案时才起作用,因此即使您以不同的方式调整了矩阵,它也不会为您工作。

<小时/>

对您的更新的答复:

看来你没有捕获我的回答的重点。您的 4x4 问题有无数个答案,因此没有任何程序可以选择您想要的特定答案。 np.linalg.lstsq 例程可以找到您问题的答案之一,但可能找不到您想要的答案。您应该认为这是一个巧合,在您的第一个问题中使用该例程给出了您想要的答案 - 这可能不适用于其他问题。

解释新问题的给定答案有点困难,因为科学记数法很难阅读。但所有这些矩阵值都是精确的,在这里它们是特定格式的有理数,这应该是显而易见的:

-20          -10-(3+1/8)  - 5+(3+1/8)    0
-10+(3+1/8)  -20          -10          - 5-(3+1/8)
- 5-(3+1/8)    0          -10          -20+(3+1/8)
-10          -20+(3+1/8)  -10-(3+1/8)  - 5

您会看到 numpy 的答案正是您所期望的,其中将值 3+1/8 添加到一半的数组值中或从中减去。这使得 x=3+1/8 成为我为您的第一个问题提供的一般答案。

这正如您所期望的那样好。 Numpy 给了你一个正确的答案——它不知道如何从问题的无数正确答案中选择你头脑中的答案。获得一个答案的唯一方法是改变你的问题——也许说明第一行和第二列中的值,或者任何一行中第一个和第三个值的总和,或者类似的东西。

关于python - 如何使用 Python 求解具有 16 个未知数的 4 x 4 数组(更新),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55579049/

相关文章:

java - 3D相机缩放并遵循java中的物理原理?

python - scipy.optimize 约束最小化 SLSQP - 无法 100% 匹配目标

python - 当数据框 B 中的列值不相似时,从数据框 A 中删除行

python - Django javascript 翻译目录文件加载失败,显示错误 - ReferenceError : gettext is not defined

python - 调整矩阵数组乘法以使用 Numpy Tensordot

javascript - 在两个方向上迭代一个范围

python - Matplotlib 绘图以错误的方式绘制

python - PostgreSQL 表上的更新查询不起作用

java - 检查字符串是否包含其他字符串Java的一部分

math - 如何计算表面由三角形组成的 3D 网格对象的体积