예제 #1
0
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 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)
예제 #3
0
def solve(matrix: (list, Matrix), free_column: (list, Matrix)) -> list:
    """Решение СЛАУ оптимальным методом"""
    if isinstance(matrix, list):
        matrix = Matrix(matrix)
    if isinstance(free_column, Matrix):
        free_column = free_column.vector_to_list
    solution = None
    if matrix.is_triple_diagonal:
        decision = triple(matrix, free_column)
    else:
        # TODO: разобраться в причине неработоспособности метода Гаусса
        # decision = gauss.gauss_method(matrix, free_column)
        decision = kramer(matrix, free_column)
    for step in decision:
        solution = step.get('Решение')
    return solution
예제 #4
0
def final_difference(equation: str,
                     boundaries_conditions: list,
                     boundaries_in: dict = None,
                     boundary_x: tuple = None,
                     num_of_sections: int = 4,
                     section_step: float = None,
                     level_of_detail: int = 3):
    """
    Решение краевой задачи для ОДУ методом конечных разностей

    Args:
        boundaries_conditions (list): раевые условия (список строк)
        equation (str): уравнение
        boundaries_in (dict): краевые условия
        boundary_x (tuple): краевые иксы (2 значения)
        num_of_sections (int): количество отрезков
        section_step (float): шаг (имеет приоритет над num_of_sections)
        level_of_detail (int): уровень детализации

    Yields:
        dict: значения шага решения

    """

    if boundaries_in is None:
        boundaries_in = dict()
    if boundary_x is None:
        boundary_x = [None, None]

    def get_boundaries(expression, bound_conditions):
        # поиск краевых условий через регулярные выражения (K и L и M)
        regexp = "(?:(?P<K>.*y'{2})|(?P<L>.*y'{1})|(?P<M>.*y))"
        group_names = list('KLM')
        left, right = expression.split('=')
        out = {'F': parse_expr(right)}
        for match in re.finditer(regexp, left):
            for name in group_names:
                if match.group(name):
                    out.update({
                        name:
                        parse_expr(match.group(name).replace("'",
                                                             '')).subs({y: 1})
                    })

        section = [None, None]
        # поиск краевых условий через регулярные выражения (S и R) I - край отрезка
        regexp = r"(?P<S>[a-zA-Z0-9 \+\-\*\/]*y(?!\'))|(?P<R>[a-zA-Z0-9 \+\-\*\/]*y(?=\'))|(?P<I>(?<=\().+?(?=\)))"
        group_names = list('SRI')
        left, right = bound_conditions[0].split('=')
        out.update({'T': parse_expr(right)})
        for match in re.finditer(regexp, left):
            for name in group_names:
                if match.group(name):
                    if name == 'I':
                        section[0] = parse_expr(match.group(name))
                    else:
                        out.update(
                            {name: parse_expr(match.group(name)).subs({y: 1})})
        # поиск краевых условий через регулярные выражения (W и V) I - край отрезка
        regexp = r"(?P<W>[a-zA-Z0-9 \+\-\*\/]*y(?!\'))|(?P<V>[a-zA-Z0-9 \+\-\*\/]*y(?=\'))|(?P<I>(?<=\().+?(?=\)))"
        group_names = list('WVI')
        left, right = bound_conditions[1].split('=')
        out.update({'Z': parse_expr(right)})
        for match in re.finditer(regexp, left):
            for name in group_names:
                if match.group(name):
                    if name == 'I':
                        section[1] = parse_expr(match.group(name))
                    else:
                        out.update(
                            {name: parse_expr(match.group(name)).subs({y: 1})})

        return out, min(section), max(section)

    def get_a_x(x_value):
        return boundaries['K'].evalf(subs={x: x_value}) / section_x_len ** 2 - \
               boundaries['L'].evalf(subs={x: x_value}) / (2 * section_x_len)

    def get_b_x(x_value):
        return -2 * boundaries['K'].evalf(subs={x: x_value}) / (section_x_len ** 2) + \
               boundaries['M'].evalf(subs={x: x_value})

    def get_c_x(x_value):
        return boundaries['K'].evalf(subs={x: x_value}) / section_x_len ** 2 + \
               boundaries['L'].evalf(subs={x: x_value}) / (2 * section_x_len)

    def get_d_x(x_value):
        return boundaries['F'].evalf(subs={x: x_value})

    boundaries, boundary_x[0], boundary_x[1] = get_boundaries(
        equation, boundaries_conditions)
    boundaries.update(
        {key: parse_expr(str(boundaries_in[key]))
         for key in boundaries_in})
    if section_step is not None:
        section_x_len = section_step
        num_of_sections = int((boundary_x[1] - boundary_x[0]) / section_x_len)
    else:
        section_x_len = (boundary_x[1] - boundary_x[0]) / num_of_sections  # h

    if level_of_detail < 3:
        yield {'Выражение': equation, 'h': section_x_len, **boundaries}

    points_x = [
        boundary_x[0] + section * section_x_len
        for section in range(num_of_sections + 1)
    ]

    diagonal_a = [get_a_x(value) for value in points_x]
    diagonal_b = [get_b_x(value) for value in points_x]
    diagonal_c = [get_c_x(value) for value in points_x]
    free_col_d = [get_d_x(value) for value in points_x]

    diagonal_a.pop(0)
    diagonal_b[0] = -boundaries['R'] / section_x_len + boundaries['S']
    diagonal_c[0] = boundaries['R'] / section_x_len
    free_col_d[0] = boundaries['T']
    free_col_d[-1] = -boundaries['Z']
    diagonal_a[-1] = boundaries['V'] / section_x_len
    diagonal_b[-1] = -boundaries['V'] / section_x_len - boundaries['W']
    diagonal_c.pop(-1)

    free_col_d = list(map(float, free_col_d))

    if level_of_detail < 3:
        yield {
            'Список значений c': diagonal_c,
            'Список значений b': diagonal_b,
            'Список значений a': diagonal_a,
            'Список значений d': free_col_d,
        }

    matrix = fill_triple_from_lists(diagonal_c, diagonal_b, diagonal_a).map(
        lambda val: val if isinstance(val, int) else float(val))

    if level_of_detail < 3:
        drop_matrix = matrix.copy()
        drop_matrix.append_column(free_col_d)
        yield {'Матрица': drop_matrix}

    decision = triple(matrix, free_col_d, level_of_detail=level_of_detail)
    solution = None
    for step in decision:
        if level_of_detail < 3 and not 'Решение' in step:
            yield step
        solution = step.get('Решение')
    solution = list(map(float, solution))
    if level_of_detail < 4:
        yield {'Решение': {'X': points_x, 'Y': solution}}