Нашли ошибку?
Скачать чистый
урок 4 из 5дополнительно≈ 10 минупражнения: 0 из 3

Системы уравнений

Найти неизвестные по нескольким суммам — цены по чекам, состав смеси. Система линейных уравнений в виде A @ x = b и её решение np.linalg.solve.

Python запустится при первом выполнении

Этот урок — дополнительный: дальше в курсе системы уравнений не понадобятся, его можно пропустить и вернуться, когда встретится такая задача. Он короткий и опирается на матричное умножение из урока «Матричное умножение».

От умножения — к обратной задаче

В уроке о матричном умножении мы знали количества и цены и считали суммы чеков: 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, а не ==.

[ ]Упражнение 1Латте и круассан решено

Два чека из кафе: 2 латте и 1 круассан — 520 ₽; 1 латте и 3 круассана — 560 ₽. Сохраните в A таблицу коэффициентов (строка — чек, столбцы — латте, круассан), в b — суммы чеков, а в cafe_prices — цены латте и круассана.

A = ...
b = ...
cafe_prices = ...

Неизвестных может быть сколько угодно — нужно столько же уравнений:

[ ]Упражнение 2Три чека решено

Три чека: 2 кофе, 1 чай и 1 пирожное — 690 ₽; 1 кофе и 3 чая — 720 ₽; 2 чая и 2 пирожных — 900 ₽. Сохраните в A3 таблицу коэффициентов (строка — чек, столбцы — кофе, чай, пирожное), в b3 — суммы чеков, а в unit_prices — цены трёх позиций.

A3 = ...
b3 = ...
unit_prices = ...

Не только чеки

Системой уравнений записывается любая задача «несколько неизвестных, несколько известных сумм». Например, смесь: уравнение о весе и уравнение о стоимости.

[ ]Упражнение 3Кофейная смесь решено

Нужно 10 кг смеси по 950 ₽ за килограмм из двух сортов: один стоит 800 ₽/кг, другой — 1200 ₽/кг. Сохраните в blend массив из двух чисел — сколько килограммов каждого сорта взять (сначала дешёвого, потом дорогого).

blend = ...

Когда однозначного решения нет

Решение существует и единственно, если ни одно уравнение не получается из других — умножением на число и сложением. Если второй чек — это первый, умноженный на два, новой информации в нём нет: подходит сколько угодно пар цен, и однозначно их не найти. Ячейка ниже перехватывает ошибку через 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 в ответе) — какое-то уравнение получается из других, однозначного решения нет.

Подробнее в справочнике

Нашли ошибку?