Этот урок — дополнительный: дальше в курсе системы уравнений не понадобятся, его можно пропустить и вернуться, когда встретится такая задача. Он короткий и опирается на матричное умножение из урока «Матричное умножение».
От умножения — к обратной задаче
В уроке о матричном умножении мы знали количества и цены и считали суммы чеков: orders @ prices. Теперь
наоборот: суммы чеков известны, а цены — нет. Два чека: 3 пачки кофе и 2 кружки — 690 ₽; 1 пачка и 4 кружки —
730 ₽. Сколько стоит пачка и кружка? Это система двух уравнений:
3x + 2y = 690
1x + 4y = 730
Коэффициенты — таблица A (строка — чек, столбец — товар), правые части — вектор b. Вся система записывается
одной строкой: A @ [x, y] = b. Функция np.linalg.solve(A, b) находит [x, y]. Проверить ответ легко —
умножить обратно и сравнить с b:
import numpy as np
A_demo = np.array([[3, 2], [1, 4]])
b_demo = np.array([690, 730])
x = np.linalg.solve(A_demo, b_demo)
print(np.round(x, 2)) # пачка кофе и кружка
print(np.round(A_demo @ x, 2)) # умножили обратно — получили суммы чеков
print(np.allclose(A_demo @ x, b_demo))[130. 150.] [690. 730.] True
Ответ дробного типа, даже если числа целые: внутри solve делит. Поэтому сравнивать результат с ожидаемым
лучше через np.allclose, а не ==.
Два чека из кафе: 2 латте и 1 круассан — 520 ₽; 1 латте и 3 круассана — 560 ₽. Сохраните в A таблицу
коэффициентов (строка — чек, столбцы — латте, круассан), в b — суммы чеков, а в cafe_prices — цены латте
и круассана.
A — сколько чего в чеке: [2, 1] и [1, 3]; b — [520, 560].np.linalg.solve(A, b).Заготовка упражнения обновилась с тех пор, как вы сохранили свой код.
Вернуть заготовку? Ваш код в этом упражнении будет удалён.
A = ...
b = ...
cafe_prices = ...Упражнение пока не решено, поэтому для ячеек ниже выполнено эталонное решение — ваш код не изменён.
A = np.array([[2, 1], [1, 3]])
b = np.array([520, 560])
cafe_prices = np.linalg.solve(A, b)Неизвестных может быть сколько угодно — нужно столько же уравнений:
Три чека: 2 кофе, 1 чай и 1 пирожное — 690 ₽; 1 кофе и 3 чая — 720 ₽; 2 чая и 2 пирожных — 900 ₽. Сохраните
в A3 таблицу коэффициентов (строка — чек, столбцы — кофе, чай, пирожное), в b3 — суммы чеков, а в
unit_prices — цены трёх позиций.
[2, 1, 1], [1, 3, 0], [0, 2, 2].np.linalg.solve(A3, b3).Заготовка упражнения обновилась с тех пор, как вы сохранили свой код.
Вернуть заготовку? Ваш код в этом упражнении будет удалён.
A3 = ...
b3 = ...
unit_prices = ...Упражнение пока не решено, поэтому для ячеек ниже выполнено эталонное решение — ваш код не изменён.
A3 = np.array([[2, 1, 1], [1, 3, 0], [0, 2, 2]])
b3 = np.array([690, 720, 900])
unit_prices = np.linalg.solve(A3, b3)Не только чеки
Системой уравнений записывается любая задача «несколько неизвестных, несколько известных сумм». Например, смесь: уравнение о весе и уравнение о стоимости.
Нужно 10 кг смеси по 950 ₽ за килограмм из двух сортов: один стоит 800 ₽/кг, другой — 1200 ₽/кг. Сохраните
в blend массив из двух чисел — сколько килограммов каждого сорта взять (сначала дешёвого, потом дорогого).
x + y = 10 (вес) и 800x + 1200y = 9500 (стоимость всей смеси: 10 × 950).np.linalg.solve(np.array([[1, 1], [800, 1200]]), np.array([10, 9500])).Заготовка упражнения обновилась с тех пор, как вы сохранили свой код.
Вернуть заготовку? Ваш код в этом упражнении будет удалён.
blend = ...Упражнение пока не решено, поэтому для ячеек ниже выполнено эталонное решение — ваш код не изменён.
blend = np.linalg.solve(np.array([[1, 1], [800, 1200]]), np.array([10, 9500]))Когда однозначного решения нет
Решение существует и единственно, если ни одно уравнение не получается из других — умножением на число
и сложением. Если второй чек — это первый, умноженный на два, новой информации в нём нет: подходит сколько
угодно пар цен, и однозначно их не найти. Ячейка ниже перехватывает ошибку
через try / except, чтобы показать её текст:
same = np.array([[3, 2], [6, 4]]) # второй чек — первый, умноженный на два
try:
print(np.linalg.solve(same, np.array([690, 1380])))
except np.linalg.LinAlgError as error:
print("LinAlgError:", error)[nan nan]
В Jupyter на компьютере solve сообщает об ошибке LinAlgError: Singular matrix. Python в браузере устроен
немного иначе и вместо ошибки возвращает [nan nan] — «не числа» из модуля о пропусках. Смысл один: однозначного ответа нет.
Итоги
- Система линейных уравнений — это
A @ x = b: строкаA— уравнение, столбец — неизвестное. np.linalg.solve(A, b)находитx; уравнений должно быть столько же, сколько неизвестных.- Проверка — умножить обратно:
np.allclose(A @ x, b). Singular matrix(в браузере —nanв ответе) — какое-то уравнение получается из других, однозначного решения нет.