Мне нужно решить массив 2 на 2 с 4 неизвестными
А Б
КОМПАКТ ДИСК
Я знаю всю горизонтальную сумму 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 неизвестными
А Б В Г
Э Ф Г Ч
Я Дж К Л
М Н О П
Я знаю горизонтальную сумму 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
Я в правильном направлении? Мне нужно будет решить 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]
Что мне попробовать? Заранее спасибо.
Определитель вашей матрицы равен 0, поэтому его нельзя инвертировать, вы можете проверить это самостоятельно с помощью print(np.linalg.det(C))
Я вижу 22 суммы в тексте, но только 16 строк в матрице.
Символически это муторно. Вы должны использовать разложение LU, если вы делаете это численно. Это будет необходимо, если вы хотите общее решение.
Я добавил обновление к своему ответу, чтобы оно соответствовало обновлению вашего вопроса. Резюме: для получения одного ответа нужно добавить больше информации к требованиям задачи.
КРАТКИЙ ОТВЕТ: У вашей проблемы бесконечно много решений. Так что это требует более сложного анализа уравнений.
ДЛИННЫЙ ОТВЕТ: У вас несколько проблем с кодом.
Во-первых, вы легко допускаете ошибки, так как строки вашей матрицы не соответствуют тем данным, которые вы представляете. Хуже того, у вас нет комментариев, чтобы объяснить вещи. Это несоответствие, вероятно, вызовет ошибки. У вас есть 22 элемента данных в ваших суммах, так что используйте их. Вы пытались объединить некоторые суммы и проигнорировать другие (четыре угла), но сделали это неправильно и в итоге получили сингулярную матрицу.
Затем вы используете linalg.solve
. В вашей задаче элементов данных (22) больше, чем неизвестных (16), поэтому solve
не подходит. Документация numpy для 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
, а не 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
Функция solve
numpy работает только в том случае, если есть только одно решение, поэтому, даже если вы настроили свою матрицу по-другому, она не сработала бы для вас.
ОТВЕТ НА ВАШЕ ОБНОВЛЕНИЕ:
Кажется, вы не поняли суть моего ответа. У вашей задачи 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 дал вам правильный ответ — он понятия не имеет, как выбрать ответ, который был у вас в голове, из бесконечного множества правильных ответов на вашу проблему. Единственный способ получить только один ответ — изменить задачу — например, указать значение в первой строке и втором столбце, или сумму первого и третьего значений в любой из строк, или что-то подобное.
Спасибо, сэр Рори Долтон, за подробный ответ. Это очень помогает.
Я принял лучший ответ, но у меня пока нет репутации, чтобы голосовать.
@SimonSimoon: я понимаю, поэтому я сказал «если у вас достаточно репутации» в моем (теперь удаленном) комментарии. Вы молодец: задали хороший вопрос и хорошо ответили на него. Я надеюсь, что вы продолжите на этом сайте.
Я попробовал np.linalg.lstsq для следующего массива 4X4.
Вы можете посмотреть здесь.