Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file not shown.
Binary file not shown.
73 changes: 73 additions & 0 deletions Р3213/vlasov_356550/lab1/src/gauss_method.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import copy


class GaussMethod:
def __init__(self, matrix_a, vector_b):
self.a_original = copy.deepcopy(matrix_a) # Исходная матрица A
self.b_original = copy.deepcopy(vector_b) # Исходный вектор B
self.a = copy.deepcopy(matrix_a) # Рабочая матрица для вычислений
self.b = copy.deepcopy(vector_b) # Рабочий вектор правой части
self.n = len(matrix_a) # Размерность матрицы
self.det = 1.0 # Инициализация определителя
self.swap_counter = 0


def forward_elimination(self):
for i in range(self.n):
diagonal_element = self.a[i][i]
# Проверяем, не равен ли диагональный элемент нулю (с учетом погрешности)
if abs(diagonal_element) < 1e-10:
for k in range(i+1, self.n):
if abs(self.a[k][i]) > 1e-10:
self.a[i], self.a[k] = self.a[k], self.a[i]
self.b[i], self.b[k] = self.b[k], self.b[i]
self.swap_counter += 1
self.det *= -1
diagonal_element = self.a[i][i]

break
else:
raise ValueError("матрица вырожденная")

# Умножаем определитель на текущий диагональный элемент
self.det *= diagonal_element

# Устраняем элементы под диагональю в текущем столбце
for j in range(i + 1, self.n):
m = self.a[j][i] / diagonal_element # Коэффициент для обнуления элемента

# Вручную вычитаем строку i, умноженную на m
for k in range(self.n):
self.a[j][k] -= m * self.a[i][k]

self.b[j] -= m * self.b[i] # Преобразуем правую часть


def back_substitution(self):
x = [0.0] * self.n # Вектор решения

# Идем снизу вверх по треугольной матрице
for i in range(self.n - 1, -1, -1):

# Вычисляем сумму уже найденных неизвестных вручную
s = 0.0
for k in range(i + 1, self.n):
s += self.a[i][k] * x[k]

# Находим текущую неизвестную
x[i] = (self.b[i] - s) / self.a[i][i]

return x


def solve(self):
self.forward_elimination() # Приводим к треугольному виду
return self.back_substitution() # Находим решение


def get_triangular_matrix(self):
return self.a, self.b


def get_determinant(self):
return self.det
85 changes: 85 additions & 0 deletions Р3213/vlasov_356550/lab1/src/input_handler.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import numpy as np


class InputHandler:
@staticmethod
def generate_random_matrix(n):
matrix_a = np.random.uniform(-10, 10, (n, n)).tolist()
vector_b = np.random.uniform(-10, 10, n).tolist()
return matrix_a, vector_b


@staticmethod
def _input_from_keyboard():
try:
n = int(input("Введите размерность матрицы n (n <= 20): "))
if n <= 0 or n > 20:
raise ValueError("Размерность должна быть от 1 до 20!")

print("Введите матрицу A (по строкам, числа через пробел):")

matrix_a = []
for _ in range(n):
row = list(map(float, input().replace(',', '.').split()))

if len(row) != n:
raise ValueError("Некорректное количество элементов в строке!")

matrix_a.append(row)

print("Введите вектор B (по одному числу в строке):")
vector_b = [float(input().replace(',', '.')) for _ in range(n)]

return matrix_a, vector_b, False
except ValueError as e:
raise ValueError(f"Ошибка ввода: {e}!")


@staticmethod
def _input_from_file():
print("Содержимое файла должно быть в следующем формате: первая строка - n (размерность), далее n строк матрицы A (числа через пробел), затем n строк вектора B (по одному числу).")
print("Пример:\n2\n2.0 3.0\n1.0 1.0\n5.0\n2.0")

try:
filename = input("Введите имя файла: ")
with open(filename, 'r') as f:
n = int(f.readline().strip())
if n <= 0 or n > 20:
raise ValueError("Размерность должна быть от 1 до 20!")

matrix_a = [list(map(float, f.readline().replace(',', '.').split())) for _ in range(n)]
vector_b = [float(f.readline().replace(',', '.')) for _ in range(n)]

if any(len(row) != n for row in matrix_a):
raise ValueError("Некорректное количество элементов в строке матрицы!")

return matrix_a, vector_b, False
except FileNotFoundError:
raise ValueError("Файл не найден!")
except ValueError as e:
raise ValueError(f"Ошибка чтения файла: {e}!")


@staticmethod
def _input_random():
try:
n = int(input("Введите размерность случайной матрицы n (n <= 20): "))
if n <= 0 or n > 20:
raise ValueError("Размерность должна быть от 1 до 20!")

matrix_a, vector_b = InputHandler.generate_random_matrix(n)

return matrix_a, vector_b, True
except ValueError as e:
raise ValueError(f"Ошибка генерации: {e}!")

def get_input(self):
choice = input("Выберите способ ввода (1 - клавиатура, 2 - файл, 3 - случайная матрица): ")
if choice == '1':
return self._input_from_keyboard()
elif choice == '2':
return self._input_from_file()
elif choice == '3':
return self._input_random()
else:
raise ValueError("Некорректный выбор способа ввода!")
53 changes: 53 additions & 0 deletions Р3213/vlasov_356550/lab1/src/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
from gauss_method import GaussMethod
from input_handler import InputHandler
from output_handler import print_matrix, print_vector
from residuals_calculator import compute_residuals
from numpy_comparator import compare_with_numpy


class Application:
def __init__(self):
self.input_handler = InputHandler()


def run(self):
try:
# Ввод данных
matrix_a, vector_b, is_random = self.input_handler.get_input()

if is_random:
print("\n[ СГЕНЕРИРОВАННАЯ СЛУЧАЙНАЯ МАТРИЦА ]")
print_matrix(matrix_a, "Матрица A")
print_vector(vector_b, "Вектор B")
else:
print("\n[ ВВЕДЁННЫЕ ДАННЫЕ ]")
print_matrix(matrix_a, "Матрица A")
print_vector(vector_b, "Вектор B")

# Решение системы
gauss = GaussMethod(matrix_a, vector_b)
x = gauss.solve()
det = gauss.get_determinant()
triangular_a, triangular_b = gauss.get_triangular_matrix()
residuals = compute_residuals(matrix_a, x, vector_b)

# Вывод результатов
print("\n[ РЕЗУЛЬТАТЫ ВЫЧИСЛЕНИЙ ]")
print_matrix(triangular_a, "Треугольная матрица A")
print_vector(triangular_b, "Преобразованный вектор B")
print_vector(x, "Вектор неизвестных x")
print(f"Определитель: {det:.6f}")
print_vector(residuals, "Вектор невязок r")

# Сравнение с numpy
compare_with_numpy(matrix_a, vector_b)

except ValueError as e:
print(f"Ошибка: {e}!")
except Exception as e:
print(f"Произошла непредвиденная ошибка: {e}!")


if __name__ == "__main__":
app = Application()
app.run()
12 changes: 12 additions & 0 deletions Р3213/vlasov_356550/lab1/src/numpy_comparator.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import numpy as np
from output_handler import print_vector


def compare_with_numpy(matrix_a, vector_b):
matrix_a_np = np.array(matrix_a)
vector_b_np = np.array(vector_b)
x_np = np.linalg.solve(matrix_a_np, vector_b_np)
det_np = np.linalg.det(matrix_a_np)
print("\n[ СРАВНИЕ С БИБЛИОТЕКОЙ NUMPY ]")
print_vector(x_np, "Решение с помощью numpy")
print(f"Определитель с помощью numpy: {det_np:.6f}")
10 changes: 10 additions & 0 deletions Р3213/vlasov_356550/lab1/src/output_handler.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
def print_matrix(matrix, name):
print(f"{name}:")
for row in matrix:
print(" ".join(f"{x:10.6f}" for x in row))


def print_vector(vector, name):
print(f"{name}:")
for x in vector:
print(f"{x:10.6f}")
12 changes: 12 additions & 0 deletions Р3213/vlasov_356550/lab1/src/residuals_calculator.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
def compute_residuals(a_original, x, b_original):
n = len(a_original)
r = [0.0] * n

# Вычисляем a_original * x
for i in range(n):
for j in range(n):
r[i] += a_original[i][j] * x[j]
# Вычитаем b_original
r[i] -= b_original[i]

return r
Binary file not shown.
Binary file not shown.
Empty file.
47 changes: 47 additions & 0 deletions Р3213/vlasov_356550/lab2/src/equations/nonlinear_equations.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# equations/nonlinear_equations.py

from typing import Callable
import numpy as np


class NonlinearEquations:
@staticmethod
def get_equations() -> dict[int, Callable[[float], float]]:
return {
1: lambda x: np.sin(x) - x + 1,
2: lambda x: x ** 3 - 2 * np.cos(x) - 1,
3: lambda x: np.exp(x) - 3 * x - 2,
4: lambda x: x ** 2 - 4 * np.sin(x),
5: lambda x: np.tan(np.clip(x, -np.pi / 2 + 0.1, np.pi / 2 - 0.1)) - x - 1 # Ограничение
}


@staticmethod
def get_derivative(eq_id: int) -> Callable[[float], float]:
derivatives = {
1: lambda x: np.cos(x) - 1,
2: lambda x: 3 * x ** 2 + 2 * np.sin(x),
3: lambda x: np.exp(x) - 3,
4: lambda x: 2 * x - 4 * np.cos(x),
5: lambda x: 1 / (np.cos(np.clip(x, -np.pi / 2 + 0.1, np.pi / 2 - 0.1)) ** 2) - 1
}

if eq_id in derivatives:
return derivatives[eq_id]

raise ValueError("Производная не определена для данного уравнения")


@staticmethod
def get_phi(eq_id: int, a: float, b: float) -> Callable[[float], float]:
f = NonlinearEquations.get_equations()[eq_id]
f_prime = NonlinearEquations.get_derivative(eq_id)
x_vals = np.linspace(a, b, 100)
max_f_prime = max(abs(f_prime(x)) for x in x_vals if -1e10 < f_prime(x) < 1e10)

if max_f_prime < 1e-6:
raise ValueError("Производная равна нулю на интервале")

lambda_val = 0.9 / max_f_prime

return lambda x: x - lambda_val * f(x)
27 changes: 27 additions & 0 deletions Р3213/vlasov_356550/lab2/src/equations/nonlinear_systems.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# equations/nonlinear_systems.py

from typing import Callable, Tuple
import numpy as np


class NonlinearSystems:
@staticmethod
def get_systems() -> dict[int, Tuple[Callable[[float, float], float], Callable[[float, float], float]]]:
return {
1: (lambda x, y: np.sin(x) + y - 1,
lambda x, y: x - np.cos(y)),
2: (lambda x, y: np.exp(x) - y - 1,
lambda x, y: 2 * x + np.sin(y) - 2)
}


@staticmethod
def get_phi_system(sys_id: int) -> Tuple[Callable[[float, float], float], Callable[[float, float], float]]:
if sys_id == 1:
return (lambda x, y: np.cos(y), # x = cos(y)
lambda x, y: 1 - np.sin(x)) # y = 1 - sin(x)
elif sys_id == 2:
return (lambda x, y: np.log(1 + y) if 1 + y > 0 else x, # x = ln(1 + y)
lambda x, y: (2 - np.sin(y)) / 2) # y = (2 - sin(y)) / 2

raise ValueError("Неверный номер системы")
Empty file.
40 changes: 40 additions & 0 deletions Р3213/vlasov_356550/lab2/src/methods/bisection.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# methods/bisection.py

from typing import Callable


class BisectionMethod:
@staticmethod
def check_roots(f: Callable[[float], float], a: float, b: float) -> str | None:
fa, fb = f(a), f(b)

if fa * fb >= 0:
return "Функция не меняет знак на концах интервала"

return None


@staticmethod
def solve(f: Callable[[float], float], a: float, b: float, eps: float) -> tuple[float, int]:
if a >= b:
raise ValueError("Левая граница должна быть меньше правой")

error = BisectionMethod.check_roots(f, a, b)

if error:
raise ValueError(error)

iters = 0
while abs(b - a) > eps: # Итерируем до нужной точности
x = (a + b) / 2 # Вычисляем середину

if f(x) == 0:
return x, iters + 1
elif f(a) * f(x) < 0: # Корень в левой половине, обновляем b = x
b = x
else: # Иначе корень в правой половине, обновляем a = x
a = x

iters += 1

return (a + b) / 2, iters
Loading