Как решить 4 х 4 массива с 16 неизвестными с Python (обновление) - PullRequest
1 голос
/ 08 апреля 2019

Мне нужно решить массив 2 на 2 с 4 неизвестными

AB
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 на 4 с 16 неизвестными

ABCD
EFGH
IJKL
MNOP

Я знаю горизонтальную сумму 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
Другая диагональная сумма A = 1, B + E = 7, C + F + I = 18, D + G + J + M = 34, H + K + N = 33, L + O = 27, P = 16
Что означает, что я знаю значение 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

Am Iв правильном направлении?Мне нужно будет решить 5X5 с 25 неизвестными, 6X6 с 36 неизвестными и так далее.Есть ли более простой способ?

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

Следуя решению мистера Рори Дольтона, я могу без проблем решить вышеупомянутый массив 4X4 с 1 по 16, но когда использую егодругой массив с отрицательным числом, он не дает ожидаемого ответа;

Отрицательный массив 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]

Что мне попробовать?Заранее спасибо.

1 Ответ

2 голосов
/ 08 апреля 2019

КОРОТКИЙ ОТВЕТ: Существует бесконечно много решений вашей проблемы.Так что для этого требуется более сложный анализ уравнений.

ДЛИННЫЙ ОТВЕТ: У вас много проблем с вашим кодом.

Во-первых, вы облегчаете делать ошибки,поскольку строки вашей матрицы не соответствуют данным, которые вы предоставляете.Хуже того, у вас нет комментариев, чтобы объяснить вещи.Это несовпадение, вероятно, приведет к ошибкам.У вас есть 22 части данных в ваших суммах, поэтому используйте их.Вы пытались объединить некоторые суммы и игнорировать другие (четыре угла), но не сделали это должным образом, и у вас получилась единичная матрица.

Далее вы используете linalg.solve.В вашей задаче у вас больше элементов данных (22), чем неизвестных (16), поэтому solve неуместно. Цифровая документация для solve состояний

a должна быть квадратной и иметь полный ранг, т. Е. Все строки (или, что то же самое, столбцы) должны быть линейно независимыми;если что-то не так, используйте lstsq для наилучшего «решения» наименьших квадратов системы / уравнения.

Матрица, полученная из ваших данных, не является квадратной, поэтомустроки не являются линейно независимыми, поэтому вы должны использовать lstsq вместо solve.Процедура lstsq дает больше информации, чем нужно для вашей задачи, поэтому просто напечатайте первый элемент в результирующем списке.

Объединение этих идей и добавление нескольких комментариев дает следующий код:

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

Функция numy solve работает только при наличии только одного решения, поэтому, даже если вы изменили матрицу по-другому, она бы не работала для вас.


ОТВЕТЬТЕ НА СВОЕ ОБНОВЛЕНИЕ:

Похоже, вы пропустилисмысл моего ответа.Ваша проблема 4х4 имеет бесконечно много ответов, поэтому нет процедуры, которая могла бы выбрать конкретный ответ, который вы имеете в виду.Процедура 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 дал вам правильный ответ - он не знает, как выбрать ответ, который у вас был в голове, из бесконечного множества правильных ответов на вашу проблему.Единственный способ получить только один ответ - изменить проблему - возможно, указать значение в первой строке и втором столбце или сумму первого и третьего значений в любой из строк или что-то подобное.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...