Сообщество Engee

Правило Крамера

Автор
avatar-maximsidorovmaximsidorov
Notebook

Решение системы линейных уравнений методом Крамера

Этот пример демонстрирует реализацию алгоритма решения системы линейных уравнений методом Крамера на языке программирования Julia.

Введение

Что такое метод Крамера?

Метод Крамера — это способ решения систем линейных алгебраических уравнений, в которых число уравнений совпадает с числом неизвестных, и определитель матрицы системы отличен от нуля. Этот метод основан на вычислении определителей и позволяет найти единственное решение системы.

Зачем он нужен?

Метод Крамера удобен тем, что дает явную формулу для решения системы и хорошо подходит для теоретического анализа. Однако с практической точки зрения он неэффективен для больших систем из-за необходимости вычисления множества определителей.

Метод применяется в тех случаях, когда необходимо получить точное аналитическое представление решения или размерность системы мала.

Основная часть

Установка и подключение необходимого пакета

import Pkg; Pkg.add("LinearAlgebra")
using LinearAlgebra 

Функция, реализующая правило Крамера

function cramersolve(A::Matrix, b::Vector)
    # Вычисляем главный определитель системы
    det_A = det(A)

    # Проверяем, что система имеет единственное решение (определитель не равен 0)
    if det_A  0
        error("Система не имеет единственного решения (определитель равен нулю)")
    end

    # Создаем массив для хранения решений переменных x1, x2, ..., xn
    solutions = Float64[]

    # Проходим по каждому столбцу матрицы A
    for i in eachindex(b)
        # Копируем исходную матрицу коэффициентов
        B = copy(A)
        
        # Заменяем i-ый столбец на вектор свободных членов b
        B[:, i] = b
        
        # Считаем определитель измененной матрицы и делим его на главный определитель
        push!(solutions, det(B) / det_A)
    end
    
    # Возвращаем полученные значения переменных
    return solutions
end
cramersolve (generic function with 1 method)
# Матрица коэффициентов при переменных
A = [2 -1  5  1;
     3  2  2 -6;
     1  3  3 -1;
     5 -2 -3  3]

# Вектор свободных членов
b = [-3, -32, -47, 49]
4-element Vector{Int64}:
  -3
 -32
 -47
  49

Вызываем функцию и выводим результат

println("Решение системы линейных уравнений методом Крамера:")
@show cramersolve(A, b);
Решение системы линейных уравнений методом Крамера:
cramersolve(A, b) = [2.0, -11.999999999999998, -4.0, 1.0000000000000009]

Пошаговое объяснение алгоритма:

Шаг 1. Сначала считается определитель основной матрицы det(A). Это важно, потому что метод Крамера применим только тогда, когда этот определитель не равен нулю.

Шаг 2. Далее создается временная матрица B, которая копирует оригинальную матрицу A. Для каждого неизвестного (, и т.д.) мы заменяем соответствующий столбец матрицы A на вектор правых частей b.

Шаг 3. После этого мы считаем определитель полученной модифицированной матрицы det(B) и делим его на главный определитель det(A). Получаем значение одного из корней системы.

Шаг 4. Эти шаги повторяются столько раз, сколько есть переменных, в результате чего формируется полный вектор решений.

Компактная версия с использованием генератора

Исходный вариант вашей функции использует конструкцию генератора, что делает её более компактной.

# Более компактный способ записи функции через генератор
function cramersolve_compact(A::Matrix, b::Vector)
    return [let B = copy(A); B[:, i] = b; det(B) end for i in eachindex(b)] ./ det(A)
end
cramersolve_compact (generic function with 1 method)

Обратите внимание: здесь выражение let ... end создаёт локальную область видимости, позволяющую безопасно изменять копию матрицы внутри цикла. Конструкция [expr for i in collection] — это генератор массивов в языке Julia.

@show cramersolve_compact(A, b);
cramersolve_compact(A, b) = [2.0, -11.999999999999998, -4.0, 1.0000000000000009]

Заключение

Мы рассмотрели реализацию классического метода решения систем линейных уравнений — метода Крамера — с использованием языка программирования Julia. Мы написали собственную функцию cramersolve, которая позволяет находить единственное решение системы уравнений при условии невырожденности (определитель матрицы системы отличен от нуля).

Данный подход хорош для понимания сути алгоритма, но в реальных задачах, особенно с большими матрицами (>1000×1000), используются более эффективные способы, такие как LU-разложение или SVD. Тем не менее, использование правила Крамера актуально в учебных и исследовательских задачах для получения аналитического представления решения.

Результат выполнения показывает, что реализация работает корректно и выдает решение для заданной системы уравнений.

Пример разработан с использованием материалов Rosetta Code