Системы уравнений в Python: от простых до сложных
Основной метод: решение линейных систем с помощью NumPy
Для систем линейных уравнений вида Ax = b самым быстрым и надёжным способом является вызов numpy.linalg.solve. Матрица коэффициентов A должна быть квадратной и невырожденной. Пример системы:
import numpy as np
A = np.array([[2.0, 1.0], [1.0, -3.0]])
b = np.array([7.0, 1.0])
x = np.linalg.solve(A, b)
print(x) # [ 3. -1.]Python решение примера (решение примера на python)
Как решить систему линейных уравнений с квадратной матрицей?
Функция solve использует разложение LU и решает систему за O(n³). Если матрица вырождена (детерминант равен нулю), возникает ошибка LinAlgError.
Типичные ошибки:
- Матрица A или вектор b имеют неправильные размеры. Решение: проверить shape, использовать reshape.
- Матрица плохо обусловлена. Результат может быть неточным. Рекомендуется нормировка или использование numpy.linalg.lstsq.
- Перепутаны строки и столбцы при формировании A.
Как решить переопределённую систему (метод наименьших квадратов)?
Когда уравнений больше, чем неизвестных, точного решения нет. Используется numpy.linalg.lstsq, который минимизирует ||Ax - b||₂.
A = np.array([[1, 1], [1, 2], [1, 3]])
b = np.array([2, 3, 5])
x, residuals, rank, s = np.linalg.lstsq(A, b, rcond=None)
print(x) # [1.1667 1.1667]Python вычисление значения выражений (вычисление значения выражений в python)
Вектор x даёт наилучшее приближение. Параметр rcond=None автоматически выбирает порог для отбрасывания малых сингулярных чисел.
Проблема: при очень плохой обусловленности решение может быть неустойчивым. Рекомендуется регуляризация (например, scipy.linalg.lstsq с параметром lapack_driver='gelsy').
Как решить систему нелинейных уравнений с помощью SciPy?
Для нелинейных систем используется scipy.optimize.fsolve. Систему нужно записать в виде F(x) = 0. Пример:
from scipy.optimize import fsolve
def equations(vars):
x, y = vars
eq1 = x**2 + y**2 - 1
eq2 = x - y
return [eq1, eq2]
x0 = [0.5, 0.5]
solution = fsolve(equations, x0)
print(solution) # [0.7071 0.7071]
вычисление функции в python (вычисление значения функции в python)
Как найти корни нелинейной системы с несколькими неизвестными?
Функция fsolve требует начальное приближение x0. Результат сильно зависит от начальной догадки. Если система имеет несколько решений, можно перебирать разные x0.
Ошибки: fsolve может сходиться к локальному минимуму, а не к корню. Рекомендуется проверять невязку в найденной точке. Если fsolve выдает ошибку 'The iteration is not making good progress', следует изменить начальное приближение или уменьшить xtol.
Как получить аналитическое (символьное) решение с помощью SymPy?
Библиотека SymPy позволяет решать системы символьно. Пример:
import sympy as sp
x, y = sp.symbols('x y')
eq1 = sp.Eq(x**2 + y**2, 1)
eq2 = sp.Eq(x - y, 0)
sol = sp.solve((eq1, eq2), (x, y))
print(sol) # [(-sqrt(2)/2, -sqrt(2)/2), (sqrt(2)/2, sqrt(2)/2)]Python вычисление корня (вычисление квадратного корня в python)
Для линейных систем можно использовать sp.linsolve. Символьное решение даёт точные выражения, но для больших систем может быть медленным.
Проблема: solve может не найти решение, если оно выражается через специальные функции. В таких случаях помогает nsolve (численный метод) из SymPy.
Как решить большую разреженную систему итерационными методами?
Для матриц большой размерности и разреженной структуры эффективны итерационные методы из scipy.sparse.linalg, например cg (сопряжённые градиенты) для симметричных положительно определённых матриц.
from scipy.sparse import csr_matrix
from scipy.sparse.linalg import cg
A = csr_matrix([[4, 1], [1, 3]])
b = np.array([1, 2])
x, info = cg(A, b)
print(x) # [0.0909 0.6364]Параметр info равен 0 при успешной сходимости. Итерационные методы экономят память, но требуют предобуславливания для ускорения сходимости.
Типичная ошибка: матрица не является положительно определённой (для CG). Решение: использовать gmres или bicgstab для несимметричных матриц.
Расширенные примеры решения систем уравнений
Пример 1: Система с комплексными коэффициентами
Линейная система, где матрица A и вектор b содержат комплексные числа, решается теми же функциями NumPy.
import numpy as np
A = np.array([[1+2j, 3-1j], [4j, 2+0j]])
b = np.array([5+1j, 3-2j])
x = np.linalg.solve(A, b)
print(x)# Результат: [ 1.08333333-1.08333333j -0.58333333+0.08333333j]
Пример 2: Система нелинейных уравнений с несколькими корнями
Уравнения sin(x) = 0 и cos(y) = 0 имеют бесконечно много решений. Разные начальные приближения приводят к разным корням.
from scipy.optimize import fsolve
import numpy as np
def f(vars):
x, y = vars
return [np.sin(x), np.cos(y)]
for guess in [(0, 0), (3, 1), (6, 2)]:
sol = fsolve(f, guess)
print(f'Начальн. {guess}: решение {np.round(sol,3)}')# Результат: Начальн. (0, 0): решение [0. 1.571] Начальн. (3, 1): решение [3.142 1.571] Начальн. (6, 2): решение [6.283 1.571]
Как видно, fsolve находит корни, ближайшие к начальному приближению.
Пример 3: Решение параметрического семейства систем
Рассмотрим систему x + a*y = 1, a*x - y = 0 с параметром a. Для серии значений a можно вычислить решения в цикле.
import numpy as np
def solve_parametric(a):
A = np.array([[1, a], [a, -1]])
b = np.array([1, 0])
return np.linalg.solve(A, b)
alphas = np.linspace(0, 2, 5)
solutions = [solve_parametric(a) for a in alphas]
for a, sol in zip(alphas, solutions):
print(f'a={a:.1f}: x={sol[0]:.4f}, y={sol[1]:.4f}')# Результат: a=0.0: x=1.0000, y=0.0000 a=0.5: x=0.8000, y=0.4000 a=1.0: x=1.0000, y=1.0000 a=1.5: x=-0.8000, y=-1.2000 a=2.0: x=-0.3333, y=-0.6667
Пример 4: Использование автоматического вычисления Якобиана в fsolve
Для ускорения сходимости можно передать якобиан (матрицу частных производных) в fsolve.
from scipy.optimize import fsolve
import numpy as np
def equations(vars):
x, y = vars
return [x**2 + y**2 - 2, np.exp(x) + y - 1]
def jacobian(vars):
x, y = vars
return [[2*x, 2*y], [np.exp(x), 1]]
sol = fsolve(equations, [0.5, 0.5], fprime=jacobian)
print(sol) # [ 0.1553 1.4108]Передача аналитического якобиана уменьшает число итераций. Если якобиан неизвестен, fsolve аппроксимирует его численно.
Пример 5: Решение системы дифференциальных уравнений (сведение к системе нелинейных)
Иногда требуется решить краевую задачу для системы ОДУ. Метод стрельбы сводит её к системе нелинейных уравнений. Пример для уравнения y'' = -y с граничными условиями y(0)=0, y(π/2)=1.
from scipy.optimize import fsolve
from scipy.integrate import solve_ivp
import numpy as np
def shoot(s0):
# интегрирование с начальным y'(0)=s0
def ode(t, y):
return [y[1], -y[0]]
sol = solve_ivp(ode, [0, np.pi/2], [0, s0], method='RK45', max_step=0.01)
return sol.y[0, -1] - 1 # невязка в правой границе
s_guess = 1.0
s_root = fsolve(shoot, s_guess)[0]
print(f'Начальная производная: {s_root:.4f}') # ~1.0# Результат: Начальная производная: 1.0000
Этим способом можно решать краевые задачи для систем ОДУ.