def main(): # Матрица из задания matrix = Matrix([[-11, 7, -1, 6], [-11, -9, 2, -7], [9, -3, 1, -2], [-5, 4, -1, -11]]) # Столбец свободных членов free_column = [74, 60, -54, -66] # ============================================================ # ВНИМАНИЕ! Пугливым ниже не смотреть! Дальше программный код! # ATTENTION! Not for timid people! Below is the program code! # ============================================================ print("Введенная матрица:") matrix.console_display() print(f'Определитель данной матрицы равен {matrix.det}\n') print("Матрица, обратная данной:") (matrix**(-1)).console_display() print('\n' + " Решение методом Гаусса для данной СЛАУ: ".center(75, '=')) decision = gauss(matrix.copy(), free_column, level_of_details=2) for step in decision: for info in step: if 'Матрица' in info: step[info].console_display() else: print(f"{info}: {step[info]}")
def main(): # Матрица из задания matrix = Matrix([[19, 5, 8], [5, -1, -6], [8, -6, -3]]) # Количество итераций number_of_iterations = 21 # ============================================================ # ВНИМАНИЕ! Пугливым ниже не смотреть! Дальше программный код! # ATTENTION! Not for timid people! Below is the program code! # ============================================================ print("Введенная матрица:\n") matrix.console_display() print("Нахождение спектрального радиуса степенным методом:\n") decision = power_method(matrix, level_of_detail=2, iterations=number_of_iterations) for step in decision: step_info = '' for info in step: if info not in ['Матрица']: if isinstance(step[info], (tuple, list)): step_info += f'{info}: {list(map(lambda x: round(x, 8), step[info]))}\n' elif isinstance(step[info], float): step_info += f'{info}: {round(step[info], 8)}\n' else: step_info += f'{info}: {step[info]}\n' print(step_info)
def main(): # Матрица из задания matrix = Matrix([[7, -1, 0, 0, 0], [5, -11, -4, 0, 0], [0, 2, -8, 4, 0], [0, 0, -4, 7, -4], [0, 0, 0, 4, -8]]) # Столбец свободных членов free_column = [10, 54, 42, 28, -16] # ============================================================ # ВНИМАНИЕ! Пугливым ниже не смотреть! Дальше программный код! # ATTENTION! Not for timid people! Below is the program code! # ============================================================ print(f"Столбец свободных членов: {free_column}\n") print("Введенная матрица:\n") matrix.console_display() print("Решение методом прогонки:\n") solution = triple(matrix, free_column, level_of_detail=2) for step in solution: step_info = '' for info in step: if info not in ['Матрица']: if isinstance(step[info], (tuple, list)): step_info += f'{info}: {list(map(lambda x: round(x, 8), step[info]))}\n' elif isinstance(step[info], float): step_info += f'{info}: {round(step[info], 8)}\n' else: step_info += f'{info}: {step[info]}\n' print(step_info)
def main(): # Матрица из задания matrix = Matrix([ [38, -10, -1], [2, -36, 9], [6, -1, -37], ]) # Столбец свободных членов free_column = [-293, -23, -303] print("Введенная матрица:") matrix.console_display() # ============================================================ # ВНИМАНИЕ! Пугливым ниже не смотреть! Дальше программный код! # ATTENTION! Not for timid people! Below is the program code! # ============================================================ print(f"Столбец свободных членов: {free_column}\n") if not matrix.is_dominant: print("Матрица не сходится") input('Нажмите "Enter" чтобы выйти...') exit() else: print(f"\n{' Решение методом простых итераций '.center(50, '=')}\n") solution = simple(matrix, free_column, iterations=10, level_of_detail=2) for step in solution: step_info = '' for info in step: if info not in ['Матрица']: if info in ['Нормы матрицы', 'Нормы вектора', 'Решение']: step_info += f'{info}: {list(map(lambda x: round(x, 8), step[info]))}\n' else: step_info += f'{info}: ' \ f'{step[info] if not isinstance(step[info], float) else round(step[info], 8)}\n' print(step_info) print(f"\n{' Решение методом Зейделя '.center(50, '=')}\n") solution = zeidel(matrix, free_column, iterations=5, level_of_detail=2) for step in solution: step_info = '' for info in step: if info not in ['Матрица']: if info in ['Нормы матрицы', 'Нормы вектора', 'Решение']: step_info += f'{info}: {list(map(lambda x: round(x, 8), step[info]))}\n' else: step_info += f'{info}: ' \ f'{step[info] if not isinstance(step[info], float) else round(step[info], 8)}\n' print(step_info)
def test_reverse_matrix(): matrix = Matrix([ [2, 3, 6], [3, 6, 2], [6, 2, 8], ]) true_solution = Matrix([[-11 / 32, 3 / 32, 15 / 64], [3 / 32, 5 / 32, -7 / 64], [15 / 64, -7 / 64, -3 / 128]]) solution = matrix**-1 assert solution.map(lambda value: round(float( value), 8)) == true_solution.map(lambda value: round(float(value), 8))
def test_gauss(): matrix = Matrix([[2, 5, 1], [-1, 2, -2], [6, 2, 1]]) free = [1, 2, 3] true_solution = [12 / 9, 10 / 57, -65 / 57] solution = get_solution(gauss(matrix, free)) assert list_round(solution) == list_round(true_solution)
def runge_refinement(results, steps, level_of_details=3): if len(results) != len(steps): raise IndexError('Количество результатов рассчетов должно совпадать с количеством значений шагов') if level_of_details < 3: yield { 'Этап': 'Получены значения', 'Результаты': results, 'Величины шагов': steps } matrix_first = Matrix(len(results)) matrix_second = Matrix(len(results)) for row_no in matrix_first.r_rows: matrix_first[row_no][0] = results[row_no] matrix_second[row_no][0] = 1 for row_no in matrix_first.r_rows: for col_no in range(1, matrix_first.columns): value = steps[row_no] ** (col_no + 1) matrix_first[row_no][col_no] = value matrix_second[row_no][col_no] = value if level_of_details < 3: yield { 'Этап': 'Сформированы матрицы', 'Первая матрица': matrix_first, 'Вторая матрица': matrix_second } first_determinant = matrix_first.det second_determinant = matrix_second.det if level_of_details < 3: yield { 'Этап': 'Рассчитаны определители', 'Первый определитель': float(first_determinant), 'Второй определитель': float(second_determinant) } if level_of_details < 4: yield { 'Решение': first_determinant / second_determinant }
def test_triple_solve(): matrix = Matrix([[-34, -26, 0, 0, 0], [64, -124, -56, 0, 0], [0, 94, -274, -86, 0], [0, 0, 124, -484, -116], [0, 0, 0, 154, -754]]) free = [34, 38, 42, 46, 50] true_solution = [-.6181818, -.4993007, -.2794706, -.1437131, -.0956655] solution = get_solution(triple(matrix, free)) assert list_round(solution, 7) == list_round(true_solution, 7)
def test_second_problem_power_method(): matrix = Matrix([ [-12, 4, 8], [4, 11, -6], [8, -6, 2], ]) true_solution = -17 solution = get_solution(second_problem.power_method(matrix)) assert round(float(solution)) == true_solution
def test_second_problem_yakobi_rotation(): matrix = Matrix([ [17, 1, 1], [1, 17, 2], [1, 2, 4], ]) true_solution = [16.0349, 18.31907, 3.646025] solution = get_solution( second_problem.yakobi_rotation(matrix))['Собственные числа'] assert list_round(solution, 4) == list_round(true_solution, 4)
def test_first_problem_iteration_simple(): matrix = Matrix([ [20, 4, -8], [-3, 15, 5], [6, 3, -18], ]) free = [1, -2, 3] true_solution = [-.0077608, -.0743338, -.1816226] solution = get_solution( first_problem_iteration.simple(matrix, free, iterations=7)) assert list_round(solution, 7) == list_round(true_solution, 7)
def test_first_problem_iteration_zeidel(): matrix = Matrix([ [20, 4, -8], [-3, 15, 5], [6, 3, -18], ]) free = [1, -2, 3] true_solution = [-.0077778, -.0743447, -.18165] solution = get_solution( first_problem_iteration.zeidel(matrix, free, iterations=5)) assert list_round(solution, 7) == list_round(true_solution, 7)
def main(): # Матрица из задания matrix = Matrix([ [-4, 4, -4], [4, 2, -8], [-4, -8, 15] ]) # Количество итераций number_of_iterations = 8 # ============================================================ # ВНИМАНИЕ! Пугливым ниже не смотреть! Дальше программный код! # ATTENTION! Not for timid people! Below is the program code! # ============================================================ print("Введенная матрица:\n") matrix.console_display() print("Нахождение собственных чисел и векторов методом вращения Якоби:\n") decision = yakobi_rotation(matrix, level_of_detail=2, iterations=number_of_iterations) for step in decision: for info in step: if 'матрица' in info.lower(): print(info, end=':\n\n') step[info].console_display() elif info == 'Решение': print('\n', ' Решение '.center(75, '='), '\n') solution = step['Решение'] for own_num_no in range(len(solution['Собственные числа'])): print(f'{own_num_no + 1} собственное число: {round(solution["Собственные числа"][own_num_no], 8)}') print(f'{own_num_no + 1} собственный вектор: ' f'{[round(_, 8) for _ in solution["Собственные векторы"][own_num_no]]}\n') elif info == 'Угол поворота фи': print(f'\n{info}: {step[info]}\n') else: print(f' {info}: {step[info]} '.center(75, '='))
def canonical_polynomial(x_list_of_values, y_list_of_values): if len(x_list_of_values) != len(y_list_of_values): raise IndexError( "Количество занчений X не совпадает с количеством значений Y") matrix = [] for row_no in range(len(x_list_of_values)): row = [] for i in range(len(x_list_of_values) - 1, 0, -1): row.append(x_list_of_values[row_no]**i) row.append(1) matrix.append(row) matrix = Matrix(matrix) # решение СЛАУ относительно сгененрированной матрицы и столбца свободных членов koefs = matrix.slau_solve(y_list_of_values) polynomial = 0 for koef_no in range(len(koefs)): polynomial += koefs[::-1][koef_no] * x**koef_no return { 'Матрица': matrix, 'Столбец свободных членов': y_list_of_values, 'Решение СЛАУ': koefs, 'Полином': polynomial, 'Функция python': lambdify(x, polynomial) }
def linearization(system, variables, approximation, accuracy_order=8, level_of_details=3, iterations=None): """ Решение СНЛАУ методом линеаризации (Ньютона) Args: system (list): список строк СНЛАУ variables (list): используемые пременные approximation (tuple): начальное приближение accuracy_order (int): необходимая точность level_of_details (int): необходимый уровень детализации iterations (int): неоюходимое количество итераций Yields: dict: информация о текущем шаге решения """ def get_subs(vars_, approx): out = {} approx = approx.vector_to_list for var_no in range(len(vars_)): out.update({vars_[var_no]: approx[var_no]}) return out def stop_iteration(): return all([ delta < 10**(-accuracy_order), (iteration_counter >= iterations) if iterations is not None else True, system_calc.vector_norma_1 < 10**(-accuracy_order) ]) system = parse_list(system) variables = parse_list(variables) if level_of_details < 3: yield { 'Этап': 'Получены значения', 'Система уравнений': Matrix(system).T, 'Использованные переменные': variables, 'Начальное приближение': approximation } approximation = Matrix(list(approximation)).T matrix_j_n = Matrix(len(system), len(variables)) for row_no, col_no in matrix_j_n: matrix_j_n[row_no][col_no] = diff(system[row_no], variables[col_no]) if level_of_details < 2: yield {"Этап": "Получена матрица Якоби", 'J_n': matrix_j_n} system = Matrix(system) matrix_j_n_rev = (matrix_j_n**(-1)).map(simplify) if level_of_details < 2: yield { "Этап": "Получена обратная матрица для матрицы Якоби", 'J_n ** (-1)': matrix_j_n_rev } iteration_matrix = (matrix_j_n_rev * system).map(simplify) if level_of_details < 3: yield { "Этап": "Вычислена матрица для совершения итераций", 'J_n ** (-1) * f(n)': iteration_matrix } evalfed_matrix = Matrix(iteration_matrix.rows, iteration_matrix.columns) iteration_counter = 0 while True: system_calc = system.T functions = [] for row_no in iteration_matrix.r_rows: evalfed_matrix[row_no][0] = iteration_matrix[row_no][0].evalf( subs=get_subs(variables, approximation)) system_calc[row_no][0] = system_calc[row_no][0].evalf( subs=get_subs(variables, approximation)) functions.append(system_calc[row_no][0]) old_approx = approximation if level_of_details < 3: yield { "Номер итерации": iteration_counter, 'Решение': get_subs(variables, approximation), '||F||_1': system_calc.vector_norma_1, 'F_1': functions[0], 'F_2': functions[1] } approximation -= evalfed_matrix delta = (old_approx - approximation).vector_norma_1 if stop_iteration(): if level_of_details < 4: yield {'Решение': get_subs(variables, approximation)} break iteration_counter += 1
def zeidel_method(system, variables, approximation, transformed_system=None, accuracy_order=8, level_of_details=3, iterations=None): raise Exception("Этот метод временно недоступен") # TODO: узнать откуда комплексные числа def transform(solutions): solutions = list(map(simplify, solutions)) min_sol = solutions[0] min_len = len(str(min_sol)) for solution in solutions: if len(str(solution)) < min_len: min_sol = solution min_len = len(str(min_sol)) return min_sol def calc_delta(old_subs, nw_subs): return sum(((elem1 - elem2) ** 2 for elem1, elem2 in zip(old_subs.values(), nw_subs.values()))) ** .5 def stop_iteration(): return all([ delta < 10 ** (-accuracy_order), (iteration_counter >= iterations) if iterations is not None else True ]) system = parse_list(system) variables = parse_list(variables) if transformed_system is None: transformed_system = {} for var_no in reversed(range(len(variables))): transformed_system.update({variables[::-1][var_no]: transform(solve(system[var_no], variables[::-1][var_no]))}) else: new_transformed = {} for key in transformed_system: new_transformed.update({parse_expr(key): simplify(parse_expr(transformed_system[key]))}) transformed_system = new_transformed.copy() if level_of_details < 3: yield { 'Этап': 'Получены значения', 'Система': Matrix(system).T, 'Начальное приближение': approximation, 'Преобразованная система': transformed_system, } for_subs = {} for var_no in range(len(variables)): for_subs.update({variables[var_no]: approximation[var_no]}) old_subs = for_subs.copy() iteration_counter = 1 while True: for key in transformed_system: for_subs.update({key: transformed_system[key].evalf(subs=for_subs)}) delta = calc_delta(old_subs, for_subs) old_subs = for_subs.copy() if level_of_details < 3: answer = { 'Номер итерации': iteration_counter, 'd': delta } answer.update(for_subs) yield answer if stop_iteration(): if level_of_details < 4: yield {'Решение': for_subs} break iteration_counter += 1
def minimal_sqr(table, level_of_details=3): """ Аппроксимация методом наименьших квадратов (квадратичная) Args: table (list): таблица значений (список из двух списков - x и y) level_of_details (int): необходимый уровень детализации Yields: dict: информация о текущем шаге решения """ def sum_xny(target_list, _power, second_list=None): if second_list is None: return sum((elem**_power for elem in target_list)) else: return sum((elem**_power * elem2 for elem, elem2 in zip(target_list, second_list))) def check_len(target_matrix): pr_len = len(target_matrix[0]) for line in target_matrix: if pr_len != len(line): return False return True def function(x_): return polynomial.evalf(subs={x: x_}) if not check_len(table): raise IndexError("Количество элементов в строках не совпадает") s = 3 system = [] for j in range(s): new_row = [] for koef_power in range(s): power = s - j - koef_power + 1 if power > 0: new_row.append(sum_xny(table[0], power)) else: new_row.append(len(table[0])) system.append(new_row) free_column = [] for koef_power in reversed(range(len(system))): free_column.append(sum_xny(table[0], koef_power, table[1])) if level_of_details < 3: yield { 'Матрица': Matrix(system), 'Столбец свободных членов': free_column } koefs = Matrix(system).slau_solve(free_column) polynomial = 0 for koef_power in range(len(koefs)): polynomial += x**koef_power * koefs[::-1][koef_power] sqr_nev = 0 for i in range(len(table[0])): sqr_nev += (function(table[0][i]) - table[1][i])**2 if level_of_details < 4: yield {'Многочлен': polynomial} if level_of_details < 3: yield { 'Коэффициенты': koefs, 'Функция python': function, 'Квадратическая невязка': sqr_nev }